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