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