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