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