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