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