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  // Extract file extensions
1865  QString csvExtension = QString (".%1")
1866  .arg (exportStrategy.fileExtensionCsv());
1867  QString tsvExtension = QString (".%1")
1868  .arg (exportStrategy.fileExtensionTsv());
1869  QString fileExtensionVersusCsv = fileName.right (csvExtension.size());
1870  QString fileExtensionVersusTsv = fileName.right (tsvExtension.size());
1871 
1872  // Override if CSV or TSV was selected. We cannot use QFileDialog::selecedNameFilter() since that is
1873  // broken in Linux, so we use the file extension
1874  if (csvExtension.compare (fileExtensionVersusCsv, Qt::CaseInsensitive) == 0) {
1875  modelExportFormatAfter.setDelimiter (EXPORT_DELIMITER_COMMA);
1876  } else if (tsvExtension.compare (fileExtensionVersusTsv, Qt::CaseInsensitive) == 0) {
1877  modelExportFormatAfter.setDelimiter (EXPORT_DELIMITER_TAB);
1878  }
1879 
1880  return modelExportFormatAfter;
1881 }
1882 
1884 {
1885  return m_modelMainWindow;
1886 }
1887 
1888 void MainWindow::rebuildRecentFileListForCurrentFile(const QString &filePath)
1889 {
1890  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::rebuildRecentFileListForCurrentFile";
1891 
1892  setWindowFilePath (filePath);
1893 
1894  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
1895  QStringList recentFilePaths = settings.value (SETTINGS_RECENT_FILE_LIST).toStringList();
1896  recentFilePaths.removeAll (filePath); // Remove previous instance of the current filePath
1897  recentFilePaths.prepend (filePath); // Insert current filePath at start
1898  while (recentFilePaths.count () > (int) MAX_RECENT_FILE_LIST_SIZE) {
1899  recentFilePaths.removeLast (); // Remove entry since the number of entries exceeds the limit
1900  }
1901  settings.setValue (SETTINGS_RECENT_FILE_LIST, recentFilePaths);
1902 
1903  updateRecentFileList();
1904 }
1905 
1906 void MainWindow::resizeEvent(QResizeEvent * /* event */)
1907 {
1908  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::resizeEvent";
1909 
1910  if (m_actionZoomFill->isChecked ()) {
1911  slotViewZoomFill();
1912  }
1913 }
1914 
1915 bool MainWindow::saveDocumentFile (const QString &fileName)
1916 {
1917  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::saveDocumentFile fileName=" << fileName.toLatin1 ().data ();
1918 
1919  QFile file(fileName);
1920  if (!file.open(QFile::WriteOnly)) {
1921  QMessageBox::warning (this,
1922  engaugeWindowTitle(),
1923  QString ("%1 %2: \n%3.")
1924  .arg(tr ("Cannot write file"))
1925  .arg(fileName)
1926  .arg(file.errorString()));
1927  return false;
1928  }
1929 
1930  rebuildRecentFileListForCurrentFile (fileName);
1931 
1932  QApplication::setOverrideCursor (Qt::WaitCursor);
1933  QXmlStreamWriter writer(&file);
1934  writer.setAutoFormatting(true);
1935  writer.writeStartDocument();
1936  writer.writeDTD("<!DOCTYPE engauge>");
1937  m_cmdMediator->document().saveXml(writer);
1938  writer.writeEndDocument();
1939  QApplication::restoreOverrideCursor ();
1940 
1941  // Notify the undo stack that the current state is now considered "clean". This will automatically trigger a
1942  // signal back to this class that will update the modified marker in the title bar
1943  m_cmdMediator->setClean ();
1944 
1945  setCurrentFile(fileName);
1946  m_engaugeFile = fileName;
1947  updateAfterCommand (); // Enable Save button now that m_engaugeFile is set
1948  m_statusBar->showTemporaryMessage("File saved");
1949 
1950  return true;
1951 }
1952 
1953 void MainWindow::saveErrorReportFileAndExit (const char *context,
1954  const char *file,
1955  int line,
1956  const char *comment) const
1957 {
1958  if (m_cmdMediator != 0) {
1959 
1960  QString report = saveErrorReportFileAndExitXml (context,
1961  file,
1962  line,
1963  comment);
1964  DlgErrorReport dlg (report);
1965 
1966  // Ask user if report should be uploaded, and if the document is included when it is uploaded
1967  if (dlg.exec() == QDialog::Accepted) {
1968 
1969  // Upload the error report to the server
1970  m_networkClient->uploadErrorReport (dlg.xmlToUpload());
1971  }
1972  }
1973 }
1974 
1975 QString MainWindow::saveErrorReportFileAndExitXml (const char *context,
1976  const char *file,
1977  int line,
1978  const char *comment) const
1979 {
1980  const bool DEEP_COPY = true;
1981 
1982  QString xmlErrorReport;
1983  QXmlStreamWriter writer (&xmlErrorReport);
1984  writer.setAutoFormatting(true);
1985 
1986  // Entire error report contains metadata, commands and other details
1987  writer.writeStartElement(DOCUMENT_SERIALIZE_ERROR_REPORT);
1988 
1989  // Version
1990  writer.writeStartElement(DOCUMENT_SERIALIZE_APPLICATION);
1991  writer.writeAttribute(DOCUMENT_SERIALIZE_APPLICATION_VERSION_NUMBER, VERSION_NUMBER);
1992  writer.writeEndElement();
1993 
1994  // Document
1995  // Insert snapshot xml into writer stream, by reading from reader stream. Highest level of snapshot is DOCUMENT_SERIALIZE_APPLICATION
1996  QXmlStreamReader reader (m_startingDocumentSnapshot);
1997  while (!reader.atEnd ()) {
1998  reader.readNext ();
1999  if (reader.tokenType() != QXmlStreamReader::StartDocument &&
2000  reader.tokenType() != QXmlStreamReader::EndDocument) {
2001  writer.writeCurrentToken (reader);
2002  }
2003  }
2004 
2005  // Operating system
2006  writer.writeStartElement(DOCUMENT_SERIALIZE_OPERATING_SYSTEM);
2007  writer.writeAttribute(DOCUMENT_SERIALIZE_OPERATING_SYSTEM_ENDIAN, EndianToString (QSysInfo::ByteOrder));
2008  writer.writeAttribute(DOCUMENT_SERIALIZE_OPERATING_SYSTEM_WORD_SIZE, QString::number (QSysInfo::WordSize));
2009  writer.writeEndElement();
2010 
2011  // Placeholder for original file, before the commands in the command stack were applied
2012  writer.writeStartElement(DOCUMENT_SERIALIZE_FILE);
2013  writer.writeAttribute(DOCUMENT_SERIALIZE_FILE_IMPORTED,
2014  m_originalFileWasImported ? DOCUMENT_SERIALIZE_BOOL_TRUE : DOCUMENT_SERIALIZE_BOOL_FALSE);
2015  writer.writeEndElement();
2016 
2017  // Commands
2018  m_cmdMediator->saveXml(writer);
2019 
2020  // Error
2021  writer.writeStartElement(DOCUMENT_SERIALIZE_ERROR);
2022  writer.writeAttribute(DOCUMENT_SERIALIZE_ERROR_CONTEXT, context);
2023  writer.writeAttribute(DOCUMENT_SERIALIZE_ERROR_FILE, file);
2024  writer.writeAttribute(DOCUMENT_SERIALIZE_ERROR_LINE, QString::number (line));
2025  writer.writeAttribute(DOCUMENT_SERIALIZE_ERROR_COMMENT, comment);
2026  writer.writeEndElement();
2027 
2028  writer.writeEndElement();
2029 
2030  // Put string into DOM
2031  QDomDocument domErrorReport ("ErrorReport");
2032  domErrorReport.setContent (xmlErrorReport);
2033 
2034  // Postprocessing
2035  if (!m_originalFileWasImported) {
2036 
2037  // Insert the original file into its placeholder, by manipulating the source and target xml as DOM documents. Very early
2038  // in the loading process, the original file may not be specified yet (m_originalFile is empty)
2039  QDomDocument domInputFile;
2040  loadInputFileForErrorReport (domInputFile);
2041  QDomDocumentFragment fragmentFileFrom = domErrorReport.createDocumentFragment();
2042  if (!domInputFile.isNull()) {
2043  fragmentFileFrom.appendChild (domErrorReport.importNode (domInputFile.documentElement(), DEEP_COPY));
2044  }
2045  QDomNodeList nodesFileTo = domErrorReport.elementsByTagName (DOCUMENT_SERIALIZE_FILE);
2046  if (nodesFileTo.count () > 0) {
2047  QDomNode nodeFileTo = nodesFileTo.at (0);
2048  nodeFileTo.appendChild (fragmentFileFrom);
2049  }
2050 
2051  // Replace DOCUMENT_SERIALIZE_IMAGE by same node with CDATA removed, since:
2052  // 1) it is very big and working with smaller files, especially in emails, is easier
2053  // 2) removing the image better preserves user's privacy
2054  // 3) having the actual image does not help that much when debugging
2055  QDomNodeList nodesDocument = domErrorReport.elementsByTagName (DOCUMENT_SERIALIZE_DOCUMENT);
2056  for (int i = 0 ; i < nodesDocument.count(); i++) {
2057  QDomNode nodeDocument = nodesDocument.at (i);
2058  QDomElement elemImage = nodeDocument.firstChildElement(DOCUMENT_SERIALIZE_IMAGE);
2059  if (!elemImage.isNull()) {
2060 
2061  // Get old image attributes so we can create an empty document with the same size
2062  if (elemImage.hasAttribute (DOCUMENT_SERIALIZE_IMAGE_WIDTH) &&
2063  elemImage.hasAttribute (DOCUMENT_SERIALIZE_IMAGE_HEIGHT)) {
2064 
2065  int width = elemImage.attribute(DOCUMENT_SERIALIZE_IMAGE_WIDTH).toInt();
2066  int height = elemImage.attribute(DOCUMENT_SERIALIZE_IMAGE_HEIGHT).toInt();
2067 
2068  QDomNode nodeReplacement;
2069  QDomElement elemReplacement = nodeReplacement.toElement();
2070  elemReplacement.setAttribute (DOCUMENT_SERIALIZE_IMAGE_WIDTH, width);
2071  elemReplacement.setAttribute (DOCUMENT_SERIALIZE_IMAGE_HEIGHT, height);
2072 
2073  // Replace with the new and then remove the old
2074  nodeDocument.insertBefore (nodeReplacement,
2075  elemImage);
2076  nodeDocument.removeChild(elemImage);
2077  }
2078  }
2079  }
2080  }
2081 
2082  return domErrorReport.toString();
2083 }
2084 
2085 void MainWindow::saveStartingDocumentSnapshot()
2086 {
2087  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::saveStartingDocumentSnapshot";
2088 
2089  QXmlStreamWriter writer (&m_startingDocumentSnapshot);
2090  writer.setAutoFormatting (true);
2091  m_cmdMediator->document().saveXml (writer);
2092 }
2093 
2095 {
2096  ENGAUGE_CHECK_PTR (m_scene);
2097  return *m_scene;
2098 }
2099 
2100 BackgroundImage MainWindow::selectOriginal(BackgroundImage backgroundImage)
2101 {
2102  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::selectBackgroundOriginal";
2103 
2104  BackgroundImage previousBackground = (BackgroundImage) m_cmbBackground->currentData().toInt();
2105 
2106  int index = m_cmbBackground->findData (backgroundImage);
2107  ENGAUGE_ASSERT (index >= 0);
2108 
2109  m_cmbBackground->setCurrentIndex(index);
2110 
2111  return previousBackground;
2112 }
2113 
2115 {
2116  return m_cmbCurve->currentText ();
2117 }
2118 
2119 void MainWindow::setCurrentFile (const QString &fileName)
2120 {
2121  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::setCurrentFile";
2122 
2123  QString fileNameStripped;
2124  if (!fileName.isEmpty()) {
2125 
2126  // Strip out path and file extension
2127  QFileInfo fileInfo (fileName);
2128  fileNameStripped = fileInfo.baseName();
2129  }
2130 
2131  m_currentFile = fileNameStripped;
2132  m_currentFileWithPathAndFileExtension = fileName;
2133 
2134  updateWindowTitle ();
2135 }
2136 
2137 void MainWindow::setCurrentPathFromFile (const QString &fileName)
2138 {
2139  QDir dir = QFileInfo (fileName).absoluteDir();
2140 
2141  if (dir.exists ()) {
2142 
2143  bool success = QDir::setCurrent (dir.absolutePath ()); // Return to chosen directory the next time
2144  ENGAUGE_ASSERT (success);
2145 
2146  } else {
2147 
2148  // File was a url so it is irrelevant to the current directory
2149  }
2150 }
2151 
2152 void MainWindow::setPixmap (const QPixmap &pixmap)
2153 {
2154  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::setPixmap";
2155 
2156  m_digitizeStateContext->setImageIsLoaded (m_cmdMediator,
2157  true);
2158  m_backgroundStateContext->setPixmap (m_transformation,
2159  m_cmdMediator->document().modelGridRemoval(),
2160  m_cmdMediator->document().modelColorFilter(),
2161  pixmap);
2162 }
2163 
2164 void MainWindow::settingsRead ()
2165 {
2166  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
2167 
2168  settingsReadEnvironment (settings);
2169  settingsReadMainWindow (settings);
2170 }
2171 
2172 void MainWindow::settingsReadEnvironment (QSettings &settings)
2173 {
2174  settings.beginGroup (SETTINGS_GROUP_ENVIRONMENT);
2175  QDir::setCurrent (settings.value (SETTINGS_CURRENT_DIRECTORY,
2176  QDir::currentPath ()).toString ());
2177  settings.endGroup ();
2178 }
2179 
2180 void MainWindow::settingsReadMainWindow (QSettings &settings)
2181 {
2182  settings.beginGroup(SETTINGS_GROUP_MAIN_WINDOW);
2183 
2184  // Main window geometry
2185  resize (settings.value (SETTINGS_SIZE,
2186  QSize (400, 400)).toSize ());
2187  move (settings.value (SETTINGS_POS,
2188  QPoint (200, 200)).toPoint ());
2189 
2190  // Help window geometry
2191  QSize helpSize = settings.value (SETTINGS_HELP_SIZE,
2192  QSize (900, 600)).toSize();
2193  m_helpWindow->resize (helpSize);
2194  if (settings.contains (SETTINGS_HELP_POS)) {
2195  QPoint helpPos = settings.value (SETTINGS_HELP_POS).toPoint();
2196  m_helpWindow->move (helpPos);
2197  }
2198 
2199  // Checklist guide wizard
2200  m_actionHelpChecklistGuideWizard->setChecked (settings.value (SETTINGS_CHECKLIST_GUIDE_WIZARD,
2201  true).toBool ());
2202 
2203  // Background toolbar visibility
2204  bool viewBackgroundToolBar = settings.value (SETTINGS_VIEW_BACKGROUND_TOOLBAR,
2205  true).toBool ();
2206  m_actionViewBackground->setChecked (viewBackgroundToolBar);
2207  m_toolBackground->setVisible (viewBackgroundToolBar);
2208  BackgroundImage backgroundImage = (BackgroundImage) settings.value (SETTINGS_BACKGROUND_IMAGE,
2209  BACKGROUND_IMAGE_FILTERED).toInt ();
2210  int indexBackground = m_cmbBackground->findData (QVariant (backgroundImage));
2211  m_cmbBackground->setCurrentIndex (indexBackground);
2212 
2213  // Digitize toolbar visibility
2214  bool viewDigitizeToolBar = settings.value (SETTINGS_VIEW_DIGITIZE_TOOLBAR,
2215  true).toBool ();
2216  m_actionViewDigitize->setChecked (viewDigitizeToolBar);
2217  m_toolDigitize->setVisible (viewDigitizeToolBar);
2218 
2219  // Views toolbar visibility
2220  bool viewSettingsViewsToolBar = settings.value (SETTINGS_VIEW_SETTINGS_VIEWS_TOOLBAR,
2221  true).toBool ();
2222  m_actionViewSettingsViews->setChecked (viewSettingsViewsToolBar);
2223  m_toolSettingsViews->setVisible (viewSettingsViewsToolBar);
2224 
2225  // Coordinate system toolbar visibility
2226  bool viewCoordSystemToolbar = settings.value (SETTINGS_VIEW_COORD_SYSTEM_TOOLBAR,
2227  false).toBool ();
2228  m_actionViewCoordSystem->setChecked (viewCoordSystemToolbar);
2229  m_toolCoordSystem->setVisible (viewCoordSystemToolbar);
2230 
2231  // Tooltips visibility
2232  bool viewToolTips = settings.value (SETTINGS_VIEW_TOOL_TIPS,
2233  true).toBool ();
2234  m_actionViewToolTips->setChecked (viewToolTips);
2235  loadToolTips ();
2236 
2237  // Statusbar visibility
2238  StatusBarMode statusBarMode = (StatusBarMode) settings.value (SETTINGS_VIEW_STATUS_BAR,
2239  false).toInt ();
2240  m_statusBar->setStatusBarMode (statusBarMode);
2241  m_actionStatusNever->setChecked (statusBarMode == STATUS_BAR_MODE_NEVER);
2242  m_actionStatusTemporary->setChecked (statusBarMode == STATUS_BAR_MODE_TEMPORARY);
2243  m_actionStatusAlways->setChecked (statusBarMode == STATUS_BAR_MODE_ALWAYS);
2244 
2245  // Checklist guide is docked or undocked. Default is undocked so user knows it can be undocked
2246  Qt::DockWidgetArea area = (Qt::DockWidgetArea) settings.value (SETTINGS_CHECKLIST_GUIDE_DOCK_AREA,
2247  Qt::NoDockWidgetArea).toInt();
2248 
2249  if (area == Qt::NoDockWidgetArea) {
2250 
2251  addDockWidget (Qt::RightDockWidgetArea,
2252  m_dockChecklistGuide); // Add on the right to prevent error message, then immediately make undocked
2253  m_dockChecklistGuide->setFloating(true); // Undock
2254  if (settings.contains (SETTINGS_CHECKLIST_GUIDE_DOCK_GEOMETRY)) {
2255  m_dockChecklistGuide->restoreGeometry (settings.value (SETTINGS_CHECKLIST_GUIDE_DOCK_GEOMETRY).toByteArray());
2256  }
2257 
2258  } else {
2259 
2260  addDockWidget (area,
2261  m_dockChecklistGuide);
2262 
2263  }
2264 
2265  // Main window settings. Preference for initial zoom factor is 100%, rather than fill mode, for issue #25. Some or all
2266  // settings are saved to the application AND saved to m_modelMainWindow for use in DlgSettingsMainWindow
2267  QLocale localeDefault;
2268  QLocale::Language language = (QLocale::Language) settings.value (SETTINGS_LOCALE_LANGUAGE,
2269  QVariant (localeDefault.language())).toInt();
2270  QLocale::Country country = (QLocale::Country) settings.value (SETTINGS_LOCALE_COUNTRY,
2271  QVariant (localeDefault.country())).toInt();
2272  QLocale locale (language,
2273  country);
2274  slotViewZoom ((ZoomFactor) settings.value (SETTINGS_ZOOM_FACTOR,
2275  QVariant (ZOOM_1_TO_1)).toInt());
2276  m_modelMainWindow.setLocale (locale);
2277  m_modelMainWindow.setZoomFactorInitial((ZoomFactorInitial) settings.value (SETTINGS_ZOOM_FACTOR_INITIAL,
2278  QVariant (DEFAULT_ZOOM_FACTOR_INITIAL)).toInt());
2279  m_modelMainWindow.setZoomControl ((ZoomControl) settings.value (SETTINGS_ZOOM_CONTROL,
2280  QVariant (ZOOM_CONTROL_MENU_WHEEL_PLUSMINUS)).toInt());
2281  m_modelMainWindow.setMainTitleBarFormat ((MainTitleBarFormat) settings.value (SETTINGS_MAIN_TITLE_BAR_FORMAT,
2282  QVariant (MAIN_TITLE_BAR_FORMAT_PATH)).toInt());
2284 
2285  settings.endGroup();
2286 }
2287 
2288 void MainWindow::settingsWrite ()
2289 {
2290  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
2291 
2292  settings.beginGroup (SETTINGS_GROUP_ENVIRONMENT);
2293  settings.setValue (SETTINGS_CURRENT_DIRECTORY, QDir::currentPath ());
2294  settings.endGroup ();
2295 
2296  settings.beginGroup (SETTINGS_GROUP_MAIN_WINDOW);
2297  settings.setValue (SETTINGS_SIZE, size ());
2298  settings.setValue (SETTINGS_POS, pos ());
2299  settings.setValue (SETTINGS_HELP_SIZE, m_helpWindow->size());
2300  settings.setValue (SETTINGS_HELP_POS, m_helpWindow->pos ());
2301  if (m_dockChecklistGuide->isFloating()) {
2302 
2303  settings.setValue (SETTINGS_CHECKLIST_GUIDE_DOCK_AREA, Qt::NoDockWidgetArea);
2304  settings.setValue (SETTINGS_CHECKLIST_GUIDE_DOCK_GEOMETRY, m_dockChecklistGuide->saveGeometry ());
2305 
2306  } else {
2307 
2308  settings.setValue (SETTINGS_CHECKLIST_GUIDE_DOCK_AREA, dockWidgetArea (m_dockChecklistGuide));
2309 
2310  }
2311  settings.setValue (SETTINGS_CHECKLIST_GUIDE_WIZARD, m_actionHelpChecklistGuideWizard->isChecked ());
2312  settings.setValue (SETTINGS_LOCALE_LANGUAGE, m_modelMainWindow.locale().language());
2313  settings.setValue (SETTINGS_LOCALE_COUNTRY, m_modelMainWindow.locale().country());
2314  settings.setValue (SETTINGS_VIEW_BACKGROUND_TOOLBAR, m_actionViewBackground->isChecked());
2315  settings.setValue (SETTINGS_BACKGROUND_IMAGE, m_cmbBackground->currentData().toInt());
2316  settings.setValue (SETTINGS_VIEW_DIGITIZE_TOOLBAR, m_actionViewDigitize->isChecked ());
2317  settings.setValue (SETTINGS_VIEW_STATUS_BAR, m_statusBar->statusBarMode ());
2318  settings.setValue (SETTINGS_VIEW_SETTINGS_VIEWS_TOOLBAR, m_actionViewSettingsViews->isChecked ());
2319  settings.setValue (SETTINGS_VIEW_COORD_SYSTEM_TOOLBAR, m_actionViewCoordSystem->isChecked ());
2320  settings.setValue (SETTINGS_VIEW_TOOL_TIPS, m_actionViewToolTips->isChecked ());
2321  settings.setValue (SETTINGS_ZOOM_CONTROL, m_modelMainWindow.zoomControl());
2322  settings.setValue (SETTINGS_ZOOM_FACTOR, currentZoomFactor ());
2323  settings.setValue (SETTINGS_ZOOM_FACTOR_INITIAL, m_modelMainWindow.zoomFactorInitial());
2324  settings.setValue (SETTINGS_MAIN_TITLE_BAR_FORMAT, m_modelMainWindow.mainTitleBarFormat());
2325  settings.endGroup ();
2326 }
2327 
2328 bool MainWindow::setupAfterLoad (const QString &fileName,
2329  const QString &temporaryMessage ,
2330  ImportType importType)
2331 {
2332  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::setupAfterLoad"
2333  << " file=" << fileName.toLatin1().data()
2334  << " message=" << temporaryMessage.toLatin1().data()
2335  << " importType=" << importType;
2336 
2337  const QString EMPTY_CURVE_NAME_TO_SKIP_BACKGROUND_PROCESSING; // For bootstrapping the preview
2338 
2339  // At this point the code assumes CmdMediator for the NEW Document is already stored in m_cmdMediator
2340 
2341  m_digitizeStateContext->resetOnLoad (m_cmdMediator); // Before setPixmap
2342  m_backgroundStateContext->setCurveSelected (m_transformation,
2343  m_cmdMediator->document().modelGridRemoval(),
2344  m_cmdMediator->document().modelColorFilter(),
2345  EMPTY_CURVE_NAME_TO_SKIP_BACKGROUND_PROCESSING); // Before setPixmap
2346  setPixmap (m_cmdMediator->pixmap ()); // Set background immediately so it is visible as a preview when any dialogs are displayed
2347 
2348  // Image is visible now so the user can refer to it when we ask for the number of coordinate systems. Note that the Document
2349  // may already have multiple CoordSystem if user loaded a file that had multiple CoordSystem entries
2350  if (importType == IMPORT_TYPE_ADVANCED) {
2351 
2352  applyZoomFactorAfterLoad(); // Apply the currently selected zoom factor
2353 
2354  DlgImportAdvanced dlgImportAdvanced (*this);
2355  dlgImportAdvanced.exec();
2356 
2357  if (dlgImportAdvanced.result() == QDialog::Rejected) {
2358  return false;
2359  }
2360 
2361  int numberCoordSystem = dlgImportAdvanced.numberCoordSystem();
2362  m_cmdMediator->document().addCoordSystems (numberCoordSystem - 1);
2363  m_cmdMediator->setDocumentAxesPointsRequired (dlgImportAdvanced.documentAxesPointsRequired());
2364  }
2365 
2366  m_transformation.resetOnLoad();
2367  m_transformationStateContext->resetOnLoad();
2368  m_scene->resetOnLoad();
2369 
2370  connect (m_actionEditUndo, SIGNAL (triggered ()), m_cmdMediator, SLOT (undo ()));
2371  connect (m_actionEditUndo, SIGNAL (triggered ()), m_cmdStackShadow, SLOT (slotUndo ()));
2372  connect (m_actionEditRedo, SIGNAL (triggered ()), m_cmdMediator, SLOT (redo ())); // No effect until CmdMediator::undo and CmdStackShadow::slotUndo get called
2373  connect (m_actionEditRedo, SIGNAL (triggered ()), m_cmdStackShadow, SLOT (slotRedo ())); // No effect after CmdMediator::undo and CmdStackShadow::slotUndo get called
2374  connect (m_cmdMediator, SIGNAL (canRedoChanged(bool)), this, SLOT (slotCanRedoChanged (bool)));
2375  connect (m_cmdMediator, SIGNAL (canUndoChanged(bool)), this, SLOT (slotCanUndoChanged (bool)));
2376  connect (m_cmdMediator, SIGNAL (redoTextChanged (const QString &)), this, SLOT (slotRedoTextChanged (const QString &)));
2377  connect (m_cmdMediator, SIGNAL (undoTextChanged (const QString &)), this, SLOT (slotUndoTextChanged (const QString &)));
2378  loadCurveListFromCmdMediator ();
2379  loadCoordSystemListFromCmdMediator ();
2381 
2382  m_isDocumentExported = false;
2383 
2384  // Background must be set (by setPixmap) before slotViewZoomFill which relies on the background. At this point
2385  // the transformation is undefined (unless the code is changed) so grid removal will not work
2386  // but updateTransformationAndItsDependencies will call this again to fix that issue. Note that the selected
2387  // curve name was set (by setCurveSelected) earlier before the call to setPixmap
2388  m_backgroundStateContext->setCurveSelected (m_transformation,
2389  m_cmdMediator->document().modelGridRemoval(),
2390  m_cmdMediator->document().modelColorFilter(),
2391  m_cmbCurve->currentText ());
2392  m_backgroundStateContext->setBackgroundImage ((BackgroundImage) m_cmbBackground->currentIndex ());
2393 
2394  applyZoomFactorAfterLoad(); // Zoom factor must be reapplied after background image is set, to have any effect
2395 
2396  setCurrentFile(fileName);
2397  m_statusBar->showTemporaryMessage (temporaryMessage);
2398  m_statusBar->wakeUp ();
2399 
2400  saveStartingDocumentSnapshot();
2401 
2402  updateAfterCommand(); // Replace stale points by points in new Document
2403 
2404  return true;
2405 }
2406 
2407 void MainWindow::showEvent (QShowEvent *event)
2408 {
2409  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::showEvent"
2410  << " files=" << m_loadStartupFiles.join (",").toLatin1().data();
2411 
2412  QMainWindow::showEvent (event);
2413 
2414  if (m_loadStartupFiles.count() > 0) {
2415 
2416  m_timerLoadStartupFiles = new QTimer;
2417  m_timerLoadStartupFiles->setSingleShot (true);
2418  connect (m_timerLoadStartupFiles, SIGNAL (timeout ()), this, SLOT (slotLoadStartupFiles ()));
2419  m_timerLoadStartupFiles->start (0); // Zero delay still waits until execution finishes and gui is available
2420 
2421  }
2422 }
2423 
2424 void MainWindow::showTemporaryMessage (const QString &temporaryMessage)
2425 {
2426  m_statusBar->showTemporaryMessage (temporaryMessage);
2427 }
2428 
2429 void MainWindow::slotBtnPrintAll ()
2430 {
2431  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotBtnPrintAll";
2432 
2433  ghostsCreate ();
2434 
2435  QPrinter printer (QPrinter::HighResolution);
2436  QPrintDialog dlg (&printer, this);
2437  if (dlg.exec() == QDialog::Accepted) {
2438  QPainter painter (&printer);
2439  m_view->render (&painter);
2440  painter.end();
2441  }
2442 
2443  ghostsDestroy ();
2444 }
2445 
2446 void MainWindow::slotBtnShowAllPressed ()
2447 {
2448  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotBtnShowAllPressed";
2449 
2450  // Start of press-release sequence
2451  ghostsCreate ();
2452 }
2453 
2454 void MainWindow::slotBtnShowAllReleased ()
2455 {
2456  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotBtnShowAllReleased";
2457 
2458  // End of press-release sequence
2459  ghostsDestroy ();
2460 }
2461 
2462 void MainWindow::slotCanRedoChanged (bool canRedo)
2463 {
2464  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotCanRedoChanged";
2465 
2466  m_actionEditRedo->setEnabled (canRedo || m_cmdStackShadow->canRedo());
2467 }
2468 
2469 void MainWindow::slotCanUndoChanged (bool canUndo)
2470 {
2471  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotCanUndoChanged";
2472 
2473  m_actionEditUndo->setEnabled (canUndo);
2474 }
2475 
2476 void MainWindow::slotChecklistClosed()
2477 {
2478  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotChecklistClosed";
2479 
2480  m_actionViewChecklistGuide->setChecked (false);
2481 }
2482 
2483 void MainWindow::slotCleanChanged(bool clean)
2484 {
2485  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotCleanChanged";
2486 
2487  setWindowModified (!clean);
2488 }
2489 
2490 void MainWindow::slotCmbBackground(int currentIndex)
2491 {
2492  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotCmbBackground";
2493 
2494  switch (currentIndex) {
2495  case BACKGROUND_IMAGE_NONE:
2496  if (!m_actionViewBackgroundNone->isChecked()) {
2497  m_actionViewBackgroundNone->toggle();
2498  }
2499  break;
2500 
2501  case BACKGROUND_IMAGE_ORIGINAL:
2502  if (!m_actionViewBackgroundOriginal->isChecked ()) {
2503  m_actionViewBackgroundOriginal->toggle();
2504  }
2505  break;
2506 
2507  case BACKGROUND_IMAGE_FILTERED:
2508  if (!m_actionViewBackgroundFiltered->isChecked ()) {
2509  m_actionViewBackgroundFiltered->toggle();
2510  }
2511  break;
2512  }
2513 
2514  m_backgroundStateContext->setBackgroundImage ((BackgroundImage) currentIndex);
2515 }
2516 
2517 void MainWindow::slotCmbCoordSystem(int index)
2518 {
2519  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotCmbCoordSystem";
2520 
2521  CmdSelectCoordSystem *cmd = new CmdSelectCoordSystem (*this,
2522  m_cmdMediator->document(),
2523  index);
2524 
2525  m_cmdMediator->push (cmd);
2526 }
2527 
2528 void MainWindow::slotCmbCurve(int /* index */)
2529 {
2530  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotCmbCurve";
2531 
2532  m_backgroundStateContext->setCurveSelected (m_transformation,
2533  m_cmdMediator->document().modelGridRemoval(),
2534  m_cmdMediator->document().modelColorFilter(),
2535  m_cmbCurve->currentText ());
2536  m_digitizeStateContext->handleCurveChange (m_cmdMediator);
2537 
2538  updateViewedCurves();
2540 }
2541 
2542 void MainWindow::slotContextMenuEvent (QString pointIdentifier)
2543 {
2544  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotContextMenuEvent point=" << pointIdentifier.toLatin1 ().data ();
2545 
2546  m_digitizeStateContext->handleContextMenuEvent (m_cmdMediator,
2547  pointIdentifier);
2548 }
2549 
2550 void MainWindow::slotDigitizeAxis ()
2551 {
2552  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeAxis";
2553 
2554  m_digitizeStateContext->requestImmediateStateTransition (m_cmdMediator,
2555  DIGITIZE_STATE_AXIS);
2556  m_cmbCurve->setEnabled (false); // Graph curve is irrelevant in this mode
2557  m_viewPointStyle->setEnabled (true); // Point style is important in this mode
2558  m_viewSegmentFilter->setEnabled (true); // Filtering is important in this mode
2559 }
2560 
2561 void MainWindow::slotDigitizeColorPicker ()
2562 {
2563  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeColorPicker";
2564 
2565  m_digitizeStateContext->requestImmediateStateTransition (m_cmdMediator,
2566  DIGITIZE_STATE_COLOR_PICKER);
2567  m_cmbCurve->setEnabled (true);
2568  m_viewPointStyle->setEnabled (true);
2569  m_viewSegmentFilter->setEnabled (true);
2570 }
2571 
2572 void MainWindow::slotDigitizeCurve ()
2573 {
2574  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeCurve";
2575 
2576  m_digitizeStateContext->requestImmediateStateTransition (m_cmdMediator,
2577  DIGITIZE_STATE_CURVE);
2578  m_cmbCurve->setEnabled (true);
2579  m_viewPointStyle->setEnabled (true);
2580  m_viewSegmentFilter->setEnabled (true);
2581 }
2582 
2583 void MainWindow::slotDigitizePointMatch ()
2584 {
2585  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizePointMatch";
2586 
2587  m_digitizeStateContext->requestImmediateStateTransition (m_cmdMediator,
2588  DIGITIZE_STATE_POINT_MATCH);
2589  m_cmbCurve->setEnabled (true);
2590  m_viewPointStyle->setEnabled (true);
2591  m_viewSegmentFilter->setEnabled (true);
2592 }
2593 
2594 void MainWindow::slotDigitizeSegment ()
2595 {
2596  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeSegment";
2597 
2598  m_digitizeStateContext->requestImmediateStateTransition (m_cmdMediator,
2599  DIGITIZE_STATE_SEGMENT);
2600  m_cmbCurve->setEnabled (true);
2601  m_viewPointStyle->setEnabled (true);
2602  m_viewSegmentFilter->setEnabled (true);
2603 }
2604 
2605 void MainWindow::slotDigitizeSelect ()
2606 {
2607  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeSelect";
2608 
2609  m_digitizeStateContext->requestImmediateStateTransition (m_cmdMediator,
2610  DIGITIZE_STATE_SELECT);
2611  m_cmbCurve->setEnabled (false);
2612  m_viewPointStyle->setEnabled (false);
2613  m_viewSegmentFilter->setEnabled (false);
2614 }
2615 
2616 void MainWindow::slotEditCopy ()
2617 {
2618  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditCopy";
2619 
2620  CmdCopy *cmd = new CmdCopy (*this,
2621  m_cmdMediator->document(),
2622  m_scene->selectedPointIdentifiers ());
2623  m_digitizeStateContext->appendNewCmd (m_cmdMediator,
2624  cmd);
2625 }
2626 
2627 void MainWindow::slotEditCut ()
2628 {
2629  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditCut";
2630 
2631  CmdCut *cmd = new CmdCut (*this,
2632  m_cmdMediator->document(),
2633  m_scene->selectedPointIdentifiers ());
2634  m_digitizeStateContext->appendNewCmd (m_cmdMediator,
2635  cmd);
2636 }
2637 
2638 void MainWindow::slotEditDelete ()
2639 {
2640  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditDelete";
2641 
2642  CmdDelete *cmd = new CmdDelete (*this,
2643  m_cmdMediator->document(),
2644  m_scene->selectedPointIdentifiers ());
2645  m_digitizeStateContext->appendNewCmd (m_cmdMediator,
2646  cmd);
2647 }
2648 
2649 void MainWindow::slotEditMenu ()
2650 {
2651  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditMenu";
2652 
2653  m_actionEditPasteAsNew->setEnabled (!QApplication::clipboard()->image().isNull());
2654  m_actionEditPasteAsNewAdvanced->setEnabled (!QApplication::clipboard()->image().isNull());
2655 }
2656 
2657 void MainWindow::slotEditPaste ()
2658 {
2659  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditPaste";
2660 }
2661 
2662 void MainWindow::slotEditPasteAsNew ()
2663 {
2664  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditPasteAsNew";
2665 
2666  filePaste (IMPORT_TYPE_SIMPLE);
2667 }
2668 
2669 void MainWindow::slotEditPasteAsNewAdvanced ()
2670 {
2671  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditPasteAsNewAdvanced";
2672 
2673  filePaste (IMPORT_TYPE_ADVANCED);
2674 }
2675 
2676 void MainWindow::slotFileClose()
2677 {
2678  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileClose";
2679 
2680  if (maybeSave ()) {
2681 
2682  // Transition from defined to undefined. This must be after the clearing of the screen
2683  // since the axes checker screen item (and maybe others) must still exist
2684  m_transformationStateContext->triggerStateTransition(TRANSFORMATION_STATE_UNDEFINED,
2685  *m_cmdMediator,
2686  m_transformation,
2687  selectedGraphCurve());
2688 
2689  // Transition to empty state so an inadvertent mouse press does not trigger, for example,
2690  // the creation of an axis point on a non-existent GraphicsScene (=crash)
2691  m_digitizeStateContext->requestImmediateStateTransition (m_cmdMediator,
2692  DIGITIZE_STATE_EMPTY);
2693 
2694  // Remove screen objects
2695  m_scene->resetOnLoad ();
2696 
2697  // Remove background
2698  m_backgroundStateContext->close ();
2699 
2700  // Remove scroll bars if they exist
2701  m_scene->setSceneRect (QRectF (0, 0, 1, 1));
2702 
2703  // Deallocate Document
2704  delete m_cmdMediator;
2705 
2706  // Remove file information
2707  m_cmdMediator = 0;
2708  m_currentFile = "";
2709  m_engaugeFile = "";
2710  setWindowTitle (engaugeWindowTitle ());
2711 
2712  updateControls();
2713  }
2714 }
2715 
2716 void MainWindow::slotFileExport ()
2717 {
2718  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileExport";
2719 
2720  if (m_transformation.transformIsDefined()) {
2721 
2722  ExportToFile exportStrategy;
2723  QString filter = QString ("%1;;%2;;All files (*.*)")
2724  .arg (exportStrategy.filterCsv ())
2725  .arg (exportStrategy.filterTsv ());
2726  QString defaultFileName = QString ("%1/%2.%3")
2727  .arg (QDir::currentPath ())
2728  .arg (m_currentFile)
2729  .arg (exportStrategy.fileExtensionCsv ());
2730  QFileDialog dlg;
2731  QString filterCsv = exportStrategy.filterCsv ();
2732  QString fileName = dlg.getSaveFileName (this,
2733  tr("Export"),
2734  defaultFileName,
2735  filter,
2736  &filterCsv);
2737  if (!fileName.isEmpty ()) {
2738 
2739  fileExport(fileName,
2740  exportStrategy);
2741  }
2742  } else {
2743  DlgRequiresTransform dlg ("Export");
2744  dlg.exec ();
2745  }
2746 }
2747 
2748 void MainWindow::slotFileImport ()
2749 {
2750  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileImport";
2751 
2752  fileImportWithPrompts (IMPORT_TYPE_SIMPLE);
2753 }
2754 
2755 void MainWindow::slotFileImportAdvanced ()
2756 {
2757  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileImportAdvanced";
2758 
2759  fileImportWithPrompts (IMPORT_TYPE_ADVANCED);
2760 }
2761 
2762 void MainWindow::slotFileImportDraggedImage(QImage image)
2763 {
2764  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileImportDraggedImage";
2765 
2766  // No need to check return value from loadImage since there are no prompts that give the user a chance to cancel
2767  loadImage ("",
2768  image,
2769  IMPORT_TYPE_SIMPLE);
2770 }
2771 
2772 void MainWindow::slotFileImportDraggedImageUrl(QUrl url)
2773 {
2774  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileImportDraggedImageUrl url=" << url.toString ().toLatin1 ().data ();
2775 
2776  m_loadImageFromUrl->startLoadImage (url);
2777 }
2778 
2779 void MainWindow::slotFileImportImage(QString fileName, QImage image)
2780 {
2781  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileImportImage fileName=" << fileName.toLatin1 ().data ();
2782 
2783  // No need to check return value from loadImage since there are no prompts that give the user a chance to cancel
2784  loadImage (fileName,
2785  image,
2786  IMPORT_TYPE_SIMPLE);
2787 }
2788 
2789 void MainWindow::slotFileOpen()
2790 {
2791  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileOpen";
2792 
2793  if (maybeSave ()) {
2794 
2795  // Allow selection of files with strange suffixes in case the file extension was changed. Since
2796  // the default is the first filter, the wildcard filter is added afterwards (it is the off-nominal case)
2797  QString filter = QString ("%1 (*.%2);; All Files (*.*)")
2798  .arg (ENGAUGE_FILENAME_DESCRIPTION)
2799  .arg (ENGAUGE_FILENAME_EXTENSION);
2800 
2801  QString fileName = QFileDialog::getOpenFileName (this,
2802  tr("Open Document"),
2803  QDir::currentPath (),
2804  filter);
2805  if (!fileName.isEmpty ()) {
2806 
2807  loadDocumentFile (fileName);
2808 
2809  }
2810  }
2811 }
2812 
2813 void MainWindow::slotFileOpenDraggedDigFile (QString fileName)
2814 {
2815  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileOpenDraggedDigFile";
2816 
2817  loadDocumentFile (fileName);
2818 }
2819 
2820 void MainWindow::slotFilePrint()
2821 {
2822  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFilePrint";
2823 
2824  QPrinter printer (QPrinter::HighResolution);
2825  QPrintDialog dlg (&printer, this);
2826  if (dlg.exec() == QDialog::Accepted) {
2827  QPainter painter (&printer);
2828  m_view->render (&painter);
2829  painter.end();
2830  }
2831 }
2832 
2833 bool MainWindow::slotFileSave()
2834 {
2835  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileSave";
2836 
2837  if (m_engaugeFile.isEmpty()) {
2838  return slotFileSaveAs();
2839  } else {
2840  return saveDocumentFile (m_engaugeFile);
2841  }
2842 }
2843 
2844 bool MainWindow::slotFileSaveAs()
2845 {
2846  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileSaveAs";
2847 
2848  // Append engauge file extension if it is not already there
2849  QString filenameDefault = m_currentFile;
2850  if (!m_currentFile.endsWith (ENGAUGE_FILENAME_EXTENSION)) {
2851  filenameDefault = QString ("%1.%2")
2852  .arg (m_currentFile)
2853  .arg (ENGAUGE_FILENAME_EXTENSION);
2854  }
2855 
2856  if (!m_engaugeFile.isEmpty()) {
2857  filenameDefault = m_engaugeFile;
2858  }
2859 
2860  QString filterDigitizer = QString ("%1 (*.%2)")
2861  .arg (ENGAUGE_FILENAME_DESCRIPTION)
2862  .arg (ENGAUGE_FILENAME_EXTENSION);
2863  QString filterAll ("All files (*. *)");
2864 
2865  QStringList filters;
2866  filters << filterDigitizer;
2867  filters << filterAll;
2868 
2869  QFileDialog dlg(this);
2870  dlg.selectNameFilter (filterDigitizer);
2871  dlg.setNameFilters (filters);
2872  dlg.setWindowModality(Qt::WindowModal);
2873  dlg.setAcceptMode(QFileDialog::AcceptSave);
2874  dlg.selectFile(filenameDefault);
2875  if (dlg.exec()) {
2876 
2877  QStringList files = dlg.selectedFiles();
2878  return saveDocumentFile(files.at(0));
2879  }
2880 
2881  return false;
2882 }
2883 
2884 void MainWindow::slotHelpAbout()
2885 {
2886  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotHelpAbout";
2887 
2888  DlgAbout dlg (*this);
2889  dlg.exec ();
2890 }
2891 
2892 void MainWindow::slotHelpTutorial()
2893 {
2894  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotHelpTutorial";
2895 
2896  m_tutorialDlg->show ();
2897  m_tutorialDlg->exec ();
2898 }
2899 
2900 void MainWindow::slotKeyPress (Qt::Key key,
2901  bool atLeastOneSelectedItem)
2902 {
2903  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotKeyPress"
2904  << " key=" << QKeySequence (key).toString().toLatin1 ().data ()
2905  << " atLeastOneSelectedItem=" << (atLeastOneSelectedItem ? "true" : "false");
2906 
2907  m_digitizeStateContext->handleKeyPress (m_cmdMediator,
2908  key,
2909  atLeastOneSelectedItem);
2910 }
2911 
2912 void MainWindow::slotLeave ()
2913 {
2914  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotLeave";
2915 
2916  m_digitizeStateContext->handleLeave (m_cmdMediator);
2917 }
2918 
2919 void MainWindow::slotLoadStartupFiles ()
2920 {
2921  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotLoadStartupFiles";
2922 
2923  ENGAUGE_ASSERT (m_loadStartupFiles.count() > 0);
2924 
2925  QString fileName = m_loadStartupFiles.front(); // Get next file name
2926  m_loadStartupFiles.pop_front(); // Remove next file name
2927 
2928  // Load next file into this instance of Engauge
2929  LoadFileInfo loadFileInfo;
2930  if (loadFileInfo.loadsAsDigFile(fileName)) {
2931 
2932  loadDocumentFile (fileName);
2933 
2934  } else {
2935 
2936  fileImport (fileName,
2937  IMPORT_TYPE_SIMPLE);
2938 
2939  }
2940 
2941  if (m_loadStartupFiles.count() > 0) {
2942 
2943  // Fork off another instance of this application to handle the remaining files recursively. New process
2944  // is detached so killing/terminating this process does not automatically kill the child process(es) also
2945  QProcess::startDetached (QCoreApplication::applicationFilePath(),
2946  m_loadStartupFiles);
2947  }
2948 }
2949 
2950 void MainWindow::slotMouseMove (QPointF pos)
2951 {
2952 // LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotMouseMove pos=" << QPointFToString (pos).toLatin1 ().data ();
2953 
2954  // Ignore mouse moves before Document is loaded
2955  if (m_cmdMediator != 0) {
2956 
2957  // Get status bar coordinates
2958  QString coordsScreen, coordsGraph, resolutionGraph;
2959  m_transformation.coordTextForStatusBar (pos,
2960  coordsScreen,
2961  coordsGraph,
2962  resolutionGraph);
2963 
2964  // Update status bar coordinates
2965  m_statusBar->setCoordinates (coordsScreen,
2966  coordsGraph,
2967  resolutionGraph);
2968 
2969  // There used to be a call to updateGraphicsLinesToMatchGraphicsPoints here, but that resulted
2970  // in hundreds of gratuitous log messages as the cursor was moved around, and nothing important happened
2971 
2972  m_digitizeStateContext->handleMouseMove (m_cmdMediator,
2973  pos);
2974  }
2975 }
2976 
2977 void MainWindow::slotMousePress (QPointF pos)
2978 {
2979  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotMousePress";
2980 
2981  m_scene->resetPositionHasChangedFlags();
2982 
2983  m_digitizeStateContext->handleMousePress (m_cmdMediator,
2984  pos);
2985 }
2986 
2987 void MainWindow::slotMouseRelease (QPointF pos)
2988 {
2989  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotMouseRelease";
2990 
2991  if (pos.x() < 0 || pos.y() < 0) {
2992 
2993  // Cursor is outside the image so drop this event. However, call updateControls since this may be
2994  // a click-and-drag to select in which case the controls (especially Copy and Cut) reflect the new selection
2995  updateControls ();
2996 
2997  } else {
2998 
2999  // Cursor is within the image so process this as a normal mouse release
3000  m_digitizeStateContext->handleMouseRelease (m_cmdMediator,
3001  pos);
3002  }
3003 }
3004 
3005 void MainWindow::slotRecentFileAction ()
3006 {
3007  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotRecentFileAction";
3008 
3009  QAction *action = qobject_cast<QAction*>(sender ());
3010 
3011  if (action) {
3012  QString fileName = action->data().toString();
3013  loadDocumentFile (fileName);
3014  }
3015 }
3016 
3017 void MainWindow::slotRecentFileClear ()
3018 {
3019  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotRecentFileClear";
3020 
3021  QStringList emptyList;
3022 
3023  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
3024  settings.setValue (SETTINGS_RECENT_FILE_LIST,
3025  emptyList);
3026 
3027  updateRecentFileList();
3028 }
3029 
3030 void MainWindow::slotRedoTextChanged (const QString &text)
3031 {
3032  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotRedoTextChanged";
3033 
3034  QString completeText ("Redo");
3035  if (!text.isEmpty ()) {
3036  completeText += QString (" \"%1\"").arg (text);
3037  }
3038  m_actionEditRedo->setText (completeText);
3039 }
3040 
3041 void MainWindow::slotSetOverrideCursor (QCursor cursor)
3042 {
3043  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSetOverrideCursor";
3044 
3045  m_digitizeStateContext->handleSetOverrideCursor (m_cmdMediator,
3046  cursor);
3047 }
3048 
3049 void MainWindow::slotSettingsAxesChecker ()
3050 {
3051  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsAxesChecker";
3052 
3053  m_dlgSettingsAxesChecker->load (*m_cmdMediator);
3054  m_dlgSettingsAxesChecker->show ();
3055 }
3056 
3057 void MainWindow::slotSettingsColorFilter ()
3058 {
3059  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsColorFilter";
3060 
3061  m_dlgSettingsColorFilter->load (*m_cmdMediator);
3062  m_dlgSettingsColorFilter->show ();
3063 }
3064 
3065 void MainWindow::slotSettingsCoords ()
3066 {
3067  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsCoords";
3068 
3069  m_dlgSettingsCoords->load (*m_cmdMediator);
3070  m_dlgSettingsCoords->show ();
3071 }
3072 
3073 void MainWindow::slotSettingsCurveAddRemove ()
3074 {
3075  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsCurveAddRemove";
3076 
3077  m_dlgSettingsCurveAddRemove->load (*m_cmdMediator);
3078  m_dlgSettingsCurveAddRemove->show ();
3079 }
3080 
3081 void MainWindow::slotSettingsCurveProperties ()
3082 {
3083  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsCurveProperties";
3084 
3085  m_dlgSettingsCurveProperties->load (*m_cmdMediator);
3086  m_dlgSettingsCurveProperties->setCurveName (selectedGraphCurve ());
3087  m_dlgSettingsCurveProperties->show ();
3088 }
3089 
3090 void MainWindow::slotSettingsDigitizeCurve ()
3091 {
3092  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsDigitizeCurve";
3093 
3094  m_dlgSettingsDigitizeCurve->load (*m_cmdMediator);
3095  m_dlgSettingsDigitizeCurve->show ();
3096 }
3097 
3098 void MainWindow::slotSettingsExportFormat ()
3099 {
3100  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsExportFormat";
3101 
3102  if (transformIsDefined()) {
3103  m_dlgSettingsExportFormat->load (*m_cmdMediator);
3104  m_dlgSettingsExportFormat->show ();
3105  } else {
3106  DlgRequiresTransform dlg ("Export settings");
3107  dlg.exec();
3108  }
3109 }
3110 
3111 void MainWindow::slotSettingsGeneral ()
3112 {
3113  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsGeneral";
3114 
3115  m_dlgSettingsGeneral->load (*m_cmdMediator);
3116  m_dlgSettingsGeneral->show ();
3117 }
3118 
3119 void MainWindow::slotSettingsGridRemoval ()
3120 {
3121  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsGridRemoval";
3122 
3123  m_dlgSettingsGridRemoval->load (*m_cmdMediator);
3124  m_dlgSettingsGridRemoval->show ();
3125 }
3126 
3127 void MainWindow::slotSettingsPointMatch ()
3128 {
3129  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsPointMatch";
3130 
3131  m_dlgSettingsPointMatch->load (*m_cmdMediator);
3132  m_dlgSettingsPointMatch->show ();
3133 }
3134 
3135 void MainWindow::slotSettingsSegments ()
3136 {
3137  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsSegments";
3138 
3139  m_dlgSettingsSegments->load (*m_cmdMediator);
3140  m_dlgSettingsSegments->show ();
3141 }
3142 
3143 void MainWindow::slotSettingsMainWindow ()
3144 {
3145  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsMainWindow";
3146 
3147  m_dlgSettingsMainWindow->loadMainWindowModel (*m_cmdMediator,
3148  m_modelMainWindow);
3149  m_dlgSettingsMainWindow->show ();
3150 }
3151 
3152 void MainWindow::slotTimeoutRegressionErrorReport ()
3153 {
3154  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotTimeoutRegressionErrorReport"
3155  << " cmdStackIndex=" << m_cmdMediator->index()
3156  << " cmdStackCount=" << m_cmdMediator->count();
3157 
3158  if (m_cmdStackShadow->canRedo()) {
3159 
3160  m_cmdStackShadow->slotRedo();
3161 
3162  } else {
3163 
3164  exportAllCoordinateSystems ();
3165 
3166  // Regression test has finished so exit. We unset the dirty flag so there is no prompt
3167  m_cmdMediator->setClean();
3168  close();
3169 
3170  }
3171 }
3172 
3173 void MainWindow::slotTimeoutRegressionFileCmdScript ()
3174 {
3175  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotTimeoutRegressionFileCmdScript";
3176 
3177  if (m_fileCmdScript->canRedo()) {
3178 
3179  m_fileCmdScript->redo(*this);
3180 
3181  } else {
3182 
3183  // Script file might already have closed the Document so export only if last was not closed
3184  if (m_cmdMediator != 0) {
3185 
3186  exportAllCoordinateSystems ();
3187 
3188  // We unset the dirty flag so there is no "Save changes?" prompt
3189  m_cmdMediator->setClean();
3190 
3191  }
3192 
3193  // Regression test has finished so exit
3194  close();
3195 
3196  }
3197 }
3198 
3199 void MainWindow::slotUndoTextChanged (const QString &text)
3200 {
3201  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotUndoTextChanged";
3202 
3203  QString completeText ("Undo");
3204  if (!text.isEmpty ()) {
3205  completeText += QString (" \"%1\"").arg (text);
3206  }
3207  m_actionEditUndo->setText (completeText);
3208 }
3209 
3210 void MainWindow::slotViewGroupBackground(QAction *action)
3211 {
3212  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewGroupBackground";
3213 
3214  // Set the combobox
3215  BackgroundImage backgroundImage;
3216  int indexBackground;
3217  if (action == m_actionViewBackgroundNone) {
3218  indexBackground = m_cmbBackground->findData (QVariant (BACKGROUND_IMAGE_NONE));
3219  backgroundImage = BACKGROUND_IMAGE_NONE;
3220  } else if (action == m_actionViewBackgroundOriginal) {
3221  indexBackground = m_cmbBackground->findData (QVariant (BACKGROUND_IMAGE_ORIGINAL));
3222  backgroundImage = BACKGROUND_IMAGE_ORIGINAL;
3223  } else if (action == m_actionViewBackgroundFiltered) {
3224  indexBackground = m_cmbBackground->findData (QVariant (BACKGROUND_IMAGE_FILTERED));
3225  backgroundImage = BACKGROUND_IMAGE_FILTERED;
3226  } else {
3227  ENGAUGE_ASSERT (false);
3228 
3229  // Defaults if assert is disabled so execution continues
3230  indexBackground = m_cmbBackground->findData (QVariant (BACKGROUND_IMAGE_ORIGINAL));
3231  backgroundImage = BACKGROUND_IMAGE_ORIGINAL;
3232  }
3233 
3234  m_cmbBackground->setCurrentIndex (indexBackground);
3235  m_backgroundStateContext->setBackgroundImage (backgroundImage);
3236 }
3237 
3238 void MainWindow::slotViewGroupCurves(QAction * /* action */)
3239 {
3240  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewGroupCurves";
3241 
3242  updateViewedCurves ();
3243 }
3244 
3245 void MainWindow::slotViewGroupStatus(QAction *action)
3246 {
3247  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewGroupStatus";
3248 
3249  ENGAUGE_CHECK_PTR (m_statusBar); // At startup, make sure status bar is already set up when View menu gets initialized
3250 
3251  if (action == m_actionStatusNever) {
3252  m_statusBar->setStatusBarMode(STATUS_BAR_MODE_NEVER);
3253  } else if (action == m_actionStatusTemporary) {
3254  m_statusBar->setStatusBarMode(STATUS_BAR_MODE_TEMPORARY);
3255  } else {
3256  m_statusBar->setStatusBarMode(STATUS_BAR_MODE_ALWAYS);
3257  }
3258 }
3259 
3260 void MainWindow::slotViewToolBarBackground ()
3261 {
3262  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarBackground";
3263 
3264  if (m_actionViewBackground->isChecked ()) {
3265  m_toolBackground->show();
3266  } else {
3267  m_toolBackground->hide();
3268  }
3269 }
3270 
3271 void MainWindow::slotViewToolBarChecklistGuide ()
3272 {
3273  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarChecklistGuide";
3274 
3275  if (m_actionViewChecklistGuide->isChecked ()) {
3276  m_dockChecklistGuide->show();
3277  } else {
3278  m_dockChecklistGuide->hide();
3279  }
3280 }
3281 
3282 void MainWindow::slotViewToolBarCoordSystem ()
3283 {
3284  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarCoordSystem";
3285 
3286  if (m_actionViewCoordSystem->isChecked ()) {
3287  m_toolCoordSystem->show();
3288  } else {
3289  m_toolCoordSystem->hide();
3290  }
3291 }
3292 
3293 void MainWindow::slotViewToolBarDigitize ()
3294 {
3295  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarDigitize";
3296 
3297  if (m_actionViewDigitize->isChecked ()) {
3298  m_toolDigitize->show();
3299  } else {
3300  m_toolDigitize->hide();
3301  }
3302 }
3303 
3304 void MainWindow::slotViewToolBarSettingsViews ()
3305 {
3306  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarSettingsViews";
3307 
3308  if (m_actionViewSettingsViews->isChecked ()) {
3309  m_toolSettingsViews->show();
3310  } else {
3311  m_toolSettingsViews->hide();
3312  }
3313 }
3314 
3315 void MainWindow::slotViewToolTips ()
3316 {
3317  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolTips";
3318 
3319  loadToolTips();
3320 }
3321 
3322 void MainWindow::slotViewZoom(int zoom)
3323 {
3324  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoom";
3325 
3326  // Update zoom controls and apply the zoom factor
3327  switch ((ZoomFactor) zoom) {
3328  case ZOOM_16_TO_1:
3329  m_actionZoom16To1->setChecked(true);
3330  slotViewZoom16To1 ();
3331  break;
3332  case ZOOM_8_TO_1:
3333  m_actionZoom8To1->setChecked(true);
3334  slotViewZoom8To1 ();
3335  break;
3336  case ZOOM_4_TO_1:
3337  m_actionZoom4To1->setChecked(true);
3338  slotViewZoom4To1 ();
3339  break;
3340  case ZOOM_2_TO_1:
3341  m_actionZoom2To1->setChecked(true);
3342  slotViewZoom2To1 ();
3343  break;
3344  case ZOOM_1_TO_1:
3345  m_actionZoom1To1->setChecked(true);
3346  slotViewZoom1To1 ();
3347  break;
3348  case ZOOM_1_TO_2:
3349  m_actionZoom1To2->setChecked(true);
3350  slotViewZoom1To2 ();
3351  break;
3352  case ZOOM_1_TO_4:
3353  m_actionZoom1To4->setChecked(true);
3354  slotViewZoom1To4 ();
3355  break;
3356  case ZOOM_1_TO_8:
3357  m_actionZoom1To8->setChecked(true);
3358  slotViewZoom1To8 ();
3359  break;
3360  case ZOOM_1_TO_16:
3361  m_actionZoom1To16->setChecked(true);
3362  slotViewZoom1To16 ();
3363  break;
3364  case ZOOM_FILL:
3365  m_actionZoomFill->setChecked(true);
3366  slotViewZoomFill ();
3367  break;
3368  }
3369 }
3370 
3371 void MainWindow::slotViewZoom16To1 ()
3372 {
3373  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoom16To1";
3374 
3375  QTransform transform;
3376  transform.scale (16.0, 16.0);
3377  m_view->setTransform (transform);
3378  emit signalZoom(ZOOM_16_TO_1);
3379 }
3380 
3381 void MainWindow::slotViewZoom8To1 ()
3382 {
3383  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoom8To1";
3384 
3385  QTransform transform;
3386  transform.scale (8.0, 8.0);
3387  m_view->setTransform (transform);
3388  emit signalZoom(ZOOM_8_TO_1);
3389 }
3390 
3391 void MainWindow::slotViewZoom4To1 ()
3392 {
3393  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoom4To1";
3394 
3395  QTransform transform;
3396  transform.scale (4.0, 4.0);
3397  m_view->setTransform (transform);
3398  emit signalZoom(ZOOM_4_TO_1);
3399 }
3400 
3401 void MainWindow::slotViewZoom2To1 ()
3402 {
3403  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotZoom2To1";
3404 
3405  QTransform transform;
3406  transform.scale (2.0, 2.0);
3407  m_view->setTransform (transform);
3408  emit signalZoom(ZOOM_2_TO_1);
3409 }
3410 
3411 void MainWindow::slotViewZoom1To1 ()
3412 {
3413  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoom1To1";
3414 
3415  QTransform transform;
3416  transform.scale (1.0, 1.0);
3417  m_view->setTransform (transform);
3418  emit signalZoom(ZOOM_1_TO_1);
3419 }
3420 
3421 void MainWindow::slotViewZoom1To2 ()
3422 {
3423  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotZoom1To2";
3424 
3425  QTransform transform;
3426  transform.scale (0.5, 0.5);
3427  m_view->setTransform (transform);
3428  emit signalZoom(ZOOM_1_TO_2);
3429 }
3430 
3431 void MainWindow::slotViewZoom1To4 ()
3432 {
3433  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotZoom1To4";
3434 
3435  QTransform transform;
3436  transform.scale (0.25, 0.25);
3437  m_view->setTransform (transform);
3438  emit signalZoom(ZOOM_1_TO_4);
3439 }
3440 
3441 void MainWindow::slotViewZoom1To8 ()
3442 {
3443  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotZoom1To8";
3444 
3445  QTransform transform;
3446  transform.scale (0.125, 0.125);
3447  m_view->setTransform (transform);
3448  emit signalZoom(ZOOM_1_TO_8);
3449 }
3450 
3451 void MainWindow::slotViewZoom1To16 ()
3452 {
3453  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotZoom1To16";
3454 
3455  QTransform transform;
3456  transform.scale (0.0625, 0.0625);
3457  m_view->setTransform (transform);
3458  emit signalZoom(ZOOM_1_TO_16);
3459 }
3460 
3461 void MainWindow::slotViewZoomFill ()
3462 {
3463  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoomFill";
3464 
3465  m_backgroundStateContext->fitInView (*m_view);
3466 
3467  emit signalZoom(ZOOM_FILL);
3468 }
3469 
3470 void MainWindow::slotViewZoomIn ()
3471 {
3472  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoomIn";
3473 
3474  // Try to zoom in. First determine what the next zoom factor should be
3475 
3476  bool goto16To1 = false, goto8To1 = false, goto4To1 = false, goto2To1 = false;
3477  bool goto1To1 = false;
3478  bool goto1To2 = false, goto1To4 = false, goto1To8 = false, goto1To16 = false;
3479  if (m_actionZoomFill->isChecked ()) {
3480 
3481  // Zooming in means user probably wants the more squished direction to be zoomed in by one step
3482  double xScale = m_view->transform().m11();
3483  double yScale = m_view->transform().m22();
3484  double scale = qMin(xScale, yScale);
3485  if (scale < 0.125) {
3486  goto1To8 = true;
3487  } else if (scale < 0.25) {
3488  goto1To4 = true;
3489  } else if (scale < 0.5) {
3490  goto1To2 = true;
3491  } else if (scale < 1) {
3492  goto1To1 = true;
3493  } else if (scale < 2) {
3494  goto2To1 = true;
3495  } else if (scale < 4) {
3496  goto4To1 = true;
3497  } else if (scale < 8) {
3498  goto8To1 = true;
3499  } else {
3500  goto1To16 = true;
3501  }
3502  } else {
3503  goto16To1 = m_actionZoom8To1->isChecked ();
3504  goto8To1 = m_actionZoom4To1->isChecked ();
3505  goto4To1 = m_actionZoom2To1->isChecked ();
3506  goto2To1 = m_actionZoom1To1->isChecked ();
3507  goto1To1 = m_actionZoom1To2->isChecked ();
3508  goto1To2 = m_actionZoom1To4->isChecked ();
3509  goto1To4 = m_actionZoom1To8->isChecked ();
3510  goto1To8 = m_actionZoom1To16->isChecked ();
3511  }
3512 
3513  // Update controls and apply zoom factor
3514  if (goto16To1) {
3515  m_actionZoom16To1->setChecked (true);
3516  slotViewZoom16To1 ();
3517  } else if (goto8To1) {
3518  m_actionZoom8To1->setChecked (true);
3519  slotViewZoom8To1 ();
3520  } else if (goto4To1) {
3521  m_actionZoom4To1->setChecked (true);
3522  slotViewZoom4To1 ();
3523  } else if (goto2To1) {
3524  m_actionZoom2To1->setChecked (true);
3525  slotViewZoom2To1 ();
3526  } else if (goto1To1) {
3527  m_actionZoom1To1->setChecked (true);
3528  slotViewZoom1To1 ();
3529  } else if (goto1To2) {
3530  m_actionZoom1To2->setChecked (true);
3531  slotViewZoom1To2 ();
3532  } else if (goto1To4) {
3533  m_actionZoom1To4->setChecked (true);
3534  slotViewZoom1To4 ();
3535  } else if (goto1To8) {
3536  m_actionZoom1To8->setChecked (true);
3537  slotViewZoom1To8 ();
3538  } else if (goto1To16) {
3539  m_actionZoom1To16->setChecked (true);
3540  slotViewZoom1To16 ();
3541  }
3542 }
3543 
3544 void MainWindow::slotViewZoomInFromWheelEvent ()
3545 {
3546  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoomInFromWheelEvent";
3547 
3548  if ((m_modelMainWindow.zoomControl() == ZOOM_CONTROL_MENU_WHEEL) ||
3549  (m_modelMainWindow.zoomControl() == ZOOM_CONTROL_MENU_WHEEL_PLUSMINUS)) {
3550 
3551  // Forward this event
3552  slotViewZoomIn ();
3553  }
3554 }
3555 
3556 void MainWindow::slotViewZoomOut ()
3557 {
3558  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoomOut";
3559 
3560  // Try to zoom out. First determine what the next zoom factor should be
3561 
3562  bool goto16To1 = false, goto8To1 = false, goto4To1 = false, goto2To1 = false;
3563  bool goto1To1 = false;
3564  bool goto1To2 = false, goto1To4 = false, goto1To8 = false, goto1To16 = false;
3565  if (m_actionZoomFill->isChecked ()) {
3566 
3567  // Zooming out means user probably wants the less squished direction to be zoomed out by one step
3568  double xScale = m_view->transform().m11();
3569  double yScale = m_view->transform().m22();
3570  double scale = qMax(xScale, yScale);
3571  if (scale > 8) {
3572  goto8To1 = true;
3573  } else if (scale > 4) {
3574  goto4To1 = true;
3575  } else if (scale > 2) {
3576  goto2To1 = true;
3577  } else if (scale > 1) {
3578  goto1To1 = true;
3579  } else if (scale > 0.5) {
3580  goto1To2 = true;
3581  } else if (scale > 0.25) {
3582  goto1To4 = true;
3583  } else if (scale > 0.125) {
3584  goto1To8 = true;
3585  } else {
3586  goto1To16 = true;
3587  }
3588  } else {
3589  goto8To1 = m_actionZoom16To1->isChecked ();
3590  goto4To1 = m_actionZoom8To1->isChecked ();
3591  goto2To1 = m_actionZoom4To1->isChecked ();
3592  goto1To1 = m_actionZoom2To1->isChecked ();
3593  goto1To2 = m_actionZoom1To1->isChecked ();
3594  goto1To4 = m_actionZoom1To2->isChecked ();
3595  goto1To8 = m_actionZoom1To4->isChecked ();
3596  goto1To16 = m_actionZoom1To8->isChecked ();
3597  }
3598 
3599  // Update controls and apply zoom factor
3600  if (goto1To16) {
3601  m_actionZoom1To16->setChecked (true);
3602  slotViewZoom1To16 ();
3603  } else if (goto1To8) {
3604  m_actionZoom1To8->setChecked (true);
3605  slotViewZoom1To8 ();
3606  } else if (goto1To4) {
3607  m_actionZoom1To4->setChecked (true);
3608  slotViewZoom1To4 ();
3609  } else if (goto1To2) {
3610  m_actionZoom1To2->setChecked (true);
3611  slotViewZoom1To2 ();
3612  } else if (goto1To1) {
3613  m_actionZoom1To1->setChecked (true);
3614  slotViewZoom1To1 ();
3615  } else if (goto2To1) {
3616  m_actionZoom2To1->setChecked (true);
3617  slotViewZoom2To1 ();
3618  } else if (goto4To1) {
3619  m_actionZoom4To1->setChecked (true);
3620  slotViewZoom4To1 ();
3621  } else if (goto8To1) {
3622  m_actionZoom8To1->setChecked (true);
3623  slotViewZoom8To1 ();
3624  } else if (goto16To1) {
3625  m_actionZoom16To1->setChecked (true);
3626  slotViewZoom16To1 ();
3627  }
3628 }
3629 
3630 void MainWindow::slotViewZoomOutFromWheelEvent ()
3631 {
3632  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoomOutFromWheelEvent";
3633 
3634  if ((m_modelMainWindow.zoomControl() == ZOOM_CONTROL_MENU_WHEEL) ||
3635  (m_modelMainWindow.zoomControl() == ZOOM_CONTROL_MENU_WHEEL_PLUSMINUS)) {
3636 
3637  // Forward this event
3638  slotViewZoomOut ();
3639  }
3640 }
3641 
3642 void MainWindow::startRegressionTestErrorReport(const QString &regressionInputFile)
3643 {
3644  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::startRegressionTestErrorReport";
3645 
3646  const int REGRESSION_INTERVAL = 400; // Milliseconds
3647 
3648  // Save output/export file name
3649  m_regressionFile = exportFilenameFromInputFilename (regressionInputFile);
3650 
3651  m_timerRegressionErrorReport = new QTimer();
3652  m_timerRegressionErrorReport->setSingleShot(false);
3653  connect (m_timerRegressionErrorReport, SIGNAL (timeout()), this, SLOT (slotTimeoutRegressionErrorReport()));
3654 
3655  m_timerRegressionErrorReport->start(REGRESSION_INTERVAL);
3656 }
3657 
3658 void MainWindow::startRegressionTestFileCmdScript()
3659 {
3660  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::startRegressionTestFileCmdScript";
3661 
3662  const int REGRESSION_INTERVAL = 400; // Milliseconds
3663 
3664  m_timerRegressionFileCmdScript = new QTimer();
3665  m_timerRegressionFileCmdScript->setSingleShot(false);
3666  connect (m_timerRegressionFileCmdScript, SIGNAL (timeout()), this, SLOT (slotTimeoutRegressionFileCmdScript()));
3667 
3668  m_timerRegressionFileCmdScript->start(REGRESSION_INTERVAL);
3669 }
3670 
3672 {
3673  return m_transformation;
3674 }
3675 
3677 {
3678  return m_transformation.transformIsDefined();
3679 }
3680 
3682 {
3683  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateAfterCommand";
3684 
3685  ENGAUGE_CHECK_PTR (m_cmdMediator);
3686 
3687  // Update transformation stuff, including the graph coordinates of every point in the Document, so coordinates in
3688  // status bar are up to date. Point coordinates in Document are also updated
3689  updateAfterCommandStatusBarCoords ();
3690 
3691  // Update the QGraphicsScene with the populated Curves. This requires the points in the Document to be already updated
3692  // by updateAfterCommandStatusBarCoords
3693  m_scene->updateAfterCommand (*m_cmdMediator);
3694 
3695  updateControls ();
3696 
3697  // Update checklist guide status
3698  m_dockChecklistGuide->update (*m_cmdMediator,
3699  m_isDocumentExported);
3700 
3701  // Final action at the end of a redo/undo is to checkpoint the Document and GraphicsScene to log files
3702  // so proper state can be verified
3703  writeCheckpointToLogFile ();
3704 }
3705 
3706 void MainWindow::updateAfterCommandStatusBarCoords ()
3707 {
3708  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateAfterCommandStatusBarCoords";
3709 
3710  // For some reason, mapFromGlobal(QCursor::pos) differs from event->pos by a little bit. We must compensate for
3711  // this so cursor coordinates in status bar match the DlgEditPoint inputs initially. After the mouse moves
3712  // the problem disappears since event->pos is available and QCursor::pos is no longer needed
3713  const QPoint HACK_SO_GRAPH_COORDINATE_MATCHES_INPUT (1, 1);
3714 
3715  Transformation m_transformationBefore (m_transformation);
3716 
3717  updateTransformationAndItsDependencies();
3718 
3719  // Trigger state transitions for transformation if appropriate
3720  if (!m_transformationBefore.transformIsDefined() && m_transformation.transformIsDefined()) {
3721 
3722  // Transition from undefined to defined
3723  m_transformationStateContext->triggerStateTransition(TRANSFORMATION_STATE_DEFINED,
3724  *m_cmdMediator,
3725  m_transformation,
3726  selectedGraphCurve());
3727 
3728  } else if (m_transformationBefore.transformIsDefined() && !m_transformation.transformIsDefined()) {
3729 
3730  // Transition from defined to undefined
3731  m_transformationStateContext->triggerStateTransition(TRANSFORMATION_STATE_UNDEFINED,
3732  *m_cmdMediator,
3733  m_transformation,
3734  selectedGraphCurve());
3735 
3736  } else if (m_transformation.transformIsDefined() && (m_transformationBefore != m_transformation)) {
3737 
3738  // There was not a define/undefined or undefined/defined transition, but the transformation changed so we
3739  // need to update the Checker
3740  m_transformationStateContext->updateAxesChecker(*m_cmdMediator,
3741  m_transformation);
3742 
3743  }
3744 
3745  QPoint posLocal = m_view->mapFromGlobal (QCursor::pos ()) - HACK_SO_GRAPH_COORDINATE_MATCHES_INPUT;
3746  QPointF posScreen = m_view->mapToScene (posLocal);
3747 
3748  slotMouseMove (posScreen); // Update the status bar coordinates to reflect the newly updated transformation
3749 }
3750 
3752 {
3753  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateAfterMouseRelease";
3754 
3755  updateControls ();
3756 }
3757 
3758 void MainWindow::updateControls ()
3759 {
3760  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateControls"
3761  << " selectedItems=" << m_scene->selectedItems().count();
3762 
3763  m_cmbBackground->setEnabled (!m_currentFile.isEmpty ());
3764 
3765  m_menuFileOpenRecent->setEnabled ((m_actionRecentFiles.count () > 0) &&
3766  (m_actionRecentFiles.at(0)->isVisible ())); // Need at least one visible recent file entry
3767  m_actionClose->setEnabled (!m_currentFile.isEmpty ());
3768  m_actionSave->setEnabled (!m_currentFile.isEmpty ());
3769  m_actionSaveAs->setEnabled (!m_currentFile.isEmpty ());
3770  m_actionExport->setEnabled (!m_currentFile.isEmpty ());
3771  m_actionPrint->setEnabled (!m_currentFile.isEmpty ());
3772 
3773  if (m_cmdMediator == 0) {
3774  m_actionEditUndo->setEnabled (false);
3775  m_actionEditRedo->setEnabled (false);
3776  } else {
3777  m_actionEditUndo->setEnabled (m_cmdMediator->canUndo ());
3778  m_actionEditRedo->setEnabled (m_cmdMediator->canRedo () || m_cmdStackShadow->canRedo ());
3779  }
3780  m_actionEditCut->setEnabled (m_scene->selectedItems().count () > 0);
3781  m_actionEditCopy->setEnabled (m_scene->selectedItems().count () > 0);
3782  m_actionEditPaste->setEnabled (false);
3783  m_actionEditDelete->setEnabled (m_scene->selectedItems().count () > 0);
3784  // m_actionEditPasteAsNew and m_actionEditPasteAsNewAdvanced are updated when m_menuEdit is about to be shown
3785 
3786  m_actionDigitizeAxis->setEnabled (!m_currentFile.isEmpty ());
3787  m_actionDigitizeCurve ->setEnabled (!m_currentFile.isEmpty ());
3788  m_actionDigitizePointMatch->setEnabled (!m_currentFile.isEmpty ());
3789  m_actionDigitizeColorPicker->setEnabled (!m_currentFile.isEmpty ());
3790  m_actionDigitizeSegment->setEnabled (!m_currentFile.isEmpty ());
3791  m_actionDigitizeSelect->setEnabled (!m_currentFile.isEmpty ());
3792 
3793  m_actionViewBackground->setEnabled (!m_currentFile.isEmpty());
3794  m_actionViewChecklistGuide->setEnabled (!m_dockChecklistGuide->browserIsEmpty());
3795  m_actionViewDigitize->setEnabled (!m_currentFile.isEmpty ());
3796  m_actionViewSettingsViews->setEnabled (!m_currentFile.isEmpty ());
3797 
3798  m_actionSettingsCoords->setEnabled (!m_currentFile.isEmpty ());
3799  m_actionSettingsCurveAddRemove->setEnabled (!m_currentFile.isEmpty ());
3800  m_actionSettingsCurveProperties->setEnabled (!m_currentFile.isEmpty ());
3801  m_actionSettingsDigitizeCurve->setEnabled (!m_currentFile.isEmpty ());
3802  m_actionSettingsExport->setEnabled (!m_currentFile.isEmpty ());
3803  m_actionSettingsColorFilter->setEnabled (!m_currentFile.isEmpty ());
3804  m_actionSettingsAxesChecker->setEnabled (!m_currentFile.isEmpty ());
3805  m_actionSettingsGridRemoval->setEnabled (!m_currentFile.isEmpty ());
3806  m_actionSettingsPointMatch->setEnabled (!m_currentFile.isEmpty ());
3807  m_actionSettingsSegments->setEnabled (!m_currentFile.isEmpty ());
3808  m_actionSettingsGeneral->setEnabled (!m_currentFile.isEmpty ());
3809 
3810  m_groupBackground->setEnabled (!m_currentFile.isEmpty ());
3811  m_groupCurves->setEnabled (!m_currentFile.isEmpty ());
3812  m_groupZoom->setEnabled (!m_currentFile.isEmpty ());
3813 
3814  m_actionZoomIn->setEnabled (!m_currentFile.isEmpty ()); // Disable at startup so shortcut has no effect
3815  m_actionZoomOut->setEnabled (!m_currentFile.isEmpty ()); // Disable at startup so shortcut has no effect
3816 }
3817 
3818 void MainWindow::updateCoordSystem(CoordSystemIndex coordSystemIndex)
3819 {
3820  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateCoordSystem";
3821 
3822  m_cmdMediator->document().setCoordSystemIndex (coordSystemIndex);
3823  updateTransformationAndItsDependencies(); // Transformation state may have changed
3824  updateSettingsAxesChecker(m_cmdMediator->document().modelAxesChecker()); // Axes checker dependes on transformation state
3825 
3826  // Nice trick for showing that a new coordinate system is in effect is to show the axes checker
3827  m_transformationStateContext->updateAxesChecker (*m_cmdMediator,
3828  m_transformation);
3829 
3831 }
3832 
3833 void MainWindow::updateDigitizeStateIfSoftwareTriggered (DigitizeState digitizeState)
3834 {
3835  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateDigitizeStateIfSoftwareTriggered";
3836 
3837  switch (digitizeState) {
3838  case DIGITIZE_STATE_AXIS:
3839  m_actionDigitizeAxis->setChecked(true);
3840  slotDigitizeAxis(); // Call the slot that the setChecked call fails to trigger
3841  break;
3842 
3843  case DIGITIZE_STATE_COLOR_PICKER:
3844  m_actionDigitizeColorPicker->setChecked(true);
3845  slotDigitizeColorPicker(); // Call the slot that the setChecked call fails to trigger
3846  break;
3847 
3848  case DIGITIZE_STATE_CURVE:
3849  m_actionDigitizeCurve->setChecked(true);
3850  slotDigitizeCurve(); // Call the slot that the setChecked call fails to trigger
3851  break;
3852 
3853  case DIGITIZE_STATE_EMPTY:
3854  break;
3855 
3856  case DIGITIZE_STATE_POINT_MATCH:
3857  m_actionDigitizePointMatch->setChecked(true);
3858  slotDigitizePointMatch(); // Call the slot that the setChecked call fails to trigger
3859  break;
3860 
3861  case DIGITIZE_STATE_SEGMENT:
3862  m_actionDigitizeSegment->setChecked(true);
3863  slotDigitizeSegment(); // Call the slot that the setChecked call fails to trigger
3864  break;
3865 
3866  case DIGITIZE_STATE_SELECT:
3867  m_actionDigitizeSelect->setChecked(true);
3868  slotDigitizeSelect(); // Call the slot that the setChecked call fails to trigger
3869  break;
3870 
3871  default:
3872  LOG4CPP_ERROR_S ((*mainCat)) << "MainWindow::updateDigitizeStateIfSoftwareTriggered";
3873  break;
3874  }
3875 }
3876 
3878 {
3879  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateGraphicsLinesToMatchGraphicsPoints";
3880 
3882  m_transformation);
3883 }
3884 
3885 void MainWindow::updateRecentFileList()
3886 {
3887  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateRecentFileList";
3888 
3889  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
3890  QStringList recentFilePaths = settings.value(SETTINGS_RECENT_FILE_LIST).toStringList();
3891 
3892  // Determine the desired size of the path list
3893  unsigned int count = recentFilePaths.size();
3894  if (count > MAX_RECENT_FILE_LIST_SIZE) {
3895  count = MAX_RECENT_FILE_LIST_SIZE;
3896  }
3897 
3898  // Add visible entries
3899  unsigned int i;
3900  for (i = 0; i < count; i++) {
3901  QString strippedName = QFileInfo (recentFilePaths.at(i)).fileName();
3902  m_actionRecentFiles.at (i)->setText (strippedName);
3903  m_actionRecentFiles.at (i)->setData (recentFilePaths.at (i));
3904  m_actionRecentFiles.at (i)->setVisible (true);
3905  }
3906 
3907  // Hide any extra entries
3908  for (i = count; i < MAX_RECENT_FILE_LIST_SIZE; i++) {
3909  m_actionRecentFiles.at (i)->setVisible (false);
3910  }
3911 }
3912 
3914 {
3915  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsAxesChecker";
3916 
3917  m_cmdMediator->document().setModelAxesChecker(modelAxesChecker);
3918  if (m_transformation.transformIsDefined()) {
3919  m_transformationStateContext->triggerStateTransition(TRANSFORMATION_STATE_DEFINED,
3920  *m_cmdMediator,
3921  m_transformation,
3922  m_cmbCurve->currentText());
3923  } else {
3924  m_transformationStateContext->triggerStateTransition(TRANSFORMATION_STATE_UNDEFINED,
3925  *m_cmdMediator,
3926  m_transformation,
3927  m_cmbCurve->currentText());
3928  }
3929 }
3930 
3932 {
3933  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsColorFilter";
3934 
3935  m_cmdMediator->document().setModelColorFilter(modelColorFilter);
3936  m_backgroundStateContext->updateColorFilter (m_transformation,
3937  m_cmdMediator->document().modelGridRemoval(),
3938  modelColorFilter);
3939  m_digitizeStateContext->handleCurveChange (m_cmdMediator);
3941 }
3942 
3944 {
3945  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsCoords";
3946 
3947  m_cmdMediator->document().setModelCoords(modelCoords);
3948 }
3949 
3951 {
3952  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsCurveAddRemove";
3953 
3954  m_cmdMediator->document().setCurvesGraphs (curvesGraphs);
3955  loadCurveListFromCmdMediator();
3957 }
3958 
3960 {
3961  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsCurveStyles";
3962 
3963  m_scene->updateCurveStyles(modelCurveStyles);
3964  m_cmdMediator->document().setModelCurveStyles(modelCurveStyles);
3966 }
3967 
3969 {
3970  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsDigitizeCurve";
3971 
3972  m_cmdMediator->document().setModelDigitizeCurve(modelDigitizeCurve);
3973  m_digitizeStateContext->updateModelDigitizeCurve (m_cmdMediator,
3974  modelDigitizeCurve);
3975 }
3976 
3978 {
3979  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsExportFormat";
3980 
3981  m_cmdMediator->document().setModelExport (modelExport);
3982 }
3983 
3985 {
3986  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsGeneral";
3987 
3988  m_cmdMediator->document().setModelGeneral(modelGeneral);
3989 }
3990 
3992 {
3993  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsGridRemoval";
3994 
3995  m_cmdMediator->document().setModelGridRemoval(modelGridRemoval);
3996 }
3997 
3998 void MainWindow::updateSettingsMainWindow()
3999 {
4000  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsMainWindow";
4001 
4002  if (m_modelMainWindow.zoomControl() == ZOOM_CONTROL_MENU_ONLY ||
4003  m_modelMainWindow.zoomControl() == ZOOM_CONTROL_MENU_WHEEL) {
4004 
4005  m_actionZoomIn->setShortcut (tr (""));
4006  m_actionZoomOut->setShortcut (tr (""));
4007 
4008  } else {
4009 
4010  m_actionZoomIn->setShortcut (tr ("+"));
4011  m_actionZoomOut->setShortcut (tr ("-"));
4012 
4013  }
4014 
4015  updateWindowTitle();
4016 }
4017 
4019 {
4020  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsMainWindow";
4021 
4022  m_modelMainWindow = modelMainWindow;
4024 }
4025 
4027 {
4028  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsPointMatch";
4029 
4030  m_cmdMediator->document().setModelPointMatch(modelPointMatch);
4031 }
4032 
4034 {
4035  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsSegments";
4036 
4037  m_cmdMediator->document().setModelSegments(modelSegments);
4038  m_digitizeStateContext->updateModelSegments(modelSegments);
4039 }
4040 
4041 void MainWindow::updateTransformationAndItsDependencies()
4042 {
4043  m_transformation.update (!m_currentFile.isEmpty (),
4044  *m_cmdMediator,
4045  m_modelMainWindow);
4046 
4047  // Grid removal is affected by new transformation
4048  m_backgroundStateContext->setCurveSelected (m_transformation,
4049  m_cmdMediator->document().modelGridRemoval(),
4050  m_cmdMediator->document().modelColorFilter(),
4051  m_cmbCurve->currentText ());
4052 }
4053 
4054 void MainWindow::updateViewedCurves ()
4055 {
4056  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateViewedCurves";
4057 
4058  if (m_actionViewCurvesAll->isChecked ()) {
4059 
4060  m_scene->showCurves (true, true);
4061 
4062  } else if (m_actionViewCurvesSelected->isChecked ()) {
4063 
4064  m_scene->showCurves (true, false, selectedGraphCurve ());
4065 
4066  } else if (m_actionViewCurvesNone->isChecked ()) {
4067 
4068  m_scene->showCurves (false);
4069 
4070  } else {
4071  ENGAUGE_ASSERT (false);
4072  }
4073 }
4074 
4076 {
4077  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateViewsOfSettings";
4078 
4079  QString activeCurve = m_digitizeStateContext->activeCurve ();
4080 
4081  updateViewsOfSettings (activeCurve);
4082 }
4083 
4084 void MainWindow::updateViewsOfSettings (const QString &activeCurve)
4085 {
4086  if (activeCurve.isEmpty ()) {
4087 
4088  m_viewPointStyle->unsetPointStyle ();
4089  m_viewSegmentFilter->unsetColorFilterSettings ();
4090 
4091 
4092  } else {
4093 
4094  PointStyle pointStyle = m_cmdMediator->document().modelCurveStyles().curveStyle(activeCurve).pointStyle();
4095  m_viewPointStyle->setPointStyle (pointStyle);
4096 
4097  ColorFilterSettings colorFilterSettings = m_cmdMediator->document().modelColorFilter().colorFilterSettings(activeCurve);
4098  m_viewSegmentFilter->setColorFilterSettings (colorFilterSettings,
4099  m_cmdMediator->pixmap ());
4100 
4101  }
4102 }
4103 
4104 void MainWindow::updateWindowTitle ()
4105 {
4106  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateWindowTitle";
4107 
4108  const QString PLACEHOLDER ("[*]");
4109 
4110  QString title = QString (tr ("Engauge Digitizer %1")
4111  .arg (VERSION_NUMBER));
4112 
4113  QString fileNameMaybeStripped;
4114  if (!m_currentFileWithPathAndFileExtension.isEmpty()) {
4115 
4116  QFileInfo fileInfo (m_currentFileWithPathAndFileExtension);
4117 
4118  switch (m_modelMainWindow.mainTitleBarFormat())
4119  {
4120  case MAIN_TITLE_BAR_FORMAT_NO_PATH:
4121  fileNameMaybeStripped = fileInfo.baseName(); // Remove file extension and path for "clean look"
4122  break;
4123 
4124  case MAIN_TITLE_BAR_FORMAT_PATH:
4125  fileNameMaybeStripped = m_currentFileWithPathAndFileExtension;
4126  break;
4127  }
4128 
4129  title += QString (": %1")
4130  .arg (fileNameMaybeStripped);
4131  }
4132 
4133  // To prevent "QWidget::setWindowModified: The window title does not contain a [*] placeholder" warnings,
4134  // we always append a placeholder
4135  title += PLACEHOLDER;
4136 
4137  setWindowTitle (title);
4138 }
4139 
4141 {
4142  ENGAUGE_CHECK_PTR (m_view);
4143  return *m_view;
4144 }
4145 
4147 {
4148  ENGAUGE_CHECK_PTR (m_view);
4149  return *m_view;
4150 }
4151 
4152 void MainWindow::writeCheckpointToLogFile ()
4153 {
4154  // Document
4155  QString checkpointDoc;
4156  QTextStream strDoc (&checkpointDoc);
4157  m_cmdMediator->document().printStream(INDENTATION_PAST_TIMESTAMP,
4158  strDoc);
4159 
4160  // Scene
4161  QString checkpointScene;
4162  QTextStream strScene (&checkpointScene);
4163  m_scene->printStream (INDENTATION_PAST_TIMESTAMP,
4164  strScene);
4165 
4166  // Skip slow string manipulation if BEFORE call to LOG4CPP_DEBUG_S
4167  if (mainCat->getPriority() == log4cpp::Priority::DEBUG) {
4168 
4169  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::writeCheckpointToLogFile\n"
4170  << "--------------DOCUMENT CHECKPOINT START----------" << "\n"
4171  << checkpointDoc.toLatin1().data()
4172  << "---------------DOCUMENT CHECKPOINT END-----------" << "\n"
4173  << "----------------SCENE CHECKPOINT START-----------" << "\n"
4174  << checkpointScene.toLatin1().data()
4175  << "-----------------SCENE CHECKPOINT END------------" ;
4176  }
4177 }
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
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.