Engauge Digitizer  2
 All Classes Files Functions Variables Enumerations Enumerator Friends Pages
MainWindow.cpp
1 #include "BackgroundImage.h"
2 #include "BackgroundStateContext.h"
3 #include "img/bannerapp_16.xpm"
4 #include "img/bannerapp_32.xpm"
5 #include "img/bannerapp_64.xpm"
6 #include "img/bannerapp_128.xpm"
7 #include "img/bannerapp_256.xpm"
8 #include "ChecklistGuide.h"
9 #include "ChecklistGuideWizard.h"
10 #include "CmdCopy.h"
11 #include "CmdCut.h"
12 #include "CmdDelete.h"
13 #include "CmdMediator.h"
14 #include "CmdStackShadow.h"
15 #include "ColorFilter.h"
16 #include "Curve.h"
17 #include "DataKey.h"
18 #include "DigitizeStateContext.h"
19 #include "DigitAxis.xpm"
20 #include "DigitColorPicker.xpm"
21 #include "DigitCurve.xpm"
22 #include "DigitPointMatch.xpm"
23 #include "DigitSegment.xpm"
24 #include "DigitSelect.xpm"
25 #include "DlgAbout.h"
26 #include "DlgErrorReport.h"
27 #include "DlgRequiresTransform.h"
28 #include "DlgSettingsAxesChecker.h"
29 #include "DlgSettingsColorFilter.h"
30 #include "DlgSettingsCommon.h"
31 #include "DlgSettingsCoords.h"
32 #include "DlgSettingsCurveAddRemove.h"
33 #include "DlgSettingsCurveProperties.h"
34 #include "DlgSettingsDigitizeCurve.h"
35 #include "DlgSettingsExportFormat.h"
36 #include "DlgSettingsGridRemoval.h"
37 #include "DlgSettingsPointMatch.h"
38 #include "DlgSettingsSegments.h"
39 #include "DocumentSerialize.h"
40 #include "EngaugeAssert.h"
41 #include "EnumsToQt.h"
42 #include "ExportToFile.h"
43 #include "GraphicsItemType.h"
44 #include "GraphicsScene.h"
45 #include "GraphicsView.h"
46 #include "HelpWindow.h"
47 #ifdef ENGAUGE_JPEG2000
48 #include "Jpeg2000.h"
49 #endif // ENGAUGE_JPEG2000
50 #include "LoadImageFromUrl.h"
51 #include "Logger.h"
52 #include "MainWindow.h"
53 #include "NetworkClient.h"
54 #include <QAction>
55 #include <QApplication>
56 #include <QCloseEvent>
57 #include <QComboBox>
58 #include <QDebug>
59 #include <QDesktopServices>
60 #include <QDockWidget>
61 #include <QDomDocument>
62 #include <QKeyEvent>
63 #include <QFileDialog>
64 #include <QFileInfo>
65 #include <QGraphicsLineItem>
66 #include <QImageReader>
67 #include <QKeyEvent>
68 #include <QKeySequence>
69 #include <QLabel>
70 #include <QMenu>
71 #include <QMenuBar>
72 #include <QMessageBox>
73 #include <QPrintDialog>
74 #include <QPrinter>
75 #include <QSettings>
76 #include <QTextStream>
77 #include <QtHelp>
78 #include <QToolBar>
79 #include <QToolButton>
80 #include "QtToString.h"
81 #include <QVBoxLayout>
82 #include <QWhatsThis>
83 #include <QXmlStreamReader>
84 #include <QXmlStreamWriter>
85 #include "Settings.h"
86 #include "StatusBar.h"
87 #include "TransformationStateContext.h"
88 #include "TutorialDlg.h"
89 #include "Version.h"
90 #include "ViewPointStyle.h"
91 #include "ViewSegmentFilter.h"
92 #include "ZoomFactor.h"
93 
94 // These constants are used for the menu item text AND for tooltip text
95 const QString DIGITIZE_ACTION_AXIS_POINT (QObject::tr ("Axis Point Tool"));
96 const QString DIGITIZE_ACTION_COLOR_PICKER (QObject::tr ("Color Picker Tool"));
97 const QString DIGITIZE_ACTION_CURVE_POINT (QObject::tr ("Curve Point Tool"));
98 const QString DIGITIZE_ACTION_POINT_MATCH (QObject::tr ("Point Match Tool"));
99 const QString DIGITIZE_ACTION_SEGMENT_POINTS (QObject::tr ("Segment Fill Tool"));
100 const QString DIGITIZE_ACTION_SELECT (QObject::tr ("Select Tool"));
101 
102 const QString EMPTY_FILENAME ("");
103 const QString ENGAUGE_FILENAME_DESCRIPTION ("Engauge Document");
104 const QString ENGAUGE_FILENAME_EXTENSION ("dig");
105 const QString CSV_FILENAME_EXTENSION ("csv");
106 const QString TSV_FILENAME_EXTENSION ("tsv");
107 
108 const unsigned int MAX_RECENT_FILE_LIST_SIZE = 8;
109 
110 MainWindow::MainWindow(const QString &errorReportFile,
111  bool isGnuplot,
112  QWidget *parent) :
113  QMainWindow(parent),
114  m_isDocumentExported (false),
115  m_engaugeFile (EMPTY_FILENAME),
116  m_currentFile (EMPTY_FILENAME),
117  m_layout (0),
118  m_scene (0),
119  m_view (0),
120  m_cmdMediator (0),
121  m_digitizeStateContext (0),
122  m_transformationStateContext (0),
123  m_backgroundStateContext (0),
124  m_isGnuplot (isGnuplot)
125 {
127 
128  QString initialPath = QDir::currentPath();
129 
130  setCurrentFile ("");
131  createIcons();
132  setWindowFlags (Qt::WindowContextHelpButtonHint | windowFlags ()); // Add help to default buttons
133  setWindowTitle (engaugeWindowTitle ());
134 
135  createCentralWidget();
136  createActions ();
137  createStatusBar ();
138  createMenus ();
139  createToolBars ();
140  createHelpWindow ();
141  createTutorial ();
142  createScene ();
143  createNetwork ();
144  createLoadImageFromUrl ();
145  createStateContextBackground ();
146  createStateContextDigitize ();
147  createStateContextTransformation ();
148  createSettingsDialogs ();
149  createCommandStackShadow ();
150  updateControls ();
151 
152  settingsRead ();
153  setCurrentFile ("");
154  setUnifiedTitleAndToolBarOnMac(true);
155 
156  installEventFilter(this);
157  if (!errorReportFile.isEmpty()) {
158  loadErrorReportFile(initialPath,
159  errorReportFile);
160  }
161 }
162 
163 MainWindow::~MainWindow()
164 {
165 }
166 
167 void MainWindow::closeEvent(QCloseEvent *event)
168 {
169  if (maybeSave()) {
170  settingsWrite ();
171  event->accept ();
172  } else {
173  event->ignore ();
174  }
175 }
176 
178 {
179  ENGAUGE_CHECK_PTR (m_cmdMediator);
180 
181  return *m_cmdMediator;
182 }
183 
184 void MainWindow::createActions()
185 {
186  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createActions";
187 
188  createActionsFile ();
189  createActionsEdit ();
190  createActionsDigitize ();
191  createActionsView ();
192  createActionsSettings ();
193  createActionsHelp ();
194 }
195 
196 void MainWindow::createActionsDigitize ()
197 {
198  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createActionsDigitize";
199 
200  QPixmap pixmapAxis (DigitAxis_xpm);
201  QPixmap pixmapCurve (DigitCurve_xpm);
202  QPixmap pixmapColorPicker (DigitColorPicker_xpm);
203  QPixmap pixmapPointMatch (DigitPointMatch_xpm);
204  QPixmap pixmapSegment (DigitSegment_xpm);
205  QPixmap pixmapSelect (DigitSelect_xpm);
206 
207  QIcon iconAxis (pixmapAxis);
208  QIcon iconCurve (pixmapCurve);
209  QIcon iconColorPicker (pixmapColorPicker);
210  QIcon iconPointMatch (pixmapPointMatch);
211  QIcon iconSegment (pixmapSegment);
212  QIcon iconSelect (pixmapSelect);
213 
214  m_actionDigitizeSelect = new QAction (iconSelect, DIGITIZE_ACTION_SELECT, this);
215  m_actionDigitizeSelect->setShortcut (QKeySequence (tr ("Shift+F2")));
216  m_actionDigitizeSelect->setCheckable (true);
217  m_actionDigitizeSelect->setStatusTip (tr ("Select points on screen."));
218  m_actionDigitizeSelect->setWhatsThis (tr ("Select\n\n"
219  "Select points on the screen."));
220  connect (m_actionDigitizeSelect, SIGNAL (triggered ()), this, SLOT (slotDigitizeSelect ()));
221 
222  m_actionDigitizeAxis = new QAction (iconAxis, DIGITIZE_ACTION_AXIS_POINT, this);
223  m_actionDigitizeAxis->setShortcut (QKeySequence (tr ("Shift+F3")));
224  m_actionDigitizeAxis->setCheckable (true);
225  m_actionDigitizeAxis->setStatusTip (tr ("Digitize axis points."));
226  m_actionDigitizeAxis->setWhatsThis (tr ("Digitize Axis Point\n\n"
227  "Digitizes an axis point by placing a new point at the cursor "
228  "after a mouse click. The coordinates of the axis point are then "
229  "entered. In a graph, three axis points are required to define "
230  "the graph coordinates."));
231  connect (m_actionDigitizeAxis, SIGNAL (triggered ()), this, SLOT (slotDigitizeAxis ()));
232 
233  m_actionDigitizeCurve = new QAction (iconCurve, DIGITIZE_ACTION_CURVE_POINT, this);
234  m_actionDigitizeCurve->setShortcut (QKeySequence (tr ("Shift+F4")));
235  m_actionDigitizeCurve->setCheckable (true);
236  m_actionDigitizeCurve->setStatusTip (tr ("Digitize curve points."));
237  m_actionDigitizeCurve->setWhatsThis (tr ("Digitize Curve Point\n\n"
238  "Digitizes a curve point by placing a new point at the cursor "
239  "after a mouse click. Use this mode to digitize points along curves "
240  "one by one.\n\n"
241  "New points will be assigned to the currently selected curve."));
242  connect (m_actionDigitizeCurve, SIGNAL (triggered ()), this, SLOT (slotDigitizeCurve ()));
243 
244  m_actionDigitizePointMatch = new QAction (iconPointMatch, DIGITIZE_ACTION_POINT_MATCH, this);
245  m_actionDigitizePointMatch->setShortcut (QKeySequence (tr ("Shift+F5")));
246  m_actionDigitizePointMatch->setCheckable (true);
247  m_actionDigitizePointMatch->setStatusTip (tr ("Digitize curve points in a point plot by matching a point."));
248  m_actionDigitizePointMatch->setWhatsThis (tr ("Digitize Curve Points by Point Matching\n\n"
249  "Digitizes curve points in a point plot by finding points that match a sample point. The process "
250  "starts by selecting a representative sample point.\n\n"
251  "New points will be assigned to the currently selected curve."));
252  connect (m_actionDigitizePointMatch, SIGNAL (triggered ()), this, SLOT (slotDigitizePointMatch ()));
253 
254  m_actionDigitizeColorPicker = new QAction (iconColorPicker, DIGITIZE_ACTION_COLOR_PICKER, this);
255  m_actionDigitizeColorPicker->setShortcut (QKeySequence (tr ("Shift+F6")));
256  m_actionDigitizeColorPicker->setCheckable (true);
257  m_actionDigitizeColorPicker->setStatusTip (tr ("Select color settings for filtering in Segment Fill mode."));
258  m_actionDigitizeColorPicker->setWhatsThis (tr ("Select color settings for Segment Fill filtering\n\n"
259  "Select a pixel along the currently selected curve. That pixel and its neighbors will "
260  "define the filter settings (color, brightness, and so on) of the currently selected curve "
261  "while in Segment Fill mode."));
262  connect (m_actionDigitizeColorPicker, SIGNAL (triggered ()), this, SLOT (slotDigitizeColorPicker ()));
263 
264  m_actionDigitizeSegment = new QAction (iconSegment, DIGITIZE_ACTION_SEGMENT_POINTS, this);
265  m_actionDigitizeSegment->setShortcut (QKeySequence (tr ("Shift+F7")));
266  m_actionDigitizeSegment->setCheckable (true);
267  m_actionDigitizeSegment->setStatusTip (tr ("Digitize curve points along a segment of a curve."));
268  m_actionDigitizeSegment->setWhatsThis (tr ("Digitize Curve Points With Segment Fill\n\n"
269  "Digitizes curve points by placing new points along the highlighted "
270  "segment under the cursor. Use this mode to quickly digitize multiple points along a "
271  "curve with a single click.\n\n"
272  "New points will be assigned to the currently selected curve."));
273  connect (m_actionDigitizeSegment, SIGNAL (triggered ()), this, SLOT (slotDigitizeSegment ()));
274 
275  m_groupDigitize = new QActionGroup (this);
276  m_groupDigitize->addAction (m_actionDigitizeSelect);
277  m_groupDigitize->addAction (m_actionDigitizeAxis);
278  m_groupDigitize->addAction (m_actionDigitizeCurve);
279  m_groupDigitize->addAction (m_actionDigitizePointMatch);
280  m_groupDigitize->addAction (m_actionDigitizeColorPicker);
281  m_groupDigitize->addAction (m_actionDigitizeSegment);
282 }
283 
284 void MainWindow::createActionsEdit ()
285 {
286  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createActionsEdit";
287 
288  m_actionEditUndo = new QAction(tr ("&Undo"), this);
289  m_actionEditUndo->setShortcut (QKeySequence::Undo);
290  m_actionEditUndo->setStatusTip (tr ("Undo the last operation."));
291  m_actionEditUndo->setWhatsThis (tr ("Undo\n\n"
292  "Undo the last operation."));
293  // connect is applied when CmdMediator appears
294 
295  m_actionEditRedo = new QAction(tr ("&Redo"), this);
296  m_actionEditRedo->setShortcut (QKeySequence::Redo);
297  m_actionEditRedo->setStatusTip (tr ("Redo the last operation."));
298  m_actionEditRedo->setWhatsThis (tr ("Redo\n\n"
299  "Redo the last operation."));
300  // connect is applied when CmdMediator appears
301 
302  m_actionEditCut = new QAction (tr ("Cut"), this);
303  m_actionEditCut->setShortcut (QKeySequence::Cut);
304  m_actionEditCut->setStatusTip (tr ("Cuts the selected points and copies them to the clipboard."));
305  m_actionEditCut->setWhatsThis (tr ("Cut\n\n"
306  "Cuts the selected points and copies them to the clipboard."));
307  connect (m_actionEditCut, SIGNAL (triggered ()), this, SLOT (slotEditCut ()));
308 
309  m_actionEditCopy = new QAction (tr ("Copy"), this);
310  m_actionEditCopy->setShortcut (QKeySequence::Copy);
311  m_actionEditCopy->setStatusTip (tr ("Copies the selected points to the clipboard."));
312  m_actionEditCopy->setWhatsThis (tr ("Copy\n\n"
313  "Copies the selected points to the clipboard."));
314  connect (m_actionEditCopy, SIGNAL (triggered ()), this, SLOT (slotEditCopy ()));
315 
316  m_actionEditPaste = new QAction (tr ("Paste"), this);
317  m_actionEditPaste->setShortcut (QKeySequence::Paste);
318  m_actionEditPaste->setStatusTip (tr ("Pastes the selected points from the clipboard."));
319  m_actionEditPaste->setWhatsThis (tr ("Paste\n\n"
320  "Pastes the selected points from the clipboard. They will be assigned to the current curve."));
321  connect (m_actionEditPaste, SIGNAL (triggered ()), this, SLOT (slotEditPaste ()));
322 
323  m_actionEditDelete = new QAction (tr ("Delete"), this);
324  m_actionEditDelete->setShortcut (QKeySequence::Delete);
325  m_actionEditDelete->setStatusTip (tr ("Deletes the selected points, after copying them to the clipboard."));
326  m_actionEditDelete->setWhatsThis (tr ("Delete\n\n"
327  "Deletes the selected points, after copying them to the clipboard."));
328  connect (m_actionEditDelete, SIGNAL (triggered ()), this, SLOT (slotEditDelete ()));
329 }
330 
331 void MainWindow::createActionsFile ()
332 {
333  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createActionsFile";
334 
335  m_actionImport = new QAction(tr ("&Import"), this);
336  m_actionImport->setShortcut (tr ("Ctrl+I"));
337  m_actionImport->setStatusTip (tr ("Creates a new document by importing an image."));
338  m_actionImport->setWhatsThis (tr ("New Document\n\n"
339  "Creates a new document by importing an image."));
340  connect (m_actionImport, SIGNAL (triggered ()), this, SLOT (slotFileImport ()));
341 
342  m_actionOpen = new QAction(tr ("&Open"), this);
343  m_actionOpen->setShortcut (QKeySequence::Open);
344  m_actionOpen->setStatusTip (tr ("Opens an existing document."));
345  m_actionOpen->setWhatsThis (tr ("Open Document\n\n"
346  "Opens an existing document."));
347  connect (m_actionOpen, SIGNAL (triggered ()), this, SLOT (slotFileOpen ()));
348 
349  for (unsigned int i = 0; i < MAX_RECENT_FILE_LIST_SIZE; i++) {
350  QAction *recentFileAction = new QAction (this);
351  recentFileAction->setVisible (true);
352  connect (recentFileAction, SIGNAL (triggered ()), this, SLOT (slotRecentFileAction ()));
353  m_actionRecentFiles.append (recentFileAction);
354  }
355 
356  m_actionClose = new QAction(tr ("&Close"), this);
357  m_actionClose->setShortcut (QKeySequence::Close);
358  m_actionClose->setStatusTip (tr ("Closes the open document document."));
359  m_actionClose->setWhatsThis (tr ("Close Document\n\n"
360  "Closes the open document."));
361  connect (m_actionClose, SIGNAL (triggered ()), this, SLOT (slotFileClose ()));
362 
363  m_actionSave = new QAction(tr ("&Save"), this);
364  m_actionSave->setShortcut (QKeySequence::Save);
365  m_actionSave->setStatusTip (tr ("Saves the current document."));
366  m_actionSave->setWhatsThis (tr ("Save Document\n\n"
367  "Saves the current document."));
368  connect (m_actionSave, SIGNAL (triggered ()), this, SLOT (slotFileSave ()));
369 
370  m_actionSaveAs = new QAction(tr ("Save As"), this);
371  m_actionSaveAs->setShortcut (QKeySequence::SaveAs);
372  m_actionSaveAs->setStatusTip (tr ("Saves the current document under a new filename."));
373  m_actionSaveAs->setWhatsThis (tr ("Save Document As\n\n"
374  "Saves the current document under a new filename."));
375  connect (m_actionSaveAs, SIGNAL (triggered ()), this, SLOT (slotFileSaveAs ()));
376 
377  m_actionExport = new QAction (tr ("Export"), this);
378  m_actionExport->setShortcut (tr ("Ctrl+E"));
379  m_actionExport->setStatusTip (tr ("Exports the current document into a text file."));
380  m_actionExport->setWhatsThis (tr ("Export Document\n\n"
381  "Exports the current document into a text file."));
382  connect (m_actionExport, SIGNAL (triggered ()), this, SLOT (slotFileExport ()));
383 
384  m_actionPrint = new QAction (tr ("&Print"), this);
385  m_actionPrint->setShortcut (QKeySequence::Print);
386  m_actionPrint->setStatusTip (tr ("Print the current document."));
387  m_actionPrint->setWhatsThis (tr ("Print Document\n\n"
388  "Print the current document to a printer or file."));
389  connect (m_actionPrint, SIGNAL (triggered ()), this, SLOT (slotFilePrint ()));
390 
391  m_actionExit = new QAction(tr ("&Exit"), this);
392  m_actionExit->setShortcut (QKeySequence::Quit);
393  m_actionExit->setStatusTip (tr ("Quits the application."));
394  m_actionExit->setWhatsThis (tr ("Exit\n\n"
395  "Quits the application."));
396  connect (m_actionExit, SIGNAL (triggered ()), this, SLOT (close ()));
397 }
398 
399 void MainWindow::createActionsHelp ()
400 {
401  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createActionsHelp";
402 
403  m_actionHelpChecklistGuideWizard = new QAction (tr ("Checklist Guide Wizard"), this);
404  m_actionHelpChecklistGuideWizard->setCheckable (true);
405  m_actionHelpChecklistGuideWizard->setStatusTip (tr ("Open Checklist Guide Wizard during import to define digitizing steps"));
406  m_actionHelpChecklistGuideWizard->setWhatsThis (tr ("Checklist Guide Wizard\n\n"
407  "Use Checklist Guide Wizard during import to generate a checklist of steps "
408  "for the imported document"));
409 
410  m_actionHelpWhatsThis = QWhatsThis::createAction(this);
411  m_actionHelpWhatsThis->setShortcut (QKeySequence::WhatsThis);
412 
413  m_actionHelpTutorial = new QAction (tr ("Tutorial"), this);
414  m_actionHelpTutorial->setStatusTip (tr ("Play tutorial showing steps for digitizing curves"));
415  m_actionHelpTutorial->setWhatsThis (tr ("Tutorial\n\n"
416  "Play tutorial showing steps for digitizing points from curves drawn with lines "
417  "and/or point"));
418  connect (m_actionHelpTutorial, SIGNAL (triggered ()), this, SLOT (slotHelpTutorial()));
419 
420  m_actionHelpHelp = new QAction (tr ("Help"), this);
421  m_actionHelpHelp->setShortcut (QKeySequence::HelpContents);
422  m_actionHelpHelp->setStatusTip (tr ("Help documentation"));
423  m_actionHelpHelp->setWhatsThis (tr ("Help Documentation\n\n"
424  "Searchable help documentation"));
425  // This action gets connected directly to the QDockWidget when that is created
426 
427  m_actionHelpAbout = new QAction(tr ("About Engauge"), this);
428  m_actionHelpAbout->setStatusTip (tr ("About the application."));
429  m_actionHelpAbout->setWhatsThis (tr ("About Engauge\n\nAbout the application."));
430  connect (m_actionHelpAbout, SIGNAL (triggered ()), this, SLOT (slotHelpAbout ()));
431 }
432 
433 void MainWindow::createActionsSettings ()
434 {
435  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createActionsSettings";
436 
437  m_actionSettingsCoords = new QAction (tr ("Coordinates"), this);
438  m_actionSettingsCoords->setStatusTip (tr ("Edit Coordinate settings."));
439  m_actionSettingsCoords->setWhatsThis (tr ("Coordinate Settings\n\n"
440  "Coordinate settings determine how the graph coordinates are mapped to the pixels in the image"));
441  connect (m_actionSettingsCoords, SIGNAL (triggered ()), this, SLOT (slotSettingsCoords ()));
442 
443  m_actionSettingsCurveAddRemove = new QAction (tr ("Add/Remove Curve"), this);
444  m_actionSettingsCurveAddRemove->setStatusTip (tr ("Add or Remove Curves."));
445  m_actionSettingsCurveAddRemove->setWhatsThis (tr ("Add/Remove Curve\n\n"
446  "Add/Remove Curve settings control which curves are included in the current document"));
447  connect (m_actionSettingsCurveAddRemove, SIGNAL (triggered ()), this, SLOT (slotSettingsCurveAddRemove ()));
448 
449  m_actionSettingsCurveProperties = new QAction (tr ("Curve Properties"), this);
450  m_actionSettingsCurveProperties->setStatusTip (tr ("Edit Curve Properties settings."));
451  m_actionSettingsCurveProperties->setWhatsThis (tr ("Curve Properties Settings\n\n"
452  "Curves properties settings determine how each curve appears"));
453  connect (m_actionSettingsCurveProperties, SIGNAL (triggered ()), this, SLOT (slotSettingsCurveProperties ()));
454 
455  m_actionSettingsDigitizeCurve = new QAction (tr ("Digitize Curve"), this);
456  m_actionSettingsDigitizeCurve->setStatusTip (tr ("Edit Digitize Axis and Graph Curve settings."));
457  m_actionSettingsDigitizeCurve->setWhatsThis (tr ("Digitize Axis and Graph Curve Settings\n\n"
458  "Digitize Curve settings determine how points are digitized in Digitize Axis Point and "
459  "Digitize Graph Point modes"));
460  connect (m_actionSettingsDigitizeCurve, SIGNAL (triggered ()), this, SLOT (slotSettingsDigitizeCurve ()));
461 
462  m_actionSettingsExport = new QAction (tr ("Export Format"), this);
463  m_actionSettingsExport->setStatusTip (tr ("Edit Export Format settings."));
464  m_actionSettingsExport->setWhatsThis (tr ("Export Format Settings\n\n"
465  "Export format settings affect how exported files are formatted"));
466  connect (m_actionSettingsExport, SIGNAL (triggered ()), this, SLOT (slotSettingsExportFormat ()));
467 
468  m_actionSettingsColorFilter = new QAction (tr ("Color Filter"), this);
469  m_actionSettingsColorFilter->setStatusTip (tr ("Edit Color Filter settings."));
470  m_actionSettingsColorFilter->setWhatsThis (tr ("Color Filter Settings\n\n"
471  "Color filtering simplifies the graphs for easier Point Matching and Segment Filling"));
472  connect (m_actionSettingsColorFilter, SIGNAL (triggered ()), this, SLOT (slotSettingsColorFilter ()));
473 
474  m_actionSettingsAxesChecker = new QAction (tr ("Axes Checker"), this);
475  m_actionSettingsAxesChecker->setStatusTip (tr ("Edit Axes Checker settings."));
476  m_actionSettingsAxesChecker->setWhatsThis (tr ("Axes Checker Settings\n\n"
477  "Axes checker can reveal any axis point mistakes, which are otherwise hard to find."));
478  connect (m_actionSettingsAxesChecker, SIGNAL (triggered ()), this, SLOT (slotSettingsAxesChecker ()));
479 
480  m_actionSettingsGridRemoval = new QAction (tr ("Grid Line Removal"), this);
481  m_actionSettingsGridRemoval->setStatusTip (tr ("Edit Grid Line Removal settings."));
482  m_actionSettingsGridRemoval->setWhatsThis (tr ("Grid Line Removal Settings\n\n"
483  "Grid line removal isolates curve lines for easier Point Matching and Segment Filling, when "
484  "Color Filtering is not able to separate grid lines from curve lines."));
485  connect (m_actionSettingsGridRemoval, SIGNAL (triggered ()), this, SLOT (slotSettingsGridRemoval ()));
486 
487  m_actionSettingsPointMatch = new QAction (tr ("Point Match"), this);
488  m_actionSettingsPointMatch->setStatusTip (tr ("Edit Point Match settings."));
489  m_actionSettingsPointMatch->setWhatsThis (tr ("Point Match Settings\n\n"
490  "Point match settings determine how points are matched while in Point Match mode"));
491  connect (m_actionSettingsPointMatch, SIGNAL (triggered ()), this, SLOT (slotSettingsPointMatch ()));
492 
493  m_actionSettingsSegments = new QAction (tr ("Segment Fill"), this);
494  m_actionSettingsSegments->setStatusTip (tr ("Edit Segment Fill settings."));
495  m_actionSettingsSegments->setWhatsThis (tr ("Segment Fill Settings\n\n"
496  "Segment fill settings determine how points are generated in the Segment Fill mode"));
497  connect (m_actionSettingsSegments, SIGNAL (triggered ()), this, SLOT (slotSettingsSegments ()));
498 
499  m_actionSettingsCommon = new QAction (tr ("Common"), this);
500  m_actionSettingsCommon->setStatusTip (tr ("Edit Common settings."));
501  m_actionSettingsCommon->setWhatsThis (tr ("Common Settings\n\n"
502  "Common settings are changed to fine tune cursor behavior and output formatting for "
503  "multiple modes"));
504  connect (m_actionSettingsCommon, SIGNAL (triggered ()), this, SLOT (slotSettingsCommon ()));
505 }
506 
507 void MainWindow::createActionsView ()
508 {
509  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createActionsView";
510 
511  m_actionViewBackground = new QAction (tr ("Background Toolbar"), this);
512  m_actionViewBackground->setCheckable (true);
513  m_actionViewBackground->setChecked (true);
514  m_actionViewBackground->setStatusTip (tr ("Show or hide the background toolbar."));
515  m_actionViewBackground->setWhatsThis (tr ("View Background ToolBar\n\n"
516  "Show or hide the background toolbar"));
517  connect (m_actionViewBackground, SIGNAL (triggered ()), this, SLOT (slotViewToolBarBackground ()));
518 
519  m_actionViewChecklistGuide = new QAction (tr ("Checklist Guide Toolbar"), this);
520  m_actionViewChecklistGuide->setCheckable (true);
521  m_actionViewChecklistGuide->setChecked (false);
522  m_actionViewChecklistGuide->setStatusTip (tr ("Show or hide the checklist guide toolbar."));
523  m_actionViewChecklistGuide->setWhatsThis (tr ("View Checklist Guide ToolBar\n\n"
524  "Show or hide the checklist guide toolbar"));
525  connect (m_actionViewChecklistGuide, SIGNAL (changed ()), this, SLOT (slotViewToolBarChecklistGuide()));
526 
527  m_actionViewDigitize = new QAction (tr ("Digitizing Tools Toolbar"), this);
528  m_actionViewDigitize->setCheckable (true);
529  m_actionViewDigitize->setChecked (true);
530  m_actionViewDigitize->setStatusTip (tr ("Show or hide the digitizing tools toolbar."));
531  m_actionViewDigitize->setWhatsThis (tr ("View Digitizing Tools ToolBar\n\n"
532  "Show or hide the digitizing tools toolbar"));
533  connect (m_actionViewDigitize, SIGNAL (triggered ()), this, SLOT (slotViewToolBarDigitize()));
534 
535  m_actionViewSettingsViews = new QAction (tr ("Settings Views Toolbar"), this);
536  m_actionViewSettingsViews->setCheckable (true);
537  m_actionViewSettingsViews->setChecked (true);
538  m_actionViewSettingsViews->setStatusTip (tr ("Show or hide the settings views toolbar."));
539  m_actionViewSettingsViews->setWhatsThis (tr ("View Settings Views ToolBar\n\n"
540  "Show or hide the settings views toolbar. These views graphically show the "
541  "most important settings."));
542  connect (m_actionViewSettingsViews, SIGNAL (triggered ()), this, SLOT (slotViewToolBarSettingsViews()));
543 
544  m_actionViewToolTips = new QAction (tr ("Tool Tips"), this);
545  m_actionViewToolTips->setCheckable (true);
546  m_actionViewToolTips->setChecked (true);
547  m_actionViewToolTips->setStatusTip (tr ("Show or hide the tool tips."));
548  m_actionViewToolTips->setWhatsThis (tr ("View Tool Tips\n\n"
549  "Show or hide the tool tips"));
550  connect (m_actionViewToolTips, SIGNAL (triggered ()), this, SLOT (slotViewToolTips()));
551 
552  m_actionViewBackgroundNone = new QAction (tr ("No Background"), this);
553  m_actionViewBackgroundNone->setCheckable (true);
554  m_actionViewBackgroundNone->setStatusTip (tr ("Do not show the image underneath the points."));
555  m_actionViewBackgroundNone->setWhatsThis (tr ("No Background\n\n"
556  "No image is shown so points are easier to see"));
557 
558  m_actionViewBackgroundOriginal = new QAction (tr ("Show Original Image"), this);
559  m_actionViewBackgroundOriginal->setCheckable (true);
560  m_actionViewBackgroundOriginal->setStatusTip (tr ("Show the original image underneath the points."));
561  m_actionViewBackgroundOriginal->setWhatsThis (tr ("Show Original Image\n\n"
562  "Show the original image underneath the points"));
563 
564  m_actionViewBackgroundFiltered = new QAction (tr ("Show Filtered Image"), this);
565  m_actionViewBackgroundFiltered->setCheckable (true);
566  m_actionViewBackgroundFiltered->setChecked (true);
567  m_actionViewBackgroundFiltered->setStatusTip (tr ("Show the filtered image underneath the points."));
568  m_actionViewBackgroundFiltered->setWhatsThis (tr ("Show Filtered Image\n\n"
569  "Show the filtered image underneath the points.\n\n"
570  "The filtered image is created from the original image according to the "
571  "Filter preferences so unimportant information is hidden and important "
572  "information is emphasized"));
573 
574  m_actionViewCurvesNone = new QAction (tr ("Hide All Curves"), this);
575  m_actionViewCurvesNone->setCheckable (true);
576  m_actionViewCurvesNone->setStatusTip (tr ("Hide all digitized curves."));
577  m_actionViewCurvesNone->setWhatsThis (tr ("Hide All Curves\n\n"
578  "No axis points or digitized graph curves are shown so the image is easier to see."));
579 
580  m_actionViewCurvesSelected = new QAction (tr ("Show Selected Curve"), this);
581  m_actionViewCurvesSelected->setCheckable (true);
582  m_actionViewCurvesSelected->setStatusTip (tr ("Show only the currently selected curve."));
583  m_actionViewCurvesSelected->setWhatsThis (tr ("Show Selected Curve\n\n"
584  "Show only the digitized points and line that belong to the currently selected curve."));
585 
586  m_actionViewCurvesAll = new QAction (tr ("Show All Curves"), this);
587  m_actionViewCurvesAll->setCheckable (true);
588  m_actionViewCurvesAll->setChecked (true);
589  m_actionViewCurvesAll->setStatusTip (tr ("Show all curves."));
590  m_actionViewCurvesAll->setWhatsThis (tr ("Show All Curves\n\n"
591  "Show all digitized axis points and graph curves"));
592 
593  m_groupBackground = new QActionGroup(this);
594  m_groupBackground->addAction (m_actionViewBackgroundNone);
595  m_groupBackground->addAction (m_actionViewBackgroundOriginal);
596  m_groupBackground->addAction (m_actionViewBackgroundFiltered);
597  connect (m_groupBackground, SIGNAL(triggered (QAction*)), this, SLOT (slotViewGroupBackground(QAction*)));
598 
599  m_groupCurves = new QActionGroup(this);
600  m_groupCurves->addAction (m_actionViewCurvesNone);
601  m_groupCurves->addAction (m_actionViewCurvesSelected);
602  m_groupCurves->addAction (m_actionViewCurvesAll);
603  connect (m_groupCurves, SIGNAL(triggered (QAction*)), this, SLOT (slotViewGroupCurves(QAction*)));
604 
605  m_actionStatusNever = new QAction (tr ("Hide Always"), this);
606  m_actionStatusNever->setCheckable(true);
607  m_actionStatusNever->setStatusTip (tr ("Always hide the status bar."));
608  m_actionStatusNever->setWhatsThis (tr ("Hide the status bar. No temporary status or feedback messages will appear."));
609 
610  m_actionStatusTemporary = new QAction (tr ("Show Temporary Messages"), this);
611  m_actionStatusTemporary->setCheckable(true);
612  m_actionStatusTemporary->setStatusTip (tr ("Hide the status bar except when display temporary messages."));
613  m_actionStatusTemporary->setWhatsThis (tr ("Hide the status bar, except when displaying temporary status and feedback messages."));
614 
615  m_actionStatusAlways = new QAction (tr ("Show Always"), this);
616  m_actionStatusAlways->setCheckable(true);
617  m_actionStatusAlways->setStatusTip (tr ("Always show the status bar."));
618  m_actionStatusAlways->setWhatsThis (tr ("Show the status bar. Besides displaying temporary status and feedback messages, "
619  "the status bar also displays information about the cursor position."));
620 
621  m_groupStatus = new QActionGroup(this);
622  m_groupStatus->addAction (m_actionStatusNever);
623  m_groupStatus->addAction (m_actionStatusTemporary);
624  m_groupStatus->addAction (m_actionStatusAlways);
625  connect (m_groupStatus, SIGNAL (triggered (QAction*)), this, SLOT (slotViewGroupStatus(QAction*)));
626 
627  m_actionZoomOut = new QAction (tr ("Zoom Out"), this);
628  m_actionZoomOut->setStatusTip (tr ("Zoom out"));
629  m_actionZoomOut->setShortcut (tr ("-"));
630  connect (m_actionZoomOut, SIGNAL (triggered ()), this, SLOT (slotViewZoomOut ()));
631 
632  m_actionZoomIn = new QAction (tr ("Zoom In"), this);
633  m_actionZoomIn->setStatusTip (tr ("Zoom in"));
634  m_actionZoomIn->setShortcut (tr ("+"));
635  connect (m_actionZoomIn, SIGNAL (triggered ()), this, SLOT (slotViewZoomIn ()));
636 
637  m_actionZoom16To1 = new QAction (tr ("16:1 (1600%)"), this);
638  m_actionZoom16To1->setCheckable (true);
639  m_actionZoom16To1->setStatusTip (tr ("Zoom 16:1"));
640  connect (m_actionZoom16To1, SIGNAL (triggered ()), this, SLOT (slotViewZoom16To1 ()));
641 
642  m_actionZoom8To1 = new QAction (tr ("8:1 (800%)"), this);
643  m_actionZoom8To1->setCheckable (true);
644  m_actionZoom8To1->setStatusTip (tr ("Zoom 8:1"));
645  connect (m_actionZoom8To1, SIGNAL (triggered ()), this, SLOT (slotViewZoom8To1 ()));
646 
647  m_actionZoom4To1 = new QAction (tr ("4:1 (400%)"), this);
648  m_actionZoom4To1->setCheckable (true);
649  m_actionZoom4To1->setStatusTip (tr ("Zoom 4:1"));
650  connect (m_actionZoom4To1, SIGNAL (triggered ()), this, SLOT (slotViewZoom4To1 ()));
651 
652  m_actionZoom2To1 = new QAction (tr ("2:1 (200%)"), this);
653  m_actionZoom2To1->setCheckable (true);
654  m_actionZoom2To1->setStatusTip (tr ("Zoom 2:1"));
655  connect (m_actionZoom2To1, SIGNAL (triggered ()), this, SLOT (slotViewZoom2To1 ()));
656 
657  m_actionZoom1To1 = new QAction (tr ("1:1 (100%)"), this);
658  m_actionZoom1To1->setCheckable (true);
659  m_actionZoom1To1->setChecked (true);
660  m_actionZoom1To1->setStatusTip (tr ("Zoom 6:1"));
661  connect (m_actionZoom1To1, SIGNAL (triggered ()), this, SLOT (slotViewZoom1To1 ()));
662 
663  m_actionZoom1To2 = new QAction (tr ("1:2 (50%)"), this);
664  m_actionZoom1To2->setCheckable (true);
665  m_actionZoom1To2->setStatusTip (tr ("Zoom 1:2"));
666  connect (m_actionZoom1To2, SIGNAL (triggered ()), this, SLOT (slotViewZoom1To2 ()));
667 
668  m_actionZoom1To4 = new QAction (tr ("1:4 (25%)"), this);
669  m_actionZoom1To4->setCheckable (true);
670  m_actionZoom1To4->setStatusTip (tr ("Zoom 1:4"));
671  connect (m_actionZoom1To4, SIGNAL (triggered ()), this, SLOT (slotViewZoom1To4 ()));
672 
673  m_actionZoom1To8 = new QAction (tr ("1:8 (12.5%)"), this);
674  m_actionZoom1To8->setCheckable (true);
675  m_actionZoom1To8->setStatusTip (tr ("Zoom 1:8"));
676  connect (m_actionZoom1To8, SIGNAL (triggered ()), this, SLOT (slotViewZoom1To8 ()));
677 
678  m_actionZoom1To16 = new QAction (tr ("1:16 (6.25%)"), this);
679  m_actionZoom1To16->setCheckable (true);
680  m_actionZoom1To16->setStatusTip (tr ("Zoom 1:16"));
681  connect (m_actionZoom1To16, SIGNAL (triggered ()), this, SLOT (slotViewZoom1To16 ()));
682 
683  m_actionZoomFill = new QAction (tr ("Fill"), this);
684  m_actionZoomFill->setCheckable (true);
685  m_actionZoomFill->setStatusTip (tr ("Zoom with stretching to fill window"));
686  connect (m_actionZoomFill, SIGNAL (triggered ()), this, SLOT (slotViewZoomFill ()));
687 
688  m_groupZoom = new QActionGroup (this);
689  m_groupZoom->addAction (m_actionZoom16To1);
690  m_groupZoom->addAction (m_actionZoom8To1);
691  m_groupZoom->addAction (m_actionZoom4To1);
692  m_groupZoom->addAction (m_actionZoom2To1);
693  m_groupZoom->addAction (m_actionZoom1To1);
694  m_groupZoom->addAction (m_actionZoom1To2);
695  m_groupZoom->addAction (m_actionZoom1To4);
696  m_groupZoom->addAction (m_actionZoom1To8);
697  m_groupZoom->addAction (m_actionZoom1To16);
698  m_groupZoom->addAction (m_actionZoomFill);
699 }
700 
701 void MainWindow::createCentralWidget ()
702 {
703  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createCentralWidget";
704 
705  QWidget *widget = new QWidget;
706  setCentralWidget (widget);
707  m_layout = new QVBoxLayout;
708  widget->setLayout (m_layout);
709 }
710 
711 void MainWindow::createCommandStackShadow ()
712 {
713  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createCommandStackShadow";
714 
715  m_cmdStackShadow = new CmdStackShadow;
716 }
717 
718 void MainWindow::createHelpWindow ()
719 {
720  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createHelpWindow";
721 
722  m_helpWindow = new HelpWindow (this);
723  m_helpWindow->hide ();
724  addDockWidget (Qt::RightDockWidgetArea,
725  m_helpWindow); // Dock area is required by addDockWidget but immediately overridden in next line
726  m_helpWindow->setFloating (true);
727 
728  connect (m_actionHelpHelp, SIGNAL (triggered ()), m_helpWindow, SLOT (show ()));
729 }
730 
731 void MainWindow::createIcons()
732 {
733  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createIcons";
734 
735  QIcon icon;
736  QPixmap icon16 (bannerapp_16);
737  QPixmap icon32 (bannerapp_32);
738  QPixmap icon64 (bannerapp_64);
739  QPixmap icon128 (bannerapp_128);
740  QPixmap icon256 (bannerapp_256);
741 
742  icon.addPixmap (icon16);
743  icon.addPixmap (icon32);
744  icon.addPixmap (icon64);
745  icon.addPixmap (icon128);
746  icon.addPixmap (icon256);
747 
748  setWindowIcon (icon);
749 }
750 
751 void MainWindow::createLoadImageFromUrl ()
752 {
753  m_loadImageFromUrl = new LoadImageFromUrl (*this);
754 }
755 
756 void MainWindow::createMenus()
757 {
758  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createMenus";
759 
760  m_menuFile = menuBar()->addMenu(tr("&File"));
761  m_menuFile->addAction (m_actionImport);
762  m_menuFile->addAction (m_actionOpen);
763  m_menuFileOpenRecent = new QMenu (tr ("Open &Recent"));
764  for (unsigned int i = 0; i < MAX_RECENT_FILE_LIST_SIZE; i++) {
765  m_menuFileOpenRecent->addAction (m_actionRecentFiles.at (i));
766  }
767  m_menuFile->addMenu (m_menuFileOpenRecent);
768  m_menuFile->addAction (m_actionClose);
769  m_menuFile->insertSeparator (m_actionSave);
770  m_menuFile->addAction (m_actionSave);
771  m_menuFile->addAction (m_actionSaveAs);
772  m_menuFile->addAction (m_actionExport);
773  m_menuFile->insertSeparator (m_actionPrint);
774  m_menuFile->addAction (m_actionPrint);
775  m_menuFile->insertSeparator (m_actionExit);
776  m_menuFile->addAction (m_actionExit);
777 
778  m_menuEdit = menuBar()->addMenu(tr("&Edit"));
779  m_menuEdit->addAction (m_actionEditUndo);
780  m_menuEdit->addAction (m_actionEditRedo);
781  m_menuEdit->insertSeparator (m_actionEditCut);
782  m_menuEdit->addAction (m_actionEditCut);
783  m_menuEdit->addAction (m_actionEditCopy);
784  m_menuEdit->addAction (m_actionEditPaste);
785  m_menuEdit->addAction (m_actionEditDelete);
786 
787  m_menuDigitize = menuBar()->addMenu(tr("Digitize"));
788  m_menuDigitize->addAction (m_actionDigitizeSelect);
789  m_menuDigitize->addAction (m_actionDigitizeAxis);
790  m_menuDigitize->addAction (m_actionDigitizeCurve);
791  m_menuDigitize->addAction (m_actionDigitizePointMatch);
792  m_menuDigitize->addAction (m_actionDigitizeColorPicker);
793  m_menuDigitize->addAction (m_actionDigitizeSegment);
794 
795  m_menuView = menuBar()->addMenu(tr("View"));
796  m_menuView->addAction (m_actionViewBackground);
797  m_menuView->addAction (m_actionViewDigitize);
798  m_menuView->addAction (m_actionViewChecklistGuide);
799  m_menuView->addAction (m_actionViewSettingsViews);
800  m_menuView->insertSeparator (m_actionViewToolTips);
801  m_menuView->addAction (m_actionViewToolTips);
802  m_menuView->insertSeparator (m_actionViewBackgroundNone);
803  m_menuViewBackground = new QMenu (tr ("Background"));
804  m_menuViewBackground->addAction (m_actionViewBackgroundNone);
805  m_menuViewBackground->addAction (m_actionViewBackgroundOriginal);
806  m_menuViewBackground->addAction (m_actionViewBackgroundFiltered);
807  m_menuView->addMenu (m_menuViewBackground);
808  m_menuViewCurves = new QMenu (tr ("Curves"));
809  m_menuViewCurves->addAction (m_actionViewCurvesNone);
810  m_menuViewCurves->addAction (m_actionViewCurvesSelected);
811  m_menuViewCurves->addAction (m_actionViewCurvesAll);
812  m_menuView->addMenu (m_menuViewCurves);
813  m_menuViewStatus = new QMenu (tr ("Status Bar"));
814  m_menuViewStatus->addAction (m_actionStatusNever);
815  m_menuViewStatus->addAction (m_actionStatusTemporary);
816  m_menuViewStatus->addAction (m_actionStatusAlways);
817  m_menuView->addMenu (m_menuViewStatus);
818  m_menuViewZoom = new QMenu (tr ("Zoom"));
819  m_menuViewZoom->addAction (m_actionZoomOut);
820  m_menuViewZoom->addAction (m_actionZoomIn);
821  m_menuViewZoom->insertSeparator (m_actionZoom16To1);
822  m_menuViewZoom->addAction (m_actionZoom16To1);
823  m_menuViewZoom->addAction (m_actionZoom8To1);
824  m_menuViewZoom->addAction (m_actionZoom4To1);
825  m_menuViewZoom->addAction (m_actionZoom2To1);
826  m_menuViewZoom->addAction (m_actionZoom1To1);
827  m_menuViewZoom->addAction (m_actionZoom1To2);
828  m_menuViewZoom->addAction (m_actionZoom1To4);
829  m_menuViewZoom->addAction (m_actionZoom1To8);
830  m_menuViewZoom->addAction (m_actionZoom1To16);
831  m_menuViewZoom->addAction (m_actionZoomFill);
832  m_menuView->addMenu (m_menuViewZoom);
833 
834  m_menuSettings = menuBar()->addMenu(tr ("Settings"));
835  m_menuSettings->addAction (m_actionSettingsCoords);
836  m_menuSettings->addAction (m_actionSettingsCurveAddRemove);
837  m_menuSettings->addAction (m_actionSettingsCurveProperties);
838  m_menuSettings->addAction (m_actionSettingsDigitizeCurve);
839  m_menuSettings->addAction (m_actionSettingsExport);
840  m_menuSettings->addAction (m_actionSettingsColorFilter);
841  m_menuSettings->addAction (m_actionSettingsAxesChecker);
842  m_menuSettings->addAction (m_actionSettingsGridRemoval);
843  m_menuSettings->addAction (m_actionSettingsPointMatch);
844  m_menuSettings->addAction (m_actionSettingsSegments);
845  m_menuSettings->addAction (m_actionSettingsCommon);
846 
847  m_menuHelp = menuBar()->addMenu(tr("&Help"));
848  m_menuHelp->addAction (m_actionHelpChecklistGuideWizard);
849  m_menuHelp->insertSeparator(m_actionHelpWhatsThis);
850  m_menuHelp->addAction (m_actionHelpWhatsThis);
851  m_menuHelp->addAction (m_actionHelpTutorial);
852  m_menuHelp->addAction (m_actionHelpHelp);
853  m_menuHelp->addAction (m_actionHelpAbout);
854 
855  updateRecentFileList();
856 }
857 
858 void MainWindow::createNetwork ()
859 {
860  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createNetwork";
861 
862  m_networkClient = new NetworkClient (this);
863 }
864 
865 void MainWindow::createSettingsDialogs ()
866 {
867  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createSettingsDialogs";
868 
869  m_dlgSettingsCoords = new DlgSettingsCoords (*this);
870  m_dlgSettingsCurveAddRemove = new DlgSettingsCurveAddRemove (*this);
871  m_dlgSettingsCurveProperties = new DlgSettingsCurveProperties (*this);
872  m_dlgSettingsDigitizeCurve = new DlgSettingsDigitizeCurve (*this);
873  m_dlgSettingsExportFormat = new DlgSettingsExportFormat (*this);
874  m_dlgSettingsColorFilter = new DlgSettingsColorFilter (*this);
875  m_dlgSettingsAxesChecker = new DlgSettingsAxesChecker (*this);
876  m_dlgSettingsGridRemoval = new DlgSettingsGridRemoval (*this);
877  m_dlgSettingsPointMatch = new DlgSettingsPointMatch (*this);
878  m_dlgSettingsSegments = new DlgSettingsSegments (*this);
879  m_dlgSettingsCommon = new DlgSettingsCommon (*this);
880 
881  m_dlgSettingsCoords->setVisible (false);
882  m_dlgSettingsCurveAddRemove->setVisible (false);
883  m_dlgSettingsCurveProperties->setVisible (false);
884  m_dlgSettingsDigitizeCurve->setVisible (false);
885  m_dlgSettingsExportFormat->setVisible (false);
886  m_dlgSettingsColorFilter->setVisible (false);
887  m_dlgSettingsAxesChecker->setVisible (false);
888  m_dlgSettingsGridRemoval->setVisible (false);
889  m_dlgSettingsPointMatch->setVisible (false);
890  m_dlgSettingsSegments->setVisible (false);
891  m_dlgSettingsCommon->setVisible (false);
892 }
893 
894 void MainWindow::createScene ()
895 {
896  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createScene";
897 
898  m_scene = new GraphicsScene (this);
899  m_view = new GraphicsView (m_scene, *this);
900  m_layout->addWidget (m_view);
901 }
902 
903 void MainWindow::createStateContextBackground ()
904 {
905  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createStateContextBackground";
906 
907  m_backgroundStateContext = new BackgroundStateContext (*this);
908 }
909 
910 void MainWindow::createStateContextDigitize ()
911 {
912  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createStateContextDigitize";
913 
914  m_digitizeStateContext = new DigitizeStateContext (*this,
915  *m_view,
916  m_isGnuplot);
917 }
918 
919 void MainWindow::createStateContextTransformation ()
920 {
921  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createStateContextTransformation";
922 
923  ENGAUGE_CHECK_PTR (m_scene);
924 
925  m_transformationStateContext = new TransformationStateContext (*m_scene,
926  m_isGnuplot);
927 }
928 
929 void MainWindow::createStatusBar ()
930 {
931  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createStatusBar";
932 
933  m_statusBar = new StatusBar (*statusBar ());
934  connect (this, SIGNAL (signalZoom(int)), m_statusBar, SLOT (slotZoom(int)));
935  connect (m_statusBar, SIGNAL (signalZoom (int)), this, SLOT (slotViewZoom (int)));
936 }
937 
938 void MainWindow::createToolBars ()
939 {
940  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createToolBars";
941 
942  const int VIEW_SIZE = 22;
943 
944  // Background toolbar widgets
945  m_cmbBackground = new QComboBox ();
946  m_cmbBackground->setEnabled (false);
947  m_cmbBackground->setStatusTip (tr ("Select background image"));
948  m_cmbBackground->setWhatsThis (tr ("Selected Background\n\n"
949  "Select background image:\n"
950  "1) No background which highlights points\n"
951  "2) Original image which shows everything\n"
952  "3) Filtered image which highlights important details"));
953  m_cmbBackground->addItem ("No background", QVariant (BACKGROUND_IMAGE_NONE));
954  m_cmbBackground->addItem ("Original image", QVariant (BACKGROUND_IMAGE_ORIGINAL));
955  m_cmbBackground->addItem ("Filtered image", QVariant (BACKGROUND_IMAGE_FILTERED));
956  // selectBackgroundOriginal needs currentIndexChanged
957  connect (m_cmbBackground, SIGNAL (currentIndexChanged (int)), this, SLOT (slotCmbBackground (int)));
958 
959  // Background toolbar
960  m_toolBackground = new QToolBar (tr ("Background"), this);
961  m_toolBackground->addWidget (m_cmbBackground);
962  addToolBar (m_toolBackground);
963 
964  // Digitize toolbar widgets that are not created elsewhere
965  m_cmbCurve = new QComboBox ();
966  m_cmbCurve->setEnabled (false);
967  m_cmbCurve->setMinimumWidth (180);
968  m_cmbCurve->setStatusTip (tr ("Select curve for new points."));
969  m_cmbCurve->setWhatsThis (tr ("Selected Curve Name\n\n"
970  "Select curve for any new points. Every point belongs to one curve."));
971  connect (m_cmbCurve, SIGNAL (activated (int)), this, SLOT (slotCmbCurve (int))); // activated() ignores code changes
972 
973  // Digitize toolbar
974  m_toolDigitize = new QToolBar (tr ("Drawing"), this);
975  m_toolDigitize->addAction (m_actionDigitizeSelect);
976  m_toolDigitize->insertSeparator (m_actionDigitizeAxis);
977  m_toolDigitize->addAction (m_actionDigitizeAxis);
978  m_toolDigitize->insertSeparator (m_actionDigitizeCurve);
979  m_toolDigitize->addAction (m_actionDigitizeCurve);
980  m_toolDigitize->addAction (m_actionDigitizePointMatch);
981  m_toolDigitize->addAction (m_actionDigitizeColorPicker);
982  m_toolDigitize->addAction (m_actionDigitizeSegment);
983  m_toolDigitize->addWidget (m_cmbCurve);
984  addToolBar (m_toolDigitize);
985 
986  // Views toolbar widgets
987  m_viewPointStyle = new ViewPointStyle();
988  m_viewPointStyle->setMinimumSize(VIEW_SIZE, VIEW_SIZE);
989  m_viewPointStyle->setMaximumSize(VIEW_SIZE, VIEW_SIZE);
990  m_viewPointStyle->setStatusTip (tr ("Points style for the currently selected curve"));
991  m_viewPointStyle->setWhatsThis (tr ("Points Style\n\n"
992  "Points style for the currently selected curve. The points style is only "
993  "displayed in this toolbar. To change the points style, "
994  "use the Curve Properties dialog."));
995 
996  m_viewSegmentFilter = new ViewSegmentFilter();
997  m_viewSegmentFilter->setMinimumSize(VIEW_SIZE, VIEW_SIZE);
998  m_viewSegmentFilter->setMaximumSize(VIEW_SIZE, VIEW_SIZE);
999  m_viewSegmentFilter->setStatusTip (tr ("View of filter for current curve in Segment Fill mode"));
1000  m_viewSegmentFilter->setWhatsThis (tr ("Segment Fill Filter\n\n"
1001  "View of filter for the current curve in Segment Fill mode. The filter settings are only "
1002  "displayed in this toolbar. To changed the filter settings, "
1003  "use the Color Picker mode or the Filter Settings dialog."));
1004 
1005  // Settings views toolbar
1006  m_toolSettingsViews = new QToolBar (tr ("Views"), this);
1007  m_toolSettingsViews->addWidget (m_viewPointStyle);
1008  m_toolSettingsViews->addWidget (new QLabel (" ")); // A hack, but this works to put some space between the adjacent widgets
1009  m_toolSettingsViews->addWidget (m_viewSegmentFilter);
1010  addToolBar (m_toolSettingsViews);
1011 
1012  // Checklist guide starts out hidden. It will be positioned in settingsRead
1013  m_dockChecklistGuide = new ChecklistGuide (this);
1014  connect (m_dockChecklistGuide, SIGNAL (signalChecklistClosed()), this, SLOT (slotChecklistClosed()));
1015 }
1016 
1017 void MainWindow::createTutorial ()
1018 {
1019  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::createTutorial";
1020 
1021  m_tutorialDlg = new TutorialDlg (this);
1022  m_tutorialDlg->setModal (true);
1023  m_tutorialDlg->setMinimumSize (500, 400);
1024  m_tutorialDlg->hide();
1025 }
1026 
1027 bool MainWindow::eventFilter(QObject *target, QEvent *event)
1028 {
1029  if (event->type () == QEvent::KeyPress) {
1030 
1031  QKeyEvent *eventKeyPress = (QKeyEvent *) event;
1032 
1033  if ((eventKeyPress->key() == Qt::Key_E) &&
1034  ((eventKeyPress->modifiers() & Qt::ShiftModifier) != 0) &&
1035  ((eventKeyPress->modifiers() & Qt::ControlModifier) != 0)) {
1036 
1037  saveErrorReportFileAndExit ("Shift+Control+E",
1038  __FILE__,
1039  __LINE__,
1040  "userTriggered");
1041  }
1042  }
1043 
1044  return QObject::eventFilter (target, event);
1045 }
1046 
1047 void MainWindow::fileImport (const QString &fileName)
1048 {
1049  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::fileImport fileName=" << fileName.toLatin1 ().data ();
1050 
1051  QString originalFileOld = m_originalFile;
1052  bool originalFileWasImported = m_originalFileWasImported;
1053 
1054  m_originalFile = fileName; // Make this available for logging in case an error occurs during the load
1055  m_originalFileWasImported = true;
1056 
1057  QImage image;
1058  bool loaded = false;
1059 #ifdef ENGAUGE_JPEG2000
1060  Jpeg2000 jpeg2000;
1061  loaded = jpeg2000.load (fileName,
1062  image);
1063 #endif // ENGAUGE_JPEG2000
1064  if (!loaded) {
1065  loaded = image.load (fileName);
1066  }
1067 
1068  if (!loaded) {
1069  QMessageBox::warning (this,
1070  engaugeWindowTitle(),
1071  tr("Cannot read file %1.").
1072  arg(fileName));
1073 
1074  // Reset
1075  m_originalFile = originalFileOld;
1076  m_originalFileWasImported = originalFileWasImported;
1077 
1078  return;
1079  }
1080 
1081  loadImage (fileName,
1082  image);
1083 }
1084 
1086 {
1087  return m_backgroundStateContext->imageForCurveState();
1088 }
1089 
1091 {
1092  return m_isGnuplot;
1093 }
1094 
1095 void MainWindow::loadCurveListFromCmdMediator ()
1096 {
1097  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::loadCurveListFromCmdMediator";
1098 
1099  m_cmbCurve->clear ();
1100  QStringList curvesGraphsNames = m_cmdMediator->curvesGraphsNames ();
1101  QStringList::iterator itr;
1102  for (itr = curvesGraphsNames.begin (); itr != curvesGraphsNames.end (); itr++) {
1103 
1104  QString curvesGraphName = *itr;
1105  m_cmbCurve->addItem (curvesGraphName);
1106  }
1107 
1108  // Arbitrarily pick the first curve
1109  m_cmbCurve->setCurrentIndex (0);
1110 }
1111 
1112 void MainWindow::loadDocumentFile (const QString &fileName)
1113 {
1114  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::loadDocumentFile fileName=" << fileName.toLatin1 ().data ();
1115 
1116  QApplication::setOverrideCursor(Qt::WaitCursor);
1117  CmdMediator *cmdMediator = new CmdMediator (*this,
1118  fileName);
1119  QApplication::restoreOverrideCursor();
1120 
1121  if (cmdMediator->successfulRead ()) {
1122 
1123  setCurrentPathFromFile (fileName);
1124  rebuildRecentFileListForCurrentFile(fileName);
1125  m_currentFile = fileName; // This enables the FileSaveAs menu option
1126 
1127  if (m_cmdMediator != 0) {
1128  delete m_cmdMediator;
1129  m_cmdMediator = 0;
1130  }
1131 
1132  m_cmdMediator = cmdMediator;
1133  setupAfterLoad(fileName,
1134  "File opened");
1135 
1136  // Start select mode
1137  m_actionDigitizeSelect->setChecked (true); // We assume user wants to first select existing stuff
1138  slotDigitizeSelect(); // Trigger transition so cursor gets updated immediately
1139 
1140  m_engaugeFile = fileName;
1141  m_originalFile = fileName; // This is needed by updateAfterCommand below if an error report is generated
1142  m_originalFileWasImported = false;
1143 
1144  updateAfterCommand (); // Enable Save button now that m_engaugeFile is set
1145 
1146  } else {
1147 
1148  QMessageBox::warning (this,
1149  engaugeWindowTitle(),
1150  tr("Cannot read file %1:\n%2.").
1151  arg(fileName).
1152  arg(cmdMediator->reasonForUnsuccessfulRead ()));
1153  delete cmdMediator;
1154 
1155  }
1156 }
1157 
1158 void MainWindow::loadErrorReportFile(const QString &initialPath,
1159  const QString &errorReportFile)
1160 {
1161  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::loadErrorReportFile"
1162  << " path=" << initialPath.toLatin1().data()
1163  << " file=" << errorReportFile.toLatin1().data();
1164 
1165  // The default path has been changed from its original executable-based initial value to the last directory used
1166  // according to the settings. Since the executable-based directory is much more stable, and we want a predictable
1167  // directory in the likely event that the error report file has a relative path, we temporarily switch the default path
1168  // back to the executable-based initial value
1169  QString originalPath = QDir::currentPath();
1170  QDir::setCurrent(initialPath);
1171 
1172  QFile file (errorReportFile);
1173  if (!file.exists()) {
1174  // Convert path from relative to absolute so file-not-found errors are easier to fix
1175  QFileInfo fileInfo (errorReportFile);
1176 
1177  QMessageBox::critical (this,
1178  engaugeWindowTitle(),
1179  tr ("File not found: ") + fileInfo.absoluteFilePath());
1180  exit (-1);
1181  }
1182 
1183  // Open the error report file as if it was a regular Document file
1184  QXmlStreamReader reader (&file);
1185  file.open(QIODevice::ReadOnly | QIODevice::Text);
1186  m_cmdMediator = new CmdMediator(*this,
1187  errorReportFile);
1188 
1189  // Load the commands into the shadow command stack
1190  m_cmdStackShadow->loadCommands (*this,
1191  m_cmdMediator->document(),
1192  reader);
1193  file.close();
1194 
1195  // Reset the original path now that the error report file has been read in
1196  QDir::setCurrent(originalPath);
1197 
1198  setupAfterLoad(errorReportFile,
1199  "Error report opened");
1200 
1201  // Start select mode
1202  m_actionDigitizeSelect->setChecked (true); // We assume user wants to first select existing stuff
1203  slotDigitizeSelect(); // Trigger transition so cursor gets updated immediately
1204 
1205  updateAfterCommand ();
1206 }
1207 
1208 void MainWindow::loadImage (const QString &fileName,
1209  const QImage &image)
1210 {
1211  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::loadImage fileName=" << fileName.toLatin1 ().data ();
1212 
1213  QApplication::setOverrideCursor(Qt::WaitCursor);
1214  CmdMediator *cmdMediator = new CmdMediator (*this,
1215  image);
1216  QApplication::restoreOverrideCursor();
1217 
1218  setCurrentPathFromFile (fileName);
1219  // We do not call rebuildRecentFileListForCurrentFile for an image file, so only proper Engauge document files appear in the recent file list
1220  m_engaugeFile = EMPTY_FILENAME; // Forces first Save to be treated as Save As
1221 
1222  if (m_cmdMediator != 0) {
1223  delete m_cmdMediator;
1224  m_cmdMediator = 0;
1225  }
1226 
1227  m_cmdMediator = cmdMediator;
1228  setupAfterLoad(fileName,
1229  "File imported");
1230 
1231  if (m_actionHelpChecklistGuideWizard->isChecked ()) {
1232 
1233  // Show wizard
1234  ChecklistGuideWizard *wizard = new ChecklistGuideWizard (*this);
1235  if (wizard->exec() == QDialog::Accepted) {
1236 
1237  // Populate the checklist guide
1238  m_dockChecklistGuide->setTemplateHtml (wizard->templateHtml(),
1239  wizard->curveNames());
1240 
1241  // Unhide the checklist guide
1242  m_actionViewChecklistGuide->setChecked (true);
1243 
1244  // Update Document
1245  CurvesGraphs curvesGraphs;
1246  wizard->populateCurvesGraphs (curvesGraphs);
1247  m_cmdMediator->document().setCurvesGraphs(curvesGraphs);
1248 
1249  // Update the curve dropdown
1250  loadCurveListFromCmdMediator();
1251  }
1252  delete wizard;
1253  }
1254 
1255  // Start axis mode
1256  m_actionDigitizeAxis->setChecked (true); // We assume user first wants to digitize axis points
1257  slotDigitizeAxis (); // Trigger transition so cursor gets updated immediately
1258 
1259  updateControls ();
1260 }
1261 
1262 void MainWindow::loadInputFileForErrorReport(QDomDocument &domInputFile) const
1263 {
1264  QFile file (m_originalFile);
1265 
1266  // File should be available for opening, if not then the dom will be left empty. We assume it has not been
1267  // modified since opened
1268  if (!file.open (QIODevice::ReadOnly)) {
1269  return;
1270  }
1271 
1272  domInputFile.setContent (&file);
1273  file.close();
1274 }
1275 
1276 void MainWindow::loadToolTips()
1277 {
1278  if (m_actionViewToolTips->isChecked ()) {
1279 
1280  // Show tool tips
1281  m_actionDigitizeSelect->setToolTip (DIGITIZE_ACTION_SELECT);
1282  m_actionDigitizeAxis->setToolTip (DIGITIZE_ACTION_AXIS_POINT);
1283  m_actionDigitizeCurve->setToolTip (DIGITIZE_ACTION_CURVE_POINT);
1284  m_actionDigitizePointMatch->setToolTip (DIGITIZE_ACTION_POINT_MATCH);
1285  m_actionDigitizeColorPicker->setToolTip (DIGITIZE_ACTION_COLOR_PICKER);
1286  m_actionDigitizeSegment->setToolTip (DIGITIZE_ACTION_SEGMENT_POINTS);
1287  m_cmbBackground->setToolTip (tr ("Background image."));
1288  m_cmbCurve->setToolTip (tr ("Currently selected curve."));
1289  m_viewPointStyle->setToolTip (tr ("Point style for currently selected curve."));
1290  m_viewSegmentFilter->setToolTip (tr ("Segment Fill filter for currently selected curve."));
1291 
1292  } else {
1293 
1294  // Remove any previous tool tips
1295  m_actionDigitizeSelect->setToolTip ("");
1296  m_actionDigitizeAxis->setToolTip ("");
1297  m_actionDigitizeCurve->setToolTip ("");
1298  m_actionDigitizePointMatch->setToolTip ("");
1299  m_actionDigitizeColorPicker->setToolTip ("");
1300  m_actionDigitizeSegment->setToolTip ("");
1301  m_cmbBackground->setToolTip ("");
1302  m_cmbCurve->setToolTip ("");
1303  m_viewPointStyle->setToolTip ("");
1304  m_viewSegmentFilter->setToolTip ("");
1305 
1306  }
1307 }
1308 
1309 bool MainWindow::maybeSave()
1310 {
1311  if (m_cmdMediator != 0) {
1312  if (m_cmdMediator->isModified()) {
1313  QMessageBox::StandardButton ret = QMessageBox::warning (this,
1314  engaugeWindowTitle(),
1315  tr("The document has been modified.\n"
1316  "Do you want to save your changes?"),
1317  QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
1318  if (ret == QMessageBox::Save) {
1319  return slotFileSave();
1320  } else if (ret == QMessageBox::Cancel) {
1321  return false;
1322  }
1323  }
1324  }
1325 
1326  return true;
1327 }
1328 
1329 void MainWindow::rebuildRecentFileListForCurrentFile(const QString &filePath)
1330 {
1331  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::rebuildRecentFileListForCurrentFile";
1332 
1333  setWindowFilePath (filePath);
1334 
1335  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
1336  QStringList recentFilePaths = settings.value (SETTINGS_RECENT_FILE_LIST).toStringList();
1337  recentFilePaths.removeAll (filePath); // Remove previous instance of the current filePath
1338  recentFilePaths.prepend (filePath); // Insert current filePath at start
1339  while (recentFilePaths.count () > (int) MAX_RECENT_FILE_LIST_SIZE) {
1340  recentFilePaths.removeLast (); // Remove entry since the number of entries exceeds the limit
1341  }
1342  settings.setValue (SETTINGS_RECENT_FILE_LIST, recentFilePaths);
1343 
1344  updateRecentFileList();
1345 }
1346 
1347 void MainWindow::resizeEvent(QResizeEvent * /* event */)
1348 {
1349  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::resizeEvent";
1350 
1351  if (m_actionZoomFill->isChecked ()) {
1352  slotViewZoomFill();
1353  }
1354 }
1355 
1356 bool MainWindow::saveDocumentFile (const QString &fileName)
1357 {
1358  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::saveDocumentFile fileName=" << fileName.toLatin1 ().data ();
1359 
1360  QFile file(fileName);
1361  if (!file.open(QFile::WriteOnly)) {
1362  QMessageBox::warning (this,
1363  engaugeWindowTitle(),
1364  tr ("Cannot write file %1: \n%2.").
1365  arg(fileName).
1366  arg(file.errorString()));
1367  return false;
1368  }
1369 
1370  rebuildRecentFileListForCurrentFile (fileName);
1371 
1372  QApplication::setOverrideCursor (Qt::WaitCursor);
1373  QXmlStreamWriter writer(&file);
1374  writer.setAutoFormatting(true);
1375  writer.writeStartDocument();
1376  writer.writeDTD("<!DOCTYPE engauge>");
1377  m_cmdMediator->document().saveXml(writer);
1378  writer.writeEndDocument();
1379  QApplication::restoreOverrideCursor ();
1380 
1381  // Notify the undo stack that the current state is now considered "clean". This will automatically trigger a
1382  // signal back to this class that will update the modified marker in the title bar
1383  m_cmdMediator->setClean ();
1384 
1385  setCurrentFile(fileName);
1386  m_engaugeFile = fileName;
1387  updateAfterCommand (); // Enable Save button now that m_engaugeFile is set
1388  m_statusBar->showTemporaryMessage("File saved");
1389 
1390  return true;
1391 }
1392 
1393 void MainWindow::saveErrorReportFileAndExit (const char *context,
1394  const char *file,
1395  int line,
1396  const char *comment) const
1397 {
1398  if (m_cmdMediator != 0) {
1399 
1400  QString reportWithoutDocument = saveErrorReportFileAndExitXml (context,
1401  file,
1402  line,
1403  comment,
1404  false);
1405  QString reportWithDocument = saveErrorReportFileAndExitXml (context,
1406  file,
1407  line,
1408  comment,
1409  true);
1410  DlgErrorReport dlg (reportWithoutDocument,
1411  reportWithDocument);
1412 
1413  // Ask user if report should be uploaded, and if the document is included when it is uploaded
1414  if (dlg.exec() == QDialog::Accepted) {
1415 
1416  // Upload the error report to the server
1417  m_networkClient->uploadErrorReport (dlg.xmlToUpload());
1418  }
1419  }
1420 }
1421 
1422 QString MainWindow::saveErrorReportFileAndExitXml (const char *context,
1423  const char *file,
1424  int line,
1425  const char *comment,
1426  bool includeDocument) const
1427 {
1428  const bool DEEP_COPY = true;
1429 
1430  QString xmlErrorReport;
1431  QXmlStreamWriter writer (&xmlErrorReport);
1432  writer.setAutoFormatting(true);
1433 
1434  // Entire error report contains metadata, commands and other details
1435  writer.writeStartElement(DOCUMENT_SERIALIZE_ERROR_REPORT);
1436 
1437  // Version
1438  writer.writeStartElement(DOCUMENT_SERIALIZE_APPLICATION);
1439  writer.writeAttribute(DOCUMENT_SERIALIZE_APPLICATION_VERSION_NUMBER, VERSION_NUMBER);
1440  writer.writeEndElement();
1441 
1442  // Document
1443  if (includeDocument) {
1444  // Insert snapshot xml into writer stream, by reading from reader stream. Highest level of snapshot is DOCUMENT_SERIALIZE_APPLICATION
1445  QXmlStreamReader reader (m_startingDocumentSnapshot);
1446  while (!reader.atEnd ()) {
1447  reader.readNext ();
1448  if (reader.tokenType() != QXmlStreamReader::StartDocument &&
1449  reader.tokenType() != QXmlStreamReader::EndDocument) {
1450  writer.writeCurrentToken (reader);
1451  }
1452  }
1453  }
1454 
1455  // Operating system
1456  writer.writeStartElement(DOCUMENT_SERIALIZE_OPERATING_SYSTEM);
1457  writer.writeAttribute(DOCUMENT_SERIALIZE_OPERATING_SYSTEM_ENDIAN, EndianToString (QSysInfo::ByteOrder));
1458  writer.writeAttribute(DOCUMENT_SERIALIZE_OPERATING_SYSTEM_WORD_SIZE, QString::number (QSysInfo::WordSize));
1459  writer.writeEndElement();
1460 
1461  // Image
1462  writer.writeStartElement(DOCUMENT_SERIALIZE_IMAGE);
1463  writer.writeAttribute(DOCUMENT_SERIALIZE_IMAGE_WIDTH, QString::number (m_cmdMediator->pixmap().width ()));
1464  writer.writeAttribute(DOCUMENT_SERIALIZE_IMAGE_HEIGHT, QString::number (m_cmdMediator->pixmap().height ()));
1465  writer.writeEndElement();
1466 
1467  // Placeholder for original file, before the commands in the command stack were applied
1468  writer.writeStartElement(DOCUMENT_SERIALIZE_FILE);
1469  writer.writeAttribute(DOCUMENT_SERIALIZE_FILE_IMPORTED,
1470  m_originalFileWasImported ? DOCUMENT_SERIALIZE_BOOL_TRUE : DOCUMENT_SERIALIZE_BOOL_FALSE);
1471  writer.writeEndElement();
1472 
1473  // Commands
1474  m_cmdMediator->saveXml(writer);
1475 
1476  // Error
1477  writer.writeStartElement(DOCUMENT_SERIALIZE_ERROR);
1478  writer.writeAttribute(DOCUMENT_SERIALIZE_ERROR_CONTEXT, context);
1479  writer.writeAttribute(DOCUMENT_SERIALIZE_ERROR_FILE, file);
1480  writer.writeAttribute(DOCUMENT_SERIALIZE_ERROR_LINE, QString::number (line));
1481  writer.writeAttribute(DOCUMENT_SERIALIZE_ERROR_COMMENT, comment);
1482  writer.writeEndElement();
1483 
1484  writer.writeEndElement();
1485 
1486  // Put string into DOM
1487  QDomDocument domErrorReport ("ErrorReport");
1488  domErrorReport.setContent (xmlErrorReport);
1489 
1490  // Postprocessing
1491  if (!m_originalFileWasImported) {
1492 
1493  // Insert the original file into its placeholder, by manipulating the source and target xml as DOM documents. Very early
1494  // in the loading process, the original file may not be specified yet (m_originalFile is empty)
1495  QDomDocument domInputFile;
1496  loadInputFileForErrorReport (domInputFile);
1497  QDomDocumentFragment fragmentFileFrom = domErrorReport.createDocumentFragment();
1498  if (!domInputFile.isNull()) {
1499  fragmentFileFrom.appendChild (domErrorReport.importNode (domInputFile.documentElement(), DEEP_COPY));
1500  }
1501  QDomNodeList nodesFileTo = domErrorReport.elementsByTagName (DOCUMENT_SERIALIZE_FILE);
1502  if (nodesFileTo.count () > 0) {
1503  QDomNode nodeFileTo = nodesFileTo.at (0);
1504  nodeFileTo.appendChild (fragmentFileFrom);
1505  }
1506 
1507  // Replace DOCUMENT_SERIALIZE_IMAGE by same node with CDATA removed, since:
1508  // 1) it is very big and working with smaller files, especially in emails, is easier
1509  // 2) removing the image better preserves user's privacy
1510  // 3) having the actual image does not help that much when debugging
1511  QDomNodeList nodesDocument = domErrorReport.elementsByTagName (DOCUMENT_SERIALIZE_DOCUMENT);
1512  for (int i = 0 ; i < nodesDocument.count(); i++) {
1513  QDomNode nodeDocument = nodesDocument.at (i);
1514  QDomElement elemImage = nodeDocument.firstChildElement(DOCUMENT_SERIALIZE_IMAGE);
1515  if (!elemImage.isNull()) {
1516 
1517  // Get old image attributes so we can create an empty document with the same size
1518  if (elemImage.hasAttribute (DOCUMENT_SERIALIZE_IMAGE_WIDTH) &&
1519  elemImage.hasAttribute (DOCUMENT_SERIALIZE_IMAGE_HEIGHT)) {
1520 
1521  int width = elemImage.attribute(DOCUMENT_SERIALIZE_IMAGE_WIDTH).toInt();
1522  int height = elemImage.attribute(DOCUMENT_SERIALIZE_IMAGE_HEIGHT).toInt();
1523 
1524  QDomNode nodeReplacement;
1525  QDomElement elemReplacement = nodeReplacement.toElement();
1526  elemReplacement.setAttribute (DOCUMENT_SERIALIZE_IMAGE_WIDTH, width);
1527  elemReplacement.setAttribute (DOCUMENT_SERIALIZE_IMAGE_HEIGHT, height);
1528 
1529  // Replace with the new and then remove the old
1530  nodeDocument.insertBefore (nodeReplacement,
1531  elemImage);
1532  nodeDocument.removeChild(elemImage);
1533  }
1534  }
1535  }
1536  }
1537 
1538  return domErrorReport.toString();
1539 }
1540 
1541 void MainWindow::saveStartingDocumentSnapshot()
1542 {
1543  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::saveStartingDocumentSnapshot";
1544 
1545  QXmlStreamWriter writer (&m_startingDocumentSnapshot);
1546  writer.setAutoFormatting (true);
1547  m_cmdMediator->document().saveXml (writer);
1548 }
1549 
1551 {
1552  ENGAUGE_CHECK_PTR (m_scene);
1553  return *m_scene;
1554 }
1555 
1556 BackgroundImage MainWindow::selectOriginal(BackgroundImage backgroundImage)
1557 {
1558  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::selectBackgroundOriginal";
1559 
1560  BackgroundImage previousBackground = (BackgroundImage) m_cmbBackground->currentData().toInt();
1561 
1562  int index = m_cmbBackground->findData (backgroundImage);
1563  ENGAUGE_ASSERT (index >= 0);
1564 
1565  m_cmbBackground->setCurrentIndex(index);
1566 
1567  return previousBackground;
1568 }
1569 
1571 {
1572  return m_cmbCurve->currentText ();
1573 }
1574 
1575 void MainWindow::setCurrentFile (const QString &fileName)
1576 {
1577  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::setCurrentFile";
1578 
1579  const QString PLACEHOLDER ("[*]");
1580 
1581  QString title = QString (tr ("Engauge Digitizer %1")
1582  .arg (VERSION_NUMBER));
1583 
1584  QString fileNameStripped = fileName;
1585  if (!fileName.isEmpty()) {
1586 
1587  // Strip out path and file extension
1588  QFileInfo fileInfo (fileName);
1589  fileNameStripped = fileInfo.baseName();
1590 
1591  title += QString (": %1")
1592  .arg (fileNameStripped);
1593  }
1594 
1595  m_currentFile = fileNameStripped;
1596 
1597  // To prevent "QWidget::setWindowModified: The window title does not contain a [*] placeholder" warnings,
1598  // we always append a placeholder
1599  title += PLACEHOLDER;
1600 
1601  setWindowTitle (title);
1602 }
1603 
1604 void MainWindow::setCurrentPathFromFile (const QString &fileName)
1605 {
1606  QDir dir = QFileInfo (fileName).absoluteDir();
1607 
1608  if (dir.exists ()) {
1609 
1610  bool success = QDir::setCurrent (dir.absolutePath ()); // Return to chosen directory the next time
1611  ENGAUGE_ASSERT (success);
1612 
1613  } else {
1614 
1615  // File was a url so it is irrelevant to the current directory
1616  }
1617 }
1618 
1619 void MainWindow::setPixmap (const QPixmap &pixmap)
1620 {
1621  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::setPixmap";
1622 
1623  m_digitizeStateContext->setImageIsLoaded (true);
1624  m_backgroundStateContext->setPixmap (m_transformation,
1625  m_cmdMediator->document().modelGridRemoval(),
1626  m_cmdMediator->document().modelColorFilter(),
1627  pixmap);
1628 }
1629 
1630 void MainWindow::settingsRead ()
1631 {
1632  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
1633 
1634  settingsReadEnvironment (settings);
1635  settingsReadMainWindow (settings);
1636 }
1637 
1638 void MainWindow::settingsReadEnvironment (QSettings &settings)
1639 {
1640  settings.beginGroup (SETTINGS_GROUP_ENVIRONMENT);
1641  QDir::setCurrent (settings.value (SETTINGS_CURRENT_DIRECTORY,
1642  QDir::currentPath ()).toString ());
1643  settings.endGroup ();
1644 }
1645 
1646 void MainWindow::settingsReadMainWindow (QSettings &settings)
1647 {
1648  settings.beginGroup(SETTINGS_GROUP_MAIN_WINDOW);
1649 
1650  // Main window geometry
1651  resize (settings.value (SETTINGS_SIZE,
1652  QSize (400, 400)).toSize ());
1653  move (settings.value (SETTINGS_POS,
1654  QPoint (200, 200)).toPoint ());
1655 
1656  // Help window geometry
1657  QSize helpSize = settings.value (SETTINGS_HELP_SIZE,
1658  QSize (900, 600)).toSize();
1659  m_helpWindow->resize (helpSize);
1660  if (settings.contains (SETTINGS_HELP_POS)) {
1661  QPoint helpPos = settings.value (SETTINGS_HELP_POS).toPoint();
1662  m_helpWindow->move (helpPos);
1663  }
1664 
1665  // Checklist guide wizard
1666  m_actionHelpChecklistGuideWizard->setChecked (settings.value (SETTINGS_CHECKLIST_GUIDE_WIZARD,
1667  true).toBool ());
1668 
1669  // Background toolbar visibility
1670  bool viewBackgroundToolBar = settings.value (SETTINGS_VIEW_BACKGROUND_TOOLBAR,
1671  true).toBool ();
1672  m_actionViewBackground->setChecked (viewBackgroundToolBar);
1673  m_toolBackground->setVisible (viewBackgroundToolBar);
1674  BackgroundImage backgroundImage = (BackgroundImage) settings.value (SETTINGS_BACKGROUND_IMAGE,
1675  BACKGROUND_IMAGE_FILTERED).toInt ();
1676  int indexBackground = m_cmbBackground->findData (QVariant (backgroundImage));
1677  m_cmbBackground->setCurrentIndex (indexBackground);
1678 
1679  // Digitize toolbar visibility
1680  bool viewDigitizeToolBar = settings.value (SETTINGS_VIEW_DIGITIZE_TOOLBAR,
1681  true).toBool ();
1682  m_actionViewDigitize->setChecked (viewDigitizeToolBar);
1683  m_toolDigitize->setVisible (viewDigitizeToolBar);
1684 
1685  // Views toolbar visibility
1686  bool viewSettingsViewsToolBar = settings.value (SETTINGS_VIEW_SETTINGS_VIEWS_TOOLBAR,
1687  true).toBool ();
1688  m_actionViewSettingsViews->setChecked (viewSettingsViewsToolBar);
1689  m_toolSettingsViews->setVisible (viewSettingsViewsToolBar);
1690 
1691  // Tooltips visibility
1692  bool viewToolTips = settings.value (SETTINGS_VIEW_TOOL_TIPS,
1693  true).toBool ();
1694  m_actionViewToolTips->setChecked (viewToolTips);
1695  loadToolTips ();
1696 
1697  // Statusbar visibility
1698  StatusBarMode statusBarMode = (StatusBarMode) settings.value (SETTINGS_VIEW_STATUS_BAR,
1699  false).toInt ();
1700  m_statusBar->setStatusBarMode (statusBarMode);
1701  m_actionStatusNever->setChecked (statusBarMode == STATUS_BAR_MODE_NEVER);
1702  m_actionStatusTemporary->setChecked (statusBarMode == STATUS_BAR_MODE_TEMPORARY);
1703  m_actionStatusAlways->setChecked (statusBarMode == STATUS_BAR_MODE_ALWAYS);
1704 
1705  // Checklist guide is docked or undocked. Default is undocked so user knows it can be undocked
1706  Qt::DockWidgetArea area = (Qt::DockWidgetArea) settings.value (SETTINGS_CHECKLIST_GUIDE_DOCK_AREA,
1707  Qt::NoDockWidgetArea).toInt();
1708 
1709  if (area == Qt::NoDockWidgetArea) {
1710 
1711  addDockWidget (Qt::RightDockWidgetArea,
1712  m_dockChecklistGuide); // Add on the right to prevent error message, then immediately make undocked
1713  m_dockChecklistGuide->setFloating(true); // Undock
1714  if (settings.contains (SETTINGS_CHECKLIST_GUIDE_DOCK_GEOMETRY)) {
1715  m_dockChecklistGuide->restoreGeometry (settings.value (SETTINGS_CHECKLIST_GUIDE_DOCK_GEOMETRY).toByteArray());
1716  }
1717 
1718  } else {
1719 
1720  addDockWidget (area,
1721  m_dockChecklistGuide);
1722 
1723  }
1724 
1725  settings.endGroup();
1726 }
1727 
1728 void MainWindow::settingsWrite ()
1729 {
1730  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
1731 
1732  settings.beginGroup (SETTINGS_GROUP_ENVIRONMENT);
1733  settings.setValue (SETTINGS_CURRENT_DIRECTORY, QDir::currentPath ());
1734  settings.endGroup ();
1735 
1736  settings.beginGroup (SETTINGS_GROUP_MAIN_WINDOW);
1737  settings.setValue (SETTINGS_SIZE, size ());
1738  settings.setValue (SETTINGS_POS, pos ());
1739  settings.setValue (SETTINGS_HELP_SIZE, m_helpWindow->size());
1740  settings.setValue (SETTINGS_HELP_POS, m_helpWindow->pos ());
1741  if (m_dockChecklistGuide->isFloating()) {
1742 
1743  settings.setValue (SETTINGS_CHECKLIST_GUIDE_DOCK_AREA, Qt::NoDockWidgetArea);
1744  settings.setValue (SETTINGS_CHECKLIST_GUIDE_DOCK_GEOMETRY, m_dockChecklistGuide->saveGeometry ());
1745 
1746  } else {
1747 
1748  settings.setValue (SETTINGS_CHECKLIST_GUIDE_DOCK_AREA, dockWidgetArea (m_dockChecklistGuide));
1749 
1750  }
1751  settings.setValue (SETTINGS_CHECKLIST_GUIDE_WIZARD, m_actionHelpChecklistGuideWizard->isChecked ());
1752  settings.setValue (SETTINGS_VIEW_BACKGROUND_TOOLBAR, m_actionViewBackground->isChecked());
1753  settings.setValue (SETTINGS_BACKGROUND_IMAGE, m_cmbBackground->currentData().toInt());
1754  settings.setValue (SETTINGS_VIEW_DIGITIZE_TOOLBAR, m_actionViewDigitize->isChecked ());
1755  settings.setValue (SETTINGS_VIEW_STATUS_BAR, m_statusBar->statusBarMode ());
1756  settings.setValue (SETTINGS_VIEW_SETTINGS_VIEWS_TOOLBAR, m_actionViewSettingsViews->isChecked ());
1757  settings.setValue (SETTINGS_VIEW_TOOL_TIPS, m_actionViewToolTips->isChecked ());
1758  settings.endGroup ();
1759 }
1760 
1761 void MainWindow::setupAfterLoad (const QString &fileName,
1762  const QString &temporaryMessage)
1763 {
1764  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::setupAfterLoad"
1765  << " file=" << fileName.toLatin1().data()
1766  << " message=" << temporaryMessage.toLatin1().data();
1767 
1768  // Next line assumes CmdMediator for the NEW Document is already stored in m_cmdMediator
1769  m_digitizeStateContext->bindToCmdMediatorAndResetOnLoad (m_cmdMediator);
1770 
1771  m_transformation.resetOnLoad();
1772  m_transformationStateContext->resetOnLoad();
1773  m_scene->resetOnLoad();
1774 
1775  connect (m_actionEditUndo, SIGNAL (triggered ()), m_cmdMediator, SLOT (undo ()));
1776  connect (m_actionEditUndo, SIGNAL (triggered ()), m_cmdStackShadow, SLOT (slotUndo ()));
1777  connect (m_actionEditRedo, SIGNAL (triggered ()), m_cmdMediator, SLOT (redo ())); // No effect until CmdMediator::undo and CmdStackShadow::slotUndo get called
1778  connect (m_actionEditRedo, SIGNAL (triggered ()), m_cmdStackShadow, SLOT (slotRedo ())); // No effect after CmdMediator::undo and CmdStackShadow::slotUndo get called
1779  connect (m_cmdMediator, SIGNAL (canRedoChanged(bool)), this, SLOT (slotCanRedoChanged (bool)));
1780  connect (m_cmdMediator, SIGNAL (canUndoChanged(bool)), this, SLOT (slotCanUndoChanged (bool)));
1781  connect (m_cmdMediator, SIGNAL (redoTextChanged (const QString &)), this, SLOT (slotRedoTextChanged (const QString &)));
1782  connect (m_cmdMediator, SIGNAL (undoTextChanged (const QString &)), this, SLOT (slotUndoTextChanged (const QString &)));
1783  loadCurveListFromCmdMediator ();
1785 
1786  m_isDocumentExported = false;
1787 
1788  // Set up background before slotViewZoomFill which relies on the background. At this point
1789  // the transformation is undefined (unless the code is changed) so grid removal will not work
1790  // but updateTransformationAndItsDependencies will call this again to fix that issue
1791  setPixmap (m_cmdMediator->pixmap ());
1792  m_backgroundStateContext->setCurveSelected (m_transformation,
1793  m_cmdMediator->document().modelGridRemoval(),
1794  m_cmdMediator->document().modelColorFilter(),
1795  m_cmbCurve->currentText ());
1796  m_backgroundStateContext->setBackgroundImage ((BackgroundImage) m_cmbBackground->currentIndex ());
1797 
1798  // Preference for issue #25 is 100% rather than fill mode
1799  slotViewZoom1To1 ();
1800 
1801  setCurrentFile(fileName);
1802  m_statusBar->showTemporaryMessage (temporaryMessage);
1803  m_statusBar->wakeUp ();
1804 
1805  saveStartingDocumentSnapshot();
1806 
1807  updateAfterCommand(); // Replace stale points by points in new Document
1808 }
1809 
1810 void MainWindow::showTemporaryMessage (const QString &temporaryMessage)
1811 {
1812  m_statusBar->showTemporaryMessage (temporaryMessage);
1813 }
1814 
1815 void MainWindow::slotCanRedoChanged (bool canRedo)
1816 {
1817  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotCanRedoChanged";
1818 
1819  m_actionEditRedo->setEnabled (canRedo || m_cmdStackShadow->canRedo());
1820 }
1821 
1822 void MainWindow::slotCanUndoChanged (bool canUndo)
1823 {
1824  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotCanUndoChanged";
1825 
1826  m_actionEditUndo->setEnabled (canUndo);
1827 }
1828 
1829 void MainWindow::slotChecklistClosed()
1830 {
1831  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotChecklistClosed";
1832 
1833  m_actionViewChecklistGuide->setChecked (false);
1834 }
1835 
1836 void MainWindow::slotCleanChanged(bool clean)
1837 {
1838  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotCleanChanged";
1839 
1840  setWindowModified (!clean);
1841 }
1842 
1843 void MainWindow::slotCmbBackground(int currentIndex)
1844 {
1845  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotCmbBackground";
1846 
1847  switch (currentIndex) {
1848  case BACKGROUND_IMAGE_NONE:
1849  if (!m_actionViewBackgroundNone->isChecked()) {
1850  m_actionViewBackgroundNone->toggle();
1851  }
1852  break;
1853 
1854  case BACKGROUND_IMAGE_ORIGINAL:
1855  if (!m_actionViewBackgroundOriginal->isChecked ()) {
1856  m_actionViewBackgroundOriginal->toggle();
1857  }
1858  break;
1859 
1860  case BACKGROUND_IMAGE_FILTERED:
1861  if (!m_actionViewBackgroundFiltered->isChecked ()) {
1862  m_actionViewBackgroundFiltered->toggle();
1863  }
1864  break;
1865  }
1866 
1867  m_backgroundStateContext->setBackgroundImage ((BackgroundImage) currentIndex);
1868 }
1869 
1870 void MainWindow::slotCmbCurve(int /* currentIndex */)
1871 {
1872  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotCmbCurve";
1873 
1874  m_backgroundStateContext->setCurveSelected (m_transformation,
1875  m_cmdMediator->document().modelGridRemoval(),
1876  m_cmdMediator->document().modelColorFilter(),
1877  m_cmbCurve->currentText ());
1878  m_digitizeStateContext->handleCurveChange ();
1879 
1880  updateViewedCurves();
1882 }
1883 
1884 void MainWindow::slotContextMenuEvent (QString pointIdentifier)
1885 {
1886  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotContextMenuEvent point=" << pointIdentifier.toLatin1 ().data ();
1887 
1888  m_digitizeStateContext->handleContextMenuEvent (pointIdentifier);
1889 }
1890 
1891 void MainWindow::slotDigitizeAxis ()
1892 {
1893  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeAxis";
1894 
1895  m_digitizeStateContext->requestImmediateStateTransition (DIGITIZE_STATE_AXIS);
1896  m_cmbCurve->setEnabled (false); // Graph curve is irrelevant in this mode
1897  m_viewPointStyle->setEnabled (true); // Point style is important in this mode
1898  m_viewSegmentFilter->setEnabled (true); // Filtering is important in this mode
1899 }
1900 
1901 void MainWindow::slotDigitizeColorPicker ()
1902 {
1903  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeColorPicker";
1904 
1905  m_digitizeStateContext->requestImmediateStateTransition (DIGITIZE_STATE_COLOR_PICKER);
1906  m_cmbCurve->setEnabled (true);
1907  m_viewPointStyle->setEnabled (true);
1908  m_viewSegmentFilter->setEnabled (true);
1909 }
1910 
1911 void MainWindow::slotDigitizeCurve ()
1912 {
1913  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeCurve";
1914 
1915  m_digitizeStateContext->requestImmediateStateTransition (DIGITIZE_STATE_CURVE);
1916  m_cmbCurve->setEnabled (true);
1917  m_viewPointStyle->setEnabled (true);
1918  m_viewSegmentFilter->setEnabled (true);
1919 }
1920 
1921 void MainWindow::slotDigitizePointMatch ()
1922 {
1923  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizePointMatch";
1924 
1925  m_digitizeStateContext->requestImmediateStateTransition (DIGITIZE_STATE_POINT_MATCH);
1926  m_cmbCurve->setEnabled (true);
1927  m_viewPointStyle->setEnabled (true);
1928  m_viewSegmentFilter->setEnabled (true);
1929 }
1930 
1931 void MainWindow::slotDigitizeSegment ()
1932 {
1933  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeSegment";
1934 
1935  m_digitizeStateContext->requestImmediateStateTransition (DIGITIZE_STATE_SEGMENT);
1936  m_cmbCurve->setEnabled (true);
1937  m_viewPointStyle->setEnabled (true);
1938  m_viewSegmentFilter->setEnabled (true);
1939 }
1940 
1941 void MainWindow::slotDigitizeSelect ()
1942 {
1943  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeSelect";
1944 
1945  m_digitizeStateContext->requestImmediateStateTransition (DIGITIZE_STATE_SELECT);
1946  m_cmbCurve->setEnabled (false);
1947  m_viewPointStyle->setEnabled (false);
1948  m_viewSegmentFilter->setEnabled (false);
1949 }
1950 
1951 void MainWindow::slotEditCopy ()
1952 {
1953  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditCopy";
1954 
1955  CmdCopy *cmd = new CmdCopy (*this,
1956  m_cmdMediator->document(),
1957  m_scene->selectedPointIdentifiers ());
1958  m_digitizeStateContext->appendNewCmd (cmd);
1959 }
1960 
1961 void MainWindow::slotEditCut ()
1962 {
1963  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditCut";
1964 
1965  CmdCut *cmd = new CmdCut (*this,
1966  m_cmdMediator->document(),
1967  m_scene->selectedPointIdentifiers ());
1968  m_digitizeStateContext->appendNewCmd (cmd);
1969 }
1970 
1971 void MainWindow::slotEditDelete ()
1972 {
1973  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditDelete";
1974 
1975  CmdDelete *cmd = new CmdDelete (*this,
1976  m_cmdMediator->document(),
1977  m_scene->selectedPointIdentifiers ());
1978  m_digitizeStateContext->appendNewCmd (cmd);
1979 }
1980 
1981 void MainWindow::slotEditPaste ()
1982 {
1983  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditPaste";
1984 }
1985 
1986 void MainWindow::slotFileClose()
1987 {
1988  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileClose";
1989 
1990  if (maybeSave ()) {
1991 
1992  // Transition from defined to undefined. This must be after the clearing of the screen
1993  // since the axes checker screen item (and maybe others) must still exist
1994  m_transformationStateContext->triggerStateTransition(TRANSFORMATION_STATE_UNDEFINED,
1995  cmdMediator(),
1996  m_transformation,
1997  selectedGraphCurve());
1998 
1999  // Transition to empty state so an inadvertent mouse press does not trigger, for example,
2000  // the creation of an axis point on a non-existent GraphicsScene (=crash)
2001  m_digitizeStateContext->requestImmediateStateTransition (DIGITIZE_STATE_EMPTY);
2002 
2003  // Remove screen objects
2004  m_scene->resetOnLoad ();
2005 
2006  // Remove background
2007  m_backgroundStateContext->close ();
2008 
2009  // Remove scroll bars if they exist
2010  m_scene->setSceneRect (QRectF (0, 0, 1, 1));
2011 
2012  // Deallocate Document
2013  delete m_cmdMediator;
2014  m_cmdMediator = 0;
2015  m_currentFile = "";
2016  m_engaugeFile = "";
2017 
2018  updateControls();
2019  }
2020 }
2021 
2022 void MainWindow::slotFileExport ()
2023 {
2024  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileExport";
2025 
2026  if (m_transformation.transformIsDefined()) {
2027 
2028  const int SELECTED_FILTER = 0;
2029  QString filter = QString ("Text CSV (*.%1);;Text TSV (*.%2);;All files (*.*)")
2030  .arg (CSV_FILENAME_EXTENSION)
2031  .arg (TSV_FILENAME_EXTENSION);
2032  QString defaultFileName = QString ("%1/%2.%3")
2033  .arg (QDir::currentPath ())
2034  .arg (m_currentFile)
2035  .arg (CSV_FILENAME_EXTENSION);
2036  QString fileName = QFileDialog::getSaveFileName (this,
2037  tr("Export"),
2038  defaultFileName,
2039  filter,
2040  SELECTED_FILTER);
2041  if (!fileName.isEmpty ()) {
2042 
2043  QFile file (fileName);
2044  if (file.open(QIODevice::WriteOnly)) {
2045 
2046  QTextStream str (&file);
2047 
2048  ExportToFile exportStrategy;
2049  exportStrategy.exportToFile (cmdMediator().document().modelExport(),
2050  cmdMediator().document(),
2051  transformation (),
2052  str);
2053 
2054  // Update checklist guide status
2055  m_isDocumentExported = true; // Set for next line and for all checklist guide updates after this
2056  m_dockChecklistGuide->update (*m_cmdMediator,
2057  m_isDocumentExported);
2058 
2059  } else {
2060 
2061  QMessageBox::critical (0,
2062  engaugeWindowTitle(),
2063  tr ("Unable to export to file ") + fileName);
2064  }
2065  }
2066  } else {
2067  DlgRequiresTransform dlg ("Export");
2068  dlg.exec ();
2069  }
2070 }
2071 
2072 void MainWindow::slotFileImport ()
2073 {
2074  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileImport";
2075 
2076  if (maybeSave ()) {
2077 
2078  QString filter;
2079  QTextStream str (&filter);
2080 
2081  // Compile a list of supported formats into a filter
2082  QList<QByteArray>::const_iterator itr;
2083  QList<QByteArray> supportedImageFormats = QImageReader::supportedImageFormats();
2084  QStringList supportedImageFormatStrings;
2085  for (itr = supportedImageFormats.begin (); itr != supportedImageFormats.end (); itr++) {
2086  QByteArray arr = *itr;
2087  QString extensionAsWildcard = QString ("*.%1").arg (QString (arr));
2088  supportedImageFormatStrings << extensionAsWildcard;
2089  }
2090 #ifdef ENGAUGE_JPEG2000
2091  Jpeg2000 jpeg2000;
2092  supportedImageFormatStrings << jpeg2000.supportedImageWildcards();
2093 #endif // ENGAUGE_JPEG2000
2094 
2095  supportedImageFormatStrings.sort();
2096 
2097  str << "Image Files (" << supportedImageFormatStrings.join (" ") << ")";
2098 
2099  // Allow selection of files with strange suffixes in case the file extension was changed. Since
2100  // the default is the first filter, we add this afterwards (it is the off-nominal case)
2101  str << ";; All Files (*.*)";
2102 
2103  QString fileName = QFileDialog::getOpenFileName (this,
2104  tr("Import Image"),
2105  QDir::currentPath (),
2106  filter);
2107  if (!fileName.isEmpty ()) {
2108 
2109  fileImport (fileName);
2110 
2111  }
2112  }
2113 }
2114 
2115 void MainWindow::slotFileImportDraggedImage(QImage image)
2116 {
2117  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileImportDraggedImage";
2118 
2119  loadImage ("",
2120  image);
2121 }
2122 
2123 void MainWindow::slotFileImportDraggedImageUrl(QUrl url)
2124 {
2125  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileImportDraggedImageUrl url=" << url.toString ().toLatin1 ().data ();
2126 
2127  m_loadImageFromUrl->startLoadImage (url);
2128 }
2129 
2130 void MainWindow::slotFileImportImage(QString fileName, QImage image)
2131 {
2132  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileImportImage fileName=" << fileName.toLatin1 ().data ();
2133 
2134  loadImage (fileName,
2135  image);
2136 }
2137 
2138 void MainWindow::slotFileOpen()
2139 {
2140  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileOpen";
2141 
2142  if (maybeSave ()) {
2143 
2144  // Allow selection of files with strange suffixes in case the file extension was changed. Since
2145  // the default is the first filter, the wildcard filter is added afterwards (it is the off-nominal case)
2146  QString filter = QString ("%1 (*.%2);; All Files (*.*)")
2147  .arg (ENGAUGE_FILENAME_DESCRIPTION)
2148  .arg (ENGAUGE_FILENAME_EXTENSION);
2149 
2150  QString fileName = QFileDialog::getOpenFileName (this,
2151  tr("Open Document"),
2152  QDir::currentPath (),
2153  filter);
2154  if (!fileName.isEmpty ()) {
2155 
2156  loadDocumentFile (fileName);
2157 
2158  }
2159  }
2160 }
2161 
2162 void MainWindow::slotFileOpenDraggedDigFile (QString fileName)
2163 {
2164  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileOpenDraggedDigFile";
2165 
2166  loadDocumentFile (fileName);
2167 }
2168 
2169 void MainWindow::slotFilePrint()
2170 {
2171  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFilePrint";
2172 
2173  QPrinter printer (QPrinter::HighResolution);
2174  QPrintDialog dlg (&printer, this);
2175  if (dlg.exec() == QDialog::Accepted) {
2176  QPainter painter (&printer);
2177  m_view->render (&painter);
2178  painter.end();
2179  }
2180 }
2181 
2182 bool MainWindow::slotFileSave()
2183 {
2184  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileSave";
2185 
2186  if (m_engaugeFile.isEmpty()) {
2187  return slotFileSaveAs();
2188  } else {
2189  return saveDocumentFile (m_engaugeFile);
2190  }
2191 }
2192 
2193 bool MainWindow::slotFileSaveAs()
2194 {
2195  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileSaveAs";
2196 
2197  // Append engauge file extension if it is not already there
2198  QString filenameDefault = m_currentFile;
2199  if (!m_currentFile.endsWith (ENGAUGE_FILENAME_EXTENSION)) {
2200  filenameDefault = QString ("%1.%2")
2201  .arg (m_currentFile)
2202  .arg (ENGAUGE_FILENAME_EXTENSION);
2203  }
2204 
2205  if (!m_engaugeFile.isEmpty()) {
2206  filenameDefault = m_engaugeFile;
2207  }
2208 
2209  QString filterDigitizer = QString ("%1 (*.%2)")
2210  .arg (ENGAUGE_FILENAME_DESCRIPTION)
2211  .arg (ENGAUGE_FILENAME_EXTENSION);
2212  QString filterAll ("All files (*. *)");
2213 
2214  QStringList filters;
2215  filters << filterDigitizer;
2216  filters << filterAll;
2217 
2218  QFileDialog dlg(this);
2219  dlg.selectNameFilter (filterDigitizer);
2220  dlg.setNameFilters (filters);
2221  dlg.setWindowModality(Qt::WindowModal);
2222  dlg.setAcceptMode(QFileDialog::AcceptSave);
2223  dlg.selectFile(filenameDefault);
2224  if (dlg.exec()) {
2225 
2226  QStringList files = dlg.selectedFiles();
2227  return saveDocumentFile(files.at(0));
2228  }
2229 
2230  return false;
2231 }
2232 
2233 void MainWindow::slotHelpAbout()
2234 {
2235  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotHelpAbout";
2236 
2237  DlgAbout dlg (*this);
2238  dlg.exec ();
2239 }
2240 
2241 void MainWindow::slotHelpTutorial()
2242 {
2243  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotHelpTutorial";
2244 
2245  m_tutorialDlg->show ();
2246  m_tutorialDlg->exec ();
2247 }
2248 
2249 void MainWindow::slotKeyPress (Qt::Key key,
2250  bool atLeastOneSelectedItem)
2251 {
2252  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotKeyPress"
2253  << " key=" << QKeySequence (key).toString().toLatin1 ().data ()
2254  << " atLeastOneSelectedItem=" << (atLeastOneSelectedItem ? "true" : "false");
2255 
2256  m_digitizeStateContext->handleKeyPress (key,
2257  atLeastOneSelectedItem);
2258 }
2259 
2260 void MainWindow::slotLeave ()
2261 {
2262  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotLeave";
2263 
2264  m_digitizeStateContext->handleLeave ();
2265 }
2266 
2267 void MainWindow::slotMouseMove (QPointF pos)
2268 {
2269 // LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotMouseMove pos=" << QPointFToString (pos).toLatin1 ().data ();
2270 
2271  // Ignore mouse moves before Document is loaded
2272  if (m_cmdMediator != 0) {
2273 
2274  // Get status bar coordinates
2275  QString coordsScreen, coordsGraph, resolutionGraph;
2276  m_transformation.coordTextForStatusBar (pos,
2277  coordsScreen,
2278  coordsGraph,
2279  resolutionGraph);
2280 
2281  // Update status bar coordinates
2282  m_statusBar->setCoordinates (coordsScreen,
2283  coordsGraph,
2284  resolutionGraph);
2285 
2286  // There used to be a call to updateGraphicsLinesToMatchGraphicsPoints here, but that resulted
2287  // in hundreds of gratuitous log messages as the cursor was moved around, and nothing important happened
2288 
2289  m_digitizeStateContext->handleMouseMove (pos);
2290  }
2291 }
2292 
2293 void MainWindow::slotMousePress (QPointF pos)
2294 {
2295  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotMousePress";
2296 
2297  m_scene->resetPositionHasChangedFlags();
2298 
2299  m_digitizeStateContext->handleMousePress (pos);
2300 }
2301 
2302 void MainWindow::slotMouseRelease (QPointF pos)
2303 {
2304  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotMouseRelease";
2305 
2306  m_digitizeStateContext->handleMouseRelease (pos);
2307 }
2308 
2309 void MainWindow::slotRecentFileAction ()
2310 {
2311  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotRecentFileAction";
2312 
2313  QAction *action = qobject_cast<QAction*>(sender ());
2314 
2315  if (action) {
2316  QString fileName = action->data().toString();
2317  loadDocumentFile (fileName);
2318  }
2319 }
2320 
2321 void MainWindow::slotRedoTextChanged (const QString &text)
2322 {
2323  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotRedoTextChanged";
2324 
2325  QString completeText ("Redo");
2326  if (!text.isEmpty ()) {
2327  completeText += QString (" \"%1\"").arg (text);
2328  }
2329  m_actionEditRedo->setText (completeText);
2330 }
2331 
2332 void MainWindow::slotSetOverrideCursor (QCursor cursor)
2333 {
2334  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSetOverrideCursor";
2335 
2336  m_digitizeStateContext->handleSetOverrideCursor (cursor);
2337 }
2338 
2339 void MainWindow::slotSettingsAxesChecker ()
2340 {
2341  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsAxesChecker";
2342 
2343  m_dlgSettingsAxesChecker->load (*m_cmdMediator);
2344  m_dlgSettingsAxesChecker->show ();
2345 }
2346 
2347 void MainWindow::slotSettingsColorFilter ()
2348 {
2349  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsColorFilter";
2350 
2351  m_dlgSettingsColorFilter->load (*m_cmdMediator);
2352  m_dlgSettingsColorFilter->show ();
2353 }
2354 
2355 void MainWindow::slotSettingsCommon ()
2356 {
2357  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsCommon";
2358 
2359  m_dlgSettingsCommon->load (*m_cmdMediator);
2360  m_dlgSettingsCommon->show ();
2361 }
2362 
2363 void MainWindow::slotSettingsCoords ()
2364 {
2365  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsCoords";
2366 
2367  m_dlgSettingsCoords->load (*m_cmdMediator);
2368  m_dlgSettingsCoords->show ();
2369 }
2370 
2371 void MainWindow::slotSettingsCurveAddRemove ()
2372 {
2373  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsCurveAddRemove";
2374 
2375  m_dlgSettingsCurveAddRemove->load (*m_cmdMediator);
2376  m_dlgSettingsCurveAddRemove->show ();
2377 }
2378 
2379 void MainWindow::slotSettingsCurveProperties ()
2380 {
2381  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsCurveProperties";
2382 
2383  m_dlgSettingsCurveProperties->load (*m_cmdMediator);
2384  m_dlgSettingsCurveProperties->setCurveName (selectedGraphCurve ());
2385  m_dlgSettingsCurveProperties->show ();
2386 }
2387 
2388 void MainWindow::slotSettingsDigitizeCurve ()
2389 {
2390  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsDigitizeCurve";
2391 
2392  m_dlgSettingsDigitizeCurve->load (*m_cmdMediator);
2393  m_dlgSettingsDigitizeCurve->show ();
2394 }
2395 
2396 void MainWindow::slotSettingsExportFormat ()
2397 {
2398  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsExportFormat";
2399 
2400  if (transformIsDefined()) {
2401  m_dlgSettingsExportFormat->load (*m_cmdMediator);
2402  m_dlgSettingsExportFormat->show ();
2403  } else {
2404  DlgRequiresTransform dlg ("Export settings");
2405  dlg.exec();
2406  }
2407 }
2408 
2409 void MainWindow::slotSettingsGridRemoval ()
2410 {
2411  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsGridRemoval";
2412 
2413  m_dlgSettingsGridRemoval->load (*m_cmdMediator);
2414  m_dlgSettingsGridRemoval->show ();
2415 }
2416 
2417 void MainWindow::slotSettingsPointMatch ()
2418 {
2419  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsPointMatch";
2420 
2421  m_dlgSettingsPointMatch->load (*m_cmdMediator);
2422  m_dlgSettingsPointMatch->show ();
2423 }
2424 
2425 void MainWindow::slotSettingsSegments ()
2426 {
2427  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsSegments";
2428 
2429  m_dlgSettingsSegments->load (*m_cmdMediator);
2430  m_dlgSettingsSegments->show ();
2431 }
2432 
2433 void MainWindow::slotUndoTextChanged (const QString &text)
2434 {
2435  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotUndoTextChanged";
2436 
2437  QString completeText ("Undo");
2438  if (!text.isEmpty ()) {
2439  completeText += QString (" \"%1\"").arg (text);
2440  }
2441  m_actionEditUndo->setText (completeText);
2442 }
2443 
2444 void MainWindow::slotViewGroupBackground(QAction *action)
2445 {
2446  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewGroupBackground";
2447 
2448  // Set the combobox
2449  BackgroundImage backgroundImage;
2450  int indexBackground;
2451  if (action == m_actionViewBackgroundNone) {
2452  indexBackground = m_cmbBackground->findData (QVariant (BACKGROUND_IMAGE_NONE));
2453  backgroundImage = BACKGROUND_IMAGE_NONE;
2454  } else if (action == m_actionViewBackgroundOriginal) {
2455  indexBackground = m_cmbBackground->findData (QVariant (BACKGROUND_IMAGE_ORIGINAL));
2456  backgroundImage = BACKGROUND_IMAGE_ORIGINAL;
2457  } else if (action == m_actionViewBackgroundFiltered) {
2458  indexBackground = m_cmbBackground->findData (QVariant (BACKGROUND_IMAGE_FILTERED));
2459  backgroundImage = BACKGROUND_IMAGE_FILTERED;
2460  } else {
2461  ENGAUGE_ASSERT (false);
2462 
2463  // Defaults if assert is disabled so execution continues
2464  indexBackground = m_cmbBackground->findData (QVariant (BACKGROUND_IMAGE_ORIGINAL));
2465  backgroundImage = BACKGROUND_IMAGE_ORIGINAL;
2466  }
2467 
2468  m_cmbBackground->setCurrentIndex (indexBackground);
2469  m_backgroundStateContext->setBackgroundImage (backgroundImage);
2470 }
2471 
2472 void MainWindow::slotViewGroupCurves(QAction * /* action */)
2473 {
2474  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewGroupCurves";
2475 
2476  updateViewedCurves ();
2477 }
2478 
2479 void MainWindow::slotViewGroupStatus(QAction *action)
2480 {
2481  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewGroupStatus";
2482 
2483  ENGAUGE_CHECK_PTR (m_statusBar); // At startup, make sure status bar is already set up when View menu gets initialized
2484 
2485  if (action == m_actionStatusNever) {
2486  m_statusBar->setStatusBarMode(STATUS_BAR_MODE_NEVER);
2487  } else if (action == m_actionStatusTemporary) {
2488  m_statusBar->setStatusBarMode(STATUS_BAR_MODE_TEMPORARY);
2489  } else {
2490  m_statusBar->setStatusBarMode(STATUS_BAR_MODE_ALWAYS);
2491  }
2492 }
2493 
2494 void MainWindow::slotViewToolBarBackground ()
2495 {
2496  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarBackground";
2497 
2498  if (m_actionViewBackground->isChecked ()) {
2499  m_toolBackground->show();
2500  } else {
2501  m_toolBackground->hide();
2502  }
2503 }
2504 
2505 void MainWindow::slotViewToolBarChecklistGuide ()
2506 {
2507  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarChecklistGuide";
2508 
2509  if (m_actionViewChecklistGuide->isChecked ()) {
2510  m_dockChecklistGuide->show();
2511  } else {
2512  m_dockChecklistGuide->hide();
2513  }
2514 }
2515 
2516 void MainWindow::slotViewToolBarDigitize ()
2517 {
2518  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarDigitize";
2519 
2520  if (m_actionViewDigitize->isChecked ()) {
2521  m_toolDigitize->show();
2522  } else {
2523  m_toolDigitize->hide();
2524  }
2525 }
2526 
2527 void MainWindow::slotViewToolBarSettingsViews ()
2528 {
2529  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarSettingsViews";
2530 
2531  if (m_actionViewSettingsViews->isChecked ()) {
2532  m_toolSettingsViews->show();
2533  } else {
2534  m_toolSettingsViews->hide();
2535  }
2536 }
2537 
2538 void MainWindow::slotViewToolTips ()
2539 {
2540  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolTips";
2541 
2542  loadToolTips();
2543 }
2544 
2545 void MainWindow::slotViewZoom(int zoom)
2546 {
2547  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoom";
2548 
2549  // Update zoom controls and apply the zoom factor
2550  switch ((ZoomFactor) zoom) {
2551  case ZOOM_16_TO_1:
2552  m_actionZoom16To1->setChecked(true);
2553  slotViewZoom16To1 ();
2554  break;
2555  case ZOOM_8_TO_1:
2556  m_actionZoom8To1->setChecked(true);
2557  slotViewZoom8To1 ();
2558  break;
2559  case ZOOM_4_TO_1:
2560  m_actionZoom4To1->setChecked(true);
2561  slotViewZoom4To1 ();
2562  break;
2563  case ZOOM_2_TO_1:
2564  m_actionZoom2To1->setChecked(true);
2565  slotViewZoom2To1 ();
2566  break;
2567  case ZOOM_1_TO_1:
2568  m_actionZoom1To1->setChecked(true);
2569  slotViewZoom1To1 ();
2570  break;
2571  case ZOOM_1_TO_2:
2572  m_actionZoom1To2->setChecked(true);
2573  slotViewZoom1To2 ();
2574  break;
2575  case ZOOM_1_TO_4:
2576  m_actionZoom1To4->setChecked(true);
2577  slotViewZoom1To4 ();
2578  break;
2579  case ZOOM_1_TO_8:
2580  m_actionZoom1To8->setChecked(true);
2581  slotViewZoom1To8 ();
2582  break;
2583  case ZOOM_1_TO_16:
2584  m_actionZoom1To16->setChecked(true);
2585  slotViewZoom1To16 ();
2586  break;
2587  case ZOOM_FILL:
2588  m_actionZoomFill->setChecked(true);
2589  slotViewZoomFill ();
2590  break;
2591  }
2592 }
2593 
2594 void MainWindow::slotViewZoom16To1 ()
2595 {
2596  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoom16To1";
2597 
2598  QTransform transform;
2599  transform.scale (16.0, 16.0);
2600  m_view->setTransform (transform);
2601  emit signalZoom(ZOOM_16_TO_1);
2602 }
2603 
2604 void MainWindow::slotViewZoom8To1 ()
2605 {
2606  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoom8To1";
2607 
2608  QTransform transform;
2609  transform.scale (8.0, 8.0);
2610  m_view->setTransform (transform);
2611  emit signalZoom(ZOOM_8_TO_1);
2612 }
2613 
2614 void MainWindow::slotViewZoom4To1 ()
2615 {
2616  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoom4To1";
2617 
2618  QTransform transform;
2619  transform.scale (4.0, 4.0);
2620  m_view->setTransform (transform);
2621  emit signalZoom(ZOOM_4_TO_1);
2622 }
2623 
2624 void MainWindow::slotViewZoom2To1 ()
2625 {
2626  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotZoom2To1";
2627 
2628  QTransform transform;
2629  transform.scale (2.0, 2.0);
2630  m_view->setTransform (transform);
2631  emit signalZoom(ZOOM_2_TO_1);
2632 }
2633 
2634 void MainWindow::slotViewZoom1To1 ()
2635 {
2636  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoom1To1";
2637 
2638  QTransform transform;
2639  transform.scale (1.0, 1.0);
2640  m_view->setTransform (transform);
2641  emit signalZoom(ZOOM_1_TO_1);
2642 }
2643 
2644 void MainWindow::slotViewZoom1To2 ()
2645 {
2646  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotZoom1To2";
2647 
2648  QTransform transform;
2649  transform.scale (0.5, 0.5);
2650  m_view->setTransform (transform);
2651  emit signalZoom(ZOOM_1_TO_2);
2652 }
2653 
2654 void MainWindow::slotViewZoom1To4 ()
2655 {
2656  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotZoom1To4";
2657 
2658  QTransform transform;
2659  transform.scale (0.25, 0.25);
2660  m_view->setTransform (transform);
2661  emit signalZoom(ZOOM_1_TO_4);
2662 }
2663 
2664 void MainWindow::slotViewZoom1To8 ()
2665 {
2666  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotZoom1To8";
2667 
2668  QTransform transform;
2669  transform.scale (0.125, 0.125);
2670  m_view->setTransform (transform);
2671  emit signalZoom(ZOOM_1_TO_8);
2672 }
2673 
2674 void MainWindow::slotViewZoom1To16 ()
2675 {
2676  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotZoom1To16";
2677 
2678  QTransform transform;
2679  transform.scale (0.0625, 0.0625);
2680  m_view->setTransform (transform);
2681  emit signalZoom(ZOOM_1_TO_16);
2682 }
2683 
2684 void MainWindow::slotViewZoomFill ()
2685 {
2686  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoomFill";
2687 
2688  m_backgroundStateContext->fitInView (*m_view);
2689 
2690  emit signalZoom(ZOOM_FILL);
2691 }
2692 
2693 void MainWindow::slotViewZoomIn ()
2694 {
2695  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoomIn";
2696 
2697  // Try to zoom in. First determine what the next zoom factor should be
2698 
2699  bool goto16To1 = false, goto8To1 = false, goto4To1 = false, goto2To1 = false;
2700  bool goto1To1 = false;
2701  bool goto1To2 = false, goto1To4 = false, goto1To8 = false, goto1To16 = false;
2702  if (m_actionZoomFill->isChecked ()) {
2703 
2704  // Zooming in means user probably wants the more squished direction to be zoomed in by one step
2705  double xScale = m_view->transform().m11();
2706  double yScale = m_view->transform().m22();
2707  double scale = qMin(xScale, yScale);
2708  if (scale < 0.125) {
2709  goto1To8 = true;
2710  } else if (scale < 0.25) {
2711  goto1To4 = true;
2712  } else if (scale < 0.5) {
2713  goto1To2 = true;
2714  } else if (scale < 1) {
2715  goto1To1 = true;
2716  } else if (scale < 2) {
2717  goto2To1 = true;
2718  } else if (scale < 4) {
2719  goto4To1 = true;
2720  } else if (scale < 8) {
2721  goto8To1 = true;
2722  } else {
2723  goto1To16 = true;
2724  }
2725  } else {
2726  goto16To1 = m_actionZoom8To1->isChecked ();
2727  goto8To1 = m_actionZoom4To1->isChecked ();
2728  goto4To1 = m_actionZoom2To1->isChecked ();
2729  goto2To1 = m_actionZoom1To1->isChecked ();
2730  goto1To1 = m_actionZoom1To2->isChecked ();
2731  goto1To2 = m_actionZoom1To4->isChecked ();
2732  goto1To4 = m_actionZoom1To8->isChecked ();
2733  goto1To8 = m_actionZoom1To16->isChecked ();
2734  }
2735 
2736  // Update controls and apply zoom factor
2737  if (goto16To1) {
2738  m_actionZoom16To1->setChecked (true);
2739  slotViewZoom16To1 ();
2740  } else if (goto8To1) {
2741  m_actionZoom8To1->setChecked (true);
2742  slotViewZoom8To1 ();
2743  } else if (goto4To1) {
2744  m_actionZoom4To1->setChecked (true);
2745  slotViewZoom4To1 ();
2746  } else if (goto2To1) {
2747  m_actionZoom2To1->setChecked (true);
2748  slotViewZoom2To1 ();
2749  } else if (goto1To1) {
2750  m_actionZoom1To1->setChecked (true);
2751  slotViewZoom1To1 ();
2752  } else if (goto1To2) {
2753  m_actionZoom1To2->setChecked (true);
2754  slotViewZoom1To2 ();
2755  } else if (goto1To4) {
2756  m_actionZoom1To4->setChecked (true);
2757  slotViewZoom1To4 ();
2758  } else if (goto1To8) {
2759  m_actionZoom1To8->setChecked (true);
2760  slotViewZoom1To8 ();
2761  } else if (goto1To16) {
2762  m_actionZoom1To16->setChecked (true);
2763  slotViewZoom1To16 ();
2764  }
2765 }
2766 
2767 void MainWindow::slotViewZoomOut ()
2768 {
2769  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoomOut";
2770 
2771  // Try to zoom out. First determine what the next zoom factor should be
2772 
2773  bool goto16To1 = false, goto8To1 = false, goto4To1 = false, goto2To1 = false;
2774  bool goto1To1 = false;
2775  bool goto1To2 = false, goto1To4 = false, goto1To8 = false, goto1To16 = false;
2776  if (m_actionZoomFill->isChecked ()) {
2777 
2778  // Zooming out means user probably wants the less squished direction to be zoomed out by one step
2779  double xScale = m_view->transform().m11();
2780  double yScale = m_view->transform().m22();
2781  double scale = qMax(xScale, yScale);
2782  if (scale > 8) {
2783  goto8To1 = true;
2784  } else if (scale > 4) {
2785  goto4To1 = true;
2786  } else if (scale > 2) {
2787  goto2To1 = true;
2788  } else if (scale > 1) {
2789  goto1To1 = true;
2790  } else if (scale > 0.5) {
2791  goto1To2 = true;
2792  } else if (scale > 0.25) {
2793  goto1To4 = true;
2794  } else if (scale > 0.125) {
2795  goto1To8 = true;
2796  } else {
2797  goto1To16 = true;
2798  }
2799  } else {
2800  goto8To1 = m_actionZoom16To1->isChecked ();
2801  goto4To1 = m_actionZoom8To1->isChecked ();
2802  goto2To1 = m_actionZoom4To1->isChecked ();
2803  goto1To1 = m_actionZoom2To1->isChecked ();
2804  goto1To2 = m_actionZoom1To1->isChecked ();
2805  goto1To4 = m_actionZoom1To2->isChecked ();
2806  goto1To8 = m_actionZoom1To4->isChecked ();
2807  goto1To16 = m_actionZoom1To8->isChecked ();
2808  }
2809 
2810  // Update controls and apply zoom factor
2811  if (goto1To16) {
2812  m_actionZoom1To16->setChecked (true);
2813  slotViewZoom1To16 ();
2814  } else if (goto1To8) {
2815  m_actionZoom1To8->setChecked (true);
2816  slotViewZoom1To8 ();
2817  } else if (goto1To4) {
2818  m_actionZoom1To4->setChecked (true);
2819  slotViewZoom1To4 ();
2820  } else if (goto1To2) {
2821  m_actionZoom1To2->setChecked (true);
2822  slotViewZoom1To2 ();
2823  } else if (goto1To1) {
2824  m_actionZoom1To1->setChecked (true);
2825  slotViewZoom1To1 ();
2826  } else if (goto2To1) {
2827  m_actionZoom2To1->setChecked (true);
2828  slotViewZoom2To1 ();
2829  } else if (goto4To1) {
2830  m_actionZoom4To1->setChecked (true);
2831  slotViewZoom4To1 ();
2832  } else if (goto8To1) {
2833  m_actionZoom8To1->setChecked (true);
2834  slotViewZoom8To1 ();
2835  } else if (goto16To1) {
2836  m_actionZoom16To1->setChecked (true);
2837  slotViewZoom16To1 ();
2838  }
2839 }
2840 
2842 {
2843  return m_transformation;
2844 }
2845 
2847 {
2848  return m_transformation.transformIsDefined();
2849 }
2850 
2852 {
2853  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateAfterCommand";
2854 
2855  ENGAUGE_CHECK_PTR (m_cmdMediator);
2856 
2857  // Update transformation stuff, including the graph coordinates of every point in the Document, so coordinates in
2858  // status bar are up to date. Point coordinates in Document are also updated
2859  updateAfterCommandStatusBarCoords ();
2860 
2861  // Update the QGraphicsScene with the populated Curves. This requires the points in the Document to be already updated
2862  // by updateAfterCommandStatusBarCoords
2863  m_scene->updateAfterCommand (*m_cmdMediator);
2864 
2865  updateControls ();
2866 
2867  // Update checklist guide status
2868  m_dockChecklistGuide->update (*m_cmdMediator,
2869  m_isDocumentExported);
2870 
2871  // Final action at the end of a redo/undo is to checkpoint the Document and GraphicsScene to log files
2872  // so proper state can be verified
2873  writeCheckpointToLogFile ();
2874 }
2875 
2876 void MainWindow::updateAfterCommandStatusBarCoords ()
2877 {
2878  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateAfterCommandStatusBarCoords";
2879 
2880  // For some reason, mapFromGlobal(QCursor::pos) differs from event->pos by a little bit. We must compensate for
2881  // this so cursor coordinates in status bar match the DlgEditPoint inputs initially. After the mouse moves
2882  // the problem disappears since event->pos is available and QCursor::pos is no longer needed
2883  const QPoint HACK_SO_GRAPH_COORDINATE_MATCHES_INPUT (1, 1);
2884 
2885  Transformation m_transformationBefore (m_transformation);
2886 
2887  updateTransformationAndItsDependencies();
2888 
2889  // Trigger state transitions for transformation if appropriate
2890  if (!m_transformationBefore.transformIsDefined() && m_transformation.transformIsDefined()) {
2891 
2892  // Transition from undefined to defined
2893  m_transformationStateContext->triggerStateTransition(TRANSFORMATION_STATE_DEFINED,
2894  cmdMediator(),
2895  m_transformation,
2896  selectedGraphCurve());
2897 
2898  } else if (m_transformationBefore.transformIsDefined() && !m_transformation.transformIsDefined()) {
2899 
2900  // Transition from defined to undefined
2901  m_transformationStateContext->triggerStateTransition(TRANSFORMATION_STATE_UNDEFINED,
2902  cmdMediator(),
2903  m_transformation,
2904  selectedGraphCurve());
2905 
2906  } else if (m_transformation.transformIsDefined() && (m_transformationBefore != m_transformation)) {
2907 
2908  // There was not a define/undefined or undefined/defined transition, but the transformation changed so we
2909  // need to update the Checker
2910  m_transformationStateContext->updateAxesChecker(cmdMediator(),
2911  m_transformation);
2912 
2913  }
2914 
2915  QPoint posLocal = m_view->mapFromGlobal (QCursor::pos ()) - HACK_SO_GRAPH_COORDINATE_MATCHES_INPUT;
2916  QPointF posScreen = m_view->mapToScene (posLocal);
2917 
2918  slotMouseMove (posScreen); // Update the status bar coordinates to reflect the newly updated transformation
2919 }
2920 
2922 {
2923  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateAfterMouseRelease";
2924 
2925  updateControls ();
2926 }
2927 
2928 void MainWindow::updateControls ()
2929 {
2930 // LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateControls";
2931 
2932  m_cmbBackground->setEnabled (!m_currentFile.isEmpty ());
2933 
2934  m_menuFileOpenRecent->setEnabled ((m_actionRecentFiles.count () > 0) &&
2935  (m_actionRecentFiles.at(0)->isVisible ())); // Need at least one visible recent file entry
2936  m_actionClose->setEnabled (!m_currentFile.isEmpty ());
2937  m_actionSave->setEnabled (!m_currentFile.isEmpty ());
2938  m_actionSaveAs->setEnabled (!m_currentFile.isEmpty ());
2939  m_actionExport->setEnabled (!m_currentFile.isEmpty ());
2940  m_actionPrint->setEnabled (!m_currentFile.isEmpty ());
2941 
2942  if (m_cmdMediator == 0) {
2943  m_actionEditUndo->setEnabled (false);
2944  m_actionEditRedo->setEnabled (false);
2945  } else {
2946  m_actionEditUndo->setEnabled (m_cmdMediator->canUndo ());
2947  m_actionEditRedo->setEnabled (m_cmdMediator->canRedo () || m_cmdStackShadow->canRedo ());
2948  }
2949  m_actionEditCut->setEnabled (m_scene->selectedItems().count () > 0);
2950  m_actionEditCopy->setEnabled (m_scene->selectedItems().count () > 0);
2951  m_actionEditPaste->setEnabled (false);
2952  m_actionEditDelete->setEnabled (m_scene->selectedItems().count () > 0);
2953 
2954  m_actionDigitizeAxis->setEnabled (!m_currentFile.isEmpty ());
2955  m_actionDigitizeCurve ->setEnabled (!m_currentFile.isEmpty ());
2956  m_actionDigitizePointMatch->setEnabled (!m_currentFile.isEmpty ());
2957  m_actionDigitizeColorPicker->setEnabled (!m_currentFile.isEmpty ());
2958  m_actionDigitizeSegment->setEnabled (!m_currentFile.isEmpty ());
2959  m_actionDigitizeSelect->setEnabled (!m_currentFile.isEmpty ());
2960 
2961  m_actionViewBackground->setEnabled (!m_currentFile.isEmpty());
2962  m_actionViewChecklistGuide->setEnabled (!m_dockChecklistGuide->browserIsEmpty());
2963  m_actionViewDigitize->setEnabled (!m_currentFile.isEmpty ());
2964  m_actionViewSettingsViews->setEnabled (!m_currentFile.isEmpty ());
2965 
2966  m_actionSettingsCoords->setEnabled (!m_currentFile.isEmpty ());
2967  m_actionSettingsCurveAddRemove->setEnabled (!m_currentFile.isEmpty ());
2968  m_actionSettingsCurveProperties->setEnabled (!m_currentFile.isEmpty ());
2969  m_actionSettingsDigitizeCurve->setEnabled (!m_currentFile.isEmpty ());
2970  m_actionSettingsExport->setEnabled (!m_currentFile.isEmpty ());
2971  m_actionSettingsColorFilter->setEnabled (!m_currentFile.isEmpty ());
2972  m_actionSettingsAxesChecker->setEnabled (!m_currentFile.isEmpty ());
2973  m_actionSettingsGridRemoval->setEnabled (!m_currentFile.isEmpty ());
2974  m_actionSettingsPointMatch->setEnabled (!m_currentFile.isEmpty ());
2975  m_actionSettingsSegments->setEnabled (!m_currentFile.isEmpty ());
2976  m_actionSettingsCommon->setEnabled (!m_currentFile.isEmpty ());
2977 
2978  m_groupBackground->setEnabled (!m_currentFile.isEmpty ());
2979  m_groupCurves->setEnabled (!m_currentFile.isEmpty ());
2980  m_groupZoom->setEnabled (!m_currentFile.isEmpty ());
2981 
2982  m_actionZoomIn->setEnabled (!m_currentFile.isEmpty ()); // Disable at startup so shortcut has no effect
2983  m_actionZoomOut->setEnabled (!m_currentFile.isEmpty ()); // Disable at startup so shortcut has no effect
2984 }
2985 
2986 void MainWindow::updateDigitizeStateIfSoftwareTriggered (DigitizeState digitizeState)
2987 {
2988  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateDigitizeStateIfSoftwareTriggered";
2989 
2990  switch (digitizeState) {
2991  case DIGITIZE_STATE_AXIS:
2992  m_actionDigitizeAxis->setChecked(true);
2993  slotDigitizeAxis(); // Call the slot that the setChecked call fails to trigger
2994  break;
2995 
2996  case DIGITIZE_STATE_COLOR_PICKER:
2997  m_actionDigitizeColorPicker->setChecked(true);
2998  slotDigitizeColorPicker(); // Call the slot that the setChecked call fails to trigger
2999  break;
3000 
3001  case DIGITIZE_STATE_CURVE:
3002  m_actionDigitizeCurve->setChecked(true);
3003  slotDigitizeCurve(); // Call the slot that the setChecked call fails to trigger
3004  break;
3005 
3006  case DIGITIZE_STATE_EMPTY:
3007  break;
3008 
3009  case DIGITIZE_STATE_POINT_MATCH:
3010  m_actionDigitizePointMatch->setChecked(true);
3011  slotDigitizePointMatch(); // Call the slot that the setChecked call fails to trigger
3012  break;
3013 
3014  case DIGITIZE_STATE_SEGMENT:
3015  m_actionDigitizeSegment->setChecked(true);
3016  slotDigitizeSegment(); // Call the slot that the setChecked call fails to trigger
3017  break;
3018 
3019  case DIGITIZE_STATE_SELECT:
3020  m_actionDigitizeSelect->setChecked(true);
3021  slotDigitizeSelect(); // Call the slot that the setChecked call fails to trigger
3022  break;
3023 
3024  default:
3025  LOG4CPP_ERROR_S ((*mainCat)) << "MainWindow::updateDigitizeStateIfSoftwareTriggered";
3026  break;
3027  }
3028 }
3029 
3031 {
3032  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateGraphicsLinesToMatchGraphicsPoints";
3033 
3035  m_transformation);
3036 }
3037 
3038 void MainWindow::updateRecentFileList()
3039 {
3040  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateRecentFileList";
3041 
3042  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
3043  QStringList recentFilePaths = settings.value(SETTINGS_RECENT_FILE_LIST).toStringList();
3044 
3045  // Determine the desired size of the path list
3046  unsigned int count = recentFilePaths.size();
3047  if (count > MAX_RECENT_FILE_LIST_SIZE) {
3048  count = MAX_RECENT_FILE_LIST_SIZE;
3049  }
3050 
3051  // Add visible entries
3052  unsigned int i;
3053  for (i = 0; i < count; i++) {
3054  QString strippedName = QFileInfo (recentFilePaths.at(i)).fileName();
3055  m_actionRecentFiles.at (i)->setText (strippedName);
3056  m_actionRecentFiles.at (i)->setData (recentFilePaths.at (i));
3057  m_actionRecentFiles.at (i)->setVisible (true);
3058  }
3059 
3060  // Hide any extra entries
3061  for (i = count; i < MAX_RECENT_FILE_LIST_SIZE; i++) {
3062  m_actionRecentFiles.at (i)->setVisible (false);
3063  }
3064 }
3065 
3067 {
3068  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsAxesChecker";
3069 
3070  m_cmdMediator->document().setModelAxesChecker(modelAxesChecker);
3071  m_transformationStateContext->updateAxesChecker (*m_cmdMediator,
3072  m_transformation);
3073 }
3074 
3076 {
3077  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsColorFilter";
3078 
3079  m_cmdMediator->document().setModelColorFilter(modelColorFilter);
3080  m_backgroundStateContext->updateColorFilter (m_transformation,
3081  m_cmdMediator->document().modelGridRemoval(),
3082  modelColorFilter);
3083  m_digitizeStateContext->handleCurveChange ();
3085 }
3086 
3088 {
3089  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsCoords";
3090 
3091  m_cmdMediator->document().setModelCoords(modelCoords);
3092 }
3093 
3095 {
3096  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsCurveAddRemove";
3097 
3098  m_cmdMediator->document().setCurvesGraphs (curvesGraphs);
3099  loadCurveListFromCmdMediator();
3101 }
3102 
3104 {
3105  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsCommon";
3106 
3107  m_cmdMediator->document().setModelCommon(modelCommon);
3108 }
3109 
3111 {
3112  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsCurveStyles";
3113 
3114  m_scene->updateCurveStyles(modelCurveStyles);
3115  m_cmdMediator->document().setModelCurveStyles(modelCurveStyles);
3117 }
3118 
3120 {
3121  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsDigitizeCurve";
3122 
3123  m_cmdMediator->document().setModelDigitizeCurve(modelDigitizeCurve);
3124  m_digitizeStateContext->updateModelDigitizeCurve (modelDigitizeCurve);
3125 }
3126 
3128 {
3129  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsExportFormat";
3130 
3131  m_cmdMediator->document().setModelExport (modelExport);
3132 }
3133 
3135 {
3136  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsGridRemoval";
3137 
3138  m_cmdMediator->document().setModelGridRemoval(modelGridRemoval);
3139 }
3140 
3142 {
3143  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsPointMatch";
3144 
3145  m_cmdMediator->document().setModelPointMatch(modelPointMatch);
3146 }
3147 
3149 {
3150  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsSegments";
3151 
3152  m_cmdMediator->document().setModelSegments(modelSegments);
3153  m_digitizeStateContext->updateModelSegments(modelSegments);
3154 }
3155 
3156 void MainWindow::updateTransformationAndItsDependencies()
3157 {
3158  m_transformation.update (!m_currentFile.isEmpty (), *m_cmdMediator);
3159 
3160  // Grid removal is affected by new transformation
3161  m_backgroundStateContext->setCurveSelected (m_transformation,
3162  m_cmdMediator->document().modelGridRemoval(),
3163  m_cmdMediator->document().modelColorFilter(),
3164  m_cmbCurve->currentText ());
3165 }
3166 
3167 void MainWindow::updateViewedCurves ()
3168 {
3169  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateViewedCurves";
3170 
3171  if (m_actionViewCurvesAll->isChecked ()) {
3172 
3173  m_scene->showCurves (true, true);
3174 
3175  } else if (m_actionViewCurvesSelected->isChecked ()) {
3176 
3177  m_scene->showCurves (true, false, selectedGraphCurve ());
3178 
3179  } else if (m_actionViewCurvesNone->isChecked ()) {
3180 
3181  m_scene->showCurves (false);
3182 
3183  } else {
3184  ENGAUGE_ASSERT (false);
3185  }
3186 }
3187 
3189 {
3190  LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateViewsOfSettings";
3191 
3192  QString activeCurve = m_digitizeStateContext->activeCurve ();
3193 
3194  updateViewsOfSettings (activeCurve);
3195 }
3196 
3197 void MainWindow::updateViewsOfSettings (const QString &activeCurve)
3198 {
3199  if (activeCurve.isEmpty ()) {
3200 
3201  m_viewPointStyle->unsetPointStyle ();
3202  m_viewSegmentFilter->unsetColorFilterSettings ();
3203 
3204 
3205  } else {
3206 
3207  PointStyle pointStyle = m_cmdMediator->document().modelCurveStyles().curveStyle(activeCurve).pointStyle();
3208  m_viewPointStyle->setPointStyle (pointStyle);
3209 
3210  ColorFilterSettings colorFilterSettings = m_cmdMediator->document().modelColorFilter().colorFilterSettings(activeCurve);
3211  m_viewSegmentFilter->setColorFilterSettings (colorFilterSettings,
3212  m_cmdMediator->pixmap ());
3213 
3214  }
3215 }
3216 
3218 {
3219  ENGAUGE_CHECK_PTR (m_view);
3220  return *m_view;
3221 }
3222 
3224 {
3225  ENGAUGE_CHECK_PTR (m_view);
3226  return *m_view;
3227 }
3228 
3229 void MainWindow::writeCheckpointToLogFile ()
3230 {
3231  // Document
3232  QString checkpointDoc;
3233  QTextStream strDoc (&checkpointDoc);
3234  m_cmdMediator->document().printStream(INDENTATION_PAST_TIMESTAMP,
3235  strDoc);
3236 
3237  // Scene
3238  QString checkpointScene;
3239  QTextStream strScene (&checkpointScene);
3240  m_scene->printStream (INDENTATION_PAST_TIMESTAMP,
3241  strScene);
3242 
3243  // Skip slow string manipulation if BEFORE call to LOG4CPP_DEBUG_S
3244  if (mainCat->getPriority() == log4cpp::Priority::DEBUG) {
3245 
3246  LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::writeCheckpointToLogFile\n"
3247  << "--------------DOCUMENT CHECKPOINT START----------" << "\n"
3248  << checkpointDoc.toLatin1().data()
3249  << "---------------DOCUMENT CHECKPOINT END-----------" << "\n"
3250  << "----------------SCENE CHECKPOINT START-----------" << "\n"
3251  << checkpointScene.toLatin1().data()
3252  << "-----------------SCENE CHECKPOINT END------------" ;
3253  }
3254 }
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 unsetPointStyle()
Apply no PointStyle.
void handleMouseMove(QPointF pos)
See DigitizeStateAbstractBase::handleMouseMove.
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:746
void setCurveName(const QString &curveName)
Load information for the specified curve name. When called externally, the load method must have been...
Model for DlgSettingsPointMatch and CmdSettingsPointMatch.
Color filter parameters for one curve. For a class, this is handled the same as LineStyle and PointSt...
void setStatusBarMode(StatusBarMode statusBarMode)
Set the status bar visibility mode.
Definition: StatusBar.cpp:147
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:638
Command for cutting all selected Points.
Definition: CmdCut.h:12
void setModelAxesChecker(const DocumentModelAxesChecker &modelAxesChecker)
Set method for DocumentModelAxesChecker.
Definition: Document.cpp:850
void setModelGridRemoval(const DocumentModelGridRemoval &modelGridRemoval)
Set method for DocumentModelGridRemoval.
Definition: Document.cpp:906
void updateAfterCommand(CmdMediator &cmdMediator)
Update the Points and their Curves after executing a command.
void updateDigitizeStateIfSoftwareTriggered(DigitizeState digitizeState)
After software-triggered state transition, this method manually triggers the action as if user had cl...
void printStream(QString indentation, QTextStream &str)
Debugging method that supports print method of this class and printStream method of some other class(...
void saveXml(QXmlStreamWriter &writer) const
Serialize to xml.
Class that displays the current Segment Filter in a MainWindow toolbar.
Wrapper around OpenJPEG library, in C, for opening jpeg2000 files.
Definition: Jpeg2000.h:20
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:911
Model for DlgSettingsExportFormat and CmdSettingsExportFormat.
Dialog for editing point match settings, for DigitizeStatePointMatch.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
Dialog for editing axes checker settings.
QString templateHtml() const
Template html comprising the checklist for display.
Transformation transformation() const
Return read-only copy of transformation.
void setEnabled(bool enabled)
Show the style with semi-transparency or full-transparency to indicate if associated Curve is active ...
void setImageIsLoaded(bool imageIsLoaded)
Set the image so QGraphicsView cursor and drag mode are accessible.
Context class for transformation state machine.
Model for DlgSettingsCurveProperties and CmdSettingsCurveProperties.
Definition: CurveStyles.h:16
Dockable help window.
Definition: HelpWindow.h:7
void updateSettingsCurveAddRemove(const CurvesGraphs &curvesGraphs)
Update with new curves.
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:916
void bindToCmdMediatorAndResetOnLoad(CmdMediator *cmdMediator)
Bind to CmdMediator class.
void updateSettingsCommon(const DocumentModelCommon &modelCommon)
Update with new common properties.
void updateAfterMouseRelease()
Call MainWindow::updateControls (which is private) after the very specific case - a mouse press/relea...
void updateModelDigitizeCurve(const DocumentModelDigitizeCurve &modelDigitizeCurve)
Update the digitize curve settings.
Model for DlgSettingsCommon and CmdSettingsCommon.
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:128
QStringList selectedPointIdentifiers() const
Return a list of identifiers for the currently selected points.
void handleContextMenuEvent(const QString &pointIdentifier)
See DigitizeStateAbstractBase::handleContextMenuEvent.
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.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
void setModelDigitizeCurve(const DocumentModelDigitizeCurve &modelDigitizeCurve)
Set method for DocumentModelDigitizeCurve.
Definition: Document.cpp:896
CmdMediator & cmdMediator()
Accessor for commands to process the Document.
Definition: MainWindow.cpp:177
PointStyle pointStyle() const
Get method for PointStyle.
Definition: CurveStyle.cpp:69
void triggerStateTransition(TransformationState transformationState, CmdMediator &cmdMediator, const Transformation &transformation, const QString &selectedGraphCurve)
Trigger a state transition to be performed immediately.
QString xmlToUpload() const
Xml to be uploaded. Includes document if user has approved.
Document & document()
Provide the Document to commands, primarily for undo/redo processing.
Definition: CmdMediator.cpp:61
void setModelCoords(const DocumentModelCoords &modelCoords)
Set method for DocumentModelCoords.
Definition: Document.cpp:876
void wakeUp()
Enable all widgets in the status bar. This is called just after a Document becomes active...
Definition: StatusBar.cpp:278
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 uploadErrorReport(const QString &report)
Upload the error report asynchronously.
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:186
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
void updateSettingsDigitizeCurve(const DocumentModelDigitizeCurve &modelDigitizeCurve)
Update with new curve digitization styles.
Tutorial using a strategy like a comic strip with decision points deciding which panels appear...
Definition: TutorialDlg.h:13
bool isModified() const
Dirty flag.
Definition: CmdMediator.cpp:71
Strategy class for exporting to a file. This strategy is external to the Document class so that class...
Definition: ExportToFile.h:12
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:901
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:36
void setPixmap(const Transformation &transformation, const DocumentModelGridRemoval &modelGridRemoval, const DocumentModelColorFilter &modelColorFilter, const QPixmap &pixmapOriginal)
Update the images of all states, rather than just the current state.
Details for a specific Point.
Definition: PointStyle.h:14
Container for all graph curves. The axes point curve is external to this class.
Definition: CurvesGraphs.h:18
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:15
GraphicsScene & scene()
Scene container for the QImage and QGraphicsItems.
void setEnabled(bool enabled)
Show the style with semi-transparency or full-transparency to indicate if associated Curve is active ...
void updateSettingsCurveStyles(const CurveStyles &modelCurveStyles)
Update with new curve styles.
Client for interacting with Engauge server.
Definition: NetworkClient.h:10
void setModelCurveStyles(const CurveStyles &modelCurveStyles)
Set method for CurveStyles.
Definition: Document.cpp:881
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:656
QGraphicsView class with event handling added. Typically the events are sent to the active digitizing...
Definition: GraphicsView.h:14
Container for all DigitizeStateAbstractBase subclasses. This functions as the context class in a stan...
bool canRedo() const
Return true if there is a command available.
void updateModelSegments(const DocumentModelSegments &modelSegments)
Update the segments given the new settings.
void resetOnLoad()
Reset, when loading a document after the first, to same state that first document was at when loaded...
void exportToFile(const DocumentModelExportFormat &modelExport, const Document &document, const Transformation &transformation, QTextStream &str) const
Export Document points according to the settings.
void resetPositionHasChangedFlags()
Reset positionHasChanged flag for all items. Typically this is done as part of mousePressEvent.
QPixmap pixmap() const
See Document::pixmap.
Definition: CmdMediator.cpp:91
void update(bool fileIsLoaded, const CmdMediator &cmdMediator)
Update transform by iterating through the axis points.
void setModelColorFilter(const DocumentModelColorFilter &modelColorFilter)
Set method for DocumentModelColorFilter.
Definition: Document.cpp:855
void close()
Open Document is being closed so remove the background.
QImage imageForCurveState() const
Image for the Curve state, even if the current state is different.
Model for DlgSettingsCoords and CmdSettingsCoords.
void updateAfterCommand()
See GraphicsScene::updateAfterCommand.
void updateSettingsColorFilter(const DocumentModelColorFilter &modelColorFilter)
Update with new color filter properties.
void setCurveSelected(const Transformation &transformation, const DocumentModelGridRemoval &modelGridRemoval, const DocumentModelColorFilter &modelColorFilter, const QString &curveSelected)
Update the selected curve.
Command for deleting all selected Points.
Definition: CmdDelete.h:12
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 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 requestImmediateStateTransition(DigitizeState digitizeState)
Perform immediate state transition. Called from outside state machine.
void showTemporaryMessage(const QString &message)
Show temporary message in status bar. After a short interval the message will disappear.
Definition: StatusBar.cpp:157
void updateCurveStyles(const CurveStyles &modelCurveStyles)
Update curve styles after settings changed.
void unsetColorFilterSettings()
Apply no color filter.
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...
void handleLeave()
See DigitizeStateAbstractBase::handleLeave.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
void appendNewCmd(QUndoCommand *cmd)
Append just-created QUndoCommand to command stack. This is called from DigitizeStateAbstractBase subc...
bool transformIsDefined() const
Transform is defined when at least three axis points have been digitized.
Model for DlgSettingsAxesChecker and CmdSettingsAxesChecker.
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...
QStringList curveNames() const
Curve names to be placed into Document.
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.
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:72
Dialog for editing curve properties settings.
void populateCurvesGraphs(CurvesGraphs &curvesGraphs)
Create entries in CurvesGraphs for each curve name that user provided.
Command queue stack.
Definition: CmdMediator.h:16
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
MainWindow(const QString &errorReportFile, bool isGnuplot, QWidget *parent=0)
Single constructor.
Definition: MainWindow.cpp:110
void saveErrorReportFileAndExit(const char *comment, const char *file, int line, const char *context) const
Save error report and exit.
void signalZoom(int)
Send zoom selection, picked from menu or keystroke, to StatusBar.
Model for DlgSettingsSegments and CmdSettingsSegments.
void handleSetOverrideCursor(const QCursor &cursor)
See DigitizeStateAbstractBase::handleSetOverrideCursor.
void updateColorFilter(const Transformation &transformation, const DocumentModelGridRemoval &modelGridRemoval, const DocumentModelColorFilter &colorFilter)
Apply color filter settings.
void setCurvesGraphs(const CurvesGraphs &curvesGraphs)
Let CmdAbstract classes overwrite CurvesGraphs.
Definition: Document.cpp:843
void updateAxesChecker(CmdMediator &cmdMediator, const Transformation &transformation)
Apply the new DocumentModelAxesChecker.
void resizeEvent(QResizeEvent *event)
Intercept resize event so graphics scene can be appropriately resized when in Fill mode...
QStringList supportedImageWildcards() const
List the supported jpeg2000 file extensions, for filtering import files.
Definition: Jpeg2000.cpp:299
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.
void handleCurveChange()
See DigitizeStateAbstractBase::handleCurveChange.
Add point and line handling to generic QGraphicsScene.
Definition: GraphicsScene.h:25
Command for moving all selected Points by a specified translation.
Definition: CmdCopy.h:12
void handleMouseRelease(QPointF pos)
See DigitizeStateAbstractBase::handleMouseRelease.
void saveXml(QXmlStreamWriter &writer) const
Save document to xml.
Definition: Document.cpp:810
Model for DlgSettingsGridRemoval and CmdSettingsGridRemoval. The settings are unstable until the user...
void setModelCommon(const DocumentModelCommon &modelCommon)
Set method for DocumentModelCommon.
Definition: Document.cpp:871
void handleKeyPress(Qt::Key key, bool atLeastOneSelectedItem)
See DigitizeStateAbstractBase::handleKeyPress.
Dialog for sending error report.
QString reasonForUnsuccessfulRead() const
See Document::reasonForUnsuccessfulRead.
Definition: CmdMediator.cpp:98
void updateSettingsSegments(const DocumentModelSegments &modelSegments)
Update with new segments properties.
void showCurves(bool show, bool showAll=false, const QString &curveName="")
Show or hide all Curves (if showAll is true) or just the selected Curve (if showAll is false);...
Dialog for editing axes checker settings.
Dialog to be displayed whenever some operation or processing cannot be performed since the axis point...
void updateGraphicsLinesToMatchGraphicsPoints()
Update the graphics lines so they follow the graphics points, after a drag, addition, removal, and such.
DocumentModelGridRemoval modelGridRemoval() const
Get method for DocumentModelGridRemoval.
Definition: Document.cpp:674
QStringList curvesGraphsNames() const
See CurvesGraphs::curvesGraphsNames.
Definition: CmdMediator.cpp:51
void setTemplateHtml(const QString &html, const QStringList &curveNames)
Populate the browser with template html.
bool successfulRead() const
Wrapper for Document::successfulRead.
About Engauge dialog. This provides a hidden shortcut for triggering ENGAUGE_ASSERT.
Definition: DlgAbout.h:9
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
bool transformIsDefined() const
Return true if all three axis points have been defined.
void handleMousePress(QPointF pos)
See DigitizeStateAbstractBase::handleMousePress.