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