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