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