Engauge Digitizer  2
 All Classes Files Functions Variables Enumerations Enumerator Friends Pages
MainWindow.cpp
1 #include "BackgroundImage.h"
2 #include "BackgroundStateContext.h"
3 #include "img/bannerapp_16.xpm"
4 #include "img/bannerapp_32.xpm"
5 #include "img/bannerapp_64.xpm"
6 #include "img/bannerapp_128.xpm"
7 #include "img/bannerapp_256.xpm"
8 #include "ChecklistGuide.h"
9 #include "ChecklistGuideWizard.h"
10 #include "CmdCopy.h"
11 #include "CmdCut.h"
12 #include "CmdDelete.h"
13 #include "CmdMediator.h"
14 #include "CmdStackShadow.h"
15 #include "ColorFilter.h"
16 #include "Curve.h"
17 #include "DataKey.h"
18 #include "DigitizeStateContext.h"
19 #include "DigitAxis.xpm"
20 #include "DigitColorPicker.xpm"
21 #include "DigitCurve.xpm"
22 #include "DigitPointMatch.xpm"
23 #include "DigitSegment.xpm"
24 #include "DigitSelect.xpm"
25 #include "DlgAbout.h"
26 #include "DlgErrorReport.h"
27 #include "DlgRequiresTransform.h"
28 #include "DlgSettingsAxesChecker.h"
29 #include "DlgSettingsColorFilter.h"
30 #include "DlgSettingsCoords.h"
31 #include "DlgSettingsCurveAddRemove.h"
32 #include "DlgSettingsCurveProperties.h"
33 #include "DlgSettingsDigitizeCurve.h"
34 #include "DlgSettingsExportFormat.h"
35 #include "DlgSettingsGeneral.h"
36 #include "DlgSettingsGridRemoval.h"
37 #include "DlgSettingsMainWindow.h"
38 #include "DlgSettingsPointMatch.h"
39 #include "DlgSettingsSegments.h"
40 #include "DocumentSerialize.h"
41 #include "EngaugeAssert.h"
42 #include "EnumsToQt.h"
43 #include "ExportToFile.h"
44 #include "GraphicsItemType.h"
45 #include "GraphicsScene.h"
46 #include "GraphicsView.h"
47 #include "HelpWindow.h"
48 #ifdef ENGAUGE_JPEG2000
49 #include "Jpeg2000.h"
50 #endif // ENGAUGE_JPEG2000
51 #include "LoadFileInfo.h"
52 #include "LoadImageFromUrl.h"
53 #include "Logger.h"
54 #include "MainWindow.h"
55 #include "NetworkClient.h"
56 #include <QAction>
57 #include <QApplication>
58 #include <QCloseEvent>
59 #include <QComboBox>
60 #include <QDebug>
61 #include <QDesktopServices>
62 #include <QDockWidget>
63 #include <QDomDocument>
64 #include <QKeyEvent>
65 #include <QFileDialog>
66 #include <QFileInfo>
67 #include <QGraphicsLineItem>
68 #include <QImageReader>
69 #include <QKeyEvent>
70 #include <QKeySequence>
71 #include <QLabel>
72 #include <QMenu>
73 #include <QMenuBar>
74 #include <QMessageBox>
75 #include <QPrintDialog>
76 #include <QPrinter>
77 #include <QSettings>
78 #include <QTextStream>
79 #include <QtHelp>
80 #include <QTimer>
81 #include <QToolBar>
82 #include <QToolButton>
83 #include "QtToString.h"
84 #include <QVBoxLayout>
85 #include <QWhatsThis>
86 #include <QXmlStreamReader>
87 #include <QXmlStreamWriter>
88 #include "Settings.h"
89 #include "StatusBar.h"
90 #include "TransformationStateContext.h"
91 #include "TutorialDlg.h"
92 #include "Version.h"
93 #include "ViewPointStyle.h"
94 #include "ViewSegmentFilter.h"
95 #include "ZoomFactor.h"
96 #include "ZoomFactorInitial.h"
97 
98 // These constants are used for the menu item text AND for tooltip text
99 const QString DIGITIZE_ACTION_AXIS_POINT (QObject::tr ("Axis Point Tool"));
100 const QString DIGITIZE_ACTION_COLOR_PICKER (QObject::tr ("Color Picker Tool"));
101 const QString DIGITIZE_ACTION_CURVE_POINT (QObject::tr ("Curve Point Tool"));
102 const QString DIGITIZE_ACTION_POINT_MATCH (QObject::tr ("Point Match Tool"));
103 const QString DIGITIZE_ACTION_SEGMENT_POINTS (QObject::tr ("Segment Fill Tool"));
104 const QString DIGITIZE_ACTION_SELECT (QObject::tr ("Select Tool"));
105 
106 const QString EMPTY_FILENAME ("");
107 const QString ENGAUGE_FILENAME_DESCRIPTION ("Engauge Document");
108 const QString ENGAUGE_FILENAME_EXTENSION ("dig");
109 
110 const unsigned int MAX_RECENT_FILE_LIST_SIZE = 8;
111 
112 MainWindow::MainWindow(const QString &errorReportFile,
113  bool isGnuplot,
114  QStringList loadStartupFiles,
115  QWidget *parent) :
116  QMainWindow(parent),
117  m_isDocumentExported (false),
118  m_engaugeFile (EMPTY_FILENAME),
119  m_currentFile (EMPTY_FILENAME),
120  m_layout (0),
121  m_scene (0),
122  m_view (0),
123  m_cmdMediator (0),
124  m_digitizeStateContext (0),
125  m_transformationStateContext (0),
126  m_backgroundStateContext (0),
127  m_isGnuplot (isGnuplot)
128 {
130 
131  QString initialPath = QDir::currentPath();
132 
133  setCurrentFile ("");
134  createIcons();
135  setWindowFlags (Qt::WindowContextHelpButtonHint | windowFlags ()); // Add help to default buttons
136  setWindowTitle (engaugeWindowTitle ());
137 
138  createCentralWidget();
139  createActions ();
140  createStatusBar ();
141  createMenus ();
142  createToolBars ();
143  createHelpWindow ();
144  createTutorial ();
145  createScene ();
146  createNetwork ();
147  createLoadImageFromUrl ();
148  createStateContextBackground ();
149  createStateContextDigitize ();
150  createStateContextTransformation ();
151  createSettingsDialogs ();
152  createCommandStackShadow ();
153  updateControls ();
154 
155  settingsRead ();
156  setCurrentFile ("");
157  setUnifiedTitleAndToolBarOnMac(true);
158 
159  installEventFilter(this);
160  if (!errorReportFile.isEmpty()) {
161  loadErrorReportFile(initialPath,
162  errorReportFile);
163  } else {
164 
165  // Save file names for later, after gui becomes available. The file names are dropped if error report file is specified
166  // since only one of the two modes is available at any time, for simplicity
167  m_loadStartupFiles = loadStartupFiles;
168  }
169 }
170 
171 MainWindow::~MainWindow()
172 {
173 }
174 
175 void MainWindow::applyZoomFactorAfterLoad()
176 {
177  ZoomFactor zoomFactor;
178 
179  switch (m_modelMainWindow.zoomFactorInitial())
180  {
181  case ZOOM_INITIAL_16_TO_1:
182  zoomFactor = ZOOM_16_TO_1;
183  break;
184 
185  case ZOOM_INITIAL_8_TO_1:
186  zoomFactor = ZOOM_8_TO_1;
187  break;
188 
189  case ZOOM_INITIAL_4_TO_1:
190  zoomFactor = ZOOM_4_TO_1;
191  break;
192 
193  case ZOOM_INITIAL_2_TO_1:
194  zoomFactor = ZOOM_2_TO_1;
195  break;
196 
197  case ZOOM_INITIAL_1_TO_1:
198  zoomFactor = ZOOM_1_TO_1;
199  break;
200 
201  case ZOOM_INITIAL_1_TO_2:
202  zoomFactor = ZOOM_1_TO_2;
203  break;
204 
205  case ZOOM_INITIAL_1_TO_4:
206  zoomFactor = ZOOM_1_TO_4;
207  break;
208 
209  case ZOOM_INITIAL_1_TO_8:
210  zoomFactor = ZOOM_1_TO_8;
211  break;
212 
213  case ZOOM_INITIAL_1_TO_16:
214  zoomFactor = ZOOM_1_TO_16;
215  break;
216 
217  case ZOOM_INITIAL_FILL:
218  zoomFactor = ZOOM_FILL;
219  break;
220 
221  case ZOOM_INITIAL_PREVIOUS:
222  zoomFactor = currentZoomFactor();
223  break;
224 
225  default:
226  ENGAUGE_ASSERT (false);
227  zoomFactor = currentZoomFactor();
228  break;
229  }
230 
231  slotViewZoom (zoomFactor);
232 }
233 
234 void MainWindow::closeEvent(QCloseEvent *event)
235 {
236  if (maybeSave()) {
237  settingsWrite ();
238  event->accept ();
239  } else {
240  event->ignore ();
241  }
242 }
243 
245 {
246  ENGAUGE_CHECK_PTR (m_cmdMediator);
247 
248  return *m_cmdMediator;
249 }
250 
251 void MainWindow::createActions()
252 {
253  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createActions";
254 
255  createActionsFile ();
256  createActionsEdit ();
257  createActionsDigitize ();
258  createActionsView ();
259  createActionsSettings ();
260  createActionsHelp ();
261 }
262 
263 void MainWindow::createActionsDigitize ()
264 {
265  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createActionsDigitize";
266 
267  QPixmap pixmapAxis (DigitAxis_xpm);
268  QPixmap pixmapCurve (DigitCurve_xpm);
269  QPixmap pixmapColorPicker (DigitColorPicker_xpm);
270  QPixmap pixmapPointMatch (DigitPointMatch_xpm);
271  QPixmap pixmapSegment (DigitSegment_xpm);
272  QPixmap pixmapSelect (DigitSelect_xpm);
273 
274  QIcon iconAxis (pixmapAxis);
275  QIcon iconCurve (pixmapCurve);
276  QIcon iconColorPicker (pixmapColorPicker);
277  QIcon iconPointMatch (pixmapPointMatch);
278  QIcon iconSegment (pixmapSegment);
279  QIcon iconSelect (pixmapSelect);
280 
281  m_actionDigitizeSelect = new QAction (iconSelect, DIGITIZE_ACTION_SELECT, this);
282  m_actionDigitizeSelect->setShortcut (QKeySequence (tr ("Shift+F2")));
283  m_actionDigitizeSelect->setCheckable (true);
284  m_actionDigitizeSelect->setStatusTip (tr ("Select points on screen."));
285  m_actionDigitizeSelect->setWhatsThis (tr ("Select\n\n"
286  "Select points on the screen."));
287  connect (m_actionDigitizeSelect, SIGNAL (triggered ()), this, SLOT (slotDigitizeSelect ()));
288 
289  m_actionDigitizeAxis = new QAction (iconAxis, DIGITIZE_ACTION_AXIS_POINT, this);
290  m_actionDigitizeAxis->setShortcut (QKeySequence (tr ("Shift+F3")));
291  m_actionDigitizeAxis->setCheckable (true);
292  m_actionDigitizeAxis->setStatusTip (tr ("Digitize axis points."));
293  m_actionDigitizeAxis->setWhatsThis (tr ("Digitize Axis Point\n\n"
294  "Digitizes an axis point by placing a new point at the cursor "
295  "after a mouse click. The coordinates of the axis point are then "
296  "entered. In a graph, three axis points are required to define "
297  "the graph coordinates."));
298  connect (m_actionDigitizeAxis, SIGNAL (triggered ()), this, SLOT (slotDigitizeAxis ()));
299 
300  m_actionDigitizeCurve = new QAction (iconCurve, DIGITIZE_ACTION_CURVE_POINT, this);
301  m_actionDigitizeCurve->setShortcut (QKeySequence (tr ("Shift+F4")));
302  m_actionDigitizeCurve->setCheckable (true);
303  m_actionDigitizeCurve->setStatusTip (tr ("Digitize curve points."));
304  m_actionDigitizeCurve->setWhatsThis (tr ("Digitize Curve Point\n\n"
305  "Digitizes a curve point by placing a new point at the cursor "
306  "after a mouse click. Use this mode to digitize points along curves "
307  "one by one.\n\n"
308  "New points will be assigned to the currently selected curve."));
309  connect (m_actionDigitizeCurve, SIGNAL (triggered ()), this, SLOT (slotDigitizeCurve ()));
310 
311  m_actionDigitizePointMatch = new QAction (iconPointMatch, DIGITIZE_ACTION_POINT_MATCH, this);
312  m_actionDigitizePointMatch->setShortcut (QKeySequence (tr ("Shift+F5")));
313  m_actionDigitizePointMatch->setCheckable (true);
314  m_actionDigitizePointMatch->setStatusTip (tr ("Digitize curve points in a point plot by matching a point."));
315  m_actionDigitizePointMatch->setWhatsThis (tr ("Digitize Curve Points by Point Matching\n\n"
316  "Digitizes curve points in a point plot by finding points that match a sample point. The process "
317  "starts by selecting a representative sample point.\n\n"
318  "New points will be assigned to the currently selected curve."));
319  connect (m_actionDigitizePointMatch, SIGNAL (triggered ()), this, SLOT (slotDigitizePointMatch ()));
320 
321  m_actionDigitizeColorPicker = new QAction (iconColorPicker, DIGITIZE_ACTION_COLOR_PICKER, this);
322  m_actionDigitizeColorPicker->setShortcut (QKeySequence (tr ("Shift+F6")));
323  m_actionDigitizeColorPicker->setCheckable (true);
324  m_actionDigitizeColorPicker->setStatusTip (tr ("Select color settings for filtering in Segment Fill mode."));
325  m_actionDigitizeColorPicker->setWhatsThis (tr ("Select color settings for Segment Fill filtering\n\n"
326  "Select a pixel along the currently selected curve. That pixel and its neighbors will "
327  "define the filter settings (color, brightness, and so on) of the currently selected curve "
328  "while in Segment Fill mode."));
329  connect (m_actionDigitizeColorPicker, SIGNAL (triggered ()), this, SLOT (slotDigitizeColorPicker ()));
330 
331  m_actionDigitizeSegment = new QAction (iconSegment, DIGITIZE_ACTION_SEGMENT_POINTS, this);
332  m_actionDigitizeSegment->setShortcut (QKeySequence (tr ("Shift+F7")));
333  m_actionDigitizeSegment->setCheckable (true);
334  m_actionDigitizeSegment->setStatusTip (tr ("Digitize curve points along a segment of a curve."));
335  m_actionDigitizeSegment->setWhatsThis (tr ("Digitize Curve Points With Segment Fill\n\n"
336  "Digitizes curve points by placing new points along the highlighted "
337  "segment under the cursor. Use this mode to quickly digitize multiple points along a "
338  "curve with a single click.\n\n"
339  "New points will be assigned to the currently selected curve."));
340  connect (m_actionDigitizeSegment, SIGNAL (triggered ()), this, SLOT (slotDigitizeSegment ()));
341 
342  m_groupDigitize = new QActionGroup (this);
343  m_groupDigitize->addAction (m_actionDigitizeSelect);
344  m_groupDigitize->addAction (m_actionDigitizeAxis);
345  m_groupDigitize->addAction (m_actionDigitizeCurve);
346  m_groupDigitize->addAction (m_actionDigitizePointMatch);
347  m_groupDigitize->addAction (m_actionDigitizeColorPicker);
348  m_groupDigitize->addAction (m_actionDigitizeSegment);
349 }
350 
351 void MainWindow::createActionsEdit ()
352 {
353  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createActionsEdit";
354 
355  m_actionEditUndo = new QAction(tr ("&Undo"), this);
356  m_actionEditUndo->setShortcut (QKeySequence::Undo);
357  m_actionEditUndo->setStatusTip (tr ("Undo the last operation."));
358  m_actionEditUndo->setWhatsThis (tr ("Undo\n\n"
359  "Undo the last operation."));
360  // connect is applied when CmdMediator appears
361 
362  m_actionEditRedo = new QAction(tr ("&Redo"), this);
363  m_actionEditRedo->setShortcut (QKeySequence::Redo);
364  m_actionEditRedo->setStatusTip (tr ("Redo the last operation."));
365  m_actionEditRedo->setWhatsThis (tr ("Redo\n\n"
366  "Redo the last operation."));
367  // connect is applied when CmdMediator appears
368 
369  m_actionEditCut = new QAction (tr ("Cut"), this);
370  m_actionEditCut->setShortcut (QKeySequence::Cut);
371  m_actionEditCut->setStatusTip (tr ("Cuts the selected points and copies them to the clipboard."));
372  m_actionEditCut->setWhatsThis (tr ("Cut\n\n"
373  "Cuts the selected points and copies them to the clipboard."));
374  connect (m_actionEditCut, SIGNAL (triggered ()), this, SLOT (slotEditCut ()));
375 
376  m_actionEditCopy = new QAction (tr ("Copy"), this);
377  m_actionEditCopy->setShortcut (QKeySequence::Copy);
378  m_actionEditCopy->setStatusTip (tr ("Copies the selected points to the clipboard."));
379  m_actionEditCopy->setWhatsThis (tr ("Copy\n\n"
380  "Copies the selected points to the clipboard."));
381  connect (m_actionEditCopy, SIGNAL (triggered ()), this, SLOT (slotEditCopy ()));
382 
383  m_actionEditPaste = new QAction (tr ("Paste"), this);
384  m_actionEditPaste->setShortcut (QKeySequence::Paste);
385  m_actionEditPaste->setStatusTip (tr ("Pastes the selected points from the clipboard."));
386  m_actionEditPaste->setWhatsThis (tr ("Paste\n\n"
387  "Pastes the selected points from the clipboard. They will be assigned to the current curve."));
388  connect (m_actionEditPaste, SIGNAL (triggered ()), this, SLOT (slotEditPaste ()));
389 
390  m_actionEditDelete = new QAction (tr ("Delete"), this);
391  m_actionEditDelete->setShortcut (QKeySequence::Delete);
392  m_actionEditDelete->setStatusTip (tr ("Deletes the selected points, after copying them to the clipboard."));
393  m_actionEditDelete->setWhatsThis (tr ("Delete\n\n"
394  "Deletes the selected points, after copying them to the clipboard."));
395  connect (m_actionEditDelete, SIGNAL (triggered ()), this, SLOT (slotEditDelete ()));
396 }
397 
398 void MainWindow::createActionsFile ()
399 {
400  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createActionsFile";
401 
402  m_actionImport = new QAction(tr ("&Import..."), this);
403  m_actionImport->setShortcut (tr ("Ctrl+I"));
404  m_actionImport->setStatusTip (tr ("Creates a new document by importing an image."));
405  m_actionImport->setWhatsThis (tr ("New Document\n\n"
406  "Creates a new document by importing an image."));
407  connect (m_actionImport, SIGNAL (triggered ()), this, SLOT (slotFileImport ()));
408 
409  m_actionOpen = new QAction(tr ("&Open..."), this);
410  m_actionOpen->setShortcut (QKeySequence::Open);
411  m_actionOpen->setStatusTip (tr ("Opens an existing document."));
412  m_actionOpen->setWhatsThis (tr ("Open Document\n\n"
413  "Opens an existing document."));
414  connect (m_actionOpen, SIGNAL (triggered ()), this, SLOT (slotFileOpen ()));
415 
416  for (unsigned int i = 0; i < MAX_RECENT_FILE_LIST_SIZE; i++) {
417  QAction *recentFileAction = new QAction (this);
418  recentFileAction->setVisible (true);
419  connect (recentFileAction, SIGNAL (triggered ()), this, SLOT (slotRecentFileAction ()));
420  m_actionRecentFiles.append (recentFileAction);
421  }
422 
423  m_actionClose = new QAction(tr ("&Close"), this);
424  m_actionClose->setShortcut (QKeySequence::Close);
425  m_actionClose->setStatusTip (tr ("Closes the open document document."));
426  m_actionClose->setWhatsThis (tr ("Close Document\n\n"
427  "Closes the open document."));
428  connect (m_actionClose, SIGNAL (triggered ()), this, SLOT (slotFileClose ()));
429 
430  m_actionSave = new QAction(tr ("&Save"), this);
431  m_actionSave->setShortcut (QKeySequence::Save);
432  m_actionSave->setStatusTip (tr ("Saves the current document."));
433  m_actionSave->setWhatsThis (tr ("Save Document\n\n"
434  "Saves the current document."));
435  connect (m_actionSave, SIGNAL (triggered ()), this, SLOT (slotFileSave ()));
436 
437  m_actionSaveAs = new QAction(tr ("Save As..."), this);
438  m_actionSaveAs->setShortcut (QKeySequence::SaveAs);
439  m_actionSaveAs->setStatusTip (tr ("Saves the current document under a new filename."));
440  m_actionSaveAs->setWhatsThis (tr ("Save Document As\n\n"
441  "Saves the current document under a new filename."));
442  connect (m_actionSaveAs, SIGNAL (triggered ()), this, SLOT (slotFileSaveAs ()));
443 
444  m_actionExport = new QAction (tr ("Export..."), this);
445  m_actionExport->setShortcut (tr ("Ctrl+E"));
446  m_actionExport->setStatusTip (tr ("Exports the current document into a text file."));
447  m_actionExport->setWhatsThis (tr ("Export Document\n\n"
448  "Exports the current document into a text file."));
449  connect (m_actionExport, SIGNAL (triggered ()), this, SLOT (slotFileExport ()));
450 
451  m_actionPrint = new QAction (tr ("&Print..."), this);
452  m_actionPrint->setShortcut (QKeySequence::Print);
453  m_actionPrint->setStatusTip (tr ("Print the current document."));
454  m_actionPrint->setWhatsThis (tr ("Print Document\n\n"
455  "Print the current document to a printer or file."));
456  connect (m_actionPrint, SIGNAL (triggered ()), this, SLOT (slotFilePrint ()));
457 
458  m_actionExit = new QAction(tr ("&Exit"), this);
459  m_actionExit->setShortcut (QKeySequence::Quit);
460  m_actionExit->setStatusTip (tr ("Quits the application."));
461  m_actionExit->setWhatsThis (tr ("Exit\n\n"
462  "Quits the application."));
463  connect (m_actionExit, SIGNAL (triggered ()), this, SLOT (close ()));
464 }
465 
466 void MainWindow::createActionsHelp ()
467 {
468  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createActionsHelp";
469 
470  m_actionHelpChecklistGuideWizard = new QAction (tr ("Checklist Guide Wizard"), this);
471  m_actionHelpChecklistGuideWizard->setCheckable (true);
472  m_actionHelpChecklistGuideWizard->setStatusTip (tr ("Open Checklist Guide Wizard during import to define digitizing steps"));
473  m_actionHelpChecklistGuideWizard->setWhatsThis (tr ("Checklist Guide Wizard\n\n"
474  "Use Checklist Guide Wizard during import to generate a checklist of steps "
475  "for the imported document"));
476 
477  m_actionHelpWhatsThis = QWhatsThis::createAction(this);
478  m_actionHelpWhatsThis->setShortcut (QKeySequence::WhatsThis);
479 
480  m_actionHelpTutorial = new QAction (tr ("Tutorial"), this);
481  m_actionHelpTutorial->setStatusTip (tr ("Play tutorial showing steps for digitizing curves"));
482  m_actionHelpTutorial->setWhatsThis (tr ("Tutorial\n\n"
483  "Play tutorial showing steps for digitizing points from curves drawn with lines "
484  "and/or point"));
485  connect (m_actionHelpTutorial, SIGNAL (triggered ()), this, SLOT (slotHelpTutorial()));
486 
487  m_actionHelpHelp = new QAction (tr ("Help"), this);
488  m_actionHelpHelp->setShortcut (QKeySequence::HelpContents);
489  m_actionHelpHelp->setStatusTip (tr ("Help documentation"));
490  m_actionHelpHelp->setWhatsThis (tr ("Help Documentation\n\n"
491  "Searchable help documentation"));
492  // This action gets connected directly to the QDockWidget when that is created
493 
494  m_actionHelpAbout = new QAction(tr ("About Engauge"), this);
495  m_actionHelpAbout->setStatusTip (tr ("About the application."));
496  m_actionHelpAbout->setWhatsThis (tr ("About Engauge\n\nAbout the application."));
497  connect (m_actionHelpAbout, SIGNAL (triggered ()), this, SLOT (slotHelpAbout ()));
498 }
499 
500 void MainWindow::createActionsSettings ()
501 {
502  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createActionsSettings";
503 
504  m_actionSettingsCoords = new QAction (tr ("Coordinates..."), this);
505  m_actionSettingsCoords->setStatusTip (tr ("Edit Coordinate settings."));
506  m_actionSettingsCoords->setWhatsThis (tr ("Coordinate Settings\n\n"
507  "Coordinate settings determine how the graph coordinates are mapped to the pixels in the image"));
508  connect (m_actionSettingsCoords, SIGNAL (triggered ()), this, SLOT (slotSettingsCoords ()));
509 
510  m_actionSettingsCurveAddRemove = new QAction (tr ("Add/Remove Curve..."), this);
511  m_actionSettingsCurveAddRemove->setStatusTip (tr ("Add or Remove Curves."));
512  m_actionSettingsCurveAddRemove->setWhatsThis (tr ("Add/Remove Curve\n\n"
513  "Add/Remove Curve settings control which curves are included in the current document"));
514  connect (m_actionSettingsCurveAddRemove, SIGNAL (triggered ()), this, SLOT (slotSettingsCurveAddRemove ()));
515 
516  m_actionSettingsCurveProperties = new QAction (tr ("Curve Properties..."), this);
517  m_actionSettingsCurveProperties->setStatusTip (tr ("Edit Curve Properties settings."));
518  m_actionSettingsCurveProperties->setWhatsThis (tr ("Curve Properties Settings\n\n"
519  "Curves properties settings determine how each curve appears"));
520  connect (m_actionSettingsCurveProperties, SIGNAL (triggered ()), this, SLOT (slotSettingsCurveProperties ()));
521 
522  m_actionSettingsDigitizeCurve = new QAction (tr ("Digitize Curve..."), this);
523  m_actionSettingsDigitizeCurve->setStatusTip (tr ("Edit Digitize Axis and Graph Curve settings."));
524  m_actionSettingsDigitizeCurve->setWhatsThis (tr ("Digitize Axis and Graph Curve Settings\n\n"
525  "Digitize Curve settings determine how points are digitized in Digitize Axis Point and "
526  "Digitize Graph Point modes"));
527  connect (m_actionSettingsDigitizeCurve, SIGNAL (triggered ()), this, SLOT (slotSettingsDigitizeCurve ()));
528 
529  m_actionSettingsExport = new QAction (tr ("Export Format..."), this);
530  m_actionSettingsExport->setStatusTip (tr ("Edit Export Format settings."));
531  m_actionSettingsExport->setWhatsThis (tr ("Export Format Settings\n\n"
532  "Export format settings affect how exported files are formatted"));
533  connect (m_actionSettingsExport, SIGNAL (triggered ()), this, SLOT (slotSettingsExportFormat ()));
534 
535  m_actionSettingsColorFilter = new QAction (tr ("Color Filter..."), this);
536  m_actionSettingsColorFilter->setStatusTip (tr ("Edit Color Filter settings."));
537  m_actionSettingsColorFilter->setWhatsThis (tr ("Color Filter Settings\n\n"
538  "Color filtering simplifies the graphs for easier Point Matching and Segment Filling"));
539  connect (m_actionSettingsColorFilter, SIGNAL (triggered ()), this, SLOT (slotSettingsColorFilter ()));
540 
541  m_actionSettingsAxesChecker = new QAction (tr ("Axes Checker..."), this);
542  m_actionSettingsAxesChecker->setStatusTip (tr ("Edit Axes Checker settings."));
543  m_actionSettingsAxesChecker->setWhatsThis (tr ("Axes Checker Settings\n\n"
544  "Axes checker can reveal any axis point mistakes, which are otherwise hard to find."));
545  connect (m_actionSettingsAxesChecker, SIGNAL (triggered ()), this, SLOT (slotSettingsAxesChecker ()));
546 
547  m_actionSettingsGridRemoval = new QAction (tr ("Grid Line Removal..."), this);
548  m_actionSettingsGridRemoval->setStatusTip (tr ("Edit Grid Line Removal settings."));
549  m_actionSettingsGridRemoval->setWhatsThis (tr ("Grid Line Removal Settings\n\n"
550  "Grid line removal isolates curve lines for easier Point Matching and Segment Filling, when "
551  "Color Filtering is not able to separate grid lines from curve lines."));
552  connect (m_actionSettingsGridRemoval, SIGNAL (triggered ()), this, SLOT (slotSettingsGridRemoval ()));
553 
554  m_actionSettingsPointMatch = new QAction (tr ("Point Match..."), this);
555  m_actionSettingsPointMatch->setStatusTip (tr ("Edit Point Match settings."));
556  m_actionSettingsPointMatch->setWhatsThis (tr ("Point Match Settings\n\n"
557  "Point match settings determine how points are matched while in Point Match mode"));
558  connect (m_actionSettingsPointMatch, SIGNAL (triggered ()), this, SLOT (slotSettingsPointMatch ()));
559 
560  m_actionSettingsSegments = new QAction (tr ("Segment Fill..."), this);
561  m_actionSettingsSegments->setStatusTip (tr ("Edit Segment Fill settings."));
562  m_actionSettingsSegments->setWhatsThis (tr ("Segment Fill Settings\n\n"
563  "Segment fill settings determine how points are generated in the Segment Fill mode"));
564  connect (m_actionSettingsSegments, SIGNAL (triggered ()), this, SLOT (slotSettingsSegments ()));
565 
566  m_actionSettingsGeneral = new QAction (tr ("General..."), this);
567  m_actionSettingsGeneral->setStatusTip (tr ("Edit General settings."));
568  m_actionSettingsGeneral->setWhatsThis (tr ("General Settings\n\n"
569  "General settings are document-specific settings that affect multiple modes. For example, the cursor size setting affects "
570  "both Color Picker and Point Match modes"));
571  connect (m_actionSettingsGeneral, SIGNAL (triggered ()), this, SLOT (slotSettingsGeneral ()));
572 
573  m_actionSettingsMainWindow = new QAction (tr ("Main Window..."), this);
574  m_actionSettingsMainWindow->setStatusTip (tr ("Edit Main Window settings."));
575  m_actionSettingsMainWindow->setWhatsThis (tr ("Main Window Settings\n\n"
576  "Main window settings affect the user interface and are not specific to any document"));
577  connect (m_actionSettingsMainWindow, SIGNAL (triggered ()), this, SLOT (slotSettingsMainWindow ()));
578 }
579 
580 void MainWindow::createActionsView ()
581 {
582  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createActionsView";
583 
584  m_actionViewBackground = new QAction (tr ("Background Toolbar"), this);
585  m_actionViewBackground->setCheckable (true);
586  m_actionViewBackground->setChecked (true);
587  m_actionViewBackground->setStatusTip (tr ("Show or hide the background toolbar."));
588  m_actionViewBackground->setWhatsThis (tr ("View Background ToolBar\n\n"
589  "Show or hide the background toolbar"));
590  connect (m_actionViewBackground, SIGNAL (triggered ()), this, SLOT (slotViewToolBarBackground ()));
591 
592  m_actionViewChecklistGuide = new QAction (tr ("Checklist Guide Toolbar"), this);
593  m_actionViewChecklistGuide->setCheckable (true);
594  m_actionViewChecklistGuide->setChecked (false);
595  m_actionViewChecklistGuide->setStatusTip (tr ("Show or hide the checklist guide toolbar."));
596  m_actionViewChecklistGuide->setWhatsThis (tr ("View Checklist Guide ToolBar\n\n"
597  "Show or hide the checklist guide toolbar"));
598  connect (m_actionViewChecklistGuide, SIGNAL (changed ()), this, SLOT (slotViewToolBarChecklistGuide()));
599 
600  m_actionViewDigitize = new QAction (tr ("Digitizing Tools Toolbar"), this);
601  m_actionViewDigitize->setCheckable (true);
602  m_actionViewDigitize->setChecked (true);
603  m_actionViewDigitize->setStatusTip (tr ("Show or hide the digitizing tools toolbar."));
604  m_actionViewDigitize->setWhatsThis (tr ("View Digitizing Tools ToolBar\n\n"
605  "Show or hide the digitizing tools toolbar"));
606  connect (m_actionViewDigitize, SIGNAL (triggered ()), this, SLOT (slotViewToolBarDigitize()));
607 
608  m_actionViewSettingsViews = new QAction (tr ("Settings Views Toolbar"), this);
609  m_actionViewSettingsViews->setCheckable (true);
610  m_actionViewSettingsViews->setChecked (true);
611  m_actionViewSettingsViews->setStatusTip (tr ("Show or hide the settings views toolbar."));
612  m_actionViewSettingsViews->setWhatsThis (tr ("View Settings Views ToolBar\n\n"
613  "Show or hide the settings views toolbar. These views graphically show the "
614  "most important settings."));
615  connect (m_actionViewSettingsViews, SIGNAL (triggered ()), this, SLOT (slotViewToolBarSettingsViews()));
616 
617  m_actionViewToolTips = new QAction (tr ("Tool Tips"), this);
618  m_actionViewToolTips->setCheckable (true);
619  m_actionViewToolTips->setChecked (true);
620  m_actionViewToolTips->setStatusTip (tr ("Show or hide the tool tips."));
621  m_actionViewToolTips->setWhatsThis (tr ("View Tool Tips\n\n"
622  "Show or hide the tool tips"));
623  connect (m_actionViewToolTips, SIGNAL (triggered ()), this, SLOT (slotViewToolTips()));
624 
625  m_actionViewBackgroundNone = new QAction (tr ("No Background"), this);
626  m_actionViewBackgroundNone->setCheckable (true);
627  m_actionViewBackgroundNone->setStatusTip (tr ("Do not show the image underneath the points."));
628  m_actionViewBackgroundNone->setWhatsThis (tr ("No Background\n\n"
629  "No image is shown so points are easier to see"));
630 
631  m_actionViewBackgroundOriginal = new QAction (tr ("Show Original Image"), this);
632  m_actionViewBackgroundOriginal->setCheckable (true);
633  m_actionViewBackgroundOriginal->setStatusTip (tr ("Show the original image underneath the points."));
634  m_actionViewBackgroundOriginal->setWhatsThis (tr ("Show Original Image\n\n"
635  "Show the original image underneath the points"));
636 
637  m_actionViewBackgroundFiltered = new QAction (tr ("Show Filtered Image"), this);
638  m_actionViewBackgroundFiltered->setCheckable (true);
639  m_actionViewBackgroundFiltered->setChecked (true);
640  m_actionViewBackgroundFiltered->setStatusTip (tr ("Show the filtered image underneath the points."));
641  m_actionViewBackgroundFiltered->setWhatsThis (tr ("Show Filtered Image\n\n"
642  "Show the filtered image underneath the points.\n\n"
643  "The filtered image is created from the original image according to the "
644  "Filter preferences so unimportant information is hidden and important "
645  "information is emphasized"));
646 
647  m_actionViewCurvesNone = new QAction (tr ("Hide All Curves"), this);
648  m_actionViewCurvesNone->setCheckable (true);
649  m_actionViewCurvesNone->setStatusTip (tr ("Hide all digitized curves."));
650  m_actionViewCurvesNone->setWhatsThis (tr ("Hide All Curves\n\n"
651  "No axis points or digitized graph curves are shown so the image is easier to see."));
652 
653  m_actionViewCurvesSelected = new QAction (tr ("Show Selected Curve"), this);
654  m_actionViewCurvesSelected->setCheckable (true);
655  m_actionViewCurvesSelected->setStatusTip (tr ("Show only the currently selected curve."));
656  m_actionViewCurvesSelected->setWhatsThis (tr ("Show Selected Curve\n\n"
657  "Show only the digitized points and line that belong to the currently selected curve."));
658 
659  m_actionViewCurvesAll = new QAction (tr ("Show All Curves"), this);
660  m_actionViewCurvesAll->setCheckable (true);
661  m_actionViewCurvesAll->setChecked (true);
662  m_actionViewCurvesAll->setStatusTip (tr ("Show all curves."));
663  m_actionViewCurvesAll->setWhatsThis (tr ("Show All Curves\n\n"
664  "Show all digitized axis points and graph curves"));
665 
666  m_groupBackground = new QActionGroup(this);
667  m_groupBackground->addAction (m_actionViewBackgroundNone);
668  m_groupBackground->addAction (m_actionViewBackgroundOriginal);
669  m_groupBackground->addAction (m_actionViewBackgroundFiltered);
670  connect (m_groupBackground, SIGNAL(triggered (QAction*)), this, SLOT (slotViewGroupBackground(QAction*)));
671 
672  m_groupCurves = new QActionGroup(this);
673  m_groupCurves->addAction (m_actionViewCurvesNone);
674  m_groupCurves->addAction (m_actionViewCurvesSelected);
675  m_groupCurves->addAction (m_actionViewCurvesAll);
676  connect (m_groupCurves, SIGNAL(triggered (QAction*)), this, SLOT (slotViewGroupCurves(QAction*)));
677 
678  m_actionStatusNever = new QAction (tr ("Hide Always"), this);
679  m_actionStatusNever->setCheckable(true);
680  m_actionStatusNever->setStatusTip (tr ("Always hide the status bar."));
681  m_actionStatusNever->setWhatsThis (tr ("Hide the status bar. No temporary status or feedback messages will appear."));
682 
683  m_actionStatusTemporary = new QAction (tr ("Show Temporary Messages"), this);
684  m_actionStatusTemporary->setCheckable(true);
685  m_actionStatusTemporary->setStatusTip (tr ("Hide the status bar except when display temporary messages."));
686  m_actionStatusTemporary->setWhatsThis (tr ("Hide the status bar, except when displaying temporary status and feedback messages."));
687 
688  m_actionStatusAlways = new QAction (tr ("Show Always"), this);
689  m_actionStatusAlways->setCheckable(true);
690  m_actionStatusAlways->setStatusTip (tr ("Always show the status bar."));
691  m_actionStatusAlways->setWhatsThis (tr ("Show the status bar. Besides displaying temporary status and feedback messages, "
692  "the status bar also displays information about the cursor position."));
693 
694  m_groupStatus = new QActionGroup(this);
695  m_groupStatus->addAction (m_actionStatusNever);
696  m_groupStatus->addAction (m_actionStatusTemporary);
697  m_groupStatus->addAction (m_actionStatusAlways);
698  connect (m_groupStatus, SIGNAL (triggered (QAction*)), this, SLOT (slotViewGroupStatus(QAction*)));
699 
700  m_actionZoomOut = new QAction (tr ("Zoom Out"), this);
701  m_actionZoomOut->setStatusTip (tr ("Zoom out"));
702  // setShortCut is called by updateSettingsMainWindow
703  connect (m_actionZoomOut, SIGNAL (triggered ()), this, SLOT (slotViewZoomOut ()));
704 
705  m_actionZoomIn = new QAction (tr ("Zoom In"), this);
706  m_actionZoomIn->setStatusTip (tr ("Zoom in"));
707  // setShortCut is called by updateSettingsMainWindow
708  connect (m_actionZoomIn, SIGNAL (triggered ()), this, SLOT (slotViewZoomIn ()));
709 
710  m_actionZoom16To1 = new QAction (tr ("16:1 (1600%)"), this);
711  m_actionZoom16To1->setCheckable (true);
712  m_actionZoom16To1->setStatusTip (tr ("Zoom 16:1"));
713  connect (m_actionZoom16To1, SIGNAL (triggered ()), this, SLOT (slotViewZoom16To1 ()));
714 
715  m_actionZoom8To1 = new QAction (tr ("8:1 (800%)"), this);
716  m_actionZoom8To1->setCheckable (true);
717  m_actionZoom8To1->setStatusTip (tr ("Zoom 8:1"));
718  connect (m_actionZoom8To1, SIGNAL (triggered ()), this, SLOT (slotViewZoom8To1 ()));
719 
720  m_actionZoom4To1 = new QAction (tr ("4:1 (400%)"), this);
721  m_actionZoom4To1->setCheckable (true);
722  m_actionZoom4To1->setStatusTip (tr ("Zoom 4:1"));
723  connect (m_actionZoom4To1, SIGNAL (triggered ()), this, SLOT (slotViewZoom4To1 ()));
724 
725  m_actionZoom2To1 = new QAction (tr ("2:1 (200%)"), this);
726  m_actionZoom2To1->setCheckable (true);
727  m_actionZoom2To1->setStatusTip (tr ("Zoom 2:1"));
728  connect (m_actionZoom2To1, SIGNAL (triggered ()), this, SLOT (slotViewZoom2To1 ()));
729 
730  m_actionZoom1To1 = new QAction (tr ("1:1 (100%)"), this);
731  m_actionZoom1To1->setCheckable (true);
732  m_actionZoom1To1->setChecked (true);
733  m_actionZoom1To1->setStatusTip (tr ("Zoom 6:1"));
734  connect (m_actionZoom1To1, SIGNAL (triggered ()), this, SLOT (slotViewZoom1To1 ()));
735 
736  m_actionZoom1To2 = new QAction (tr ("1:2 (50%)"), this);
737  m_actionZoom1To2->setCheckable (true);
738  m_actionZoom1To2->setStatusTip (tr ("Zoom 1:2"));
739  connect (m_actionZoom1To2, SIGNAL (triggered ()), this, SLOT (slotViewZoom1To2 ()));
740 
741  m_actionZoom1To4 = new QAction (tr ("1:4 (25%)"), this);
742  m_actionZoom1To4->setCheckable (true);
743  m_actionZoom1To4->setStatusTip (tr ("Zoom 1:4"));
744  connect (m_actionZoom1To4, SIGNAL (triggered ()), this, SLOT (slotViewZoom1To4 ()));
745 
746  m_actionZoom1To8 = new QAction (tr ("1:8 (12.5%)"), this);
747  m_actionZoom1To8->setCheckable (true);
748  m_actionZoom1To8->setStatusTip (tr ("Zoom 1:8"));
749  connect (m_actionZoom1To8, SIGNAL (triggered ()), this, SLOT (slotViewZoom1To8 ()));
750 
751  m_actionZoom1To16 = new QAction (tr ("1:16 (6.25%)"), this);
752  m_actionZoom1To16->setCheckable (true);
753  m_actionZoom1To16->setStatusTip (tr ("Zoom 1:16"));
754  connect (m_actionZoom1To16, SIGNAL (triggered ()), this, SLOT (slotViewZoom1To16 ()));
755 
756  m_actionZoomFill = new QAction (tr ("Fill"), this);
757  m_actionZoomFill->setCheckable (true);
758  m_actionZoomFill->setStatusTip (tr ("Zoom with stretching to fill window"));
759  connect (m_actionZoomFill, SIGNAL (triggered ()), this, SLOT (slotViewZoomFill ()));
760 
761  m_groupZoom = new QActionGroup (this);
762  m_groupZoom->addAction (m_actionZoom16To1);
763  m_groupZoom->addAction (m_actionZoom8To1);
764  m_groupZoom->addAction (m_actionZoom4To1);
765  m_groupZoom->addAction (m_actionZoom2To1);
766  m_groupZoom->addAction (m_actionZoom1To1);
767  m_groupZoom->addAction (m_actionZoom1To2);
768  m_groupZoom->addAction (m_actionZoom1To4);
769  m_groupZoom->addAction (m_actionZoom1To8);
770  m_groupZoom->addAction (m_actionZoom1To16);
771  m_groupZoom->addAction (m_actionZoomFill);
772 }
773 
774 void MainWindow::createCentralWidget ()
775 {
776  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createCentralWidget";
777 
778  QWidget *widget = new QWidget;
779  setCentralWidget (widget);
780  m_layout = new QVBoxLayout;
781  widget->setLayout (m_layout);
782 }
783 
784 void MainWindow::createCommandStackShadow ()
785 {
786  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createCommandStackShadow";
787 
788  m_cmdStackShadow = new CmdStackShadow;
789 }
790 
791 void MainWindow::createHelpWindow ()
792 {
793  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createHelpWindow";
794 
795  m_helpWindow = new HelpWindow (this);
796  m_helpWindow->hide ();
797  addDockWidget (Qt::RightDockWidgetArea,
798  m_helpWindow); // Dock area is required by addDockWidget but immediately overridden in next line
799  m_helpWindow->setFloating (true);
800 
801  connect (m_actionHelpHelp, SIGNAL (triggered ()), m_helpWindow, SLOT (show ()));
802 }
803 
804 void MainWindow::createIcons()
805 {
806  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createIcons";
807 
808  QIcon icon;
809  QPixmap icon16 (bannerapp_16);
810  QPixmap icon32 (bannerapp_32);
811  QPixmap icon64 (bannerapp_64);
812  QPixmap icon128 (bannerapp_128);
813  QPixmap icon256 (bannerapp_256);
814 
815  icon.addPixmap (icon16);
816  icon.addPixmap (icon32);
817  icon.addPixmap (icon64);
818  icon.addPixmap (icon128);
819  icon.addPixmap (icon256);
820 
821  setWindowIcon (icon);
822 }
823 
824 void MainWindow::createLoadImageFromUrl ()
825 {
826  m_loadImageFromUrl = new LoadImageFromUrl (*this);
827 }
828 
829 void MainWindow::createMenus()
830 {
831  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createMenus";
832 
833  m_menuFile = menuBar()->addMenu(tr("&File"));
834  m_menuFile->addAction (m_actionImport);
835  m_menuFile->addAction (m_actionOpen);
836  m_menuFileOpenRecent = new QMenu (tr ("Open &Recent"));
837  for (unsigned int i = 0; i < MAX_RECENT_FILE_LIST_SIZE; i++) {
838  m_menuFileOpenRecent->addAction (m_actionRecentFiles.at (i));
839  }
840  m_menuFile->addMenu (m_menuFileOpenRecent);
841  m_menuFile->addAction (m_actionClose);
842  m_menuFile->insertSeparator (m_actionSave);
843  m_menuFile->addAction (m_actionSave);
844  m_menuFile->addAction (m_actionSaveAs);
845  m_menuFile->addAction (m_actionExport);
846  m_menuFile->insertSeparator (m_actionPrint);
847  m_menuFile->addAction (m_actionPrint);
848  m_menuFile->insertSeparator (m_actionExit);
849  m_menuFile->addAction (m_actionExit);
850 
851  m_menuEdit = menuBar()->addMenu(tr("&Edit"));
852  m_menuEdit->addAction (m_actionEditUndo);
853  m_menuEdit->addAction (m_actionEditRedo);
854  m_menuEdit->insertSeparator (m_actionEditCut);
855  m_menuEdit->addAction (m_actionEditCut);
856  m_menuEdit->addAction (m_actionEditCopy);
857  m_menuEdit->addAction (m_actionEditPaste);
858  m_menuEdit->addAction (m_actionEditDelete);
859 
860  m_menuDigitize = menuBar()->addMenu(tr("Digitize"));
861  m_menuDigitize->addAction (m_actionDigitizeSelect);
862  m_menuDigitize->addAction (m_actionDigitizeAxis);
863  m_menuDigitize->addAction (m_actionDigitizeCurve);
864  m_menuDigitize->addAction (m_actionDigitizePointMatch);
865  m_menuDigitize->addAction (m_actionDigitizeColorPicker);
866  m_menuDigitize->addAction (m_actionDigitizeSegment);
867 
868  m_menuView = menuBar()->addMenu(tr("View"));
869  m_menuView->addAction (m_actionViewBackground);
870  m_menuView->addAction (m_actionViewDigitize);
871  m_menuView->addAction (m_actionViewChecklistGuide);
872  m_menuView->addAction (m_actionViewSettingsViews);
873  m_menuView->insertSeparator (m_actionViewToolTips);
874  m_menuView->addAction (m_actionViewToolTips);
875  m_menuView->insertSeparator (m_actionViewBackgroundNone);
876  m_menuViewBackground = new QMenu (tr ("Background"));
877  m_menuViewBackground->addAction (m_actionViewBackgroundNone);
878  m_menuViewBackground->addAction (m_actionViewBackgroundOriginal);
879  m_menuViewBackground->addAction (m_actionViewBackgroundFiltered);
880  m_menuView->addMenu (m_menuViewBackground);
881  m_menuViewCurves = new QMenu (tr ("Curves"));
882  m_menuViewCurves->addAction (m_actionViewCurvesNone);
883  m_menuViewCurves->addAction (m_actionViewCurvesSelected);
884  m_menuViewCurves->addAction (m_actionViewCurvesAll);
885  m_menuView->addMenu (m_menuViewCurves);
886  m_menuViewStatus = new QMenu (tr ("Status Bar"));
887  m_menuViewStatus->addAction (m_actionStatusNever);
888  m_menuViewStatus->addAction (m_actionStatusTemporary);
889  m_menuViewStatus->addAction (m_actionStatusAlways);
890  m_menuView->addMenu (m_menuViewStatus);
891  m_menuViewZoom = new QMenu (tr ("Zoom"));
892  m_menuViewZoom->addAction (m_actionZoomOut);
893  m_menuViewZoom->addAction (m_actionZoomIn);
894  m_menuViewZoom->insertSeparator (m_actionZoom16To1);
895  m_menuViewZoom->addAction (m_actionZoom16To1);
896  m_menuViewZoom->addAction (m_actionZoom8To1);
897  m_menuViewZoom->addAction (m_actionZoom4To1);
898  m_menuViewZoom->addAction (m_actionZoom2To1);
899  m_menuViewZoom->addAction (m_actionZoom1To1);
900  m_menuViewZoom->addAction (m_actionZoom1To2);
901  m_menuViewZoom->addAction (m_actionZoom1To4);
902  m_menuViewZoom->addAction (m_actionZoom1To8);
903  m_menuViewZoom->addAction (m_actionZoom1To16);
904  m_menuViewZoom->addAction (m_actionZoomFill);
905  m_menuView->addMenu (m_menuViewZoom);
906 
907  m_menuSettings = menuBar()->addMenu(tr ("Settings"));
908  m_menuSettings->addAction (m_actionSettingsCoords);
909  m_menuSettings->addAction (m_actionSettingsCurveAddRemove);
910  m_menuSettings->addAction (m_actionSettingsCurveProperties);
911  m_menuSettings->addAction (m_actionSettingsDigitizeCurve);
912  m_menuSettings->addAction (m_actionSettingsExport);
913  m_menuSettings->addAction (m_actionSettingsColorFilter);
914  m_menuSettings->addAction (m_actionSettingsAxesChecker);
915  m_menuSettings->addAction (m_actionSettingsGridRemoval);
916  m_menuSettings->addAction (m_actionSettingsPointMatch);
917  m_menuSettings->addAction (m_actionSettingsSegments);
918  m_menuSettings->insertSeparator (m_actionSettingsGeneral);
919  m_menuSettings->addAction (m_actionSettingsGeneral);
920  m_menuSettings->addAction (m_actionSettingsMainWindow);
921 
922  m_menuHelp = menuBar()->addMenu(tr("&Help"));
923  m_menuHelp->addAction (m_actionHelpChecklistGuideWizard);
924  m_menuHelp->insertSeparator(m_actionHelpWhatsThis);
925  m_menuHelp->addAction (m_actionHelpWhatsThis);
926  m_menuHelp->addAction (m_actionHelpTutorial);
927  m_menuHelp->addAction (m_actionHelpHelp);
928  m_menuHelp->addAction (m_actionHelpAbout);
929 
930  updateRecentFileList();
931 }
932 
933 void MainWindow::createNetwork ()
934 {
935  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createNetwork";
936 
937  m_networkClient = new NetworkClient (this);
938 }
939 
940 void MainWindow::createSettingsDialogs ()
941 {
942  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createSettingsDialogs";
943 
944  m_dlgSettingsCoords = new DlgSettingsCoords (*this);
945  m_dlgSettingsCurveAddRemove = new DlgSettingsCurveAddRemove (*this);
946  m_dlgSettingsCurveProperties = new DlgSettingsCurveProperties (*this);
947  m_dlgSettingsDigitizeCurve = new DlgSettingsDigitizeCurve (*this);
948  m_dlgSettingsExportFormat = new DlgSettingsExportFormat (*this);
949  m_dlgSettingsColorFilter = new DlgSettingsColorFilter (*this);
950  m_dlgSettingsAxesChecker = new DlgSettingsAxesChecker (*this);
951  m_dlgSettingsGridRemoval = new DlgSettingsGridRemoval (*this);
952  m_dlgSettingsPointMatch = new DlgSettingsPointMatch (*this);
953  m_dlgSettingsSegments = new DlgSettingsSegments (*this);
954  m_dlgSettingsGeneral = new DlgSettingsGeneral (*this);
955  m_dlgSettingsMainWindow = new DlgSettingsMainWindow (*this);
956 
957  m_dlgSettingsCoords->setVisible (false);
958  m_dlgSettingsCurveAddRemove->setVisible (false);
959  m_dlgSettingsCurveProperties->setVisible (false);
960  m_dlgSettingsDigitizeCurve->setVisible (false);
961  m_dlgSettingsExportFormat->setVisible (false);
962  m_dlgSettingsColorFilter->setVisible (false);
963  m_dlgSettingsAxesChecker->setVisible (false);
964  m_dlgSettingsGridRemoval->setVisible (false);
965  m_dlgSettingsPointMatch->setVisible (false);
966  m_dlgSettingsSegments->setVisible (false);
967  m_dlgSettingsGeneral->setVisible (false);
968  m_dlgSettingsMainWindow->setVisible (false);
969 }
970 
971 void MainWindow::createScene ()
972 {
973  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createScene";
974 
975  m_scene = new GraphicsScene (this);
976  m_view = new GraphicsView (m_scene, *this);
977  m_layout->addWidget (m_view);
978 }
979 
980 void MainWindow::createStateContextBackground ()
981 {
982  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createStateContextBackground";
983 
984  m_backgroundStateContext = new BackgroundStateContext (*this);
985 }
986 
987 void MainWindow::createStateContextDigitize ()
988 {
989  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createStateContextDigitize";
990 
991  m_digitizeStateContext = new DigitizeStateContext (*this,
992  *m_view,
993  m_isGnuplot);
994 }
995 
996 void MainWindow::createStateContextTransformation ()
997 {
998  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createStateContextTransformation";
999 
1000  ENGAUGE_CHECK_PTR (m_scene);
1001 
1002  m_transformationStateContext = new TransformationStateContext (*m_scene,
1003  m_isGnuplot);
1004 }
1005 
1006 void MainWindow::createStatusBar ()
1007 {
1008  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createStatusBar";
1009 
1010  m_statusBar = new StatusBar (*statusBar ());
1011  connect (this, SIGNAL (signalZoom(int)), m_statusBar, SLOT (slotZoom(int)));
1012  connect (m_statusBar, SIGNAL (signalZoom (int)), this, SLOT (slotViewZoom (int)));
1013 }
1014 
1015 void MainWindow::createToolBars ()
1016 {
1017  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createToolBars";
1018 
1019  const int VIEW_SIZE = 22;
1020 
1021  // Background toolbar widgets
1022  m_cmbBackground = new QComboBox ();
1023  m_cmbBackground->setEnabled (false);
1024  m_cmbBackground->setStatusTip (tr ("Select background image"));
1025  m_cmbBackground->setWhatsThis (tr ("Selected Background\n\n"
1026  "Select background image:\n"
1027  "1) No background which highlights points\n"
1028  "2) Original image which shows everything\n"
1029  "3) Filtered image which highlights important details"));
1030  m_cmbBackground->addItem ("No background", QVariant (BACKGROUND_IMAGE_NONE));
1031  m_cmbBackground->addItem ("Original image", QVariant (BACKGROUND_IMAGE_ORIGINAL));
1032  m_cmbBackground->addItem ("Filtered image", QVariant (BACKGROUND_IMAGE_FILTERED));
1033  // selectBackgroundOriginal needs currentIndexChanged
1034  connect (m_cmbBackground, SIGNAL (currentIndexChanged (int)), this, SLOT (slotCmbBackground (int)));
1035 
1036  // Background toolbar
1037  m_toolBackground = new QToolBar (tr ("Background"), this);
1038  m_toolBackground->addWidget (m_cmbBackground);
1039  addToolBar (m_toolBackground);
1040 
1041  // Digitize toolbar widgets that are not created elsewhere
1042  m_cmbCurve = new QComboBox ();
1043  m_cmbCurve->setEnabled (false);
1044  m_cmbCurve->setMinimumWidth (180);
1045  m_cmbCurve->setStatusTip (tr ("Select curve for new points."));
1046  m_cmbCurve->setWhatsThis (tr ("Selected Curve Name\n\n"
1047  "Select curve for any new points. Every point belongs to one curve."));
1048  connect (m_cmbCurve, SIGNAL (activated (int)), this, SLOT (slotCmbCurve (int))); // activated() ignores code changes
1049 
1050  // Digitize toolbar
1051  m_toolDigitize = new QToolBar (tr ("Drawing"), this);
1052  m_toolDigitize->addAction (m_actionDigitizeSelect);
1053  m_toolDigitize->insertSeparator (m_actionDigitizeAxis);
1054  m_toolDigitize->addAction (m_actionDigitizeAxis);
1055  m_toolDigitize->insertSeparator (m_actionDigitizeCurve);
1056  m_toolDigitize->addAction (m_actionDigitizeCurve);
1057  m_toolDigitize->addAction (m_actionDigitizePointMatch);
1058  m_toolDigitize->addAction (m_actionDigitizeColorPicker);
1059  m_toolDigitize->addAction (m_actionDigitizeSegment);
1060  m_toolDigitize->addWidget (m_cmbCurve);
1061  addToolBar (m_toolDigitize);
1062 
1063  // Views toolbar widgets
1064  m_viewPointStyle = new ViewPointStyle();
1065  m_viewPointStyle->setMinimumSize(VIEW_SIZE, VIEW_SIZE);
1066  m_viewPointStyle->setMaximumSize(VIEW_SIZE, VIEW_SIZE);
1067  m_viewPointStyle->setStatusTip (tr ("Points style for the currently selected curve"));
1068  m_viewPointStyle->setWhatsThis (tr ("Points Style\n\n"
1069  "Points style for the currently selected curve. The points style is only "
1070  "displayed in this toolbar. To change the points style, "
1071  "use the Curve Properties dialog."));
1072 
1073  m_viewSegmentFilter = new ViewSegmentFilter();
1074  m_viewSegmentFilter->setMinimumSize(VIEW_SIZE, VIEW_SIZE);
1075  m_viewSegmentFilter->setMaximumSize(VIEW_SIZE, VIEW_SIZE);
1076  m_viewSegmentFilter->setStatusTip (tr ("View of filter for current curve in Segment Fill mode"));
1077  m_viewSegmentFilter->setWhatsThis (tr ("Segment Fill Filter\n\n"
1078  "View of filter for the current curve in Segment Fill mode. The filter settings are only "
1079  "displayed in this toolbar. To changed the filter settings, "
1080  "use the Color Picker mode or the Filter Settings dialog."));
1081 
1082  // Settings views toolbar
1083  m_toolSettingsViews = new QToolBar (tr ("Views"), this);
1084  m_toolSettingsViews->addWidget (m_viewPointStyle);
1085  m_toolSettingsViews->addWidget (new QLabel (" ")); // A hack, but this works to put some space between the adjacent widgets
1086  m_toolSettingsViews->addWidget (m_viewSegmentFilter);
1087  addToolBar (m_toolSettingsViews);
1088 
1089  // Checklist guide starts out hidden. It will be positioned in settingsRead
1090  m_dockChecklistGuide = new ChecklistGuide (this);
1091  connect (m_dockChecklistGuide, SIGNAL (signalChecklistClosed()), this, SLOT (slotChecklistClosed()));
1092 }
1093 
1094 void MainWindow::createTutorial ()
1095 {
1096  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createTutorial";
1097 
1098  m_tutorialDlg = new TutorialDlg (this);
1099  m_tutorialDlg->setModal (true);
1100  m_tutorialDlg->setMinimumSize (500, 400);
1101  m_tutorialDlg->hide();
1102 }
1103 
1104 ZoomFactor MainWindow::currentZoomFactor () const
1105 {
1106  if (m_actionZoom1To1->isChecked()) {
1107  return ZOOM_1_TO_1;
1108  } else if (m_actionZoom1To2->isChecked()) {
1109  return ZOOM_1_TO_2;
1110  } else if (m_actionZoom1To4->isChecked()) {
1111  return ZOOM_1_TO_4;
1112  } else if (m_actionZoom1To8->isChecked()) {
1113  return ZOOM_1_TO_8;
1114  } else if (m_actionZoom1To16->isChecked()) {
1115  return ZOOM_1_TO_16;
1116  } else if (m_actionZoom2To1->isChecked()) {
1117  return ZOOM_2_TO_1;
1118  } else if (m_actionZoom4To1->isChecked()) {
1119  return ZOOM_4_TO_1;
1120  } else if (m_actionZoom8To1->isChecked()) {
1121  return ZOOM_8_TO_1;
1122  } else if (m_actionZoom16To1->isChecked()) {
1123  return ZOOM_16_TO_1;
1124  } else if (m_actionZoomFill->isChecked()) {
1125  return ZOOM_FILL;
1126  } else {
1127  ENGAUGE_ASSERT (false);
1128  return ZOOM_1_TO_1;
1129  }
1130 }
1131 bool MainWindow::eventFilter(QObject *target, QEvent *event)
1132 {
1133  if (event->type () == QEvent::KeyPress) {
1134 
1135  QKeyEvent *eventKeyPress = (QKeyEvent *) event;
1136 
1137  if ((eventKeyPress->key() == Qt::Key_E) &&
1138  ((eventKeyPress->modifiers() & Qt::ShiftModifier) != 0) &&
1139  ((eventKeyPress->modifiers() & Qt::ControlModifier) != 0)) {
1140 
1141  saveErrorReportFileAndExit ("Shift+Control+E",
1142  __FILE__,
1143  __LINE__,
1144  "userTriggered");
1145  }
1146  }
1147 
1148  return QObject::eventFilter (target, event);
1149 }
1150 
1151 void MainWindow::fileImport (const QString &fileName)
1152 {
1153  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::fileImport"
1154  << " fileName=" << fileName.toLatin1 ().data ()
1155  << " curDir=" << QDir::currentPath().toLatin1().data();
1156 
1157  QString originalFileOld = m_originalFile;
1158  bool originalFileWasImported = m_originalFileWasImported;
1159 
1160  m_originalFile = fileName; // Make this available for logging in case an error occurs during the load
1161  m_originalFileWasImported = true;
1162 
1163  QImage image;
1164  bool loaded = false;
1165 #ifdef ENGAUGE_JPEG2000
1166  Jpeg2000 jpeg2000;
1167  loaded = jpeg2000.load (fileName,
1168  image);
1169 #endif // ENGAUGE_JPEG2000
1170  if (!loaded) {
1171  loaded = image.load (fileName);
1172  }
1173 
1174  if (!loaded) {
1175  QMessageBox::warning (this,
1176  engaugeWindowTitle(),
1177  tr("Cannot read file %1.").
1178  arg(fileName));
1179 
1180  // Reset
1181  m_originalFile = originalFileOld;
1182  m_originalFileWasImported = originalFileWasImported;
1183 
1184  return;
1185  }
1186 
1187  loadImage (fileName,
1188  image);
1189 }
1190 
1192 {
1193  return m_backgroundStateContext->imageForCurveState();
1194 }
1195 
1197 {
1198  return m_isGnuplot;
1199 }
1200 
1201 void MainWindow::loadCurveListFromCmdMediator ()
1202 {
1203  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::loadCurveListFromCmdMediator";
1204 
1205  m_cmbCurve->clear ();
1206  QStringList curvesGraphsNames = m_cmdMediator->curvesGraphsNames ();
1207  QStringList::iterator itr;
1208  for (itr = curvesGraphsNames.begin (); itr != curvesGraphsNames.end (); itr++) {
1209 
1210  QString curvesGraphName = *itr;
1211  m_cmbCurve->addItem (curvesGraphName);
1212  }
1213 
1214  // Arbitrarily pick the first curve
1215  m_cmbCurve->setCurrentIndex (0);
1216 }
1217 
1218 void MainWindow::loadDocumentFile (const QString &fileName)
1219 {
1220  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::loadDocumentFile fileName=" << fileName.toLatin1 ().data ();
1221 
1222  QApplication::setOverrideCursor(Qt::WaitCursor);
1223  CmdMediator *cmdMediator = new CmdMediator (*this,
1224  fileName);
1225  QApplication::restoreOverrideCursor();
1226 
1227  if (cmdMediator->successfulRead ()) {
1228 
1229  setCurrentPathFromFile (fileName);
1230  rebuildRecentFileListForCurrentFile(fileName);
1231  m_currentFile = fileName; // This enables the FileSaveAs menu option
1232 
1233  if (m_cmdMediator != 0) {
1234  delete m_cmdMediator;
1235  m_cmdMediator = 0;
1236  }
1237 
1238  m_cmdMediator = cmdMediator;
1239  setupAfterLoad(fileName,
1240  "File opened");
1241 
1242  // Start select mode
1243  m_actionDigitizeSelect->setChecked (true); // We assume user wants to first select existing stuff
1244  slotDigitizeSelect(); // Trigger transition so cursor gets updated immediately
1245 
1246  m_engaugeFile = fileName;
1247  m_originalFile = fileName; // This is needed by updateAfterCommand below if an error report is generated
1248  m_originalFileWasImported = false;
1249 
1250  updateAfterCommand (); // Enable Save button now that m_engaugeFile is set
1251 
1252  } else {
1253 
1254  QMessageBox::warning (this,
1255  engaugeWindowTitle(),
1256  tr("Cannot read file %1:\n%2.").
1257  arg(fileName).
1258  arg(cmdMediator->reasonForUnsuccessfulRead ()));
1259  delete cmdMediator;
1260 
1261  }
1262 }
1263 
1264 void MainWindow::loadErrorReportFile(const QString &initialPath,
1265  const QString &errorReportFile)
1266 {
1267  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::loadErrorReportFile"
1268  << " path=" << initialPath.toLatin1().data()
1269  << " file=" << errorReportFile.toLatin1().data();
1270 
1271  // The default path has been changed from its original executable-based initial value to the last directory used
1272  // according to the settings. Since the executable-based directory is much more stable, and we want a predictable
1273  // directory in the likely event that the error report file has a relative path, we temporarily switch the default path
1274  // back to the executable-based initial value
1275  QString originalPath = QDir::currentPath();
1276  QDir::setCurrent(initialPath);
1277 
1278  QFile file (errorReportFile);
1279  if (!file.exists()) {
1280  // Convert path from relative to absolute so file-not-found errors are easier to fix
1281  QFileInfo fileInfo (errorReportFile);
1282 
1283  QMessageBox::critical (this,
1284  engaugeWindowTitle(),
1285  tr ("File not found: ") + fileInfo.absoluteFilePath());
1286  exit (-1);
1287  }
1288 
1289  // Open the error report file as if it was a regular Document file
1290  QXmlStreamReader reader (&file);
1291  file.open(QIODevice::ReadOnly | QIODevice::Text);
1292  m_cmdMediator = new CmdMediator(*this,
1293  errorReportFile);
1294 
1295  // Load the commands into the shadow command stack
1296  m_cmdStackShadow->loadCommands (*this,
1297  m_cmdMediator->document(),
1298  reader);
1299  file.close();
1300 
1301  // Reset the original path now that the error report file has been read in
1302  QDir::setCurrent(originalPath);
1303 
1304  setupAfterLoad(errorReportFile,
1305  "Error report opened");
1306 
1307  // Start select mode
1308  m_actionDigitizeSelect->setChecked (true); // We assume user wants to first select existing stuff
1309  slotDigitizeSelect(); // Trigger transition so cursor gets updated immediately
1310 
1311  updateAfterCommand ();
1312 }
1313 
1314 void MainWindow::loadImage (const QString &fileName,
1315  const QImage &image)
1316 {
1317  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::loadImage fileName=" << fileName.toLatin1 ().data ();
1318 
1319  QApplication::setOverrideCursor(Qt::WaitCursor);
1320  CmdMediator *cmdMediator = new CmdMediator (*this,
1321  image);
1322  QApplication::restoreOverrideCursor();
1323 
1324  setCurrentPathFromFile (fileName);
1325  // We do not call rebuildRecentFileListForCurrentFile for an image file, so only proper Engauge document files appear in the recent file list
1326  m_engaugeFile = EMPTY_FILENAME; // Forces first Save to be treated as Save As
1327 
1328  if (m_cmdMediator != 0) {
1329  delete m_cmdMediator;
1330  m_cmdMediator = 0;
1331  }
1332 
1333  m_cmdMediator = cmdMediator;
1334  setupAfterLoad(fileName,
1335  "File imported");
1336 
1337  if (m_actionHelpChecklistGuideWizard->isChecked ()) {
1338 
1339  // Show wizard
1340  ChecklistGuideWizard *wizard = new ChecklistGuideWizard (*this);
1341  if (wizard->exec() == QDialog::Accepted) {
1342 
1343  // Populate the checklist guide
1344  m_dockChecklistGuide->setTemplateHtml (wizard->templateHtml(),
1345  wizard->curveNames());
1346 
1347  // Unhide the checklist guide
1348  m_actionViewChecklistGuide->setChecked (true);
1349 
1350  // Update Document
1351  CurvesGraphs curvesGraphs;
1352  wizard->populateCurvesGraphs (curvesGraphs);
1353  m_cmdMediator->document().setCurvesGraphs(curvesGraphs);
1354 
1355  // Update the curve dropdown
1356  loadCurveListFromCmdMediator();
1357  }
1358  delete wizard;
1359  }
1360 
1361  // Start axis mode
1362  m_actionDigitizeAxis->setChecked (true); // We assume user first wants to digitize axis points
1363  slotDigitizeAxis (); // Trigger transition so cursor gets updated immediately
1364 
1365  updateControls ();
1366 }
1367 
1368 void MainWindow::loadInputFileForErrorReport(QDomDocument &domInputFile) const
1369 {
1370  QFile file (m_originalFile);
1371 
1372  // File should be available for opening, if not then the dom will be left empty. We assume it has not been
1373  // modified since opened
1374  if (!file.open (QIODevice::ReadOnly)) {
1375  return;
1376  }
1377 
1378  domInputFile.setContent (&file);
1379  file.close();
1380 }
1381 
1382 void MainWindow::loadToolTips()
1383 {
1384  if (m_actionViewToolTips->isChecked ()) {
1385 
1386  // Show tool tips
1387  m_actionDigitizeSelect->setToolTip (DIGITIZE_ACTION_SELECT);
1388  m_actionDigitizeAxis->setToolTip (DIGITIZE_ACTION_AXIS_POINT);
1389  m_actionDigitizeCurve->setToolTip (DIGITIZE_ACTION_CURVE_POINT);
1390  m_actionDigitizePointMatch->setToolTip (DIGITIZE_ACTION_POINT_MATCH);
1391  m_actionDigitizeColorPicker->setToolTip (DIGITIZE_ACTION_COLOR_PICKER);
1392  m_actionDigitizeSegment->setToolTip (DIGITIZE_ACTION_SEGMENT_POINTS);
1393  m_cmbBackground->setToolTip (tr ("Background image."));
1394  m_cmbCurve->setToolTip (tr ("Currently selected curve."));
1395  m_viewPointStyle->setToolTip (tr ("Point style for currently selected curve."));
1396  m_viewSegmentFilter->setToolTip (tr ("Segment Fill filter for currently selected curve."));
1397 
1398  } else {
1399 
1400  // Remove any previous tool tips
1401  m_actionDigitizeSelect->setToolTip ("");
1402  m_actionDigitizeAxis->setToolTip ("");
1403  m_actionDigitizeCurve->setToolTip ("");
1404  m_actionDigitizePointMatch->setToolTip ("");
1405  m_actionDigitizeColorPicker->setToolTip ("");
1406  m_actionDigitizeSegment->setToolTip ("");
1407  m_cmbBackground->setToolTip ("");
1408  m_cmbCurve->setToolTip ("");
1409  m_viewPointStyle->setToolTip ("");
1410  m_viewSegmentFilter->setToolTip ("");
1411 
1412  }
1413 }
1414 
1415 bool MainWindow::maybeSave()
1416 {
1417  if (m_cmdMediator != 0) {
1418  if (m_cmdMediator->isModified()) {
1419  QMessageBox::StandardButton ret = QMessageBox::warning (this,
1420  engaugeWindowTitle(),
1421  tr("The document has been modified.\n"
1422  "Do you want to save your changes?"),
1423  QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
1424  if (ret == QMessageBox::Save) {
1425  return slotFileSave();
1426  } else if (ret == QMessageBox::Cancel) {
1427  return false;
1428  }
1429  }
1430  }
1431 
1432  return true;
1433 }
1434 
1435 DocumentModelExportFormat MainWindow::modelExportOverride (const DocumentModelExportFormat &modelExportFormatBefore,
1436  const ExportToFile &exportStrategy,
1437  const QString &fileName) const
1438 {
1439  DocumentModelExportFormat modelExportFormatAfter = modelExportFormatBefore;
1440 
1441  // Extract file extensions
1442  QString csvExtension = QString (".%1")
1443  .arg (exportStrategy.fileExtensionCsv());
1444  QString tsvExtension = QString (".%1")
1445  .arg (exportStrategy.fileExtensionTsv());
1446  QString fileExtensionVersusCsv = fileName.right (csvExtension.size());
1447  QString fileExtensionVersusTsv = fileName.right (tsvExtension.size());
1448 
1449  // Override if CSV or TSV was selected. We cannot use QFileDialog::selecedNameFilter() since that is
1450  // broken in Linux, so we use the file extension
1451  if (csvExtension.compare (fileExtensionVersusCsv, Qt::CaseInsensitive) == 0) {
1452  modelExportFormatAfter.setDelimiter (EXPORT_DELIMITER_COMMA);
1453  } else if (tsvExtension.compare (fileExtensionVersusTsv, Qt::CaseInsensitive) == 0) {
1454  modelExportFormatAfter.setDelimiter (EXPORT_DELIMITER_TAB);
1455  }
1456 
1457  return modelExportFormatAfter;
1458 }
1459 
1461 {
1462  return m_modelMainWindow;
1463 }
1464 
1465 void MainWindow::rebuildRecentFileListForCurrentFile(const QString &filePath)
1466 {
1467  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::rebuildRecentFileListForCurrentFile";
1468 
1469  setWindowFilePath (filePath);
1470 
1471  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
1472  QStringList recentFilePaths = settings.value (SETTINGS_RECENT_FILE_LIST).toStringList();
1473  recentFilePaths.removeAll (filePath); // Remove previous instance of the current filePath
1474  recentFilePaths.prepend (filePath); // Insert current filePath at start
1475  while (recentFilePaths.count () > (int) MAX_RECENT_FILE_LIST_SIZE) {
1476  recentFilePaths.removeLast (); // Remove entry since the number of entries exceeds the limit
1477  }
1478  settings.setValue (SETTINGS_RECENT_FILE_LIST, recentFilePaths);
1479 
1480  updateRecentFileList();
1481 }
1482 
1483 void MainWindow::resizeEvent(QResizeEvent * /* event */)
1484 {
1485  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::resizeEvent";
1486 
1487  if (m_actionZoomFill->isChecked ()) {
1488  slotViewZoomFill();
1489  }
1490 }
1491 
1492 bool MainWindow::saveDocumentFile (const QString &fileName)
1493 {
1494  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::saveDocumentFile fileName=" << fileName.toLatin1 ().data ();
1495 
1496  QFile file(fileName);
1497  if (!file.open(QFile::WriteOnly)) {
1498  QMessageBox::warning (this,
1499  engaugeWindowTitle(),
1500  tr ("Cannot write file %1: \n%2.").
1501  arg(fileName).
1502  arg(file.errorString()));
1503  return false;
1504  }
1505 
1506  rebuildRecentFileListForCurrentFile (fileName);
1507 
1508  QApplication::setOverrideCursor (Qt::WaitCursor);
1509  QXmlStreamWriter writer(&file);
1510  writer.setAutoFormatting(true);
1511  writer.writeStartDocument();
1512  writer.writeDTD("<!DOCTYPE engauge>");
1513  m_cmdMediator->document().saveXml(writer);
1514  writer.writeEndDocument();
1515  QApplication::restoreOverrideCursor ();
1516 
1517  // Notify the undo stack that the current state is now considered "clean". This will automatically trigger a
1518  // signal back to this class that will update the modified marker in the title bar
1519  m_cmdMediator->setClean ();
1520 
1521  setCurrentFile(fileName);
1522  m_engaugeFile = fileName;
1523  updateAfterCommand (); // Enable Save button now that m_engaugeFile is set
1524  m_statusBar->showTemporaryMessage("File saved");
1525 
1526  return true;
1527 }
1528 
1529 void MainWindow::saveErrorReportFileAndExit (const char *context,
1530  const char *file,
1531  int line,
1532  const char *comment) const
1533 {
1534  if (m_cmdMediator != 0) {
1535 
1536  QString reportWithoutDocument = saveErrorReportFileAndExitXml (context,
1537  file,
1538  line,
1539  comment,
1540  false);
1541  QString reportWithDocument = saveErrorReportFileAndExitXml (context,
1542  file,
1543  line,
1544  comment,
1545  true);
1546  DlgErrorReport dlg (reportWithoutDocument,
1547  reportWithDocument);
1548 
1549  // Ask user if report should be uploaded, and if the document is included when it is uploaded
1550  if (dlg.exec() == QDialog::Accepted) {
1551 
1552  // Upload the error report to the server
1553  m_networkClient->uploadErrorReport (dlg.xmlToUpload());
1554  }
1555  }
1556 }
1557 
1558 QString MainWindow::saveErrorReportFileAndExitXml (const char *context,
1559  const char *file,
1560  int line,
1561  const char *comment,
1562  bool includeDocument) const
1563 {
1564  const bool DEEP_COPY = true;
1565 
1566  QString xmlErrorReport;
1567  QXmlStreamWriter writer (&xmlErrorReport);
1568  writer.setAutoFormatting(true);
1569 
1570  // Entire error report contains metadata, commands and other details
1571  writer.writeStartElement(DOCUMENT_SERIALIZE_ERROR_REPORT);
1572 
1573  // Version
1574  writer.writeStartElement(DOCUMENT_SERIALIZE_APPLICATION);
1575  writer.writeAttribute(DOCUMENT_SERIALIZE_APPLICATION_VERSION_NUMBER, VERSION_NUMBER);
1576  writer.writeEndElement();
1577 
1578  // Document
1579  if (includeDocument) {
1580  // Insert snapshot xml into writer stream, by reading from reader stream. Highest level of snapshot is DOCUMENT_SERIALIZE_APPLICATION
1581  QXmlStreamReader reader (m_startingDocumentSnapshot);
1582  while (!reader.atEnd ()) {
1583  reader.readNext ();
1584  if (reader.tokenType() != QXmlStreamReader::StartDocument &&
1585  reader.tokenType() != QXmlStreamReader::EndDocument) {
1586  writer.writeCurrentToken (reader);
1587  }
1588  }
1589  }
1590 
1591  // Operating system
1592  writer.writeStartElement(DOCUMENT_SERIALIZE_OPERATING_SYSTEM);
1593  writer.writeAttribute(DOCUMENT_SERIALIZE_OPERATING_SYSTEM_ENDIAN, EndianToString (QSysInfo::ByteOrder));
1594  writer.writeAttribute(DOCUMENT_SERIALIZE_OPERATING_SYSTEM_WORD_SIZE, QString::number (QSysInfo::WordSize));
1595  writer.writeEndElement();
1596 
1597  // Image
1598  writer.writeStartElement(DOCUMENT_SERIALIZE_IMAGE);
1599  writer.writeAttribute(DOCUMENT_SERIALIZE_IMAGE_WIDTH, QString::number (m_cmdMediator->pixmap().width ()));
1600  writer.writeAttribute(DOCUMENT_SERIALIZE_IMAGE_HEIGHT, QString::number (m_cmdMediator->pixmap().height ()));
1601  writer.writeEndElement();
1602 
1603  // Placeholder for original file, before the commands in the command stack were applied
1604  writer.writeStartElement(DOCUMENT_SERIALIZE_FILE);
1605  writer.writeAttribute(DOCUMENT_SERIALIZE_FILE_IMPORTED,
1606  m_originalFileWasImported ? DOCUMENT_SERIALIZE_BOOL_TRUE : DOCUMENT_SERIALIZE_BOOL_FALSE);
1607  writer.writeEndElement();
1608 
1609  // Commands
1610  m_cmdMediator->saveXml(writer);
1611 
1612  // Error
1613  writer.writeStartElement(DOCUMENT_SERIALIZE_ERROR);
1614  writer.writeAttribute(DOCUMENT_SERIALIZE_ERROR_CONTEXT, context);
1615  writer.writeAttribute(DOCUMENT_SERIALIZE_ERROR_FILE, file);
1616  writer.writeAttribute(DOCUMENT_SERIALIZE_ERROR_LINE, QString::number (line));
1617  writer.writeAttribute(DOCUMENT_SERIALIZE_ERROR_COMMENT, comment);
1618  writer.writeEndElement();
1619 
1620  writer.writeEndElement();
1621 
1622  // Put string into DOM
1623  QDomDocument domErrorReport ("ErrorReport");
1624  domErrorReport.setContent (xmlErrorReport);
1625 
1626  // Postprocessing
1627  if (!m_originalFileWasImported) {
1628 
1629  // Insert the original file into its placeholder, by manipulating the source and target xml as DOM documents. Very early
1630  // in the loading process, the original file may not be specified yet (m_originalFile is empty)
1631  QDomDocument domInputFile;
1632  loadInputFileForErrorReport (domInputFile);
1633  QDomDocumentFragment fragmentFileFrom = domErrorReport.createDocumentFragment();
1634  if (!domInputFile.isNull()) {
1635  fragmentFileFrom.appendChild (domErrorReport.importNode (domInputFile.documentElement(), DEEP_COPY));
1636  }
1637  QDomNodeList nodesFileTo = domErrorReport.elementsByTagName (DOCUMENT_SERIALIZE_FILE);
1638  if (nodesFileTo.count () > 0) {
1639  QDomNode nodeFileTo = nodesFileTo.at (0);
1640  nodeFileTo.appendChild (fragmentFileFrom);
1641  }
1642 
1643  // Replace DOCUMENT_SERIALIZE_IMAGE by same node with CDATA removed, since:
1644  // 1) it is very big and working with smaller files, especially in emails, is easier
1645  // 2) removing the image better preserves user's privacy
1646  // 3) having the actual image does not help that much when debugging
1647  QDomNodeList nodesDocument = domErrorReport.elementsByTagName (DOCUMENT_SERIALIZE_DOCUMENT);
1648  for (int i = 0 ; i < nodesDocument.count(); i++) {
1649  QDomNode nodeDocument = nodesDocument.at (i);
1650  QDomElement elemImage = nodeDocument.firstChildElement(DOCUMENT_SERIALIZE_IMAGE);
1651  if (!elemImage.isNull()) {
1652 
1653  // Get old image attributes so we can create an empty document with the same size
1654  if (elemImage.hasAttribute (DOCUMENT_SERIALIZE_IMAGE_WIDTH) &&
1655  elemImage.hasAttribute (DOCUMENT_SERIALIZE_IMAGE_HEIGHT)) {
1656 
1657  int width = elemImage.attribute(DOCUMENT_SERIALIZE_IMAGE_WIDTH).toInt();
1658  int height = elemImage.attribute(DOCUMENT_SERIALIZE_IMAGE_HEIGHT).toInt();
1659 
1660  QDomNode nodeReplacement;
1661  QDomElement elemReplacement = nodeReplacement.toElement();
1662  elemReplacement.setAttribute (DOCUMENT_SERIALIZE_IMAGE_WIDTH, width);
1663  elemReplacement.setAttribute (DOCUMENT_SERIALIZE_IMAGE_HEIGHT, height);
1664 
1665  // Replace with the new and then remove the old
1666  nodeDocument.insertBefore (nodeReplacement,
1667  elemImage);
1668  nodeDocument.removeChild(elemImage);
1669  }
1670  }
1671  }
1672  }
1673 
1674  return domErrorReport.toString();
1675 }
1676 
1677 void MainWindow::saveStartingDocumentSnapshot()
1678 {
1679  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::saveStartingDocumentSnapshot";
1680 
1681  QXmlStreamWriter writer (&m_startingDocumentSnapshot);
1682  writer.setAutoFormatting (true);
1683  m_cmdMediator->document().saveXml (writer);
1684 }
1685 
1687 {
1688  ENGAUGE_CHECK_PTR (m_scene);
1689  return *m_scene;
1690 }
1691 
1692 BackgroundImage MainWindow::selectOriginal(BackgroundImage backgroundImage)
1693 {
1694  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::selectBackgroundOriginal";
1695 
1696  BackgroundImage previousBackground = (BackgroundImage) m_cmbBackground->currentData().toInt();
1697 
1698  int index = m_cmbBackground->findData (backgroundImage);
1699  ENGAUGE_ASSERT (index >= 0);
1700 
1701  m_cmbBackground->setCurrentIndex(index);
1702 
1703  return previousBackground;
1704 }
1705 
1707 {
1708  return m_cmbCurve->currentText ();
1709 }
1710 
1711 void MainWindow::setCurrentFile (const QString &fileName)
1712 {
1713  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::setCurrentFile";
1714 
1715  const QString PLACEHOLDER ("[*]");
1716 
1717  QString title = QString (tr ("Engauge Digitizer %1")
1718  .arg (VERSION_NUMBER));
1719 
1720  QString fileNameStripped = fileName;
1721  if (!fileName.isEmpty()) {
1722 
1723  // Strip out path and file extension
1724  QFileInfo fileInfo (fileName);
1725  fileNameStripped = fileInfo.baseName();
1726 
1727  title += QString (": %1")
1728  .arg (fileNameStripped);
1729  }
1730 
1731  m_currentFile = fileNameStripped;
1732 
1733  // To prevent "QWidget::setWindowModified: The window title does not contain a [*] placeholder" warnings,
1734  // we always append a placeholder
1735  title += PLACEHOLDER;
1736 
1737  setWindowTitle (title);
1738 }
1739 
1740 void MainWindow::setCurrentPathFromFile (const QString &fileName)
1741 {
1742  QDir dir = QFileInfo (fileName).absoluteDir();
1743 
1744  if (dir.exists ()) {
1745 
1746  bool success = QDir::setCurrent (dir.absolutePath ()); // Return to chosen directory the next time
1747  ENGAUGE_ASSERT (success);
1748 
1749  } else {
1750 
1751  // File was a url so it is irrelevant to the current directory
1752  }
1753 }
1754 
1755 void MainWindow::setPixmap (const QPixmap &pixmap)
1756 {
1757  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::setPixmap";
1758 
1759  m_digitizeStateContext->setImageIsLoaded (true);
1760  m_backgroundStateContext->setPixmap (m_transformation,
1761  m_cmdMediator->document().modelGridRemoval(),
1762  m_cmdMediator->document().modelColorFilter(),
1763  pixmap);
1764 }
1765 
1766 void MainWindow::settingsRead ()
1767 {
1768  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
1769 
1770  settingsReadEnvironment (settings);
1771  settingsReadMainWindow (settings);
1772 }
1773 
1774 void MainWindow::settingsReadEnvironment (QSettings &settings)
1775 {
1776  settings.beginGroup (SETTINGS_GROUP_ENVIRONMENT);
1777  QDir::setCurrent (settings.value (SETTINGS_CURRENT_DIRECTORY,
1778  QDir::currentPath ()).toString ());
1779  settings.endGroup ();
1780 }
1781 
1782 void MainWindow::settingsReadMainWindow (QSettings &settings)
1783 {
1784  settings.beginGroup(SETTINGS_GROUP_MAIN_WINDOW);
1785 
1786  // Main window geometry
1787  resize (settings.value (SETTINGS_SIZE,
1788  QSize (400, 400)).toSize ());
1789  move (settings.value (SETTINGS_POS,
1790  QPoint (200, 200)).toPoint ());
1791 
1792  // Help window geometry
1793  QSize helpSize = settings.value (SETTINGS_HELP_SIZE,
1794  QSize (900, 600)).toSize();
1795  m_helpWindow->resize (helpSize);
1796  if (settings.contains (SETTINGS_HELP_POS)) {
1797  QPoint helpPos = settings.value (SETTINGS_HELP_POS).toPoint();
1798  m_helpWindow->move (helpPos);
1799  }
1800 
1801  // Checklist guide wizard
1802  m_actionHelpChecklistGuideWizard->setChecked (settings.value (SETTINGS_CHECKLIST_GUIDE_WIZARD,
1803  true).toBool ());
1804 
1805  // Background toolbar visibility
1806  bool viewBackgroundToolBar = settings.value (SETTINGS_VIEW_BACKGROUND_TOOLBAR,
1807  true).toBool ();
1808  m_actionViewBackground->setChecked (viewBackgroundToolBar);
1809  m_toolBackground->setVisible (viewBackgroundToolBar);
1810  BackgroundImage backgroundImage = (BackgroundImage) settings.value (SETTINGS_BACKGROUND_IMAGE,
1811  BACKGROUND_IMAGE_FILTERED).toInt ();
1812  int indexBackground = m_cmbBackground->findData (QVariant (backgroundImage));
1813  m_cmbBackground->setCurrentIndex (indexBackground);
1814 
1815  // Digitize toolbar visibility
1816  bool viewDigitizeToolBar = settings.value (SETTINGS_VIEW_DIGITIZE_TOOLBAR,
1817  true).toBool ();
1818  m_actionViewDigitize->setChecked (viewDigitizeToolBar);
1819  m_toolDigitize->setVisible (viewDigitizeToolBar);
1820 
1821  // Views toolbar visibility
1822  bool viewSettingsViewsToolBar = settings.value (SETTINGS_VIEW_SETTINGS_VIEWS_TOOLBAR,
1823  true).toBool ();
1824  m_actionViewSettingsViews->setChecked (viewSettingsViewsToolBar);
1825  m_toolSettingsViews->setVisible (viewSettingsViewsToolBar);
1826 
1827  // Tooltips visibility
1828  bool viewToolTips = settings.value (SETTINGS_VIEW_TOOL_TIPS,
1829  true).toBool ();
1830  m_actionViewToolTips->setChecked (viewToolTips);
1831  loadToolTips ();
1832 
1833  // Statusbar visibility
1834  StatusBarMode statusBarMode = (StatusBarMode) settings.value (SETTINGS_VIEW_STATUS_BAR,
1835  false).toInt ();
1836  m_statusBar->setStatusBarMode (statusBarMode);
1837  m_actionStatusNever->setChecked (statusBarMode == STATUS_BAR_MODE_NEVER);
1838  m_actionStatusTemporary->setChecked (statusBarMode == STATUS_BAR_MODE_TEMPORARY);
1839  m_actionStatusAlways->setChecked (statusBarMode == STATUS_BAR_MODE_ALWAYS);
1840 
1841  // Checklist guide is docked or undocked. Default is undocked so user knows it can be undocked
1842  Qt::DockWidgetArea area = (Qt::DockWidgetArea) settings.value (SETTINGS_CHECKLIST_GUIDE_DOCK_AREA,
1843  Qt::NoDockWidgetArea).toInt();
1844 
1845  if (area == Qt::NoDockWidgetArea) {
1846 
1847  addDockWidget (Qt::RightDockWidgetArea,
1848  m_dockChecklistGuide); // Add on the right to prevent error message, then immediately make undocked
1849  m_dockChecklistGuide->setFloating(true); // Undock
1850  if (settings.contains (SETTINGS_CHECKLIST_GUIDE_DOCK_GEOMETRY)) {
1851  m_dockChecklistGuide->restoreGeometry (settings.value (SETTINGS_CHECKLIST_GUIDE_DOCK_GEOMETRY).toByteArray());
1852  }
1853 
1854  } else {
1855 
1856  addDockWidget (area,
1857  m_dockChecklistGuide);
1858 
1859  }
1860 
1861  // Main window settings. Preference for initial zoom factor is 100%, rather than fill mode, for issue #25. Some or all
1862  // settings are saved to the application AND saved to m_modelMainWindow for use in DlgSettingsMainWindow
1863  QLocale localeDefault;
1864  QLocale::Language language = (QLocale::Language) settings.value (SETTINGS_LOCALE_LANGUAGE,
1865  QVariant (localeDefault.language())).toInt();
1866  QLocale::Country country = (QLocale::Country) settings.value (SETTINGS_LOCALE_COUNTRY,
1867  QVariant (localeDefault.country())).toInt();
1868  QLocale locale (language,
1869  country);
1870  slotViewZoom ((ZoomFactor) settings.value (SETTINGS_ZOOM_FACTOR,
1871  QVariant (ZOOM_1_TO_1)).toInt());
1872  m_modelMainWindow.setLocale (locale);
1873 
1874  m_modelMainWindow.setZoomFactorInitial((ZoomFactorInitial) settings.value (SETTINGS_ZOOM_FACTOR_INITIAL,
1875  QVariant (DEFAULT_ZOOM_FACTOR_INITIAL)).toInt());
1876  m_modelMainWindow.setZoomControl ((ZoomControl) settings.value (SETTINGS_ZOOM_CONTROL,
1877  QVariant (ZOOM_CONTROL_MENU_WHEEL_PLUSMINUS)).toInt());
1879 
1880  settings.endGroup();
1881 }
1882 
1883 void MainWindow::settingsWrite ()
1884 {
1885  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
1886 
1887  settings.beginGroup (SETTINGS_GROUP_ENVIRONMENT);
1888  settings.setValue (SETTINGS_CURRENT_DIRECTORY, QDir::currentPath ());
1889  settings.endGroup ();
1890 
1891  settings.beginGroup (SETTINGS_GROUP_MAIN_WINDOW);
1892  settings.setValue (SETTINGS_SIZE, size ());
1893  settings.setValue (SETTINGS_POS, pos ());
1894  settings.setValue (SETTINGS_HELP_SIZE, m_helpWindow->size());
1895  settings.setValue (SETTINGS_HELP_POS, m_helpWindow->pos ());
1896  if (m_dockChecklistGuide->isFloating()) {
1897 
1898  settings.setValue (SETTINGS_CHECKLIST_GUIDE_DOCK_AREA, Qt::NoDockWidgetArea);
1899  settings.setValue (SETTINGS_CHECKLIST_GUIDE_DOCK_GEOMETRY, m_dockChecklistGuide->saveGeometry ());
1900 
1901  } else {
1902 
1903  settings.setValue (SETTINGS_CHECKLIST_GUIDE_DOCK_AREA, dockWidgetArea (m_dockChecklistGuide));
1904 
1905  }
1906  settings.setValue (SETTINGS_CHECKLIST_GUIDE_WIZARD, m_actionHelpChecklistGuideWizard->isChecked ());
1907  settings.setValue (SETTINGS_LOCALE_LANGUAGE, m_modelMainWindow.locale().language());
1908  settings.setValue (SETTINGS_LOCALE_COUNTRY, m_modelMainWindow.locale().country());
1909  settings.setValue (SETTINGS_VIEW_BACKGROUND_TOOLBAR, m_actionViewBackground->isChecked());
1910  settings.setValue (SETTINGS_BACKGROUND_IMAGE, m_cmbBackground->currentData().toInt());
1911  settings.setValue (SETTINGS_VIEW_DIGITIZE_TOOLBAR, m_actionViewDigitize->isChecked ());
1912  settings.setValue (SETTINGS_VIEW_STATUS_BAR, m_statusBar->statusBarMode ());
1913  settings.setValue (SETTINGS_VIEW_SETTINGS_VIEWS_TOOLBAR, m_actionViewSettingsViews->isChecked ());
1914  settings.setValue (SETTINGS_VIEW_TOOL_TIPS, m_actionViewToolTips->isChecked ());
1915  settings.setValue (SETTINGS_ZOOM_CONTROL, m_modelMainWindow.zoomControl());
1916  settings.setValue (SETTINGS_ZOOM_FACTOR, currentZoomFactor ());
1917  settings.setValue (SETTINGS_ZOOM_FACTOR_INITIAL, m_modelMainWindow.zoomFactorInitial());
1918  settings.endGroup ();
1919 }
1920 
1921 void MainWindow::setupAfterLoad (const QString &fileName,
1922  const QString &temporaryMessage)
1923 {
1924  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::setupAfterLoad"
1925  << " file=" << fileName.toLatin1().data()
1926  << " message=" << temporaryMessage.toLatin1().data();
1927 
1928  // Next line assumes CmdMediator for the NEW Document is already stored in m_cmdMediator
1929  m_digitizeStateContext->bindToCmdMediatorAndResetOnLoad (m_cmdMediator);
1930 
1931  m_transformation.resetOnLoad();
1932  m_transformationStateContext->resetOnLoad();
1933  m_scene->resetOnLoad();
1934 
1935  connect (m_actionEditUndo, SIGNAL (triggered ()), m_cmdMediator, SLOT (undo ()));
1936  connect (m_actionEditUndo, SIGNAL (triggered ()), m_cmdStackShadow, SLOT (slotUndo ()));
1937  connect (m_actionEditRedo, SIGNAL (triggered ()), m_cmdMediator, SLOT (redo ())); // No effect until CmdMediator::undo and CmdStackShadow::slotUndo get called
1938  connect (m_actionEditRedo, SIGNAL (triggered ()), m_cmdStackShadow, SLOT (slotRedo ())); // No effect after CmdMediator::undo and CmdStackShadow::slotUndo get called
1939  connect (m_cmdMediator, SIGNAL (canRedoChanged(bool)), this, SLOT (slotCanRedoChanged (bool)));
1940  connect (m_cmdMediator, SIGNAL (canUndoChanged(bool)), this, SLOT (slotCanUndoChanged (bool)));
1941  connect (m_cmdMediator, SIGNAL (redoTextChanged (const QString &)), this, SLOT (slotRedoTextChanged (const QString &)));
1942  connect (m_cmdMediator, SIGNAL (undoTextChanged (const QString &)), this, SLOT (slotUndoTextChanged (const QString &)));
1943  loadCurveListFromCmdMediator ();
1945 
1946  m_isDocumentExported = false;
1947 
1948  // Set up background before slotViewZoomFill which relies on the background. At this point
1949  // the transformation is undefined (unless the code is changed) so grid removal will not work
1950  // but updateTransformationAndItsDependencies will call this again to fix that issue
1951  setPixmap (m_cmdMediator->pixmap ());
1952  m_backgroundStateContext->setCurveSelected (m_transformation,
1953  m_cmdMediator->document().modelGridRemoval(),
1954  m_cmdMediator->document().modelColorFilter(),
1955  m_cmbCurve->currentText ());
1956  m_backgroundStateContext->setBackgroundImage ((BackgroundImage) m_cmbBackground->currentIndex ());
1957 
1958  applyZoomFactorAfterLoad(); // Zoom factor must be reapplied after background image is set, to have any effect
1959 
1960  setCurrentFile(fileName);
1961  m_statusBar->showTemporaryMessage (temporaryMessage);
1962  m_statusBar->wakeUp ();
1963 
1964  saveStartingDocumentSnapshot();
1965 
1966  updateAfterCommand(); // Replace stale points by points in new Document
1967 }
1968 
1969 void MainWindow::showEvent (QShowEvent *event)
1970 {
1971  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::showEvent"
1972  << " files=" << m_loadStartupFiles.join (",").toLatin1().data();
1973 
1974  QMainWindow::showEvent (event);
1975 
1976  if (m_loadStartupFiles.count() > 0) {
1977 
1978  m_timerLoadStartupFiles = new QTimer;
1979  m_timerLoadStartupFiles->setSingleShot (true);
1980  connect (m_timerLoadStartupFiles, SIGNAL (timeout ()), this, SLOT (slotLoadStartupFiles ()));
1981  m_timerLoadStartupFiles->start (0); // Zero delay still waits until execution finishes and gui is available
1982 
1983  }
1984 }
1985 
1986 void MainWindow::showTemporaryMessage (const QString &temporaryMessage)
1987 {
1988  m_statusBar->showTemporaryMessage (temporaryMessage);
1989 }
1990 
1991 void MainWindow::slotCanRedoChanged (bool canRedo)
1992 {
1993  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotCanRedoChanged";
1994 
1995  m_actionEditRedo->setEnabled (canRedo || m_cmdStackShadow->canRedo());
1996 }
1997 
1998 void MainWindow::slotCanUndoChanged (bool canUndo)
1999 {
2000  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotCanUndoChanged";
2001 
2002  m_actionEditUndo->setEnabled (canUndo);
2003 }
2004 
2005 void MainWindow::slotChecklistClosed()
2006 {
2007  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotChecklistClosed";
2008 
2009  m_actionViewChecklistGuide->setChecked (false);
2010 }
2011 
2012 void MainWindow::slotCleanChanged(bool clean)
2013 {
2014  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotCleanChanged";
2015 
2016  setWindowModified (!clean);
2017 }
2018 
2019 void MainWindow::slotCmbBackground(int currentIndex)
2020 {
2021  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotCmbBackground";
2022 
2023  switch (currentIndex) {
2024  case BACKGROUND_IMAGE_NONE:
2025  if (!m_actionViewBackgroundNone->isChecked()) {
2026  m_actionViewBackgroundNone->toggle();
2027  }
2028  break;
2029 
2030  case BACKGROUND_IMAGE_ORIGINAL:
2031  if (!m_actionViewBackgroundOriginal->isChecked ()) {
2032  m_actionViewBackgroundOriginal->toggle();
2033  }
2034  break;
2035 
2036  case BACKGROUND_IMAGE_FILTERED:
2037  if (!m_actionViewBackgroundFiltered->isChecked ()) {
2038  m_actionViewBackgroundFiltered->toggle();
2039  }
2040  break;
2041  }
2042 
2043  m_backgroundStateContext->setBackgroundImage ((BackgroundImage) currentIndex);
2044 }
2045 
2046 void MainWindow::slotCmbCurve(int /* currentIndex */)
2047 {
2048  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotCmbCurve";
2049 
2050  m_backgroundStateContext->setCurveSelected (m_transformation,
2051  m_cmdMediator->document().modelGridRemoval(),
2052  m_cmdMediator->document().modelColorFilter(),
2053  m_cmbCurve->currentText ());
2054  m_digitizeStateContext->handleCurveChange ();
2055 
2056  updateViewedCurves();
2058 }
2059 
2060 void MainWindow::slotContextMenuEvent (QString pointIdentifier)
2061 {
2062  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotContextMenuEvent point=" << pointIdentifier.toLatin1 ().data ();
2063 
2064  m_digitizeStateContext->handleContextMenuEvent (pointIdentifier);
2065 }
2066 
2067 void MainWindow::slotDigitizeAxis ()
2068 {
2069  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeAxis";
2070 
2071  m_digitizeStateContext->requestImmediateStateTransition (DIGITIZE_STATE_AXIS);
2072  m_cmbCurve->setEnabled (false); // Graph curve is irrelevant in this mode
2073  m_viewPointStyle->setEnabled (true); // Point style is important in this mode
2074  m_viewSegmentFilter->setEnabled (true); // Filtering is important in this mode
2075 }
2076 
2077 void MainWindow::slotDigitizeColorPicker ()
2078 {
2079  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeColorPicker";
2080 
2081  m_digitizeStateContext->requestImmediateStateTransition (DIGITIZE_STATE_COLOR_PICKER);
2082  m_cmbCurve->setEnabled (true);
2083  m_viewPointStyle->setEnabled (true);
2084  m_viewSegmentFilter->setEnabled (true);
2085 }
2086 
2087 void MainWindow::slotDigitizeCurve ()
2088 {
2089  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeCurve";
2090 
2091  m_digitizeStateContext->requestImmediateStateTransition (DIGITIZE_STATE_CURVE);
2092  m_cmbCurve->setEnabled (true);
2093  m_viewPointStyle->setEnabled (true);
2094  m_viewSegmentFilter->setEnabled (true);
2095 }
2096 
2097 void MainWindow::slotDigitizePointMatch ()
2098 {
2099  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizePointMatch";
2100 
2101  m_digitizeStateContext->requestImmediateStateTransition (DIGITIZE_STATE_POINT_MATCH);
2102  m_cmbCurve->setEnabled (true);
2103  m_viewPointStyle->setEnabled (true);
2104  m_viewSegmentFilter->setEnabled (true);
2105 }
2106 
2107 void MainWindow::slotDigitizeSegment ()
2108 {
2109  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeSegment";
2110 
2111  m_digitizeStateContext->requestImmediateStateTransition (DIGITIZE_STATE_SEGMENT);
2112  m_cmbCurve->setEnabled (true);
2113  m_viewPointStyle->setEnabled (true);
2114  m_viewSegmentFilter->setEnabled (true);
2115 }
2116 
2117 void MainWindow::slotDigitizeSelect ()
2118 {
2119  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeSelect";
2120 
2121  m_digitizeStateContext->requestImmediateStateTransition (DIGITIZE_STATE_SELECT);
2122  m_cmbCurve->setEnabled (false);
2123  m_viewPointStyle->setEnabled (false);
2124  m_viewSegmentFilter->setEnabled (false);
2125 }
2126 
2127 void MainWindow::slotEditCopy ()
2128 {
2129  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditCopy";
2130 
2131  CmdCopy *cmd = new CmdCopy (*this,
2132  m_cmdMediator->document(),
2133  m_scene->selectedPointIdentifiers ());
2134  m_digitizeStateContext->appendNewCmd (cmd);
2135 }
2136 
2137 void MainWindow::slotEditCut ()
2138 {
2139  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditCut";
2140 
2141  CmdCut *cmd = new CmdCut (*this,
2142  m_cmdMediator->document(),
2143  m_scene->selectedPointIdentifiers ());
2144  m_digitizeStateContext->appendNewCmd (cmd);
2145 }
2146 
2147 void MainWindow::slotEditDelete ()
2148 {
2149  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditDelete";
2150 
2151  CmdDelete *cmd = new CmdDelete (*this,
2152  m_cmdMediator->document(),
2153  m_scene->selectedPointIdentifiers ());
2154  m_digitizeStateContext->appendNewCmd (cmd);
2155 }
2156 
2157 void MainWindow::slotEditPaste ()
2158 {
2159  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditPaste";
2160 }
2161 
2162 void MainWindow::slotFileClose()
2163 {
2164  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileClose";
2165 
2166  if (maybeSave ()) {
2167 
2168  // Transition from defined to undefined. This must be after the clearing of the screen
2169  // since the axes checker screen item (and maybe others) must still exist
2170  m_transformationStateContext->triggerStateTransition(TRANSFORMATION_STATE_UNDEFINED,
2171  cmdMediator(),
2172  m_transformation,
2173  selectedGraphCurve());
2174 
2175  // Transition to empty state so an inadvertent mouse press does not trigger, for example,
2176  // the creation of an axis point on a non-existent GraphicsScene (=crash)
2177  m_digitizeStateContext->requestImmediateStateTransition (DIGITIZE_STATE_EMPTY);
2178 
2179  // Remove screen objects
2180  m_scene->resetOnLoad ();
2181 
2182  // Remove background
2183  m_backgroundStateContext->close ();
2184 
2185  // Remove scroll bars if they exist
2186  m_scene->setSceneRect (QRectF (0, 0, 1, 1));
2187 
2188  // Deallocate Document
2189  delete m_cmdMediator;
2190  m_cmdMediator = 0;
2191  m_currentFile = "";
2192  m_engaugeFile = "";
2193 
2194  updateControls();
2195  }
2196 }
2197 
2198 void MainWindow::slotFileExport ()
2199 {
2200  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileExport";
2201 
2202  if (m_transformation.transformIsDefined()) {
2203 
2204  ExportToFile exportStrategy;
2205  QString filter = QString ("%1;;%2;;All files (*.*)")
2206  .arg (exportStrategy.filterCsv ())
2207  .arg (exportStrategy.filterTsv ());
2208  QString defaultFileName = QString ("%1/%2.%3")
2209  .arg (QDir::currentPath ())
2210  .arg (m_currentFile)
2211  .arg (exportStrategy.fileExtensionCsv ());
2212  QFileDialog dlg;
2213  QString filterCsv = exportStrategy.filterCsv ();
2214  QString fileName = dlg.getSaveFileName (this,
2215  tr("Export"),
2216  defaultFileName,
2217  filter,
2218  &filterCsv);
2219  if (!fileName.isEmpty ()) {
2220 
2221  QFile file (fileName);
2222  if (file.open(QIODevice::WriteOnly)) {
2223 
2224  QTextStream str (&file);
2225 
2226  DocumentModelExportFormat modelExportFormat = modelExportOverride (cmdMediator().document().modelExport(),
2227  exportStrategy,
2228  fileName);
2229  exportStrategy.exportToFile (modelExportFormat,
2230  cmdMediator().document(),
2231  m_modelMainWindow,
2232  transformation (),
2233  str);
2234 
2235  // Update checklist guide status
2236  m_isDocumentExported = true; // Set for next line and for all checklist guide updates after this
2237  m_dockChecklistGuide->update (*m_cmdMediator,
2238  m_isDocumentExported);
2239 
2240  } else {
2241 
2242  QMessageBox::critical (0,
2243  engaugeWindowTitle(),
2244  tr ("Unable to export to file ") + fileName);
2245  }
2246  }
2247  } else {
2248  DlgRequiresTransform dlg ("Export");
2249  dlg.exec ();
2250  }
2251 }
2252 
2253 void MainWindow::slotFileImport ()
2254 {
2255  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileImport";
2256 
2257  if (maybeSave ()) {
2258 
2259  QString filter;
2260  QTextStream str (&filter);
2261 
2262  // Compile a list of supported formats into a filter
2263  QList<QByteArray>::const_iterator itr;
2264  QList<QByteArray> supportedImageFormats = QImageReader::supportedImageFormats();
2265  QStringList supportedImageFormatStrings;
2266  for (itr = supportedImageFormats.begin (); itr != supportedImageFormats.end (); itr++) {
2267  QByteArray arr = *itr;
2268  QString extensionAsWildcard = QString ("*.%1").arg (QString (arr));
2269  supportedImageFormatStrings << extensionAsWildcard;
2270  }
2271 #ifdef ENGAUGE_JPEG2000
2272  Jpeg2000 jpeg2000;
2273  supportedImageFormatStrings << jpeg2000.supportedImageWildcards();
2274 #endif // ENGAUGE_JPEG2000
2275 
2276  supportedImageFormatStrings.sort();
2277 
2278  str << "Image Files (" << supportedImageFormatStrings.join (" ") << ")";
2279 
2280  // Allow selection of files with strange suffixes in case the file extension was changed. Since
2281  // the default is the first filter, we add this afterwards (it is the off-nominal case)
2282  str << ";; All Files (*.*)";
2283 
2284  QString fileName = QFileDialog::getOpenFileName (this,
2285  tr("Import Image"),
2286  QDir::currentPath (),
2287  filter);
2288  if (!fileName.isEmpty ()) {
2289 
2290  fileImport (fileName);
2291 
2292  }
2293  }
2294 }
2295 
2296 void MainWindow::slotFileImportDraggedImage(QImage image)
2297 {
2298  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileImportDraggedImage";
2299 
2300  loadImage ("",
2301  image);
2302 }
2303 
2304 void MainWindow::slotFileImportDraggedImageUrl(QUrl url)
2305 {
2306  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileImportDraggedImageUrl url=" << url.toString ().toLatin1 ().data ();
2307 
2308  m_loadImageFromUrl->startLoadImage (url);
2309 }
2310 
2311 void MainWindow::slotFileImportImage(QString fileName, QImage image)
2312 {
2313  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileImportImage fileName=" << fileName.toLatin1 ().data ();
2314 
2315  loadImage (fileName,
2316  image);
2317 }
2318 
2319 void MainWindow::slotFileOpen()
2320 {
2321  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileOpen";
2322 
2323  if (maybeSave ()) {
2324 
2325  // Allow selection of files with strange suffixes in case the file extension was changed. Since
2326  // the default is the first filter, the wildcard filter is added afterwards (it is the off-nominal case)
2327  QString filter = QString ("%1 (*.%2);; All Files (*.*)")
2328  .arg (ENGAUGE_FILENAME_DESCRIPTION)
2329  .arg (ENGAUGE_FILENAME_EXTENSION);
2330 
2331  QString fileName = QFileDialog::getOpenFileName (this,
2332  tr("Open Document"),
2333  QDir::currentPath (),
2334  filter);
2335  if (!fileName.isEmpty ()) {
2336 
2337  loadDocumentFile (fileName);
2338 
2339  }
2340  }
2341 }
2342 
2343 void MainWindow::slotFileOpenDraggedDigFile (QString fileName)
2344 {
2345  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileOpenDraggedDigFile";
2346 
2347  loadDocumentFile (fileName);
2348 }
2349 
2350 void MainWindow::slotFilePrint()
2351 {
2352  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFilePrint";
2353 
2354  QPrinter printer (QPrinter::HighResolution);
2355  QPrintDialog dlg (&printer, this);
2356  if (dlg.exec() == QDialog::Accepted) {
2357  QPainter painter (&printer);
2358  m_view->render (&painter);
2359  painter.end();
2360  }
2361 }
2362 
2363 bool MainWindow::slotFileSave()
2364 {
2365  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileSave";
2366 
2367  if (m_engaugeFile.isEmpty()) {
2368  return slotFileSaveAs();
2369  } else {
2370  return saveDocumentFile (m_engaugeFile);
2371  }
2372 }
2373 
2374 bool MainWindow::slotFileSaveAs()
2375 {
2376  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileSaveAs";
2377 
2378  // Append engauge file extension if it is not already there
2379  QString filenameDefault = m_currentFile;
2380  if (!m_currentFile.endsWith (ENGAUGE_FILENAME_EXTENSION)) {
2381  filenameDefault = QString ("%1.%2")
2382  .arg (m_currentFile)
2383  .arg (ENGAUGE_FILENAME_EXTENSION);
2384  }
2385 
2386  if (!m_engaugeFile.isEmpty()) {
2387  filenameDefault = m_engaugeFile;
2388  }
2389 
2390  QString filterDigitizer = QString ("%1 (*.%2)")
2391  .arg (ENGAUGE_FILENAME_DESCRIPTION)
2392  .arg (ENGAUGE_FILENAME_EXTENSION);
2393  QString filterAll ("All files (*. *)");
2394 
2395  QStringList filters;
2396  filters << filterDigitizer;
2397  filters << filterAll;
2398 
2399  QFileDialog dlg(this);
2400  dlg.selectNameFilter (filterDigitizer);
2401  dlg.setNameFilters (filters);
2402  dlg.setWindowModality(Qt::WindowModal);
2403  dlg.setAcceptMode(QFileDialog::AcceptSave);
2404  dlg.selectFile(filenameDefault);
2405  if (dlg.exec()) {
2406 
2407  QStringList files = dlg.selectedFiles();
2408  return saveDocumentFile(files.at(0));
2409  }
2410 
2411  return false;
2412 }
2413 
2414 void MainWindow::slotHelpAbout()
2415 {
2416  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotHelpAbout";
2417 
2418  DlgAbout dlg (*this);
2419  dlg.exec ();
2420 }
2421 
2422 void MainWindow::slotHelpTutorial()
2423 {
2424  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotHelpTutorial";
2425 
2426  m_tutorialDlg->show ();
2427  m_tutorialDlg->exec ();
2428 }
2429 
2430 void MainWindow::slotKeyPress (Qt::Key key,
2431  bool atLeastOneSelectedItem)
2432 {
2433  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotKeyPress"
2434  << " key=" << QKeySequence (key).toString().toLatin1 ().data ()
2435  << " atLeastOneSelectedItem=" << (atLeastOneSelectedItem ? "true" : "false");
2436 
2437  m_digitizeStateContext->handleKeyPress (key,
2438  atLeastOneSelectedItem);
2439 }
2440 
2441 void MainWindow::slotLeave ()
2442 {
2443  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotLeave";
2444 
2445  m_digitizeStateContext->handleLeave ();
2446 }
2447 
2448 void MainWindow::slotLoadStartupFiles ()
2449 {
2450  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotLoadStartupFiles";
2451 
2452  ENGAUGE_ASSERT (m_loadStartupFiles.count() > 0);
2453 
2454  QString fileName = m_loadStartupFiles.front(); // Get next file name
2455  m_loadStartupFiles.pop_front(); // Remove next file name
2456 
2457  // Load next file into this instance of Engauge
2458  LoadFileInfo loadFileInfo;
2459  if (loadFileInfo.loadsAsDigFile(fileName)) {
2460 
2461  loadDocumentFile (fileName);
2462 
2463  } else {
2464 
2465  fileImport (fileName);
2466 
2467  }
2468 
2469  if (m_loadStartupFiles.count() > 0) {
2470 
2471  // Fork off another instance of this application to handle the remaining files recursively. New process
2472  // is detached so killing/terminating this process does not automatically kill the child process(es) also
2473  QProcess *process = new QProcess (this);
2474  process->startDetached (QCoreApplication::applicationFilePath(),
2475  m_loadStartupFiles);
2476  }
2477 }
2478 
2479 void MainWindow::slotMouseMove (QPointF pos)
2480 {
2481 // LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotMouseMove pos=" << QPointFToString (pos).toLatin1 ().data ();
2482 
2483  // Ignore mouse moves before Document is loaded
2484  if (m_cmdMediator != 0) {
2485 
2486  // Get status bar coordinates
2487  QString coordsScreen, coordsGraph, resolutionGraph;
2488  m_transformation.coordTextForStatusBar (pos,
2489  coordsScreen,
2490  coordsGraph,
2491  resolutionGraph);
2492 
2493  // Update status bar coordinates
2494  m_statusBar->setCoordinates (coordsScreen,
2495  coordsGraph,
2496  resolutionGraph);
2497 
2498  // There used to be a call to updateGraphicsLinesToMatchGraphicsPoints here, but that resulted
2499  // in hundreds of gratuitous log messages as the cursor was moved around, and nothing important happened
2500 
2501  m_digitizeStateContext->handleMouseMove (pos);
2502  }
2503 }
2504 
2505 void MainWindow::slotMousePress (QPointF pos)
2506 {
2507  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotMousePress";
2508 
2509  m_scene->resetPositionHasChangedFlags();
2510 
2511  m_digitizeStateContext->handleMousePress (pos);
2512 }
2513 
2514 void MainWindow::slotMouseRelease (QPointF pos)
2515 {
2516  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotMouseRelease";
2517 
2518  if (pos.x() < 0 || pos.y() < 0) {
2519 
2520  // Cursor is outside the image so drop this event. However, call updateControls since this may be
2521  // a click-and-drag to select in which case the controls (especially Copy and Cut) reflect the new selection
2522  updateControls ();
2523 
2524  } else {
2525 
2526  // Cursor is within the image so process this as a normal mouse release
2527  m_digitizeStateContext->handleMouseRelease (pos);
2528  }
2529 }
2530 
2531 void MainWindow::slotRecentFileAction ()
2532 {
2533  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotRecentFileAction";
2534 
2535  QAction *action = qobject_cast<QAction*>(sender ());
2536 
2537  if (action) {
2538  QString fileName = action->data().toString();
2539  loadDocumentFile (fileName);
2540  }
2541 }
2542 
2543 void MainWindow::slotRedoTextChanged (const QString &text)
2544 {
2545  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotRedoTextChanged";
2546 
2547  QString completeText ("Redo");
2548  if (!text.isEmpty ()) {
2549  completeText += QString (" \"%1\"").arg (text);
2550  }
2551  m_actionEditRedo->setText (completeText);
2552 }
2553 
2554 void MainWindow::slotSetOverrideCursor (QCursor cursor)
2555 {
2556  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSetOverrideCursor";
2557 
2558  m_digitizeStateContext->handleSetOverrideCursor (cursor);
2559 }
2560 
2561 void MainWindow::slotSettingsAxesChecker ()
2562 {
2563  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsAxesChecker";
2564 
2565  m_dlgSettingsAxesChecker->load (*m_cmdMediator);
2566  m_dlgSettingsAxesChecker->show ();
2567 }
2568 
2569 void MainWindow::slotSettingsColorFilter ()
2570 {
2571  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsColorFilter";
2572 
2573  m_dlgSettingsColorFilter->load (*m_cmdMediator);
2574  m_dlgSettingsColorFilter->show ();
2575 }
2576 
2577 void MainWindow::slotSettingsCoords ()
2578 {
2579  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsCoords";
2580 
2581  m_dlgSettingsCoords->load (*m_cmdMediator);
2582  m_dlgSettingsCoords->show ();
2583 }
2584 
2585 void MainWindow::slotSettingsCurveAddRemove ()
2586 {
2587  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsCurveAddRemove";
2588 
2589  m_dlgSettingsCurveAddRemove->load (*m_cmdMediator);
2590  m_dlgSettingsCurveAddRemove->show ();
2591 }
2592 
2593 void MainWindow::slotSettingsCurveProperties ()
2594 {
2595  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsCurveProperties";
2596 
2597  m_dlgSettingsCurveProperties->load (*m_cmdMediator);
2598  m_dlgSettingsCurveProperties->setCurveName (selectedGraphCurve ());
2599  m_dlgSettingsCurveProperties->show ();
2600 }
2601 
2602 void MainWindow::slotSettingsDigitizeCurve ()
2603 {
2604  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsDigitizeCurve";
2605 
2606  m_dlgSettingsDigitizeCurve->load (*m_cmdMediator);
2607  m_dlgSettingsDigitizeCurve->show ();
2608 }
2609 
2610 void MainWindow::slotSettingsExportFormat ()
2611 {
2612  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsExportFormat";
2613 
2614  if (transformIsDefined()) {
2615  m_dlgSettingsExportFormat->load (*m_cmdMediator);
2616  m_dlgSettingsExportFormat->show ();
2617  } else {
2618  DlgRequiresTransform dlg ("Export settings");
2619  dlg.exec();
2620  }
2621 }
2622 
2623 void MainWindow::slotSettingsGeneral ()
2624 {
2625  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsGeneral";
2626 
2627  m_dlgSettingsGeneral->load (*m_cmdMediator);
2628  m_dlgSettingsGeneral->show ();
2629 }
2630 
2631 void MainWindow::slotSettingsGridRemoval ()
2632 {
2633  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsGridRemoval";
2634 
2635  m_dlgSettingsGridRemoval->load (*m_cmdMediator);
2636  m_dlgSettingsGridRemoval->show ();
2637 }
2638 
2639 void MainWindow::slotSettingsPointMatch ()
2640 {
2641  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsPointMatch";
2642 
2643  m_dlgSettingsPointMatch->load (*m_cmdMediator);
2644  m_dlgSettingsPointMatch->show ();
2645 }
2646 
2647 void MainWindow::slotSettingsSegments ()
2648 {
2649  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsSegments";
2650 
2651  m_dlgSettingsSegments->load (*m_cmdMediator);
2652  m_dlgSettingsSegments->show ();
2653 }
2654 
2655 void MainWindow::slotSettingsMainWindow ()
2656 {
2657  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsMainWindow";
2658 
2659  m_dlgSettingsMainWindow->loadMainWindowModel (*m_cmdMediator,
2660  m_modelMainWindow);
2661  m_dlgSettingsMainWindow->show ();
2662 }
2663 
2664 void MainWindow::slotUndoTextChanged (const QString &text)
2665 {
2666  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotUndoTextChanged";
2667 
2668  QString completeText ("Undo");
2669  if (!text.isEmpty ()) {
2670  completeText += QString (" \"%1\"").arg (text);
2671  }
2672  m_actionEditUndo->setText (completeText);
2673 }
2674 
2675 void MainWindow::slotViewGroupBackground(QAction *action)
2676 {
2677  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewGroupBackground";
2678 
2679  // Set the combobox
2680  BackgroundImage backgroundImage;
2681  int indexBackground;
2682  if (action == m_actionViewBackgroundNone) {
2683  indexBackground = m_cmbBackground->findData (QVariant (BACKGROUND_IMAGE_NONE));
2684  backgroundImage = BACKGROUND_IMAGE_NONE;
2685  } else if (action == m_actionViewBackgroundOriginal) {
2686  indexBackground = m_cmbBackground->findData (QVariant (BACKGROUND_IMAGE_ORIGINAL));
2687  backgroundImage = BACKGROUND_IMAGE_ORIGINAL;
2688  } else if (action == m_actionViewBackgroundFiltered) {
2689  indexBackground = m_cmbBackground->findData (QVariant (BACKGROUND_IMAGE_FILTERED));
2690  backgroundImage = BACKGROUND_IMAGE_FILTERED;
2691  } else {
2692  ENGAUGE_ASSERT (false);
2693 
2694  // Defaults if assert is disabled so execution continues
2695  indexBackground = m_cmbBackground->findData (QVariant (BACKGROUND_IMAGE_ORIGINAL));
2696  backgroundImage = BACKGROUND_IMAGE_ORIGINAL;
2697  }
2698 
2699  m_cmbBackground->setCurrentIndex (indexBackground);
2700  m_backgroundStateContext->setBackgroundImage (backgroundImage);
2701 }
2702 
2703 void MainWindow::slotViewGroupCurves(QAction * /* action */)
2704 {
2705  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewGroupCurves";
2706 
2707  updateViewedCurves ();
2708 }
2709 
2710 void MainWindow::slotViewGroupStatus(QAction *action)
2711 {
2712  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewGroupStatus";
2713 
2714  ENGAUGE_CHECK_PTR (m_statusBar); // At startup, make sure status bar is already set up when View menu gets initialized
2715 
2716  if (action == m_actionStatusNever) {
2717  m_statusBar->setStatusBarMode(STATUS_BAR_MODE_NEVER);
2718  } else if (action == m_actionStatusTemporary) {
2719  m_statusBar->setStatusBarMode(STATUS_BAR_MODE_TEMPORARY);
2720  } else {
2721  m_statusBar->setStatusBarMode(STATUS_BAR_MODE_ALWAYS);
2722  }
2723 }
2724 
2725 void MainWindow::slotViewToolBarBackground ()
2726 {
2727  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarBackground";
2728 
2729  if (m_actionViewBackground->isChecked ()) {
2730  m_toolBackground->show();
2731  } else {
2732  m_toolBackground->hide();
2733  }
2734 }
2735 
2736 void MainWindow::slotViewToolBarChecklistGuide ()
2737 {
2738  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarChecklistGuide";
2739 
2740  if (m_actionViewChecklistGuide->isChecked ()) {
2741  m_dockChecklistGuide->show();
2742  } else {
2743  m_dockChecklistGuide->hide();
2744  }
2745 }
2746 
2747 void MainWindow::slotViewToolBarDigitize ()
2748 {
2749  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarDigitize";
2750 
2751  if (m_actionViewDigitize->isChecked ()) {
2752  m_toolDigitize->show();
2753  } else {
2754  m_toolDigitize->hide();
2755  }
2756 }
2757 
2758 void MainWindow::slotViewToolBarSettingsViews ()
2759 {
2760  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarSettingsViews";
2761 
2762  if (m_actionViewSettingsViews->isChecked ()) {
2763  m_toolSettingsViews->show();
2764  } else {
2765  m_toolSettingsViews->hide();
2766  }
2767 }
2768 
2769 void MainWindow::slotViewToolTips ()
2770 {
2771  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolTips";
2772 
2773  loadToolTips();
2774 }
2775 
2776 void MainWindow::slotViewZoom(int zoom)
2777 {
2778  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoom";
2779 
2780  // Update zoom controls and apply the zoom factor
2781  switch ((ZoomFactor) zoom) {
2782  case ZOOM_16_TO_1:
2783  m_actionZoom16To1->setChecked(true);
2784  slotViewZoom16To1 ();
2785  break;
2786  case ZOOM_8_TO_1:
2787  m_actionZoom8To1->setChecked(true);
2788  slotViewZoom8To1 ();
2789  break;
2790  case ZOOM_4_TO_1:
2791  m_actionZoom4To1->setChecked(true);
2792  slotViewZoom4To1 ();
2793  break;
2794  case ZOOM_2_TO_1:
2795  m_actionZoom2To1->setChecked(true);
2796  slotViewZoom2To1 ();
2797  break;
2798  case ZOOM_1_TO_1:
2799  m_actionZoom1To1->setChecked(true);
2800  slotViewZoom1To1 ();
2801  break;
2802  case ZOOM_1_TO_2:
2803  m_actionZoom1To2->setChecked(true);
2804  slotViewZoom1To2 ();
2805  break;
2806  case ZOOM_1_TO_4:
2807  m_actionZoom1To4->setChecked(true);
2808  slotViewZoom1To4 ();
2809  break;
2810  case ZOOM_1_TO_8:
2811  m_actionZoom1To8->setChecked(true);
2812  slotViewZoom1To8 ();
2813  break;
2814  case ZOOM_1_TO_16:
2815  m_actionZoom1To16->setChecked(true);
2816  slotViewZoom1To16 ();
2817  break;
2818  case ZOOM_FILL:
2819  m_actionZoomFill->setChecked(true);
2820  slotViewZoomFill ();
2821  break;
2822  }
2823 }
2824 
2825 void MainWindow::slotViewZoom16To1 ()
2826 {
2827  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoom16To1";
2828 
2829  QTransform transform;
2830  transform.scale (16.0, 16.0);
2831  m_view->setTransform (transform);
2832  emit signalZoom(ZOOM_16_TO_1);
2833 }
2834 
2835 void MainWindow::slotViewZoom8To1 ()
2836 {
2837  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoom8To1";
2838 
2839  QTransform transform;
2840  transform.scale (8.0, 8.0);
2841  m_view->setTransform (transform);
2842  emit signalZoom(ZOOM_8_TO_1);
2843 }
2844 
2845 void MainWindow::slotViewZoom4To1 ()
2846 {
2847  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoom4To1";
2848 
2849  QTransform transform;
2850  transform.scale (4.0, 4.0);
2851  m_view->setTransform (transform);
2852  emit signalZoom(ZOOM_4_TO_1);
2853 }
2854 
2855 void MainWindow::slotViewZoom2To1 ()
2856 {
2857  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotZoom2To1";
2858 
2859  QTransform transform;
2860  transform.scale (2.0, 2.0);
2861  m_view->setTransform (transform);
2862  emit signalZoom(ZOOM_2_TO_1);
2863 }
2864 
2865 void MainWindow::slotViewZoom1To1 ()
2866 {
2867  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoom1To1";
2868 
2869  QTransform transform;
2870  transform.scale (1.0, 1.0);
2871  m_view->setTransform (transform);
2872  emit signalZoom(ZOOM_1_TO_1);
2873 }
2874 
2875 void MainWindow::slotViewZoom1To2 ()
2876 {
2877  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotZoom1To2";
2878 
2879  QTransform transform;
2880  transform.scale (0.5, 0.5);
2881  m_view->setTransform (transform);
2882  emit signalZoom(ZOOM_1_TO_2);
2883 }
2884 
2885 void MainWindow::slotViewZoom1To4 ()
2886 {
2887  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotZoom1To4";
2888 
2889  QTransform transform;
2890  transform.scale (0.25, 0.25);
2891  m_view->setTransform (transform);
2892  emit signalZoom(ZOOM_1_TO_4);
2893 }
2894 
2895 void MainWindow::slotViewZoom1To8 ()
2896 {
2897  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotZoom1To8";
2898 
2899  QTransform transform;
2900  transform.scale (0.125, 0.125);
2901  m_view->setTransform (transform);
2902  emit signalZoom(ZOOM_1_TO_8);
2903 }
2904 
2905 void MainWindow::slotViewZoom1To16 ()
2906 {
2907  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotZoom1To16";
2908 
2909  QTransform transform;
2910  transform.scale (0.0625, 0.0625);
2911  m_view->setTransform (transform);
2912  emit signalZoom(ZOOM_1_TO_16);
2913 }
2914 
2915 void MainWindow::slotViewZoomFill ()
2916 {
2917  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoomFill";
2918 
2919  m_backgroundStateContext->fitInView (*m_view);
2920 
2921  emit signalZoom(ZOOM_FILL);
2922 }
2923 
2924 void MainWindow::slotViewZoomIn ()
2925 {
2926  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoomIn";
2927 
2928  // Try to zoom in. First determine what the next zoom factor should be
2929 
2930  bool goto16To1 = false, goto8To1 = false, goto4To1 = false, goto2To1 = false;
2931  bool goto1To1 = false;
2932  bool goto1To2 = false, goto1To4 = false, goto1To8 = false, goto1To16 = false;
2933  if (m_actionZoomFill->isChecked ()) {
2934 
2935  // Zooming in means user probably wants the more squished direction to be zoomed in by one step
2936  double xScale = m_view->transform().m11();
2937  double yScale = m_view->transform().m22();
2938  double scale = qMin(xScale, yScale);
2939  if (scale < 0.125) {
2940  goto1To8 = true;
2941  } else if (scale < 0.25) {
2942  goto1To4 = true;
2943  } else if (scale < 0.5) {
2944  goto1To2 = true;
2945  } else if (scale < 1) {
2946  goto1To1 = true;
2947  } else if (scale < 2) {
2948  goto2To1 = true;
2949  } else if (scale < 4) {
2950  goto4To1 = true;
2951  } else if (scale < 8) {
2952  goto8To1 = true;
2953  } else {
2954  goto1To16 = true;
2955  }
2956  } else {
2957  goto16To1 = m_actionZoom8To1->isChecked ();
2958  goto8To1 = m_actionZoom4To1->isChecked ();
2959  goto4To1 = m_actionZoom2To1->isChecked ();
2960  goto2To1 = m_actionZoom1To1->isChecked ();
2961  goto1To1 = m_actionZoom1To2->isChecked ();
2962  goto1To2 = m_actionZoom1To4->isChecked ();
2963  goto1To4 = m_actionZoom1To8->isChecked ();
2964  goto1To8 = m_actionZoom1To16->isChecked ();
2965  }
2966 
2967  // Update controls and apply zoom factor
2968  if (goto16To1) {
2969  m_actionZoom16To1->setChecked (true);
2970  slotViewZoom16To1 ();
2971  } else if (goto8To1) {
2972  m_actionZoom8To1->setChecked (true);
2973  slotViewZoom8To1 ();
2974  } else if (goto4To1) {
2975  m_actionZoom4To1->setChecked (true);
2976  slotViewZoom4To1 ();
2977  } else if (goto2To1) {
2978  m_actionZoom2To1->setChecked (true);
2979  slotViewZoom2To1 ();
2980  } else if (goto1To1) {
2981  m_actionZoom1To1->setChecked (true);
2982  slotViewZoom1To1 ();
2983  } else if (goto1To2) {
2984  m_actionZoom1To2->setChecked (true);
2985  slotViewZoom1To2 ();
2986  } else if (goto1To4) {
2987  m_actionZoom1To4->setChecked (true);
2988  slotViewZoom1To4 ();
2989  } else if (goto1To8) {
2990  m_actionZoom1To8->setChecked (true);
2991  slotViewZoom1To8 ();
2992  } else if (goto1To16) {
2993  m_actionZoom1To16->setChecked (true);
2994  slotViewZoom1To16 ();
2995  }
2996 }
2997 
2998 void MainWindow::slotViewZoomOut ()
2999 {
3000  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoomOut";
3001 
3002  // Try to zoom out. First determine what the next zoom factor should be
3003 
3004  bool goto16To1 = false, goto8To1 = false, goto4To1 = false, goto2To1 = false;
3005  bool goto1To1 = false;
3006  bool goto1To2 = false, goto1To4 = false, goto1To8 = false, goto1To16 = false;
3007  if (m_actionZoomFill->isChecked ()) {
3008 
3009  // Zooming out means user probably wants the less squished direction to be zoomed out by one step
3010  double xScale = m_view->transform().m11();
3011  double yScale = m_view->transform().m22();
3012  double scale = qMax(xScale, yScale);
3013  if (scale > 8) {
3014  goto8To1 = true;
3015  } else if (scale > 4) {
3016  goto4To1 = true;
3017  } else if (scale > 2) {
3018  goto2To1 = true;
3019  } else if (scale > 1) {
3020  goto1To1 = true;
3021  } else if (scale > 0.5) {
3022  goto1To2 = true;
3023  } else if (scale > 0.25) {
3024  goto1To4 = true;
3025  } else if (scale > 0.125) {
3026  goto1To8 = true;
3027  } else {
3028  goto1To16 = true;
3029  }
3030  } else {
3031  goto8To1 = m_actionZoom16To1->isChecked ();
3032  goto4To1 = m_actionZoom8To1->isChecked ();
3033  goto2To1 = m_actionZoom4To1->isChecked ();
3034  goto1To1 = m_actionZoom2To1->isChecked ();
3035  goto1To2 = m_actionZoom1To1->isChecked ();
3036  goto1To4 = m_actionZoom1To2->isChecked ();
3037  goto1To8 = m_actionZoom1To4->isChecked ();
3038  goto1To16 = m_actionZoom1To8->isChecked ();
3039  }
3040 
3041  // Update controls and apply zoom factor
3042  if (goto1To16) {
3043  m_actionZoom1To16->setChecked (true);
3044  slotViewZoom1To16 ();
3045  } else if (goto1To8) {
3046  m_actionZoom1To8->setChecked (true);
3047  slotViewZoom1To8 ();
3048  } else if (goto1To4) {
3049  m_actionZoom1To4->setChecked (true);
3050  slotViewZoom1To4 ();
3051  } else if (goto1To2) {
3052  m_actionZoom1To2->setChecked (true);
3053  slotViewZoom1To2 ();
3054  } else if (goto1To1) {
3055  m_actionZoom1To1->setChecked (true);
3056  slotViewZoom1To1 ();
3057  } else if (goto2To1) {
3058  m_actionZoom2To1->setChecked (true);
3059  slotViewZoom2To1 ();
3060  } else if (goto4To1) {
3061  m_actionZoom4To1->setChecked (true);
3062  slotViewZoom4To1 ();
3063  } else if (goto8To1) {
3064  m_actionZoom8To1->setChecked (true);
3065  slotViewZoom8To1 ();
3066  } else if (goto16To1) {
3067  m_actionZoom16To1->setChecked (true);
3068  slotViewZoom16To1 ();
3069  }
3070 }
3071 
3073 {
3074  return m_transformation;
3075 }
3076 
3078 {
3079  return m_transformation.transformIsDefined();
3080 }
3081 
3083 {
3084  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateAfterCommand";
3085 
3086  ENGAUGE_CHECK_PTR (m_cmdMediator);
3087 
3088  // Update transformation stuff, including the graph coordinates of every point in the Document, so coordinates in
3089  // status bar are up to date. Point coordinates in Document are also updated
3090  updateAfterCommandStatusBarCoords ();
3091 
3092  // Update the QGraphicsScene with the populated Curves. This requires the points in the Document to be already updated
3093  // by updateAfterCommandStatusBarCoords
3094  m_scene->updateAfterCommand (*m_cmdMediator);
3095 
3096  updateControls ();
3097 
3098  // Update checklist guide status
3099  m_dockChecklistGuide->update (*m_cmdMediator,
3100  m_isDocumentExported);
3101 
3102  // Final action at the end of a redo/undo is to checkpoint the Document and GraphicsScene to log files
3103  // so proper state can be verified
3104  writeCheckpointToLogFile ();
3105 }
3106 
3107 void MainWindow::updateAfterCommandStatusBarCoords ()
3108 {
3109  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateAfterCommandStatusBarCoords";
3110 
3111  // For some reason, mapFromGlobal(QCursor::pos) differs from event->pos by a little bit. We must compensate for
3112  // this so cursor coordinates in status bar match the DlgEditPoint inputs initially. After the mouse moves
3113  // the problem disappears since event->pos is available and QCursor::pos is no longer needed
3114  const QPoint HACK_SO_GRAPH_COORDINATE_MATCHES_INPUT (1, 1);
3115 
3116  Transformation m_transformationBefore (m_transformation);
3117 
3118  updateTransformationAndItsDependencies();
3119 
3120  // Trigger state transitions for transformation if appropriate
3121  if (!m_transformationBefore.transformIsDefined() && m_transformation.transformIsDefined()) {
3122 
3123  // Transition from undefined to defined
3124  m_transformationStateContext->triggerStateTransition(TRANSFORMATION_STATE_DEFINED,
3125  cmdMediator(),
3126  m_transformation,
3127  selectedGraphCurve());
3128 
3129  } else if (m_transformationBefore.transformIsDefined() && !m_transformation.transformIsDefined()) {
3130 
3131  // Transition from defined to undefined
3132  m_transformationStateContext->triggerStateTransition(TRANSFORMATION_STATE_UNDEFINED,
3133  cmdMediator(),
3134  m_transformation,
3135  selectedGraphCurve());
3136 
3137  } else if (m_transformation.transformIsDefined() && (m_transformationBefore != m_transformation)) {
3138 
3139  // There was not a define/undefined or undefined/defined transition, but the transformation changed so we
3140  // need to update the Checker
3141  m_transformationStateContext->updateAxesChecker(cmdMediator(),
3142  m_transformation);
3143 
3144  }
3145 
3146  QPoint posLocal = m_view->mapFromGlobal (QCursor::pos ()) - HACK_SO_GRAPH_COORDINATE_MATCHES_INPUT;
3147  QPointF posScreen = m_view->mapToScene (posLocal);
3148 
3149  slotMouseMove (posScreen); // Update the status bar coordinates to reflect the newly updated transformation
3150 }
3151 
3153 {
3154  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateAfterMouseRelease";
3155 
3156  updateControls ();
3157 }
3158 
3159 void MainWindow::updateControls ()
3160 {
3161  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateControls"
3162  << " selectedItems=" << m_scene->selectedItems().count();
3163 
3164  m_cmbBackground->setEnabled (!m_currentFile.isEmpty ());
3165 
3166  m_menuFileOpenRecent->setEnabled ((m_actionRecentFiles.count () > 0) &&
3167  (m_actionRecentFiles.at(0)->isVisible ())); // Need at least one visible recent file entry
3168  m_actionClose->setEnabled (!m_currentFile.isEmpty ());
3169  m_actionSave->setEnabled (!m_currentFile.isEmpty ());
3170  m_actionSaveAs->setEnabled (!m_currentFile.isEmpty ());
3171  m_actionExport->setEnabled (!m_currentFile.isEmpty ());
3172  m_actionPrint->setEnabled (!m_currentFile.isEmpty ());
3173 
3174  if (m_cmdMediator == 0) {
3175  m_actionEditUndo->setEnabled (false);
3176  m_actionEditRedo->setEnabled (false);
3177  } else {
3178  m_actionEditUndo->setEnabled (m_cmdMediator->canUndo ());
3179  m_actionEditRedo->setEnabled (m_cmdMediator->canRedo () || m_cmdStackShadow->canRedo ());
3180  }
3181  m_actionEditCut->setEnabled (m_scene->selectedItems().count () > 0);
3182  m_actionEditCopy->setEnabled (m_scene->selectedItems().count () > 0);
3183  m_actionEditPaste->setEnabled (false);
3184  m_actionEditDelete->setEnabled (m_scene->selectedItems().count () > 0);
3185 
3186  m_actionDigitizeAxis->setEnabled (!m_currentFile.isEmpty ());
3187  m_actionDigitizeCurve ->setEnabled (!m_currentFile.isEmpty ());
3188  m_actionDigitizePointMatch->setEnabled (!m_currentFile.isEmpty ());
3189  m_actionDigitizeColorPicker->setEnabled (!m_currentFile.isEmpty ());
3190  m_actionDigitizeSegment->setEnabled (!m_currentFile.isEmpty ());
3191  m_actionDigitizeSelect->setEnabled (!m_currentFile.isEmpty ());
3192 
3193  m_actionViewBackground->setEnabled (!m_currentFile.isEmpty());
3194  m_actionViewChecklistGuide->setEnabled (!m_dockChecklistGuide->browserIsEmpty());
3195  m_actionViewDigitize->setEnabled (!m_currentFile.isEmpty ());
3196  m_actionViewSettingsViews->setEnabled (!m_currentFile.isEmpty ());
3197 
3198  m_actionSettingsCoords->setEnabled (!m_currentFile.isEmpty ());
3199  m_actionSettingsCurveAddRemove->setEnabled (!m_currentFile.isEmpty ());
3200  m_actionSettingsCurveProperties->setEnabled (!m_currentFile.isEmpty ());
3201  m_actionSettingsDigitizeCurve->setEnabled (!m_currentFile.isEmpty ());
3202  m_actionSettingsExport->setEnabled (!m_currentFile.isEmpty ());
3203  m_actionSettingsColorFilter->setEnabled (!m_currentFile.isEmpty ());
3204  m_actionSettingsAxesChecker->setEnabled (!m_currentFile.isEmpty ());
3205  m_actionSettingsGridRemoval->setEnabled (!m_currentFile.isEmpty ());
3206  m_actionSettingsPointMatch->setEnabled (!m_currentFile.isEmpty ());
3207  m_actionSettingsSegments->setEnabled (!m_currentFile.isEmpty ());
3208  m_actionSettingsGeneral->setEnabled (!m_currentFile.isEmpty ());
3209  m_actionSettingsMainWindow->setEnabled (!m_currentFile.isEmpty ());
3210 
3211  m_groupBackground->setEnabled (!m_currentFile.isEmpty ());
3212  m_groupCurves->setEnabled (!m_currentFile.isEmpty ());
3213  m_groupZoom->setEnabled (!m_currentFile.isEmpty ());
3214 
3215  m_actionZoomIn->setEnabled (!m_currentFile.isEmpty ()); // Disable at startup so shortcut has no effect
3216  m_actionZoomOut->setEnabled (!m_currentFile.isEmpty ()); // Disable at startup so shortcut has no effect
3217 }
3218 
3219 void MainWindow::updateDigitizeStateIfSoftwareTriggered (DigitizeState digitizeState)
3220 {
3221  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateDigitizeStateIfSoftwareTriggered";
3222 
3223  switch (digitizeState) {
3224  case DIGITIZE_STATE_AXIS:
3225  m_actionDigitizeAxis->setChecked(true);
3226  slotDigitizeAxis(); // Call the slot that the setChecked call fails to trigger
3227  break;
3228 
3229  case DIGITIZE_STATE_COLOR_PICKER:
3230  m_actionDigitizeColorPicker->setChecked(true);
3231  slotDigitizeColorPicker(); // Call the slot that the setChecked call fails to trigger
3232  break;
3233 
3234  case DIGITIZE_STATE_CURVE:
3235  m_actionDigitizeCurve->setChecked(true);
3236  slotDigitizeCurve(); // Call the slot that the setChecked call fails to trigger
3237  break;
3238 
3239  case DIGITIZE_STATE_EMPTY:
3240  break;
3241 
3242  case DIGITIZE_STATE_POINT_MATCH:
3243  m_actionDigitizePointMatch->setChecked(true);
3244  slotDigitizePointMatch(); // Call the slot that the setChecked call fails to trigger
3245  break;
3246 
3247  case DIGITIZE_STATE_SEGMENT:
3248  m_actionDigitizeSegment->setChecked(true);
3249  slotDigitizeSegment(); // Call the slot that the setChecked call fails to trigger
3250  break;
3251 
3252  case DIGITIZE_STATE_SELECT:
3253  m_actionDigitizeSelect->setChecked(true);
3254  slotDigitizeSelect(); // Call the slot that the setChecked call fails to trigger
3255  break;
3256 
3257  default:
3258  LOG4CPP_ERROR_S ((*mainCat)) << "MainWindow::updateDigitizeStateIfSoftwareTriggered";
3259  break;
3260  }
3261 }
3262 
3264 {
3265  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateGraphicsLinesToMatchGraphicsPoints";
3266 
3268  m_transformation);
3269 }
3270 
3271 void MainWindow::updateRecentFileList()
3272 {
3273  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateRecentFileList";
3274 
3275  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
3276  QStringList recentFilePaths = settings.value(SETTINGS_RECENT_FILE_LIST).toStringList();
3277 
3278  // Determine the desired size of the path list
3279  unsigned int count = recentFilePaths.size();
3280  if (count > MAX_RECENT_FILE_LIST_SIZE) {
3281  count = MAX_RECENT_FILE_LIST_SIZE;
3282  }
3283 
3284  // Add visible entries
3285  unsigned int i;
3286  for (i = 0; i < count; i++) {
3287  QString strippedName = QFileInfo (recentFilePaths.at(i)).fileName();
3288  m_actionRecentFiles.at (i)->setText (strippedName);
3289  m_actionRecentFiles.at (i)->setData (recentFilePaths.at (i));
3290  m_actionRecentFiles.at (i)->setVisible (true);
3291  }
3292 
3293  // Hide any extra entries
3294  for (i = count; i < MAX_RECENT_FILE_LIST_SIZE; i++) {
3295  m_actionRecentFiles.at (i)->setVisible (false);
3296  }
3297 }
3298 
3300 {
3301  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsAxesChecker";
3302 
3303  m_cmdMediator->document().setModelAxesChecker(modelAxesChecker);
3304  if (m_transformation.transformIsDefined()) {
3305  m_transformationStateContext->triggerStateTransition(TRANSFORMATION_STATE_DEFINED,
3306  *m_cmdMediator,
3307  m_transformation,
3308  m_cmbCurve->currentText());
3309  } else {
3310  m_transformationStateContext->triggerStateTransition(TRANSFORMATION_STATE_UNDEFINED,
3311  *m_cmdMediator,
3312  m_transformation,
3313  m_cmbCurve->currentText());
3314  }
3315 }
3316 
3318 {
3319  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsColorFilter";
3320 
3321  m_cmdMediator->document().setModelColorFilter(modelColorFilter);
3322  m_backgroundStateContext->updateColorFilter (m_transformation,
3323  m_cmdMediator->document().modelGridRemoval(),
3324  modelColorFilter);
3325  m_digitizeStateContext->handleCurveChange ();
3327 }
3328 
3330 {
3331  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsCoords";
3332 
3333  m_cmdMediator->document().setModelCoords(modelCoords);
3334 }
3335 
3337 {
3338  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsCurveAddRemove";
3339 
3340  m_cmdMediator->document().setCurvesGraphs (curvesGraphs);
3341  loadCurveListFromCmdMediator();
3343 }
3344 
3346 {
3347  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsCurveStyles";
3348 
3349  m_scene->updateCurveStyles(modelCurveStyles);
3350  m_cmdMediator->document().setModelCurveStyles(modelCurveStyles);
3352 }
3353 
3355 {
3356  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsDigitizeCurve";
3357 
3358  m_cmdMediator->document().setModelDigitizeCurve(modelDigitizeCurve);
3359  m_digitizeStateContext->updateModelDigitizeCurve (modelDigitizeCurve);
3360 }
3361 
3363 {
3364  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsExportFormat";
3365 
3366  m_cmdMediator->document().setModelExport (modelExport);
3367 }
3368 
3370 {
3371  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsGeneral";
3372 
3373  m_cmdMediator->document().setModelGeneral(modelGeneral);
3374 }
3375 
3377 {
3378  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsGridRemoval";
3379 
3380  m_cmdMediator->document().setModelGridRemoval(modelGridRemoval);
3381 }
3382 
3383 void MainWindow::updateSettingsMainWindow()
3384 {
3385  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsMainWindow";
3386 
3387  if (m_modelMainWindow.zoomControl() == ZOOM_CONTROL_MENU_ONLY ||
3388  m_modelMainWindow.zoomControl() == ZOOM_CONTROL_MENU_WHEEL) {
3389 
3390  m_actionZoomIn->setShortcut (tr (""));
3391  m_actionZoomOut->setShortcut (tr (""));
3392 
3393  } else {
3394 
3395  m_actionZoomIn->setShortcut (tr ("+"));
3396  m_actionZoomOut->setShortcut (tr ("-"));
3397 
3398  }
3399 }
3400 
3402 {
3403  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsMainWindow";
3404 
3405  m_modelMainWindow = modelMainWindow;
3407 }
3408 
3410 {
3411  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsPointMatch";
3412 
3413  m_cmdMediator->document().setModelPointMatch(modelPointMatch);
3414 }
3415 
3417 {
3418  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsSegments";
3419 
3420  m_cmdMediator->document().setModelSegments(modelSegments);
3421  m_digitizeStateContext->updateModelSegments(modelSegments);
3422 }
3423 
3424 void MainWindow::updateTransformationAndItsDependencies()
3425 {
3426  m_transformation.update (!m_currentFile.isEmpty (),
3427  *m_cmdMediator,
3428  m_modelMainWindow);
3429 
3430  // Grid removal is affected by new transformation
3431  m_backgroundStateContext->setCurveSelected (m_transformation,
3432  m_cmdMediator->document().modelGridRemoval(),
3433  m_cmdMediator->document().modelColorFilter(),
3434  m_cmbCurve->currentText ());
3435 }
3436 
3437 void MainWindow::updateViewedCurves ()
3438 {
3439  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateViewedCurves";
3440 
3441  if (m_actionViewCurvesAll->isChecked ()) {
3442 
3443  m_scene->showCurves (true, true);
3444 
3445  } else if (m_actionViewCurvesSelected->isChecked ()) {
3446 
3447  m_scene->showCurves (true, false, selectedGraphCurve ());
3448 
3449  } else if (m_actionViewCurvesNone->isChecked ()) {
3450 
3451  m_scene->showCurves (false);
3452 
3453  } else {
3454  ENGAUGE_ASSERT (false);
3455  }
3456 }
3457 
3459 {
3460  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateViewsOfSettings";
3461 
3462  QString activeCurve = m_digitizeStateContext->activeCurve ();
3463 
3464  updateViewsOfSettings (activeCurve);
3465 }
3466 
3467 void MainWindow::updateViewsOfSettings (const QString &activeCurve)
3468 {
3469  if (activeCurve.isEmpty ()) {
3470 
3471  m_viewPointStyle->unsetPointStyle ();
3472  m_viewSegmentFilter->unsetColorFilterSettings ();
3473 
3474 
3475  } else {
3476 
3477  PointStyle pointStyle = m_cmdMediator->document().modelCurveStyles().curveStyle(activeCurve).pointStyle();
3478  m_viewPointStyle->setPointStyle (pointStyle);
3479 
3480  ColorFilterSettings colorFilterSettings = m_cmdMediator->document().modelColorFilter().colorFilterSettings(activeCurve);
3481  m_viewSegmentFilter->setColorFilterSettings (colorFilterSettings,
3482  m_cmdMediator->pixmap ());
3483 
3484  }
3485 }
3486 
3488 {
3489  ENGAUGE_CHECK_PTR (m_view);
3490  return *m_view;
3491 }
3492 
3494 {
3495  ENGAUGE_CHECK_PTR (m_view);
3496  return *m_view;
3497 }
3498 
3499 void MainWindow::wheelEvent(QWheelEvent *event)
3500 {
3501  const int ANGLE_THRESHOLD = 15; // From QWheelEvent documentation
3502  const int DELTAS_PER_DEGREE = 8; // From QWheelEvent documentation
3503 
3504  QPoint numDegrees = event->angleDelta() / DELTAS_PER_DEGREE;
3505 
3506  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::wheelEvent"
3507  << " degrees=" << numDegrees.y()
3508  << " phase=" << event->phase();
3509 
3510  if (m_modelMainWindow.zoomControl() == ZOOM_CONTROL_MENU_WHEEL ||
3511  m_modelMainWindow.zoomControl() == ZOOM_CONTROL_MENU_WHEEL_PLUSMINUS) {
3512 
3513  if (numDegrees.y() >= ANGLE_THRESHOLD) {
3514  // Rotated forwards away from the user, which means zoom out
3515  slotViewZoomOut();
3516  event->accept();
3517  } else if (numDegrees.y() <= -ANGLE_THRESHOLD) {
3518  // Rotated backwards towards the user, which means zoom in
3519  slotViewZoomIn();
3520  event->accept();
3521  }
3522  }
3523 }
3524 
3525 void MainWindow::writeCheckpointToLogFile ()
3526 {
3527  // Document
3528  QString checkpointDoc;
3529  QTextStream strDoc (&checkpointDoc);
3530  m_cmdMediator->document().printStream(INDENTATION_PAST_TIMESTAMP,
3531  strDoc);
3532 
3533  // Scene
3534  QString checkpointScene;
3535  QTextStream strScene (&checkpointScene);
3536  m_scene->printStream (INDENTATION_PAST_TIMESTAMP,
3537  strScene);
3538 
3539  // Skip slow string manipulation if BEFORE call to LOG4CPP_DEBUG_S
3540  if (mainCat->getPriority() == log4cpp::Priority::DEBUG) {
3541 
3542  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::writeCheckpointToLogFile\n"
3543  << "--------------DOCUMENT CHECKPOINT START----------" << "\n"
3544  << checkpointDoc.toLatin1().data()
3545  << "---------------DOCUMENT CHECKPOINT END-----------" << "\n"
3546  << "----------------SCENE CHECKPOINT START-----------" << "\n"
3547  << checkpointScene.toLatin1().data()
3548  << "-----------------SCENE CHECKPOINT END------------" ;
3549  }
3550 }
void updateGraphicsLinesToMatchGraphicsPoints(const CurveStyles &modelCurveStyles, const Transformation &transformation)
A mouse move has just occurred so move the selected points, since they were dragged.
void coordTextForStatusBar(QPointF cursorScreen, QString &coordsScreen, QString &coordsGraph, QString &resolutionGraph)
Return string descriptions of cursor coordinates for status bar.
Model for DlgSettingsGeneral and CmdSettingsGeneral.
void unsetPointStyle()
Apply no PointStyle.
void handleMouseMove(QPointF pos)
See DigitizeStateAbstractBase::handleMouseMove.
void setColorFilterSettings(const ColorFilterSettings &colorFilterSettings, const QPixmap &pixmap)
Apply the color filter of the currently selected curve. The pixmap is included so the background colo...
void printStream(QString indentation, QTextStream &str) const
Debugging method that supports print method of this class and printStream method of some other class(...
Definition: Document.cpp:752
void setCurveName(const QString &curveName)
Load information for the specified curve name. When called externally, the load method must have been...
Model for DlgSettingsPointMatch and CmdSettingsPointMatch.
Returns information about files.
Definition: LoadFileInfo.h:7
Color filter parameters for one curve. For a class, this is handled the same as LineStyle and PointSt...
void updateSettingsMainWindow(const MainWindowModel &modelMainWindow)
Update with new main window properties.
void setStatusBarMode(StatusBarMode statusBarMode)
Set the status bar visibility mode.
Definition: StatusBar.cpp:137
void resetOnLoad()
Reset, when loading a document after the first, to same state that first document was at when loaded...
DocumentModelColorFilter modelColorFilter() const
Get method for DocumentModelColorFilter.
Definition: Document.cpp:644
Command for cutting all selected Points.
Definition: CmdCut.h:12
void setModelAxesChecker(const DocumentModelAxesChecker &modelAxesChecker)
Set method for DocumentModelAxesChecker.
Definition: Document.cpp:860
void setModelGridRemoval(const DocumentModelGridRemoval &modelGridRemoval)
Set method for DocumentModelGridRemoval.
Definition: Document.cpp:916
void updateAfterCommand(CmdMediator &cmdMediator)
Update the Points and their Curves after executing a command.
void updateDigitizeStateIfSoftwareTriggered(DigitizeState digitizeState)
After software-triggered state transition, this method manually triggers the action as if user had cl...
void printStream(QString indentation, QTextStream &str)
Debugging method that supports print method of this class and printStream method of some other class(...
void saveXml(QXmlStreamWriter &writer) const
Serialize to xml.
Class that displays the current Segment Filter in a MainWindow toolbar.
Wrapper around OpenJPEG library, in C, for opening jpeg2000 files.
Definition: Jpeg2000.h:20
Dialog for editing Segments settings, for DigitizeStateSegment.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
void fitInView(GraphicsView &view)
Zoom so background fills the window.
void setModelPointMatch(const DocumentModelPointMatch &modelPointMatch)
Set method for DocumentModelPointMatch.
Definition: Document.cpp:921
Model for DlgSettingsExportFormat and CmdSettingsExportFormat.
Dialog for editing point match settings, for DigitizeStatePointMatch.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
QString templateHtml() const
Template html comprising the checklist for display.
Transformation transformation() const
Return read-only copy of transformation.
void setModelGeneral(const DocumentModelGeneral &modelGeneral)
Set method for DocumentModelGeneral.
Definition: Document.cpp:911
void setEnabled(bool enabled)
Show the style with semi-transparency or full-transparency to indicate if associated Curve is active ...
void setImageIsLoaded(bool imageIsLoaded)
Set the image so QGraphicsView cursor and drag mode are accessible.
Context class for transformation state machine.
Model for DlgSettingsCurveProperties and CmdSettingsCurveProperties.
Definition: CurveStyles.h:16
Dockable help window.
Definition: HelpWindow.h:7
void updateSettingsCurveAddRemove(const CurvesGraphs &curvesGraphs)
Update with new curves.
QString activeCurve() const
Curve name for active Curve. This can include AXIS_CURVE_NAME, and empty string.
void setModelSegments(const DocumentModelSegments &modelSegments)
Set method for DocumentModelSegments.
Definition: Document.cpp:926
void bindToCmdMediatorAndResetOnLoad(CmdMediator *cmdMediator)
Bind to CmdMediator class.
void updateAfterMouseRelease()
Call MainWindow::updateControls (which is private) after the very specific case - a mouse press/relea...
void updateModelDigitizeCurve(const DocumentModelDigitizeCurve &modelDigitizeCurve)
Update the digitize curve settings.
virtual void wheelEvent(QWheelEvent *event)
Convert wheel events into zoom in/out.
void setCoordinates(const QString &coordsScreen, const QString &coordsGraph, const QString &resolutionGraph)
Populate the coordinates fields. Unavailable values are empty. Html-encoding to highlight with colors...
Definition: StatusBar.cpp:118
QStringList selectedPointIdentifiers() const
Return a list of identifiers for the currently selected points.
void handleContextMenuEvent(const QString &pointIdentifier)
See DigitizeStateAbstractBase::handleContextMenuEvent.
void updateViewsOfSettings(const QString &activeCurve)
Update curve-specific view of settings. Private version gets active curve name from DigitizeStateCont...
QString selectedGraphCurve() const
Curve name that is currently selected in m_cmbCurve.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
void setModelDigitizeCurve(const DocumentModelDigitizeCurve &modelDigitizeCurve)
Set method for DocumentModelDigitizeCurve.
Definition: Document.cpp:901
CmdMediator & cmdMediator()
Accessor for commands to process the Document.
Definition: MainWindow.cpp:244
PointStyle pointStyle() const
Get method for PointStyle.
Definition: CurveStyle.cpp:69
void triggerStateTransition(TransformationState transformationState, CmdMediator &cmdMediator, const Transformation &transformation, const QString &selectedGraphCurve)
Trigger a state transition to be performed immediately.
QString xmlToUpload() const
Xml to be uploaded. Includes document if user has approved.
Document & document()
Provide the Document to commands, primarily for undo/redo processing.
Definition: CmdMediator.cpp:61
void setModelCoords(const DocumentModelCoords &modelCoords)
Set method for DocumentModelCoords.
Definition: Document.cpp:881
void wakeUp()
Enable all widgets in the status bar. This is called just after a Document becomes active...
Definition: StatusBar.cpp:268
BackgroundImage selectOriginal(BackgroundImage backgroundImage)
Make original background visible, for DigitizeStateColorPicker.
static void bindToMainWindow(const MainWindow *mainWindow)
Bind to MainWindow so this class can access the command stack.
Dialog for editing grid removal settings.
Dialog for editing exporting settings.
void setDelimiter(ExportDelimiter exportDelimiter)
Set method for delimiter.
void setLocale(QLocale::Language language, QLocale::Country country)
Set method for locale given attributes.
void uploadErrorReport(const QString &report)
Upload the error report asynchronously.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
void showTemporaryMessage(const QString &temporaryMessage)
Show temporary message in status bar.
Dialog for editing curve names settings.
bool load(const QString &filename, QImage &image) const
Load image from jpeg2000 file.
Definition: Jpeg2000.cpp:186
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
void updateSettingsDigitizeCurve(const DocumentModelDigitizeCurve &modelDigitizeCurve)
Update with new curve digitization styles.
void loadMainWindowModel(CmdMediator &cmdMediator, const MainWindowModel &modelMainWindow)
Replaced load method since the main window settings are independent of document, unlike other DlgSett...
Tutorial using a strategy like a comic strip with decision points deciding which panels appear...
Definition: TutorialDlg.h:13
bool isModified() const
Dirty flag.
Definition: CmdMediator.cpp:71
Strategy class for exporting to a file. This strategy is external to the Document class so that class...
Definition: ExportToFile.h:19
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
Dockable text window containing checklist guide.
void setModelExport(const DocumentModelExportFormat &modelExport)
Set method for DocumentModelExportFormat.
Definition: Document.cpp:906
Model for DlgSettingsDigitizeCurve and CmdSettingsDigitizeCurve.
GraphicsView & view()
View for the QImage and QGraphicsItems, without const.
Affine transformation between screen and graph coordinates, based on digitized axis points...
Dialog for editing filtering settings.
StatusBarMode statusBarMode() const
Current mode for status bar visibility. This is tracked locally so this class knows when to hide/show...
Definition: StatusBar.h:36
void setPixmap(const Transformation &transformation, const DocumentModelGridRemoval &modelGridRemoval, const DocumentModelColorFilter &modelColorFilter, const QPixmap &pixmapOriginal)
Update the images of all states, rather than just the current state.
ZoomControl zoomControl() const
Get method for zoom control.
QString fileExtensionTsv() const
File extension for tsv export files.
Details for a specific Point.
Definition: PointStyle.h:14
Container for all graph curves. The axes point curve is external to this class.
Definition: CurvesGraphs.h:18
void setBackgroundImage(BackgroundImage backgroundImage)
Transition to the specified state. This method is used by classes outside of the state machine to tri...
Model for DlgSettingsColorFilter and CmdSettingsColorFilter.
Wrapper around QStatusBar to manage permanent widgets.
Definition: StatusBar.h:15
GraphicsScene & scene()
Scene container for the QImage and QGraphicsItems.
void setEnabled(bool enabled)
Show the style with semi-transparency or full-transparency to indicate if associated Curve is active ...
void updateSettingsCurveStyles(const CurveStyles &modelCurveStyles)
Update with new curve styles.
Client for interacting with Engauge server.
Definition: NetworkClient.h:10
void setModelCurveStyles(const CurveStyles &modelCurveStyles)
Set method for CurveStyles.
Definition: Document.cpp:886
Context class that manages the background image state machine.
bool browserIsEmpty() const
When browser is empty, it is pointless to show it.
CurveStyles modelCurveStyles() const
Get method for CurveStyles.
Definition: Document.cpp:657
QGraphicsView class with event handling added. Typically the events are sent to the active digitizing...
Definition: GraphicsView.h:14
Container for all DigitizeStateAbstractBase subclasses. This functions as the context class in a stan...
Model for DlgSettingsMainWindow and CmdSettingsMainWindow.
bool canRedo() const
Return true if there is a command available.
void updateModelSegments(const DocumentModelSegments &modelSegments)
Update the segments given the new settings.
void resetOnLoad()
Reset, when loading a document after the first, to same state that first document was at when loaded...
Dialog for editing general settings.
void resetPositionHasChangedFlags()
Reset positionHasChanged flag for all items. Typically this is done as part of mousePressEvent.
QPixmap pixmap() const
See Document::pixmap.
Definition: CmdMediator.cpp:91
void setModelColorFilter(const DocumentModelColorFilter &modelColorFilter)
Set method for DocumentModelColorFilter.
Definition: Document.cpp:865
void close()
Open Document is being closed so remove the background.
QImage imageForCurveState() const
Image for the Curve state, even if the current state is different.
Model for DlgSettingsCoords and CmdSettingsCoords.
void updateAfterCommand()
See GraphicsScene::updateAfterCommand.
QString fileExtensionCsv() const
File extension for csv export files.
void updateSettingsColorFilter(const DocumentModelColorFilter &modelColorFilter)
Update with new color filter properties.
void setCurveSelected(const Transformation &transformation, const DocumentModelGridRemoval &modelGridRemoval, const DocumentModelColorFilter &modelColorFilter, const QString &curveSelected)
Update the selected curve.
Command for deleting all selected Points.
Definition: CmdDelete.h:12
Dialog for editing DigitizeStateCurve settings.
void updateSettingsAxesChecker(const DocumentModelAxesChecker &modelAxesChecker)
Update with new axes indicator properties.
void updateSettingsPointMatch(const DocumentModelPointMatch &modelPointMatch)
Update with new point match properties.
void updateSettingsGeneral(const DocumentModelGeneral &modelGeneral)
Update with new general properties.
void setPointStyle(const PointStyle &pointStyle)
Apply the PointStyle of the currently selected curve.
QImage imageFiltered() const
Background image that has been filtered for the current curve. This asserts if a curve-specific image...
void updateSettingsGridRemoval(const DocumentModelGridRemoval &modelGridRemoval)
Update with new grid removal properties.
Class that displays a view of the current Curve&#39;s point style.
void requestImmediateStateTransition(DigitizeState digitizeState)
Perform immediate state transition. Called from outside state machine.
void showTemporaryMessage(const QString &message)
Show temporary message in status bar. After a short interval the message will disappear.
Definition: StatusBar.cpp:147
void exportToFile(const DocumentModelExportFormat &modelExport, const Document &document, const MainWindowModel &modelMainWindow, const Transformation &transformation, QTextStream &str) const
Export Document points according to the settings.
void updateCurveStyles(const CurveStyles &modelCurveStyles)
Update curve styles after settings changed.
void unsetColorFilterSettings()
Apply no color filter.
Wizard for setting up the checklist guide.
const ColorFilterSettings colorFilterSettings(const QString &curveName) const
Get method for copying one color filter. Cannot return just a reference or else there is a warning ab...
Dialog for editing main window settings, which are entirely independent of all documents.
void handleLeave()
See DigitizeStateAbstractBase::handleLeave.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
void appendNewCmd(QUndoCommand *cmd)
Append just-created QUndoCommand to command stack. This is called from DigitizeStateAbstractBase subc...
bool transformIsDefined() const
Transform is defined when at least three axis points have been digitized.
Model for DlgSettingsAxesChecker and CmdSettingsAxesChecker.
QString filterTsv() const
QFileDialog filter for TSV files.
Command stack that shadows the CmdMediator command stack at startup when reading commands from an err...
void updateSettingsExportFormat(const DocumentModelExportFormat &modelExport)
Update with new export properties.
Dialog for editing coordinates settings.
Load QImage from url. This is trivial for a file, but requires an asynchronous download step for http...
QStringList curveNames() const
Curve names to be placed into Document.
virtual bool eventFilter(QObject *, QEvent *)
Catch secret keypresses.
void startLoadImage(const QUrl &url)
Start the asynchronous loading of an image from the specified url.
void load(CmdMediator &cmdMediator)
Load settings from Document.
bool loadsAsDigFile(const QString &urlString) const
Returns true if specified file name can be loaded as a DIG file.
void resetOnLoad()
Reset, when loading a document after the first, to same state that first document was at when loaded...
bool isGnuplot() const
Get method for gnuplot flag.
CurveStyle curveStyle(const QString &curveName) const
CurveStyle in specified curve.
Definition: CurveStyles.cpp:72
Dialog for editing curve properties settings.
void populateCurvesGraphs(CurvesGraphs &curvesGraphs)
Create entries in CurvesGraphs for each curve name that user provided.
void setZoomControl(ZoomControl zoomControl)
Set method for zoom control.
Command queue stack.
Definition: CmdMediator.h:16
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
void setZoomFactorInitial(ZoomFactorInitial zoomFactorInitial)
Set method for initial zoom factor.
void update(bool fileIsLoaded, const CmdMediator &cmdMediator, const MainWindowModel &modelMainWindow)
Update transform by iterating through the axis points.
void saveErrorReportFileAndExit(const char *comment, const char *file, int line, const char *context) const
Save error report and exit.
void signalZoom(int)
Send zoom selection, picked from menu or keystroke, to StatusBar.
Model for DlgSettingsSegments and CmdSettingsSegments.
void handleSetOverrideCursor(const QCursor &cursor)
See DigitizeStateAbstractBase::handleSetOverrideCursor.
MainWindow(const QString &errorReportFile, bool isGnuplot, QStringList loadStartupFiles, QWidget *parent=0)
Single constructor.
Definition: MainWindow.cpp:112
void updateColorFilter(const Transformation &transformation, const DocumentModelGridRemoval &modelGridRemoval, const DocumentModelColorFilter &colorFilter)
Apply color filter settings.
void setCurvesGraphs(const CurvesGraphs &curvesGraphs)
Let CmdAbstract classes overwrite CurvesGraphs.
Definition: Document.cpp:853
void updateAxesChecker(CmdMediator &cmdMediator, const Transformation &transformation)
Apply the new DocumentModelAxesChecker.
void resizeEvent(QResizeEvent *event)
Intercept resize event so graphics scene can be appropriately resized when in Fill mode...
QStringList supportedImageWildcards() const
List the supported jpeg2000 file extensions, for filtering import files.
Definition: Jpeg2000.cpp:299
void updateSettingsCoords(const DocumentModelCoords &modelCoords)
Update with new coordinate properties.
void loadCommands(MainWindow &mainWindow, Document &document, QXmlStreamReader &reader)
Load commands from serialized xml.
void update(const CmdMediator &cmdMediator, bool documentIsExported)
Update using current CmdMediator/Document state.
ZoomFactorInitial zoomFactorInitial() const
Get method for initial zoom factor.
void handleCurveChange()
See DigitizeStateAbstractBase::handleCurveChange.
Add point and line handling to generic QGraphicsScene.
Definition: GraphicsScene.h:25
QString filterCsv() const
QFileDialog filter for CSV files.
Command for moving all selected Points by a specified translation.
Definition: CmdCopy.h:12
void handleMouseRelease(QPointF pos)
See DigitizeStateAbstractBase::handleMouseRelease.
void saveXml(QXmlStreamWriter &writer) const
Save document to xml.
Definition: Document.cpp:816
QLocale locale() const
Get method for locale.
Model for DlgSettingsGridRemoval and CmdSettingsGridRemoval. The settings are unstable until the user...
void handleKeyPress(Qt::Key key, bool atLeastOneSelectedItem)
See DigitizeStateAbstractBase::handleKeyPress.
Dialog for sending error report.
QString reasonForUnsuccessfulRead() const
See Document::reasonForUnsuccessfulRead.
Definition: CmdMediator.cpp:98
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
void updateSettingsSegments(const DocumentModelSegments &modelSegments)
Update with new segments properties.
void showCurves(bool show, bool showAll=false, const QString &curveName="")
Show or hide all Curves (if showAll is true) or just the selected Curve (if showAll is false);...
Dialog for editing axes checker settings.
Dialog to be displayed whenever some operation or processing cannot be performed since the axis point...
void updateGraphicsLinesToMatchGraphicsPoints()
Update the graphics lines so they follow the graphics points, after a drag, addition, removal, and such.
DocumentModelGridRemoval modelGridRemoval() const
Get method for DocumentModelGridRemoval.
Definition: Document.cpp:680
MainWindowModel modelMainWindow() const
Get method for main window model.
QStringList curvesGraphsNames() const
See CurvesGraphs::curvesGraphsNames.
Definition: CmdMediator.cpp:51
void setTemplateHtml(const QString &html, const QStringList &curveNames)
Populate the browser with template html.
bool successfulRead() const
Wrapper for Document::successfulRead.
About Engauge dialog. This provides a hidden shortcut for triggering ENGAUGE_ASSERT.
Definition: DlgAbout.h:9
virtual void showEvent(QShowEvent *)
Processing performed after gui becomes available.
bool transformIsDefined() const
Return true if all three axis points have been defined.
void handleMousePress(QPointF pos)
See DigitizeStateAbstractBase::handleMousePress.