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