Engauge Digitizer 2
Loading...
Searching...
No Matches
MainWindow.cpp
Go to the documentation of this file.
1/******************************************************************************************************
2 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
3 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
4 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
5 ******************************************************************************************************/
6
7#include "BackgroundImage.h"
9#include "ChecklistGuide.h"
11#include "CmdAddPointsGraph.h"
12#include "CmdCopy.h"
13#include "CmdCut.h"
14#include "CmdDelete.h"
15#include "CmdMediator.h"
17#include "CmdStackShadow.h"
18#include "ColorFilter.h"
19#include "CreateFacade.h"
20#include "Curve.h"
21#include "DataKey.h"
23#include "DlgAbout.h"
24#include "DlgErrorReportLocal.h"
25#include "DlgImportAdvanced.h"
29#include "DlgSettingsCoords.h"
34#include "DlgSettingsGeneral.h"
39#include "DlgSettingsSegments.h"
40#include "DocumentScrub.h"
41#include "DocumentSerialize.h"
42#include "EngaugeAssert.h"
43#include "EnumsToQt.h"
45#include "ExportToFile.h"
46#include "FileCmdScript.h"
47#include "FittingCurve.h"
48#include "FittingWindow.h"
49#include "GeometryWindow.h"
50#include "Ghosts.h"
52#include "GraphicsItemType.h"
53#include "GraphicsScene.h"
54#include "GraphicsView.h"
55#include "GridLineFactory.h"
56#include "GridLineLimiter.h"
57#if !defined(OSX_DEBUG) && !defined(OSX_RELEASE)
58#include "HelpWindow.h"
59#endif
61#ifdef ENGAUGE_JPEG2000
62#include "Jpeg2000.h"
63#endif // ENGAUGE_JPEG2000
64#include "LoadFileInfo.h"
65#include "LoadImageFromUrl.h"
66#include "Logger.h"
68#include "MainTitleBarFormat.h"
69#include "MainWindow.h"
70#include "MimePointsImport.h"
71#ifdef NETWORKING
72#include "NetworkClient.h"
73#endif
74#include "NonPdf.h"
75#ifdef ENGAUGE_PDF
76#include "Pdf.h"
77#endif // ENGAUGE_PDF
78#include "PdfResolution.h"
79#include <QAction>
80#include <QApplication>
81#include <QClipboard>
82#include <QCloseEvent>
83#include <QComboBox>
84#include <QDebug>
85#include <QDesktopServices>
86#include <QDockWidget>
87#include <QDomDocument>
88#include <QFileDialog>
89#include <QFileInfo>
90#include <QImageReader>
91#include <QKeyEvent>
92#include <QKeySequence>
93#include <qmath.h>
94#include <QMessageBox>
95#include <QMouseEvent>
96#include <QPrintDialog>
97#include <QPrinter>
98#include <QProcess>
99#include <QPushButton>
100#include <QSettings>
101#include <QSignalMapper>
102#include <QTextStream>
103#if !defined(OSX_DEBUG) && !defined(OSX_RELEASE)
104#include <QtHelp>
105#endif
106#include <QTimer>
107#include <QToolBar>
108#include <QToolButton>
109#include "QtToString.h"
110#include <QVBoxLayout>
111#include <QWhatsThis>
112#include <QXmlStreamReader>
113#include <QXmlStreamWriter>
115#include "Settings.h"
116#include "StatusBar.h"
118#include "TutorialDlg.h"
119#include "Version.h"
120#include "ViewPointStyle.h"
121#include "ViewSegmentFilter.h"
122#include "ZoomFactor.h"
123#include "ZoomFactorInitial.h"
124#include "ZoomTransition.h"
125
127static const char *ENGAUGE_FILENAME_DESCRIPTION = "Engauge Document";
129const int REGRESSION_INTERVAL = 400; // Milliseconds
130const unsigned int MAX_RECENT_FILE_LIST_SIZE = 8;
131
134 bool isDropRegression,
135 bool isRegressionTest,
136 bool isGnuplot,
137 bool isReset,
138 bool isExportOnly,
143 QWidget *parent) :
144 QMainWindow(parent),
145 m_originalFileWasImported (false),
146 m_isDocumentExported (false),
147 m_engaugeFile (EMPTY_FILENAME),
148 m_currentFile (EMPTY_FILENAME),
149 m_layout (nullptr),
150 m_scene (nullptr),
151 m_view (nullptr),
152 m_loadImageFromUrl (nullptr),
153 m_cmdMediator (nullptr),
154 m_digitizeStateContext (nullptr),
155 m_transformationStateContext (nullptr),
156 m_backgroundStateContext (nullptr),
157 m_networkClient (nullptr),
158 m_isGnuplot (isGnuplot),
159 m_commandLineWithoutLoadStartupFiles (commandLineWithoutLoadStartupFiles),
160 m_ghosts (nullptr),
161 m_timerRegressionErrorReport(nullptr),
162 m_fileCmdScript (nullptr),
163 m_isErrorReportRegressionTest (isRegressionTest),
164 m_timerRegressionFileCmdScript(nullptr),
165 m_fittingCurve (nullptr),
166 m_isExportOnly (isExportOnly),
167 m_isExtractImageOnly (isExtractImageOnly),
168 m_extractImageOnlyExtension (extractImageOnlyExtension)
169{
170 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::MainWindow"
171 << " curDir=" << QDir::currentPath().toLatin1().data();
172
173#if defined(OSX_DEBUG) || defined(OSX_RELEASE)
174 qApp->setApplicationName ("Engauge Digitizer");
175 qApp->setOrganizationDomain ("Mark Mitchell");
176#endif
177
179
180 m_startupDirectory = QDir::currentPath();
181
182 setCurrentFile ("");
183
185 createFacade.create (*this);
186
187 updateControls ();
188
189 settingsRead (isReset); // This changes the current directory when not regression testing
190 setCurrentFile ("");
192
193 installEventFilter(this);
194
195 // Start regression scripting if appropriate. Regression scripts assume current directory is the original
196 // current directory, so we temporarily reset the current directory
197 QString originalPath = QDir::currentPath();
198 QDir::setCurrent (m_startupDirectory);
199 if (isExportOnly) {
200 m_loadStartupFiles = loadStartupFiles;
201 m_regressionFile = exportRegressionFilenameFromInputFilename (loadStartupFiles.first ()); // For regression test
202 slotLoadStartupFiles ();
203 slotFileExport (); // Export one file. QProcess::startDetached will be called for each remaining file
204 exit (0);
205 } else if (isExtractImageOnly) {
206 m_loadStartupFiles = loadStartupFiles;
207 m_regressionFile = exportRegressionFilenameFromInputFilename (loadStartupFiles.first ()); // For regression test
208 slotLoadStartupFiles ();
209 handlerFileExtractImage (); // Extract one file. QProcess::startDetached will be called for each remaining file
210 exit (0);
211 } else if (!errorReportFile.isEmpty()) {
212 loadErrorReportFile(errorReportFile);
213 if (m_isErrorReportRegressionTest) {
214 startRegressionTestErrorReport(errorReportFile);
215 }
216 } else if (!fileCmdScriptFile.isEmpty()) {
217 m_fileCmdScript = new FileCmdScript (fileCmdScriptFile);
218 startRegressionTestFileCmdScript();
219 } else if (isDropRegression) {
220 m_fileCmdScript = new FileCmdScript (""); // Hack to keep dialogs from popping up
221 startRegressionDropTest (loadStartupFiles);
222 } else {
223
224 // Save file names for later, after gui becomes available. The file names are dropped if error report file is specified
225 // since only one of the two modes is available at any time, for simplicity
226 m_loadStartupFiles = loadStartupFiles;
227 }
228 QDir::setCurrent (originalPath);
229}
230
232{
233#if !defined(OSX_DEBUG) && !defined(OSX_RELEASE)
234 delete m_helpWindow;
235#endif
236 delete m_tutorialDlg;
237 delete m_cmdMediator;
238 delete m_cmdStackShadow;
239 delete m_digitizeStateContext;
240 delete m_transformationStateContext;
241 delete m_backgroundStateContext;
242 delete m_dlgSettingsAxesChecker;
243 delete m_dlgSettingsColorFilter;
244 delete m_dlgSettingsCoords;
245 delete m_dlgSettingsCurveList;
246 delete m_dlgSettingsCurveProperties;
247 delete m_dlgSettingsDigitizeCurve;
248 delete m_dlgSettingsExportFormat;
249 delete m_dlgSettingsGeneral;
250 delete m_dlgSettingsGridDisplay;
251 delete m_dlgSettingsGridRemoval;
252 delete m_dlgSettingsMainWindow;
253 delete m_dlgSettingsPointMatch;
254 delete m_dlgSettingsSegments;
255 delete m_fileCmdScript;
256 m_gridLines.clear ();
257}
258
259void MainWindow::addDockWindow (QDockWidget *dockWidget,
263 Qt::DockWidgetArea dockWidgetArea)
264{
265 // Checklist guide is docked or undocked. Default is docked so it does not get overlooked by the user (which
266 // can happen if it opens elsewhere). The user may not know it can be undocked, but at least can resize or
267 // hide it if he/she needs more room for the main window.
268 const bool DOCKED_EQUALS_NOT_FLOATING = false;
269 Qt::DockWidgetArea area = static_cast<Qt::DockWidgetArea> (settings.value (settingsTokenArea,
270 Qt::NoDockWidgetArea).toInt());
271
272 if (area == Qt::NoDockWidgetArea) {
273
275 dockWidget); // Add on the right to prevent error message, then immediately make undocked
277 if (settings.contains (settingsTokenGeometry)) {
278 dockWidget->restoreGeometry (settings.value (settingsTokenGeometry).toByteArray());
279 }
280
281 } else {
282
284 dockWidget);
285
286 }
287}
288
289void MainWindow::applyZoomFactorAfterLoad()
290{
292 ZoomFactorInitial zoomFactorInitial = m_modelMainWindow.zoomFactorInitial();
293
294 if (m_zoomMapFromInitial.contains (zoomFactorInitial)) {
295 zoomFactor = m_zoomMapFromInitial [zoomFactorInitial];
296 } else if (zoomFactorInitial == ZOOM_INITIAL_PREVIOUS) {
297 zoomFactor = currentZoomFactor ();
298 } else {
299 ENGAUGE_ASSERT (false);
300 zoomFactor = currentZoomFactor();
301 }
302
303 slotViewZoom (zoomFactor);
304}
305
306void MainWindow::closeEvent(QCloseEvent *event)
307{
308 if (maybeSave()) {
309 settingsWrite ();
310 event->accept ();
311 } else {
312 event->ignore ();
313 }
314}
315
317{
318 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::cmdFileClose";
319
320 setWindowModified (false); // Prevent popup query asking if changes should be saved
321 slotFileClose();
322}
323
325{
326 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::cmdFileExport";
327
329 fileExport(fileName,
331}
332
334{
335 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::cmdFileImport";
336
337 m_regressionFile = exportRegressionFilenameFromInputFilename (fileName);
338 fileImport (fileName,
339 IMPORT_TYPE_SIMPLE);
340}
341
343{
344 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::cmdFileOpen";
345
346 m_regressionFile = exportRegressionFilenameFromInputFilename (fileName);
347 loadDocumentFile(fileName);
348}
349
351{
352 // We do not check m_cmdMediator with ENGAUGE_CHECK_PTR since calling code is expected to deal with null pointer at startup
353 return m_cmdMediator;
354}
355
356ZoomFactor MainWindow::currentZoomFactor () const
357{
358 // Find the zoom control that is checked
359 for (int z = 0; z < NUMBER_ZOOM_FACTORS; z++) {
360 ZoomFactor zoomFactor = static_cast<ZoomFactor> (z);
361 if (m_zoomMapToAction [zoomFactor]->isChecked ()) {
362 // This zoom control is checked
363 return zoomFactor;
364 }
365 }
366
367 ENGAUGE_ASSERT (false);
368 return ZOOM_1_TO_1;
369}
370
372{
373 if (event->type () == QEvent::KeyPress) {
374
375 QKeyEvent *eventKeyPress = static_cast<QKeyEvent *> (event);
376
377 // Special shortcuts. All of these are probably only useful for debugging and/or regression testing
378 if ((eventKeyPress->key() == Qt::Key_E) &&
379 ((eventKeyPress->modifiers() & Qt::ShiftModifier) != 0) &&
380 ((eventKeyPress->modifiers() & Qt::ControlModifier) != 0)) {
381
382 saveErrorReportFileAndExit ("Shift+Control+E",
383 __FILE__,
384 __LINE__,
385 "userTriggered");
386
387 }
388 }
389
390 return QObject::eventFilter (target, event);
391}
392
393#if !defined(OSX_DEBUG) && !defined(OSX_RELEASE)
394void MainWindow::exportAllCoordinateSystemsAfterRegressionTests()
395{
396 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::exportAllCoordinateSystemsAfterRegressionTests curDir=" << QDir::currentPath().toLatin1().data();
397
398 // Output the regression test results. One file is output for every coordinate system
399 for (CoordSystemIndex index = 0; index < m_cmdMediator->document().coordSystemCount(); index++) {
400
401 updateCoordSystem (index); // Switch to the specified coordinate system
402
403 QString regressionFile = QString ("%1_%2")
404 .arg (m_regressionFile)
405 .arg (index + 1); // Append the coordinate system index
406
407 // Normally we just export to a file, but when regression testing the export will fail since coordinates are not defined. To
408 // get an export file when regression testing, we just output the image size
409 if (m_isErrorReportRegressionTest && !m_transformation.transformIsDefined()) {
410
412 exportStrategy.fileExport (regressionFile);
413
414 } else {
415
417
418 fileExport (regressionFile,
420 }
421 }
422}
423#endif
424
425QString MainWindow::exportRegressionFilenameFromInputFilename (const QString &fileName) const
426{
427 // Include file extensions used in loading, importing or drag and drop. Note html is before htm
428 // so the "l" gets replaced
430 befores << ".dig" << ".gif" << ".html" << ".htm" << ".jp2" << ".jpg" << ".pbm"
431 << ".pdf" << ".pgm" << ".png" << ".ppm" << ".xbm" << ".xpm" << ".xml";
432
434
435 QStringList::iterator itr;
436 for (itr = befores.begin(); itr != befores.end(); itr++) {
437 QString suffix = *itr;
438
439 outFileName = outFileName.replace (suffix, ".csv_actual", Qt::CaseInsensitive);
440 }
441
442 return outFileName;
443}
444
445void MainWindow::fileExport(const QString &fileName,
447{
448 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::fileExport"
449 << " curDir=" << QDir::currentPath().toLatin1().data()
450 << " fileName=" << fileName.toLatin1().data();
451
453 if (file.open(QIODevice::WriteOnly)) {
454
456
457 DocumentModelExportFormat modelExportFormat = modelExportOverride (m_cmdMediator->document().modelExport(),
459 fileName);
460 exportStrategy.exportToFile (modelExportFormat,
461 m_cmdMediator->document(),
462 m_modelMainWindow,
464 str);
465
466 m_isDocumentExported = true; // Remember that export was performed
467
468 updateChecklistGuide ();
469 m_statusBar->showTemporaryMessage("File saved");
470
471 } else {
472
473 LOG4CPP_ERROR_S ((*mainCat)) << "MainWindow::fileExport"
474 << " file=" << fileName.toLatin1().data()
475 << " curDir=" << QDir::currentPath().toLatin1().data();
476 QMessageBox::critical (nullptr,
478 tr ("Unable to export to file") + " " + fileName);
479 }
480}
481
482void MainWindow::fileExtractImage (const QString &fileName)
483{
484 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::fileExtractImage"
485 << " curDir=" << QDir::currentPath().toLatin1().data()
486 << " fileName=" << fileName.toLatin1().data();
487
489 if (file.open(QIODevice::WriteOnly)) {
490
491 QPixmap pixmap = m_cmdMediator->pixmap();
492 pixmap.save (&file);
493
494 // Generate a checksum file if performing a regression test
495 if (m_isErrorReportRegressionTest) {
496 QString csvFile = QString ("%1_1")
497 .arg (exportRegressionFilenameFromInputFilename (m_regressionFile));
498
499 // Generate csv file with only checksum. Since QProcess cannot handle pipes, we let shell execute it
501 process.start ("bash -c \"cksum " + fileName + " | awk '{print $1}' > " + csvFile + "\"");
502 process.waitForFinished (-1);
503 }
504
505 } else {
506
507 LOG4CPP_ERROR_S ((*mainCat)) << "MainWindow::fileExtractImage"
508 << " file=" << fileName.toLatin1().data()
509 << " curDir=" << QDir::currentPath().toLatin1().data();
510 QMessageBox::critical (nullptr,
512 tr ("Unable to extract image to file") + " " + fileName);
513 }
514}
515
516void MainWindow::fileImport (const QString &fileName,
517 ImportType importType)
518{
519 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::fileImport"
520 << " fileName=" << fileName.toLatin1 ().data ()
521 << " curDir=" << QDir::currentPath().toLatin1().data()
522 << " importType=" << importType;
523
524 QString originalFileOld = m_originalFile;
525 bool originalFileWasImported = m_originalFileWasImported;
526
527 m_originalFile = fileName; // Make this available for logging in case an error occurs during the load
528 m_originalFileWasImported = true;
529
530 if (importType == IMPORT_TYPE_ADVANCED) {
531
532 // Remove any existing points, axes checker(s) and such from the previous Document so they do not appear in setupAfterLoadNewDocument
533 // when previewing for IMAGE_TYPE_ADVANCED
534 slotFileClose();
535
536 // Restore the background just closed by slotFileClose. This is required so when the image is loaded for preview, it will appear
537 m_backgroundStateContext->setBackgroundImage(BACKGROUND_IMAGE_ORIGINAL);
538 }
539
540 QImage image;
541 bool loaded = false;
542
543#ifdef ENGAUGE_JPEG2000
546 image);
547#endif // ENGAUGE_JPEG2000
548
549#ifdef ENGAUGE_PDF
550 if (!loaded) {
551
552 Pdf pdf;
554 image,
555 m_modelMainWindow.pdfResolution(),
556 m_modelMainWindow.importCropping(),
557 m_isErrorReportRegressionTest);
559
560 // User canceled so exit immediately
561 return;
562
563 }
564
566 }
567#endif // ENGAUGE_PDF
568
569 if (!loaded) {
572 image,
573 m_modelMainWindow.importCropping(),
574 m_isErrorReportRegressionTest);
576
577 // User canceled so exit immediately
578 return;
579
580 }
581
583 }
584
585 if (!loaded) {
586 QString msg = QString("%1 %2 %3 %4.")
587 .arg (tr ("Cannot read file"))
588 .arg (fileName)
589 .arg (tr ("from directory"))
590 .arg (QDir::currentPath());
591#ifdef WIN32
592 if (fileName.contains ("???")) {
593
594 // At this point the file name is filled with question marks in Windows if it had letter from
595 // more than one alphabet (e.g. latin '.dig' suffix and cyrillic basename)
596 // in which case we cannot recover the original file without user intervention
597 msg += QObject::tr ("The file appears to have characters from multiple language "
598 "alphabets, which does not work in the Windows command line");
599 }
600#endif
601 QMessageBox::warning (this,
603 msg);
604
605 // Reset
606 m_originalFile = originalFileOld;
607 m_originalFileWasImported = originalFileWasImported;
608
609 } else {
610
611 loaded = loadImage (fileName,
612 image,
613 importType);
614
615 if (loaded) {
616
617 // Success
618 if ((m_cmdMediator->document().coordSystemCount() > 1) &&
619 ! m_actionViewCoordSystem->isChecked ()) {
620
621 // User is working with multiple coordinate systems so make the coordinate system toolbar visible
622 m_actionViewCoordSystem->trigger ();
623 }
624
625 } else {
626
627 // Failed
628 if (importType == IMPORT_TYPE_ADVANCED) {
629
630 // User cancelled after another file was imported so it could be previewed. In anticipation of the loading-for-preview,
631 // we closed the current Document at the top of this method so we cannot reload. So, the only option is to close again
632 // so the half-imported current Document is removed
633 slotFileClose();
634
635 } else {
636
637 // Reset
638 m_originalFile = originalFileOld;
639 m_originalFileWasImported = originalFileWasImported;
640 }
641 }
642 }
643}
644
645void MainWindow::fileImportWithPrompts (ImportType importType)
646{
647 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::fileImportWithPrompts"
648 << " importType=" << importType;
649
650 // Skip maybeSave method for IMPORT_TYPE_REPLACE_IMAGE since open file dialog is enough to allow user to cancel the operation, and
651 // since no information is lost in that case
652 bool okToContinue = true;
653 if (importType != IMPORT_TYPE_IMAGE_REPLACE) {
654 okToContinue = maybeSave ();
655 }
656
657 if (okToContinue) {
658
659 QString filter;
660 QTextStream str (&filter);
661
664
665 str << "Image Files (" << supportedImageFormatStrings.join (" ") << ")";
666
667 // Allow selection of files with strange suffixes in case the file extension was changed. Since
668 // the default is the first filter, we add this afterwards (it is the off-nominal case)
669 str << ";; All Files (*.*)";
670
672 QString fileName = QFileDialog::getOpenFileName (this,
673 tr("Import Image"),
674 directoryPersist.getDirectoryImportOpen ().path (),
675 filter);
676 if (!fileName.isEmpty ()) {
677
678 directoryPersist.setDirectoryImportOpenFromFilename (fileName);
679
680 // We import the file BEFORE asking the number of coordinate systems, so user can see how many there are
681 fileImport (fileName,
682 importType);
683 }
684 }
685}
686
687QString MainWindow::fileNameForExportOnly () const
688{
690
692 if (m_isErrorReportRegressionTest) {
693
694 // Regression test has a specific file extension
695 fileName = QString ("%1_1")
696 .arg (exportRegressionFilenameFromInputFilename (m_regressionFile));
697
698 } else {
699
700 // User requested export-only mode so just change file extension
701 QString dir = QFileInfo (m_currentFileWithPathAndFileExtension).absolutePath();
702 fileName = QString ("%1/%2.%3")
703 .arg (dir)
704 .arg (m_currentFile)
705 .arg (exportStrategy.fileExtensionCsv ());
706 }
707
708 return fileName;
709}
710
711QString MainWindow::fileNameForExtractImageOnly () const
712{
713 // User requested export-only mode so just change file extension
714 QString dir = QFileInfo (m_currentFileWithPathAndFileExtension).absolutePath();
715 QString fileName = QString ("%1/%2.%3")
716 .arg (dir)
717 .arg (m_currentFile)
718 .arg (m_extractImageOnlyExtension);
719
720 return fileName;
721}
722
723void MainWindow::filePaste (ImportType importType)
724{
725 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::filePaste"
726 << " importType=" << importType;
727
728 QString originalFileOld = m_originalFile;
729 bool originalFileWasImported = m_originalFileWasImported;
730
731 QString fileName ("clipboard");
732 m_originalFile = fileName; // Make this available for logging in case an error occurs during the load
733 m_originalFileWasImported = true;
734
735 if (importType == IMPORT_TYPE_ADVANCED) {
736
737 // Remove any existing points, axes checker(s) and such from the previous Document so they do not appear in setupAfterLoadNewDocument
738 // when previewing for IMAGE_TYPE_ADVANCED
739 slotFileClose();
740
741 // Restore the background just closed by slotFileClose. This is required so when the image is loaded for preview, it will appear
742 m_backgroundStateContext->setBackgroundImage(BACKGROUND_IMAGE_ORIGINAL);
743 }
744
745 // An image was in the clipboard when this method was called but it may have disappeared
746 QImage image = QApplication::clipboard()->image();
747
748 bool loaded = false;
749 if (!loaded) {
750 loaded = !image.isNull();
751 }
752
753 if (!loaded) {
754 QMessageBox::warning (this,
756 QString("%1 %2 %3 %4.")
757 .arg (tr ("Cannot read file"))
758 .arg (fileName)
759 .arg (tr ("from directory"))
760 .arg (QDir::currentPath ()));
761
762 // Reset
763 m_originalFile = originalFileOld;
764 m_originalFileWasImported = originalFileWasImported;
765
766 } else {
767
768 loaded = loadImage (fileName,
769 image,
770 importType);
771
772 if (!loaded) {
773
774 // Failed
775 if (importType == IMPORT_TYPE_ADVANCED) {
776
777 // User cancelled after another file was imported so it could be previewed. In anticipation of the loading-for-preview,
778 // we closed the current Document at the top of this method so we cannot reload. So, the only option is to close again
779 // so the half-imported current Document is removed
780 slotFileClose();
781
782 } else {
783
784 // Reset
785 m_originalFile = originalFileOld;
786 m_originalFileWasImported = originalFileWasImported;
787 }
788 }
789 }
790}
791
792void MainWindow::ghostsCreate ()
793{
794 LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::ghostsCreate";
795
796 ENGAUGE_ASSERT (m_ghosts == nullptr);
797 m_ghosts = new Ghosts (m_cmdMediator->document().coordSystemIndex());
798
799 for (unsigned int index = 0; index < m_cmdMediator->document().coordSystemCount(); index++) {
800
801 // Skip this coordinate system if it is the selected coordinate system since it will be displayed anyway, so no ghosts are required
802 if (index != m_ghosts->coordSystemIndexToBeRestored ()) {
803
804 updateCoordSystem (index);
805
806 // Take a snapshot of the graphics items
807 m_ghosts->captureGraphicsItems (*m_scene);
808 }
809 }
810
811 // Restore the coordinate system that was originally selected, so its points/lines are visible
813
814 // Make visible ghosts
815 m_ghosts->createGhosts (*m_scene);
816}
817
818void MainWindow::ghostsDestroy ()
819{
820 LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::ghostsDestroy";
821
822 ENGAUGE_CHECK_PTR (m_ghosts);
823
824 m_ghosts->destroyGhosts(*m_scene);
825
826 delete m_ghosts;
827 m_ghosts = nullptr;
828}
829
830void MainWindow::handlerFileExtractImage ()
831{
832 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::handlerFileExtractImage";
833
834 if (m_isExtractImageOnly) {
835 QString fileName = fileNameForExtractImageOnly ();
836
838
840 fileExtractImage(fileName);
841 }
842}
843
845{
846 return m_backgroundStateContext->imageForCurveState();
847}
848
850{
851 return m_isGnuplot;
852}
853
854void MainWindow::loadCoordSystemListFromCmdMediator ()
855{
856 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::loadCoordSystemListFromCmdMediator";
857
858 m_cmbCoordSystem->clear();
859
860 unsigned int numberCoordSystem = m_cmdMediator->document().coordSystemCount();
861
862 for (unsigned int i = 0; i < numberCoordSystem; i++) {
863 int index1Based = signed (i + 1);
864 m_cmbCoordSystem->addItem (QString::number (index1Based),
865 QVariant (i));
866 }
867
868 // Always start with the first entry selected
869 m_cmbCoordSystem->setCurrentIndex (0);
870
871 // Disable the controls if there is only one entry. Hopefully the user will not even be distracted
872 bool enable = (m_cmbCoordSystem->count() > 1);
873 m_cmbCoordSystem->setEnabled (enable);
874 m_btnShowAll->setEnabled (enable);
875 m_btnPrintAll->setEnabled (enable);
876}
877
878void MainWindow::loadCurveListFromCmdMediator ()
879{
880 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::loadCurveListFromCmdMediator";
881
882 m_cmbCurve->clear ();
883 QStringList curvesGraphsNames = m_cmdMediator->curvesGraphsNames ();
884 QStringList::iterator itr;
885 for (itr = curvesGraphsNames.begin (); itr != curvesGraphsNames.end (); itr++) {
886
888 m_cmbCurve->addItem (curvesGraphName);
889 }
890
891 // Select the curve that is associated with the current coordinate system
892 m_cmbCurve->setCurrentText (m_cmdMediator->selectedCurveName ());
893}
894
895void MainWindow::loadDocumentFile (const QString &fileName)
896{
897 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::loadDocumentFile fileName=" << fileName.toLatin1 ().data ();
898
899 QApplication::setOverrideCursor(Qt::WaitCursor);
900 CmdMediator *cmdMediator = new CmdMediator (*this,
901 fileName);
902
903 if (cmdMediator->successfulRead ()) {
904
905 setCurrentPathFromFile (fileName);
906 rebuildRecentFileListForCurrentFile(fileName);
907 m_currentFile = fileName; // This enables the FileSaveAs menu option
908
909 delete m_cmdMediator;
910
911 m_cmdMediator = cmdMediator;
912 setupAfterLoadNewDocument (fileName,
913 tr ("File opened"),
914 IMPORT_TYPE_SIMPLE);
915
916 // Start select mode
917 m_actionDigitizeSelect->setChecked (true); // We assume user wants to first select existing stuff
918 slotDigitizeSelect(); // Trigger transition so cursor gets updated immediately
919
920 m_engaugeFile = fileName;
921 m_originalFile = fileName; // This is needed by updateAfterCommand below if an error report is generated
922 m_originalFileWasImported = false;
923
924 updateGridLines ();
925 updateAfterCommand (); // Enable Save button now that m_engaugeFile is set
926
927 QApplication::restoreOverrideCursor();
928
929 } else {
930
931 QApplication::restoreOverrideCursor();
932
933 QMessageBox::warning (this,
935 QString("%1 %2 %3 %4:\n%5.")
936 .arg (tr ("Cannot read file"))
937 .arg (fileName)
938 .arg (tr ("from directory"))
939 .arg (QDir::currentPath ())
941 delete cmdMediator;
942
943 }
944}
945
946void MainWindow::loadErrorReportFile(const QString &errorReportFile)
947{
948 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::loadErrorReportFile"
949 << " file=" << errorReportFile.toLatin1().data();
950
952 if (!file.exists()) {
953 // Convert path from relative to absolute so file-not-found errors are easier to fix
955
956 QMessageBox::critical (this,
958 tr ("File not found") + ": " + fileInfo.absoluteFilePath());
959 exit (-1);
960 }
961
962 // Open the error report file as if it was a regular Document file
964 file.open(QIODevice::ReadOnly | QIODevice::Text);
965 m_cmdMediator = new CmdMediator(*this,
967
968 // Load the commands into the shadow command stack
969 m_cmdStackShadow->loadCommands (*this,
970 m_cmdMediator->document(),
971 reader);
972 file.close();
973
974 setupAfterLoadNewDocument (errorReportFile,
975 tr ("Error report opened"),
976 IMPORT_TYPE_SIMPLE);
977
978 // Start select mode
979 m_actionDigitizeSelect->setChecked (true); // We assume user wants to first select existing stuff
980 slotDigitizeSelect(); // Trigger transition so cursor gets updated immediately
981
983}
984
985bool MainWindow::loadImage (const QString &fileName,
986 const QImage &image,
987 ImportType importType)
988{
989 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::loadImage"
990 << " fileName=" << fileName.toLatin1 ().data ()
991 << " importType=" << importType;
992
993 bool success;
994 if (importType == IMPORT_TYPE_IMAGE_REPLACE) {
995 success = loadImageReplacingImage (fileName,
996 image,
997 importType);
998 } else {
999 success = loadImageNewDocument (fileName,
1000 image,
1001 importType);
1002 }
1003
1004 return success;
1005}
1006
1007bool MainWindow::loadImageNewDocument (const QString &fileName,
1008 const QImage &image,
1009 ImportType importType)
1010{
1011 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::loadImageNewDocument"
1012 << " fileName=" << fileName.toLatin1 ().data ()
1013 << " importType=" << importType;
1014
1015 ENGAUGE_ASSERT (importType != IMPORT_TYPE_IMAGE_REPLACE);
1016
1017 QApplication::setOverrideCursor(Qt::WaitCursor);
1018 CmdMediator *cmdMediator = new CmdMediator (*this,
1019 image);
1020 QApplication::restoreOverrideCursor();
1021
1022 setCurrentPathFromFile (fileName);
1023 // We do not call rebuildRecentFileListForCurrentFile for an image file, so only proper Engauge document files appear in the recent file list
1024 m_engaugeFile = EMPTY_FILENAME; // Forces first Save to be treated as Save As
1025
1026 delete m_cmdMediator;
1027
1028 m_cmdMediator = cmdMediator;
1029 bool accepted = setupAfterLoadNewDocument (fileName,
1030 tr ("File imported"),
1031 importType);
1032
1033 if (accepted) {
1034
1035 // Show the wizard if user selected it and we are not running a script
1036 if (m_actionHelpChecklistGuideWizard->isChecked () &&
1037 (m_fileCmdScript == nullptr)) {
1038
1039 // Show wizard
1041 m_cmdMediator->document().coordSystemCount());
1042 if (wizard->exec() == QDialog::Accepted) {
1043
1044 for (CoordSystemIndex coordSystemIndex = 0; coordSystemIndex < m_cmdMediator->document().coordSystemCount(); coordSystemIndex++) {
1045
1046 // Populate the checklist guide
1047 m_dockChecklistGuide->setTemplateHtml (wizard->templateHtml(coordSystemIndex),
1048 wizard->curveNames(coordSystemIndex));
1049
1050 // Update Document
1051 CurvesGraphs curvesGraphs;
1052 wizard->populateCurvesGraphs (coordSystemIndex,
1053 curvesGraphs);
1054 m_cmdMediator->document().setCurvesGraphs(curvesGraphs);
1055 }
1056
1057 // Unhide the checklist guide
1058 m_actionViewChecklistGuide->setChecked (true);
1059
1060 // Update the curve dropdown
1061 loadCurveListFromCmdMediator();
1062
1063 // Update the CoordSystem dropdown
1064 loadCoordSystemListFromCmdMediator();
1065 }
1066 delete wizard;
1067 }
1068
1069 // Start axis mode
1070 m_actionDigitizeAxis->setChecked (true); // We assume user first wants to digitize axis points
1071
1072 // Trigger transition so cursor gets updated immediately
1073 if (modeMap ()) {
1074 slotDigitizeScale ();
1075 } else if (modeGraph ()) {
1076 slotDigitizeAxis ();
1077 }
1078
1079 updateControls ();
1080 }
1081
1082 return accepted;
1083}
1084
1085bool MainWindow::loadImageReplacingImage (const QString &fileName,
1086 const QImage &image,
1087 ImportType importType)
1088{
1089 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::loadImageReplacingImage"
1090 << " fileName=" << fileName.toLatin1 ().data ()
1091 << " importType=" << importType;
1092
1093 ENGAUGE_ASSERT (importType == IMPORT_TYPE_IMAGE_REPLACE);
1094
1095 setCurrentPathFromFile (fileName);
1096 // We do not call rebuildRecentFileListForCurrentFile for an image file, so only proper Engauge document files appear in the recent file list
1097 m_engaugeFile = EMPTY_FILENAME; // Forces first Save to be treated as Save As
1098
1099 ENGAUGE_ASSERT (m_cmdMediator != nullptr); // Menu option should only be available when a document is currently open
1100
1101 m_cmdMediator->document().setPixmap (image);
1102
1103 bool accepted = setupAfterLoadReplacingImage (fileName,
1104 tr ("File imported"),
1105 importType);
1106
1107 // No checklist guide wizard is displayed when just replacing the image
1108
1109 return accepted;
1110}
1111
1112void MainWindow::loadInputFileForErrorReport(QDomDocument &domInputFile) const
1113{
1114 QFile file (m_originalFile);
1115
1116 // File should be available for opening, if not then the dom will be left empty. We assume it has not been
1117 // modified since opened
1118 if (!file.open (QIODevice::ReadOnly)) {
1119 return;
1120 }
1121
1122 domInputFile.setContent (&file);
1123 file.close();
1124}
1125
1126void MainWindow::loadToolTips()
1127{
1128 if (m_actionViewToolTips->isChecked ()) {
1129
1130 // Show tool tips
1131 m_actionDigitizeSelect->setToolTip (m_actionDigitizeSelect->text());
1132 m_actionDigitizeAxis->setToolTip (m_actionDigitizeAxis->text());
1133 m_actionDigitizeScale->setToolTip (m_actionDigitizeScale->text());
1134 m_actionDigitizeCurve->setToolTip (m_actionDigitizeCurve->text());
1135 m_actionDigitizePointMatch->setToolTip (m_actionDigitizePointMatch->text());
1136 m_actionDigitizeColorPicker->setToolTip (m_actionDigitizeColorPicker->text());
1137 m_actionDigitizeSegment->setToolTip (m_actionDigitizeSegment->text());
1138 m_cmbBackground->setToolTip (tr ("Background image."));
1139 m_cmbCurve->setToolTip (tr ("Currently selected curve."));
1140 m_viewPointStyle->setToolTip (tr ("Point style for currently selected curve."));
1141 m_viewSegmentFilter->setToolTip (tr ("Segment Fill filter for currently selected curve."));
1142
1143 } else {
1144
1145 // Remove any previous tool tips
1146 m_actionDigitizeSelect->setToolTip ("");
1147 m_actionDigitizeAxis->setToolTip ("");
1148 m_actionDigitizeScale->setToolTip ("");
1149 m_actionDigitizeCurve->setToolTip ("");
1150 m_actionDigitizePointMatch->setToolTip ("");
1151 m_actionDigitizeColorPicker->setToolTip ("");
1152 m_actionDigitizeSegment->setToolTip ("");
1153 m_cmbBackground->setToolTip ("");
1154 m_cmbCurve->setToolTip ("");
1155 m_viewPointStyle->setToolTip ("");
1156 m_viewSegmentFilter->setToolTip ("");
1157
1158 }
1159}
1160
1161bool MainWindow::modeGraph () const
1162{
1163 bool success = false;
1164
1165 if (m_cmdMediator != nullptr) {
1167 }
1168
1169 return success;
1170}
1171
1173{
1174 bool success = false;
1175
1176 if (m_cmdMediator != nullptr) {
1178 }
1179
1180 return success;
1181}
1182
1183bool MainWindow::maybeSave()
1184{
1185 if (m_cmdMediator != nullptr) {
1186 if (m_cmdMediator->isModified()) {
1187 QMessageBox::StandardButton ret = QMessageBox::warning (this,
1189 tr("The document has been modified.\n"
1190 "Do you want to save your changes?"),
1191 QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
1192 if (ret == QMessageBox::Save) {
1193 return slotFileSave();
1194 } else if (ret == QMessageBox::Cancel) {
1195 return false;
1196 }
1197 }
1198 }
1199
1200 return true;
1201}
1202
1205 const QString &fileName) const
1206{
1208
1209 // See if delimiter setting overrides commas/tabs for files with csv/tsv file extensions respectively
1210 if (!modelExportFormatAfter.overrideCsvTsv()) {
1211
1212 // Extract file extensions
1213 QString csvExtension = QString (".%1")
1214 .arg (exportStrategy.fileExtensionCsv());
1215 QString tsvExtension = QString (".%1")
1216 .arg (exportStrategy.fileExtensionTsv());
1219
1220 // Override if CSV or TSV was selected. We cannot use QFileDialog::selectedNameFilter() since that is
1221 // broken in Linux, so we use the file extension
1222 if (csvExtension.compare (fileExtensionVersusCsv, Qt::CaseInsensitive) == 0) {
1224 } else if (tsvExtension.compare (fileExtensionVersusTsv, Qt::CaseInsensitive) == 0) {
1226 }
1227 }
1228
1230}
1231
1233{
1234 return m_modelMainWindow;
1235}
1236
1237void MainWindow::rebuildRecentFileListForCurrentFile(const QString &filePath)
1238{
1239 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::rebuildRecentFileListForCurrentFile";
1240
1242
1245 recentFilePaths.removeAll (filePath); // Remove previous instance of the current filePath
1246 recentFilePaths.prepend (filePath); // Insert current filePath at start
1247 while (recentFilePaths.count () > qFloor (MAX_RECENT_FILE_LIST_SIZE)) {
1248 recentFilePaths.removeLast (); // Remove entry since the number of entries exceeds the limit
1249 }
1251
1252 updateRecentFileList();
1253}
1254
1256{
1257 LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::resizeEvent";
1258
1259 if (m_actionZoomFill->isChecked ()) {
1260 slotViewZoomFactor (ZOOM_FILL);
1261 }
1262
1263 QMainWindow::resizeEvent(event);
1264}
1265
1266bool MainWindow::saveDocumentFile (const QString &fileName)
1267{
1268 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::saveDocumentFile fileName=" << fileName.toLatin1 ().data ();
1269
1271 if (!file.open(QFile::WriteOnly)) {
1272 QMessageBox::warning (this,
1274 QString ("%1 %2: \n%3.")
1275 .arg(tr ("Cannot write file"))
1276 .arg(fileName)
1277 .arg(file.errorString()));
1278 return false;
1279 }
1280
1281 rebuildRecentFileListForCurrentFile (fileName);
1282
1283 QApplication::setOverrideCursor (Qt::WaitCursor);
1285 writer.setAutoFormatting(true);
1286 writer.writeStartDocument();
1287 writer.writeDTD("<!DOCTYPE engauge>");
1288 m_cmdMediator->document().saveXml(writer);
1289 writer.writeEndDocument();
1290 QApplication::restoreOverrideCursor ();
1291
1292 // Notify the undo stack that the current state is now considered "clean". This will automatically trigger a
1293 // signal back to this class that will update the modified marker in the title bar
1294 m_cmdMediator->setClean ();
1295
1296 setCurrentFile(fileName);
1297 m_engaugeFile = fileName;
1298 updateAfterCommand (); // Enable Save button now that m_engaugeFile is set
1299 m_statusBar->showTemporaryMessage("File saved");
1300
1301 return true;
1302}
1303
1305 const char *file,
1306 int line,
1307 const char *comment)
1308{
1309 // Skip if currently performing a regression test - in which case the preferred behavior is to let the current test fail and
1310 // continue on to execute the remaining tests
1311 if ((m_cmdMediator != nullptr) && !m_isErrorReportRegressionTest) {
1312
1313 QString report = saveErrorReportFileAndExitXml (context,
1314 file,
1315 line,
1316 comment);
1317
1319 if (dlg.exec() == QDialog::Accepted) {
1321
1322 QString fileName = dlg.getSaveFileName (this,
1323 tr("Save"),
1324 "error_report.xml");
1325 if (!fileName.isEmpty ()) {
1326 // Save the error report
1329 fileError.open (QIODevice::WriteOnly | QIODevice::Text);
1330 str << report;
1331 fileError.close ();
1332 }
1333 }
1334
1335 exit (-1);
1336 }
1337}
1338
1339QString MainWindow::saveErrorReportFileAndExitXml (const char *context,
1340 const char *file,
1341 int line,
1342 const char *comment) const
1343{
1344 const bool DEEP_COPY = true;
1345
1348 writer.setAutoFormatting(true);
1349
1350 // Entire error report contains metadata, commands and other details
1351 writer.writeStartElement(DOCUMENT_SERIALIZE_ERROR_REPORT);
1352
1353 // Version
1354 writer.writeStartElement(DOCUMENT_SERIALIZE_APPLICATION);
1356 writer.writeEndElement();
1357
1358 // Document
1359 // Insert snapshot xml into writer stream, by reading from reader stream. Highest level of snapshot is DOCUMENT_SERIALIZE_APPLICATION
1360 QXmlStreamReader reader (m_startingDocumentSnapshot);
1361 while (!reader.atEnd ()) {
1362 reader.readNext ();
1363 if (reader.tokenType() != QXmlStreamReader::StartDocument &&
1364 reader.tokenType() != QXmlStreamReader::EndDocument &&
1365 reader.tokenType() != QXmlStreamReader::Invalid) {
1366 writer.writeCurrentToken (reader);
1367 }
1368 }
1369
1370 // Operating system
1372 writer.writeAttribute(DOCUMENT_SERIALIZE_OPERATING_SYSTEM_ENDIAN, EndianToString (QSysInfo::ByteOrder));
1373 writer.writeAttribute(DOCUMENT_SERIALIZE_OPERATING_SYSTEM_WORD_SIZE, QString::number (QSysInfo::WordSize));
1374 writer.writeEndElement();
1375
1376 // Placeholder for original file, before the commands in the command stack were applied
1377 writer.writeStartElement(DOCUMENT_SERIALIZE_FILE);
1379 m_originalFileWasImported ? DOCUMENT_SERIALIZE_BOOL_TRUE : DOCUMENT_SERIALIZE_BOOL_FALSE);
1380 writer.writeEndElement();
1381
1382 // Commands
1383 m_cmdMediator->saveXml(writer);
1384
1385 // Error
1386 writer.writeStartElement(DOCUMENT_SERIALIZE_ERROR);
1387 writer.writeAttribute(DOCUMENT_SERIALIZE_ERROR_CONTEXT, context);
1388 writer.writeAttribute(DOCUMENT_SERIALIZE_ERROR_FILE, file);
1389 writer.writeAttribute(DOCUMENT_SERIALIZE_ERROR_LINE, QString::number (line));
1391 writer.writeEndElement();
1392
1393 writer.writeEndElement();
1394
1395 // Put string into DOM
1396 QDomDocument domErrorReport ("ErrorReport");
1397 domErrorReport.setContent (xmlErrorReport);
1398
1399 // Postprocessing
1400 if (!m_originalFileWasImported) {
1401
1402 // Insert the original file into its placeholder, by manipulating the source and target xml as DOM documents. Very early
1403 // in the loading process, the original file may not be specified yet (m_originalFile is empty)
1405 loadInputFileForErrorReport (domInputFile);
1406 QDomDocumentFragment fragmentFileFrom = domErrorReport.createDocumentFragment();
1407 if (!domInputFile.isNull()) {
1408 fragmentFileFrom.appendChild (domErrorReport.importNode (domInputFile.documentElement(), DEEP_COPY));
1409 }
1411 if (nodesFileTo.count () > 0) {
1413 nodeFileTo.appendChild (fragmentFileFrom);
1414 }
1415
1416 // Replace DOCUMENT_SERIALIZE_IMAGE by same node with CDATA removed, since:
1417 // 1) it is very big and working with smaller files, especially in emails, is easier
1418 // 2) removing the image better preserves user's privacy
1419 // 3) having the actual image does not help that much when debugging
1421 for (int i = 0 ; i < nodesDocument.count(); i++) {
1424 if (!elemImage.isNull()) {
1425
1426 // Get old image attributes so we can create an empty document with the same size
1427 if (elemImage.hasAttribute (DOCUMENT_SERIALIZE_IMAGE_WIDTH) &&
1429
1430 int width = elemImage.attribute(DOCUMENT_SERIALIZE_IMAGE_WIDTH).toInt();
1431 int height = elemImage.attribute(DOCUMENT_SERIALIZE_IMAGE_HEIGHT).toInt();
1432
1435 elemReplacement.setAttribute (DOCUMENT_SERIALIZE_IMAGE_WIDTH, width);
1437
1438 // Replace with the new and then remove the old
1439 nodeDocument.insertBefore (nodeReplacement,
1440 elemImage);
1441 nodeDocument.removeChild(elemImage);
1442 }
1443 }
1444 }
1445 }
1446
1447 return domErrorReport.toString();
1448}
1449
1450void MainWindow::saveStartingDocumentSnapshot()
1451{
1452 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::saveStartingDocumentSnapshot";
1453
1454 QXmlStreamWriter writer (&m_startingDocumentSnapshot);
1455 writer.setAutoFormatting (true);
1456 m_cmdMediator->document().saveXml (writer);
1457}
1458
1460{
1461 ENGAUGE_CHECK_PTR (m_scene);
1462 return *m_scene;
1463}
1464
1466{
1467 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::selectBackgroundOriginal";
1468
1469 BackgroundImage previousBackground = static_cast<BackgroundImage> (m_cmbBackground->currentData().toInt());
1470
1471 int index = m_cmbBackground->findData (backgroundImage);
1472 ENGAUGE_ASSERT (index >= 0);
1473
1474 m_cmbBackground->setCurrentIndex(index);
1475
1476 return previousBackground;
1477}
1478
1480{
1481 return m_cmbCurve->currentText ();
1482}
1483
1484void MainWindow::setCurrentFile (const QString &fileName)
1485{
1486 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::setCurrentFile";
1487
1489 if (!fileName.isEmpty()) {
1490
1491 // Strip out path and file extension. We use completeBaseName rather than baseName so
1492 // files with multiple periods are handled correctly - all but last suffix gets kept
1494 fileNameStripped = fileInfo.completeBaseName();
1495 }
1496
1497 m_currentFile = fileNameStripped;
1498 m_currentFileWithPathAndFileExtension = fileName;
1499
1500 updateWindowTitle ();
1501}
1502
1503void MainWindow::setCurrentPathFromFile (const QString &fileName)
1504{
1505 QDir dir = QFileInfo (fileName).absoluteDir();
1506
1507 if (dir.exists ()) {
1508
1509 bool success = QDir::setCurrent (dir.absolutePath ()); // Return to chosen directory the next time
1510 ENGAUGE_ASSERT (success);
1511
1512 } else {
1513
1514 // File was a url so it is irrelevant to the current directory
1515 }
1516}
1517
1518void MainWindow::setNonFillZoomFactor (ZoomFactor newZoomFactor)
1519{
1521
1522 // Update controls and apply zoom factor
1523 m_zoomMapToAction [newZoomFactor]->setChecked (true);
1524 slotViewZoomFactor (newZoomFactor);
1525}
1526
1527void MainWindow::setPixmap (const QString &curveSelected,
1528 const QPixmap &pixmap)
1529{
1530 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::setPixmap";
1531
1532 m_digitizeStateContext->setImageIsLoaded (m_cmdMediator,
1533 true);
1534
1535 // We cannot reliably use m_cmbCurve->currentText below for the selected curve since that control
1536 // can be pointing to a curve that no longer exists so this method requires curveSelected as an argument
1537 m_backgroundStateContext->setPixmap (m_isGnuplot,
1538 m_transformation,
1539 m_cmdMediator->document().modelGridRemoval(),
1540 m_cmdMediator->document().modelColorFilter(),
1541 pixmap,
1543}
1544
1545void MainWindow::settingsRead (bool isReset)
1546{
1548
1549 if (isReset) {
1550 // Delete all settings. Default values are specified, later, for each settings as it is loaded
1551 settings.clear ();
1552 }
1553
1554 settingsReadEnvironment (settings);
1555 settingsReadMainWindow (settings);
1556}
1557
1558void MainWindow::settingsReadEnvironment (QSettings &settings)
1559{
1561 QDir::setCurrent (settings.value (SETTINGS_CURRENT_DIRECTORY,
1562 QDir::currentPath ()).toString ());
1563 settings.endGroup ();
1564}
1565
1566void MainWindow::settingsReadMainWindow (QSettings &settings)
1567{
1569
1570 // Main window geometry
1572 QSize (600, 600)).toSize ());
1573 move (settings.value (SETTINGS_POS,
1574 QPoint (200, 200)).toPoint ());
1575
1576 // Help window geometry
1577#if !defined(OSX_DEBUG) && !defined(OSX_RELEASE)
1579 QSize (900, 600)).toSize();
1580 m_helpWindow->resize (helpSize);
1581 if (settings.contains (SETTINGS_HELP_POS)) {
1582 QPoint helpPos = settings.value (SETTINGS_HELP_POS).toPoint();
1583 m_helpWindow->move (helpPos);
1584 }
1585#endif
1586
1587 // Checklist guide wizard
1588 m_actionHelpChecklistGuideWizard->setChecked (settings.value (SETTINGS_CHECKLIST_GUIDE_WIZARD,
1589 true).toBool ());
1590
1591 // Background toolbar visibility
1593 true).toBool ();
1594 m_actionViewBackground->setChecked (viewBackgroundToolBar);
1595 m_toolBackground->setVisible (viewBackgroundToolBar);
1597 BACKGROUND_IMAGE_FILTERED).toInt ());
1598 int indexBackground = m_cmbBackground->findData (QVariant (backgroundImage));
1599 m_cmbBackground->setCurrentIndex (indexBackground);
1600
1601 // Digitize toolbar visibility
1603 true).toBool ();
1604 m_actionViewDigitize->setChecked (viewDigitizeToolBar);
1605 m_toolDigitize->setVisible (viewDigitizeToolBar);
1606
1607 // Views toolbar visibility
1609 true).toBool ();
1610 m_actionViewSettingsViews->setChecked (viewSettingsViewsToolBar);
1611 m_toolSettingsViews->setVisible (viewSettingsViewsToolBar);
1612
1613 // Coordinate system toolbar visibility
1615 false).toBool ();
1616 m_actionViewCoordSystem->setChecked (viewCoordSystemToolbar);
1617 m_toolCoordSystem->setVisible (viewCoordSystemToolbar);
1618
1619 // Tooltips visibility
1621 true).toBool ();
1622 m_actionViewToolTips->setChecked (viewToolTips);
1623 loadToolTips ();
1624
1625 // Statusbar visibility
1626 StatusBarMode statusBarMode = static_cast<StatusBarMode> (settings.value (SETTINGS_VIEW_STATUS_BAR,
1627 false).toInt ());
1628 m_statusBar->setStatusBarMode (statusBarMode);
1629 m_actionStatusNever->setChecked (statusBarMode == STATUS_BAR_MODE_NEVER);
1630 m_actionStatusTemporary->setChecked (statusBarMode == STATUS_BAR_MODE_TEMPORARY);
1631 m_actionStatusAlways->setChecked (statusBarMode == STATUS_BAR_MODE_ALWAYS);
1632
1633 addDockWindow (m_dockChecklistGuide,
1634 settings,
1637 Qt::RightDockWidgetArea);
1638 addDockWindow (m_dockFittingWindow,
1639 settings,
1642 Qt::RightDockWidgetArea);
1643 addDockWindow (m_dockGeometryWindow,
1644 settings,
1647 Qt::RightDockWidgetArea);
1648
1649 // Main window settings. Preference for initial zoom factor is 100%, rather than fill mode, for issue #25. Some or all
1650 // settings are saved to the application AND saved to m_modelMainWindow for use in DlgSettingsMainWindow. Note that
1651 // TranslatorContainer has previously extracted the locale from the settings
1653 QLocale::Language language = static_cast<QLocale::Language> (settings.value (SETTINGS_LOCALE_LANGUAGE,
1654 QVariant (localeDefault.language())).toInt());
1655 QLocale::Country country = static_cast<QLocale::Country> (settings.value (SETTINGS_LOCALE_COUNTRY,
1656 QVariant (localeDefault.country())).toInt());
1657 QLocale locale (language,
1658 country);
1659 slotViewZoom (static_cast<ZoomFactor> (settings.value (SETTINGS_ZOOM_FACTOR,
1660 QVariant (ZOOM_1_TO_1)).toInt()));
1661 m_modelMainWindow.setLocale (locale);
1662 m_modelMainWindow.setZoomFactorInitial(static_cast<ZoomFactorInitial> (settings.value (SETTINGS_ZOOM_FACTOR_INITIAL,
1664 m_modelMainWindow.setZoomControl (static_cast<ZoomControl> (settings.value (SETTINGS_ZOOM_CONTROL,
1670 m_modelMainWindow.setImportCropping (static_cast<ImportCropping> (settings.value (SETTINGS_IMPORT_CROPPING,
1676 m_modelMainWindow.setSmallDialogs (settings.value (SETTINGS_SMALL_DIALOGS,
1678 m_modelMainWindow.setDragDropExport (settings.value (SETTINGS_DRAG_DROP_EXPORT,
1684
1685 // MainDirectoryPersist starts with directories from last execution
1688 QVariant (QDir::currentPath())).toString ());
1689 directoryPersist.setDirectoryImportLoadFromSavedPath (settings.value (SETTINGS_MAIN_DIRECTORY_IMPORT_LOAD,
1690 QVariant (QDir::currentPath())).toString ());
1691
1693 updateSmallDialogs();
1694
1695 settings.endGroup();
1696}
1697
1698void MainWindow::settingsWrite ()
1699{
1701
1703
1705 settings.setValue (SETTINGS_CURRENT_DIRECTORY, QDir::currentPath ());
1706 settings.endGroup ();
1707
1709 settings.setValue (SETTINGS_SIZE, size ());
1710 settings.setValue (SETTINGS_POS, pos ());
1711#if !defined(OSX_DEBUG) && !defined(OSX_RELEASE)
1712 settings.setValue (SETTINGS_HELP_SIZE, m_helpWindow->size());
1713 settings.setValue (SETTINGS_HELP_POS, m_helpWindow->pos ());
1714#endif
1715 if (m_dockChecklistGuide->isFloating()) {
1716
1717 settings.setValue (SETTINGS_CHECKLIST_GUIDE_DOCK_AREA, Qt::NoDockWidgetArea);
1718 settings.setValue (SETTINGS_CHECKLIST_GUIDE_DOCK_GEOMETRY, m_dockChecklistGuide->saveGeometry ());
1719
1720 } else {
1721
1722 settings.setValue (SETTINGS_CHECKLIST_GUIDE_DOCK_AREA, dockWidgetArea (m_dockChecklistGuide));
1723
1724 }
1725 if (m_dockFittingWindow->isFloating()) {
1726
1727 settings.setValue (SETTINGS_FITTING_WINDOW_DOCK_AREA, Qt::NoDockWidgetArea);
1728 settings.setValue (SETTINGS_FITTING_WINDOW_DOCK_GEOMETRY, m_dockFittingWindow->saveGeometry());
1729 } else {
1730
1731 settings.setValue (SETTINGS_FITTING_WINDOW_DOCK_AREA, dockWidgetArea (m_dockFittingWindow));
1732 }
1733 if (m_dockGeometryWindow->isFloating()) {
1734
1735 settings.setValue (SETTINGS_GEOMETRY_WINDOW_DOCK_AREA, Qt::NoDockWidgetArea);
1736 settings.setValue (SETTINGS_GEOMETRY_WINDOW_DOCK_GEOMETRY, m_dockGeometryWindow->saveGeometry ());
1737
1738 } else {
1739
1740 settings.setValue (SETTINGS_GEOMETRY_WINDOW_DOCK_AREA, dockWidgetArea (m_dockGeometryWindow));
1741
1742 }
1743 settings.setValue (SETTINGS_BACKGROUND_IMAGE, m_cmbBackground->currentData().toInt());
1744 settings.setValue (SETTINGS_CHECKLIST_GUIDE_WIZARD, m_actionHelpChecklistGuideWizard->isChecked ());
1745 settings.setValue (SETTINGS_DRAG_DROP_EXPORT, m_modelMainWindow.dragDropExport ());
1746 settings.setValue (SETTINGS_HIGHLIGHT_OPACITY, m_modelMainWindow.highlightOpacity());
1748 settings.setValue (SETTINGS_IMPORT_CROPPING, m_modelMainWindow.importCropping());
1749 settings.setValue (SETTINGS_IMPORT_PDF_RESOLUTION, m_modelMainWindow.pdfResolution ());
1750 settings.setValue (SETTINGS_LOCALE_LANGUAGE, m_modelMainWindow.locale().language());
1751 settings.setValue (SETTINGS_LOCALE_COUNTRY, m_modelMainWindow.locale().country());
1753 directoryPersist.getDirectoryExportSave().absolutePath());
1755 directoryPersist.getDirectoryImportOpen().absolutePath());
1756 settings.setValue (SETTINGS_MAIN_TITLE_BAR_FORMAT, m_modelMainWindow.mainTitleBarFormat());
1757 settings.setValue (SETTINGS_MAXIMUM_GRID_LINES, m_modelMainWindow.maximumGridLines());
1758 settings.setValue (SETTINGS_SMALL_DIALOGS, m_modelMainWindow.smallDialogs());
1759 settings.setValue (SETTINGS_VIEW_BACKGROUND_TOOLBAR, m_actionViewBackground->isChecked());
1760 settings.setValue (SETTINGS_VIEW_DIGITIZE_TOOLBAR, m_actionViewDigitize->isChecked ());
1761 settings.setValue (SETTINGS_VIEW_STATUS_BAR, m_statusBar->statusBarMode ());
1762 settings.setValue (SETTINGS_VIEW_SETTINGS_VIEWS_TOOLBAR, m_actionViewSettingsViews->isChecked ());
1763 settings.setValue (SETTINGS_VIEW_COORD_SYSTEM_TOOLBAR, m_actionViewCoordSystem->isChecked ());
1764 settings.setValue (SETTINGS_VIEW_TOOL_TIPS, m_actionViewToolTips->isChecked ());
1765 settings.setValue (SETTINGS_ZOOM_CONTROL, m_modelMainWindow.zoomControl());
1766 settings.setValue (SETTINGS_ZOOM_FACTOR, currentZoomFactor ());
1767 settings.setValue (SETTINGS_ZOOM_FACTOR_INITIAL, m_modelMainWindow.zoomFactorInitial());
1768 settings.endGroup ();
1769}
1770
1771bool MainWindow::setupAfterLoadNewDocument (const QString &fileName,
1772 const QString &temporaryMessage ,
1773 ImportType importType)
1774{
1775 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::setupAfterLoadNewDocument"
1776 << " file=" << fileName.toLatin1().data()
1777 << " message=" << temporaryMessage.toLatin1().data()
1778 << " importType=" << importType;
1779
1780 // The steps in this method should theoretically be a superset of the steps in setupAfterLoadNewDocument. Therefore, any
1781 // changes to this method should be considered for application to the other method also
1782
1783 const QString EMPTY_CURVE_NAME_TO_SKIP_BACKGROUND_PROCESSING; // For bootstrapping the preview
1784
1785 // At this point the code assumes CmdMediator for the NEW Document is already stored in m_cmdMediator
1786
1787 m_digitizeStateContext->resetOnLoad (m_cmdMediator); // Before setPixmap
1788 m_backgroundStateContext->setCurveSelected (m_isGnuplot,
1789 m_transformation,
1790 m_cmdMediator->document().modelGridRemoval(),
1791 m_cmdMediator->document().modelColorFilter(),
1793 setPixmap (m_cmdMediator->document().curvesGraphsNames().first(),
1794 m_cmdMediator->pixmap ()); // Set background immediately so it is visible as a preview when any dialogs are displayed
1795
1796 // Image is visible now so the user can refer to it when we ask for the number of coordinate systems. Note that the Document
1797 // may already have multiple CoordSystem if user loaded a file that had multiple CoordSystem entries
1798 if (importType == IMPORT_TYPE_ADVANCED) {
1799
1800 applyZoomFactorAfterLoad(); // Apply the currently selected zoom factor
1801
1803 dlgImportAdvanced.exec();
1804
1805 if (dlgImportAdvanced.result() == QDialog::Rejected) {
1806 return false;
1807 }
1808
1809 int numberCoordSystem = signed (dlgImportAdvanced.numberCoordSystem());
1810 m_cmdMediator->document().addCoordSystems (unsigned (numberCoordSystem - 1));
1811 m_cmdMediator->setDocumentAxesPointsRequired (dlgImportAdvanced.documentAxesPointsRequired());
1812 }
1813
1814 m_transformation.resetOnLoad();
1815 m_transformationStateContext->resetOnLoad();
1816 m_scene->resetOnLoad();
1817
1818 connect (m_actionEditUndo, SIGNAL (triggered ()), m_cmdMediator, SLOT (undo ()));
1819 connect (m_actionEditUndo, SIGNAL (triggered ()), m_cmdStackShadow, SLOT (slotUndo ()));
1820 connect (m_actionEditRedo, SIGNAL (triggered ()), m_cmdMediator, SLOT (redo ())); // No effect until CmdMediator::undo and CmdStackShadow::slotUndo get called
1821 connect (m_actionEditRedo, SIGNAL (triggered ()), m_cmdStackShadow, SLOT (slotRedo ())); // No effect after CmdMediator::undo and CmdStackShadow::slotUndo get called
1822 connect (m_cmdMediator, SIGNAL (canRedoChanged(bool)), this, SLOT (slotCanRedoChanged (bool)));
1823 connect (m_cmdMediator, SIGNAL (canUndoChanged(bool)), this, SLOT (slotCanUndoChanged (bool)));
1824 connect (m_cmdMediator, SIGNAL (redoTextChanged (const QString &)), this, SLOT (slotRedoTextChanged (const QString &)));
1825 connect (m_cmdMediator, SIGNAL (undoTextChanged (const QString &)), this, SLOT (slotUndoTextChanged (const QString &)));
1826 loadCurveListFromCmdMediator ();
1827 loadCoordSystemListFromCmdMediator ();
1829
1830 m_isDocumentExported = false;
1831
1832 // Background must be set (by setPixmap) before slotViewZoomFactor which relies on the background. At this point
1833 // the transformation is undefined (unless the code is changed) so grid removal will not work
1834 // but updateTransformationAndItsDependencies will call this again to fix that issue. Note that the selected
1835 // curve name was set (by setCurveSelected) earlier before the call to setPixmap
1836 m_backgroundStateContext->setCurveSelected (m_isGnuplot,
1837 m_transformation,
1838 m_cmdMediator->document().modelGridRemoval(),
1839 m_cmdMediator->document().modelColorFilter(),
1840 m_cmbCurve->currentText ());
1841 m_backgroundStateContext->setBackgroundImage (static_cast<BackgroundImage> (m_cmbBackground->currentIndex ()));
1842
1843 applyZoomFactorAfterLoad(); // Zoom factor must be reapplied after background image is set, to have any effect
1844
1845 setCurrentFile(fileName);
1847 m_statusBar->wakeUp ();
1848
1849 saveStartingDocumentSnapshot();
1850
1851 updateAfterCommand(); // Replace stale points by points in new Document
1852
1853 return true;
1854}
1855
1856bool MainWindow::setupAfterLoadReplacingImage (const QString &fileName,
1857 const QString &temporaryMessage ,
1858 ImportType importType)
1859{
1860 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::setupAfterLoadReplacingImage"
1861 << " file=" << fileName.toLatin1().data()
1862 << " message=" << temporaryMessage.toLatin1().data()
1863 << " importType=" << importType;
1864
1865 // The steps in this method should theoretically be just a subset of the steps in setupAfterLoadNewDocument
1866
1867 // After this point there should be no commands in CmdMediator, since we effectively have a new document
1868 m_cmdMediator->clear();
1869
1870 setPixmap (m_cmdMediator->document().curvesGraphsNames().first(),
1871 m_cmdMediator->pixmap ()); // Set background immediately so it is visible as a preview when any dialogs are displayed
1872
1873 m_isDocumentExported = false;
1874
1875 m_backgroundStateContext->setBackgroundImage (static_cast<BackgroundImage> (m_cmbBackground->currentIndex ()));
1876
1877 applyZoomFactorAfterLoad(); // Zoom factor must be reapplied after background image is set, to have any effect
1878
1879 // Some people prefer
1880 if (m_modelMainWindow.imageReplaceRenamesDocument()) {
1881 setCurrentFile(fileName);
1882 }
1883
1885 m_statusBar->wakeUp ();
1886
1887 saveStartingDocumentSnapshot();
1888
1889 updateAfterCommand(); // Replace stale points by points in new Document
1890
1891 return true;
1892}
1893
1895{
1896 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::showEvent"
1897 << " files=" << m_loadStartupFiles.join (",").toLatin1().data();
1898
1899 QMainWindow::showEvent (event);
1900
1901 if (m_loadStartupFiles.count() > 0) {
1902
1903 m_timerLoadStartupFiles = new QTimer;
1904 m_timerLoadStartupFiles->setSingleShot (true);
1905 connect (m_timerLoadStartupFiles, SIGNAL (timeout ()), this, SLOT (slotLoadStartupFiles ()));
1906 m_timerLoadStartupFiles->start (0); // Zero delay still waits until execution finishes and gui is available
1907
1908 }
1909}
1910
1915
1916void MainWindow::slotBtnPrintAll ()
1917{
1918 LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotBtnPrintAll";
1919
1920 ghostsCreate ();
1921
1922 QPrinter printer (QPrinter::HighResolution);
1923 QPrintDialog dlg (&printer, this);
1924 if (dlg.exec() == QDialog::Accepted) {
1926 m_view->render (&painter);
1927 painter.end();
1928 }
1929
1930 ghostsDestroy ();
1931}
1932
1933void MainWindow::slotBtnShowAllPressed ()
1934{
1935 LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotBtnShowAllPressed";
1936
1937 // Start of press-release sequence
1938 ghostsCreate ();
1939}
1940
1941void MainWindow::slotBtnShowAllReleased ()
1942{
1943 LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotBtnShowAllReleased";
1944
1945 // End of press-release sequence
1946 ghostsDestroy ();
1947}
1948
1949void MainWindow::slotCanRedoChanged (bool canRedo)
1950{
1951 LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotCanRedoChanged";
1952
1953 m_actionEditRedo->setEnabled (canRedo || m_cmdStackShadow->canRedo());
1954}
1955
1956void MainWindow::slotCanUndoChanged (bool canUndo)
1957{
1958 LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotCanUndoChanged";
1959
1960 m_actionEditUndo->setEnabled (canUndo);
1961}
1962
1963void MainWindow::slotChecklistClosed()
1964{
1965 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotChecklistClosed";
1966
1967 m_actionViewChecklistGuide->setChecked (false);
1968}
1969
1970void MainWindow::slotCleanChanged(bool clean)
1971{
1972 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotCleanChanged";
1973
1975}
1976
1977void MainWindow::slotCmbBackground(int currentIndex)
1978{
1979 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotCmbBackground";
1980
1981 switch (currentIndex) {
1983 if (!m_actionViewBackgroundNone->isChecked()) {
1984 m_actionViewBackgroundNone->toggle();
1985 }
1986 break;
1987
1989 if (!m_actionViewBackgroundOriginal->isChecked ()) {
1990 m_actionViewBackgroundOriginal->toggle();
1991 }
1992 break;
1993
1995 if (!m_actionViewBackgroundFiltered->isChecked ()) {
1996 m_actionViewBackgroundFiltered->toggle();
1997 }
1998 break;
1999 }
2000
2001 m_backgroundStateContext->setBackgroundImage (static_cast<BackgroundImage> (currentIndex));
2002}
2003
2004void MainWindow::slotCmbCoordSystem(int index)
2005{
2006 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotCmbCoordSystem";
2007
2009 m_cmdMediator->document(),
2010 static_cast<CoordSystemIndex> (index));
2011
2012 m_cmdMediator->push (cmd);
2013}
2014
2015void MainWindow::slotCmbCurve(int /* index */)
2016{
2017 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotCmbCurve";
2018
2019 m_backgroundStateContext->setCurveSelected (m_isGnuplot,
2020 m_transformation,
2021 m_cmdMediator->document().modelGridRemoval(),
2022 m_cmdMediator->document().modelColorFilter(),
2023 m_cmbCurve->currentText ());
2024 m_digitizeStateContext->handleCurveChange (m_cmdMediator);
2025 m_cmdMediator->setSelectedCurveName (m_cmbCurve->currentText ()); // Save for next time current coordinate system returns
2026
2027 updateViewedCurves();
2029 updateFittingWindow();
2030 updateGeometryWindow();
2031}
2032
2033void MainWindow::slotContextMenuEventAxis (QString pointIdentifier)
2034{
2035 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotContextMenuEventAxis point=" << pointIdentifier.toLatin1 ().data ();
2036
2037 m_digitizeStateContext->handleContextMenuEventAxis (m_cmdMediator,
2039}
2040
2041void MainWindow::slotContextMenuEventGraph (QStringList pointIdentifiers)
2042{
2043 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotContextMenuEventGraph point=" << pointIdentifiers.join(",").toLatin1 ().data ();
2044
2045 m_digitizeStateContext->handleContextMenuEventGraph (m_cmdMediator,
2047}
2048
2049void MainWindow::slotDigitizeAxis ()
2050{
2051 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeAxis";
2052
2053 m_digitizeStateContext->requestImmediateStateTransition (m_cmdMediator,
2055 m_cmbCurve->setEnabled (false); // Graph curve is irrelevant in this mode
2056 m_viewPointStyle->setEnabled (true); // Point style is important in this mode
2057 m_viewSegmentFilter->setEnabled (true); // Filtering is important in this mode
2058 updateControls (); // For Paste which is state dependent
2059}
2060
2061void MainWindow::slotDigitizeColorPicker ()
2062{
2063 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeColorPicker";
2064
2065 m_digitizeStateContext->requestImmediateStateTransition (m_cmdMediator,
2067 m_cmbCurve->setEnabled (true);
2068 m_viewPointStyle->setEnabled (true);
2069 m_viewSegmentFilter->setEnabled (true);
2070 updateControls (); // For Paste which is state dependent
2071}
2072
2073void MainWindow::slotDigitizeCurve ()
2074{
2075 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeCurve";
2076
2077 m_digitizeStateContext->requestImmediateStateTransition (m_cmdMediator,
2079 m_cmbCurve->setEnabled (true);
2080 m_viewPointStyle->setEnabled (true);
2081 m_viewSegmentFilter->setEnabled (true);
2082 updateControls (); // For Paste which is state dependent
2083}
2084
2085void MainWindow::slotDigitizePointMatch ()
2086{
2087 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizePointMatch";
2088
2089 m_digitizeStateContext->requestImmediateStateTransition (m_cmdMediator,
2091 m_cmbCurve->setEnabled (true);
2092 m_viewPointStyle->setEnabled (true);
2093 m_viewSegmentFilter->setEnabled (true);
2094 updateControls (); // For Paste which is state dependent
2095}
2096
2097void MainWindow::slotDigitizeScale ()
2098{
2099 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeScale";
2100
2101 m_digitizeStateContext->requestImmediateStateTransition (m_cmdMediator,
2103 m_cmbCurve->setEnabled (false);
2104 m_viewPointStyle->setEnabled (false);
2105 m_viewSegmentFilter->setEnabled (false);
2106 updateControls (); // For Paste which is state dependent
2107}
2108
2109void MainWindow::slotDigitizeSegment ()
2110{
2111 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeSegment";
2112
2113 m_digitizeStateContext->requestImmediateStateTransition (m_cmdMediator,
2115 m_cmbCurve->setEnabled (true);
2116 m_viewPointStyle->setEnabled (true);
2117 m_viewSegmentFilter->setEnabled (true);
2118 updateControls (); // For Paste which is state dependent
2119}
2120
2121void MainWindow::slotDigitizeSelect ()
2122{
2123 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotDigitizeSelect";
2124
2125 m_digitizeStateContext->requestImmediateStateTransition (m_cmdMediator,
2127 m_cmbCurve->setEnabled (false);
2128 m_viewPointStyle->setEnabled (false);
2129 m_viewSegmentFilter->setEnabled (false);
2130 updateControls (); // For Paste which is state dependent
2131}
2132
2133void MainWindow::slotEditCopy ()
2134{
2135 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditCopy";
2136
2137 // Copy command is sent to FittingWindow or GeometryWindow, or processed locally
2140 m_dockFittingWindow->getTableStatus (tableFittingIsActive, tableFittingIsCopyable); // Fitting window status
2141 m_dockGeometryWindow->getTableStatus (tableGeometryIsActive, tableGeometryIsCopyable); // Geometry window status
2142
2144
2145 // Send to FittingWindow
2146 m_dockFittingWindow->doCopy ();
2147
2148 } else if (tableGeometryIsActive) {
2149
2150 // Send to GeometryWindow
2151 m_dockGeometryWindow->doCopy ();
2152
2153 } else {
2154
2155 // Process curve points in main window
2157 const QList<QGraphicsItem*> &items = m_scene->selectedItems();
2158 QStringList pointIdentifiers = graphicsItemsExtractor.selectedPointIdentifiers (items);
2159
2160 CmdCopy *cmd = new CmdCopy (*this,
2161 m_cmdMediator->document(),
2163 m_digitizeStateContext->appendNewCmd (m_cmdMediator,
2164 cmd);
2165 }
2166}
2167
2168void MainWindow::slotEditCut ()
2169{
2170 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditCut";
2171
2172 // Copy command is sent to FittingWindow or GeometryWindow, or processed locally
2175 m_dockFittingWindow->getTableStatus (tableFittingIsActive, tableFittingIsCopyable); // Fitting window status
2176 m_dockGeometryWindow->getTableStatus (tableGeometryIsActive, tableGeometryIsCopyable); // Geometry window status
2177
2179
2180 // Cannot delete from fitting or geometry windows
2181
2182 } else {
2183
2184 // Process curve points in main window
2186 const QList<QGraphicsItem*> &items = m_scene->selectedItems();
2187 QStringList pointIdentifiers = graphicsItemsExtractor.selectedPointIdentifiers (items);
2188
2189 CmdCut *cmd = new CmdCut (*this,
2190 m_cmdMediator->document(),
2192 m_digitizeStateContext->appendNewCmd (m_cmdMediator,
2193 cmd);
2194 }
2195}
2196
2197void MainWindow::slotEditDelete ()
2198{
2199 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditDelete";
2200
2201 // Copy command is sent to FittingWindow or GeometryWindow, or processed locally
2204 m_dockFittingWindow->getTableStatus (tableFittingIsActive, tableFittingIsCopyable); // Fitting window status
2205 m_dockGeometryWindow->getTableStatus (tableGeometryIsActive, tableGeometryIsCopyable); // Geometry window status
2206
2208
2209 // Cannot delete from fitting or geometry windows
2210
2211 } else {
2212
2213 // If this is a map, which has a scale bar with two axis points, then selection of just one axis point
2214 // for deletion should result in deletion of the other point also so this object will enforce that. Otherwise
2215 // this class has no effect below
2217
2218 // Process curve points in main window
2220 const QList<QGraphicsItem*> &items = m_scene->selectedItems();
2221 QStringList pointIdentifiers = scaleBarAxisPoints.unite (m_cmdMediator,
2222 graphicsItemsExtractor.selectedPointIdentifiers (items));
2223
2224 CmdDelete *cmd = new CmdDelete (*this,
2225 m_cmdMediator->document(),
2227 m_digitizeStateContext->appendNewCmd (m_cmdMediator,
2228 cmd);
2229 }
2230}
2231
2232void MainWindow::slotEditMenu ()
2233{
2234 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditMenu";
2235
2236 m_actionEditPasteAsNew->setEnabled (!QApplication::clipboard()->image().isNull());
2237 m_actionEditPasteAsNewAdvanced->setEnabled (!QApplication::clipboard()->image().isNull());
2238}
2239
2240void MainWindow::slotEditPaste ()
2241{
2242 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditPaste";
2243
2244 QList<QPoint> points;
2246
2248 mimePointsImport.retrievePoints (m_transformation,
2249 points,
2250 ordinals);
2251
2253 m_cmdMediator->document(),
2254 m_cmbCurve->currentText (),
2255 points,
2256 ordinals);
2257 m_digitizeStateContext->appendNewCmd (m_cmdMediator,
2258 cmd);
2259}
2260
2261void MainWindow::slotEditPasteAsNew ()
2262{
2263 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditPasteAsNew";
2264
2265 filePaste (IMPORT_TYPE_SIMPLE);
2266}
2267
2268void MainWindow::slotEditPasteAsNewAdvanced ()
2269{
2270 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotEditPasteAsNewAdvanced";
2271
2272 filePaste (IMPORT_TYPE_ADVANCED);
2273}
2274
2275void MainWindow::slotFileClose()
2276{
2277 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileClose";
2278
2279 if (maybeSave ()) {
2280
2281 // Transition from defined to undefined. This must be after the clearing of the screen
2282 // since the axes checker screen item (and maybe others) must still exist
2283 m_transformationStateContext->triggerStateTransition(m_isGnuplot,
2285 *m_cmdMediator,
2286 m_transformation,
2288
2289 // Transition to empty state so an inadvertent mouse press does not trigger, for example,
2290 // the creation of an axis point on a non-existent GraphicsScene (=crash)
2291 m_digitizeStateContext->requestImmediateStateTransition (m_cmdMediator,
2293
2294 // Deallocate fitted curve
2295 if (m_fittingCurve != nullptr) {
2296 m_scene->removeItem (m_fittingCurve);
2297 m_fittingCurve = nullptr;
2298 }
2299
2300 // Remove screen objects
2301 m_scene->resetOnLoad ();
2302
2303 // Remove background
2304 m_backgroundStateContext->close ();
2305
2306 // Remove scroll bars if they exist
2307 m_scene->setSceneRect (QRectF (0, 0, 1, 1));
2308
2309 // Remove stale data from fitting window
2310 m_dockFittingWindow->clear ();
2311
2312 // Remove stale data from geometry window
2313 m_dockGeometryWindow->clear ();
2314
2315 // Deallocate Document
2316 delete m_cmdMediator;
2317
2318 // Remove file information
2319 m_cmdMediator = nullptr;
2320 m_currentFile = "";
2321 m_engaugeFile = "";
2323
2324 m_gridLines.clear();
2325 updateControls();
2326 }
2327}
2328
2329void MainWindow::slotFileExport ()
2330{
2331 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileExport";
2332
2333 if (m_transformation.transformIsDefined()) {
2334
2337
2339 if (m_isExportOnly) {
2340 fileName = fileNameForExportOnly ();
2341 } else {
2342
2343 QString filter = QString ("%1;;%2;;All files (*.*)")
2344 .arg (exportStrategy.filterCsv ())
2345 .arg (exportStrategy.filterTsv ());
2346
2347 // OSX sandbox requires, for the default, a non-empty filename
2348 QString defaultFileName = QString ("%1/%2.%3")
2349 .arg (directoryPersist.getDirectoryExportSave().path ())
2350 .arg (m_currentFile)
2351 .arg (exportStrategy.fileExtensionCsv ());
2353 QString filterCsv = exportStrategy.filterCsv ();
2354
2355 fileName = dlg.getSaveFileName (this,
2356 tr("Export"),
2358 filter,
2359 &filterCsv);
2360 }
2361
2362 if (!fileName.isEmpty ()) {
2363
2364 directoryPersist.setDirectoryExportSaveFromFilename(fileName);
2365 fileExport(fileName,
2367 }
2368 } else {
2369 DlgRequiresTransform dlg ("Export");
2370 dlg.exec ();
2371 }
2372}
2373
2374void MainWindow::slotFileImport ()
2375{
2376 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileImport";
2377
2378 fileImportWithPrompts (IMPORT_TYPE_SIMPLE);
2379}
2380
2381void MainWindow::slotFileImportAdvanced ()
2382{
2383 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileImportAdvanced";
2384
2385 fileImportWithPrompts (IMPORT_TYPE_ADVANCED);
2386}
2387
2388void MainWindow::slotFileImportDraggedImage(QImage image)
2389{
2390 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileImportDraggedImage";
2391
2392 // No need to check return value from loadImage since there are no prompts that give the user a chance to cancel
2393 loadImage ("",
2394 image,
2395 IMPORT_TYPE_SIMPLE);
2396}
2397
2398void MainWindow::slotFileImportDraggedImageUrl(QUrl url)
2399{
2400 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileImportDraggedImageUrl url=" << url.toString ().toLatin1 ().data ();
2401
2402 // This is required for drag and drop from GraphicsView. This had an #ifdef
2403 // around it for NETWORKING but restored for drag and drop
2404 m_loadImageFromUrl->startLoadImage (url);
2405}
2406
2407void MainWindow::slotFileImportImage(QString fileName, QImage image)
2408{
2409 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileImportImage fileName=" << fileName.toLatin1 ().data ();
2410
2411 // No need to check return value from loadImage since there are no prompts that give the user a chance to cancel
2412 loadImage (fileName,
2413 image,
2414 IMPORT_TYPE_SIMPLE);
2415}
2416
2417void MainWindow::slotFileImportImageReplace ()
2418{
2419 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileImportImageReplace";
2420
2421 fileImportWithPrompts (IMPORT_TYPE_IMAGE_REPLACE);
2422}
2423
2424void MainWindow::slotFileOpen()
2425{
2426 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileOpen";
2427
2428 if (maybeSave ()) {
2429
2430 // Allow selection of files with strange suffixes in case the file extension was changed. Since
2431 // the default is the first filter, the wildcard filter is added afterwards (it is the off-nominal case)
2432 QString filter = QString ("%1 (*.%2);; All Files (*.*)")
2433 .arg (ENGAUGE_FILENAME_DESCRIPTION)
2435
2437 QString fileName = QFileDialog::getOpenFileName (this,
2438 tr("Open Document"),
2439 directoryPersist.getDirectoryImportOpen ().path (),
2440 filter);
2441 if (!fileName.isEmpty ()) {
2442
2443 directoryPersist.setDirectoryImportOpenFromFilename (fileName);
2444 loadDocumentFile (fileName);
2445
2446 }
2447 }
2448}
2449
2450void MainWindow::slotFileOpenDraggedDigFile (QString fileName)
2451{
2452 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileOpenDraggedDigFile";
2453
2454 loadDocumentFile (fileName);
2455}
2456
2457void MainWindow::slotFilePrint()
2458{
2459 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFilePrint";
2460
2461 QPrinter printer (QPrinter::HighResolution);
2462 QPrintDialog dlg (&printer, this);
2463 if (dlg.exec() == QDialog::Accepted) {
2465 m_view->render (&painter);
2466 painter.end();
2467 }
2468}
2469
2470bool MainWindow::slotFileSave()
2471{
2472 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileSave";
2473
2474 if (m_engaugeFile.isEmpty()) {
2475 return slotFileSaveAs();
2476 } else {
2477 return saveDocumentFile (m_engaugeFile);
2478 }
2479}
2480
2481bool MainWindow::slotFileSaveAs()
2482{
2483 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFileSaveAs";
2484
2485 // Append engauge file extension if it is not already there
2486 QString filenameDefault = m_currentFile;
2487 if (!m_currentFile.endsWith (ENGAUGE_FILENAME_EXTENSION)) {
2488 filenameDefault = QString ("%1.%2")
2489 .arg (m_currentFile)
2491 }
2492
2493 if (!m_engaugeFile.isEmpty()) {
2494 filenameDefault = m_engaugeFile;
2495 }
2496
2497 QString filterDigitizer = QString ("%1 (*.%2)")
2498 .arg (ENGAUGE_FILENAME_DESCRIPTION)
2500 QString filterAll ("All files (*. *)");
2501
2504 filters << filterAll;
2505
2507
2508 QFileDialog dlg(this);
2509 dlg.setFileMode (QFileDialog::AnyFile);
2510 dlg.selectNameFilter (filterDigitizer);
2511 dlg.setNameFilters (filters);
2512#if !defined(OSX_DEBUG) && !defined(OSX_RELEASE)
2513 // Prevent hang in OSX
2514 dlg.setWindowModality(Qt::WindowModal);
2515#endif
2516 dlg.setAcceptMode(QFileDialog::AcceptSave);
2517 dlg.selectFile(filenameDefault);
2518 dlg.setDirectory (directoryPersist.getDirectoryExportSave ());
2519 if (dlg.exec()) {
2520
2521 QStringList files = dlg.selectedFiles();
2522 directoryPersist.setDirectoryExportSaveFromFilename (files.at(0));
2523 return saveDocumentFile(files.at(0));
2524 }
2525
2526 return false;
2527}
2528
2529void MainWindow::slotFittingWindowClosed()
2530{
2531 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFittingWindowClosed";
2532
2533 m_actionViewFittingWindow->setChecked (false);
2534}
2535
2536void MainWindow::slotFittingWindowCurveFit(FittingCurveCoefficients fittingCurveCoef,
2537 double xMin,
2538 double xMax,
2539 bool isLogXTheta,
2540 bool isLogYRadius)
2541{
2542 // Do not output elements in fittingCurveCoef here since that list may be empty
2543 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotFittingWindowCurveFit"
2544 << " order=" << fittingCurveCoef.size() - 1;
2545
2546 if (m_fittingCurve != nullptr) {
2547 m_scene->removeItem (m_fittingCurve);
2548 delete m_fittingCurve;
2549 }
2550
2551 m_fittingCurve = new FittingCurve (fittingCurveCoef,
2552 xMin,
2553 xMax,
2556 m_transformation);
2557 m_fittingCurve->setVisible (m_actionViewFittingWindow->isChecked ());
2558 m_scene->addItem (m_fittingCurve);
2559}
2560
2561void MainWindow::slotGeometryWindowClosed()
2562{
2563 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotGeometryWindowClosed";
2564
2565 m_actionViewGeometryWindow->setChecked (false);
2566}
2567
2568void MainWindow::slotHelpAbout()
2569{
2570 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotHelpAbout";
2571
2572 DlgAbout dlg (*this);
2573 dlg.exec ();
2574}
2575
2576void MainWindow::slotHelpTutorial()
2577{
2578 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotHelpTutorial";
2579
2580 m_tutorialDlg->show ();
2581 m_tutorialDlg->exec ();
2582}
2583
2584void MainWindow::slotKeyPress (Qt::Key key,
2586{
2587 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotKeyPress"
2588 << " key=" << QKeySequence (key).toString().toLatin1 ().data ()
2589 << " atLeastOneSelectedItem=" << (atLeastOneSelectedItem ? "true" : "false");
2590
2591 m_digitizeStateContext->handleKeyPress (m_cmdMediator,
2592 key,
2594}
2595
2596void MainWindow::slotLoadStartupFiles ()
2597{
2598 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotLoadStartupFiles";
2599
2600 ENGAUGE_ASSERT (m_loadStartupFiles.count() > 0);
2601
2602 QString fileName = m_loadStartupFiles.front(); // Get next file name
2603 m_loadStartupFiles.pop_front(); // Remove next file name
2604
2605 // Load next file into this instance of Engauge
2607 if (loadFileInfo.loadsAsDigFile(fileName)) {
2608
2609 loadDocumentFile (fileName);
2610
2611 } else {
2612
2613 fileImport (fileName,
2614 IMPORT_TYPE_SIMPLE);
2615
2616 }
2617
2618 if (m_loadStartupFiles.count() > 0) {
2619
2620 // Fork off another instance of this application to handle the remaining files recursively. New process
2621 // is detached so killing/terminating this process does not automatically kill the child process(es) also
2622 QProcess::startDetached (QCoreApplication::applicationFilePath(),
2623 m_commandLineWithoutLoadStartupFiles + m_loadStartupFiles);
2624 }
2625}
2626
2627void MainWindow::slotMouseMove (QPointF pos)
2628{
2629// LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotMouseMove pos=" << QPointFToString (pos).toLatin1 ().data ();
2630
2631 // Ignore mouse moves before Document is loaded
2632 if (m_cmdMediator != nullptr) {
2633
2634 // Get status bar coordinates
2636 m_transformation.coordTextForStatusBar (pos,
2640 modeMap ());
2641
2642 // Update status bar coordinates
2643 m_statusBar->setCoordinates (coordsScreen,
2646
2647 // There used to be a call to updateGraphicsLinesToMatchGraphicsPoints here, but that resulted
2648 // in hundreds of gratuitous log messages as the cursor was moved around, and nothing important happened
2649
2650 m_digitizeStateContext->handleMouseMove (m_cmdMediator,
2651 pos);
2652 }
2653}
2654
2655void MainWindow::slotMousePress (QPointF pos)
2656{
2657 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotMousePress";
2658
2660
2661 m_digitizeStateContext->handleMousePress (m_cmdMediator,
2662 pos);
2663}
2664
2665void MainWindow::slotMouseRelease (QPointF pos)
2666{
2667 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotMouseRelease";
2668
2669 if (pos.x() < 0 || pos.y() < 0) {
2670
2671 // Cursor is outside the image so drop this event. However, call updateControls since this may be
2672 // a click-and-drag to select in which case the controls (especially Copy and Cut) reflect the new selection
2673 updateControls ();
2674
2675 } else {
2676
2677 // Cursor is within the image so process this as a normal mouse release
2678 m_digitizeStateContext->handleMouseRelease (m_cmdMediator,
2679 pos);
2680 }
2681}
2682
2683void MainWindow::slotRecentFileAction ()
2684{
2685 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotRecentFileAction";
2686
2688
2689 if (action) {
2690 QString fileName = action->data().toString();
2691 loadDocumentFile (fileName);
2692 }
2693}
2694
2695void MainWindow::slotRecentFileClear ()
2696{
2697 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotRecentFileClear";
2698
2700
2703 emptyList);
2704
2705 updateRecentFileList();
2706}
2707
2708void MainWindow::slotRedoTextChanged (const QString &text)
2709{
2710 LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotRedoTextChanged";
2711
2712 QString completeText ("Redo");
2713 if (!text.isEmpty ()) {
2714 completeText += QString (" \"%1\"").arg (text);
2715 }
2716 m_actionEditRedo->setText (completeText);
2717}
2718
2719void MainWindow::slotSettingsAxesChecker ()
2720{
2721 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsAxesChecker";
2722
2723 m_dlgSettingsAxesChecker->load (*m_cmdMediator);
2724 m_dlgSettingsAxesChecker->show ();
2725}
2726
2727void MainWindow::slotSettingsColorFilter ()
2728{
2729 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsColorFilter";
2730
2731 m_dlgSettingsColorFilter->load (*m_cmdMediator);
2732 m_dlgSettingsColorFilter->show ();
2733}
2734
2735void MainWindow::slotSettingsCoords ()
2736{
2737 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsCoords";
2738
2739 m_dlgSettingsCoords->load (*m_cmdMediator);
2740 m_dlgSettingsCoords->show ();
2741}
2742
2743void MainWindow::slotSettingsCurveList ()
2744{
2745 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsCurveList";
2746
2747 m_dlgSettingsCurveList->load (*m_cmdMediator);
2748 m_dlgSettingsCurveList->show ();
2749}
2750
2751void MainWindow::slotSettingsCurveProperties ()
2752{
2753 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsCurveProperties";
2754
2755 m_dlgSettingsCurveProperties->load (*m_cmdMediator);
2756 m_dlgSettingsCurveProperties->setCurveName (selectedGraphCurve ());
2757 m_dlgSettingsCurveProperties->show ();
2758}
2759
2760void MainWindow::slotSettingsDigitizeCurve ()
2761{
2762 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsDigitizeCurve";
2763
2764 m_dlgSettingsDigitizeCurve->load (*m_cmdMediator);
2765 m_dlgSettingsDigitizeCurve->show ();
2766}
2767
2768void MainWindow::slotSettingsExportFormat ()
2769{
2770 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsExportFormat";
2771
2772 if (transformIsDefined()) {
2773 m_dlgSettingsExportFormat->load (*m_cmdMediator);
2774 m_dlgSettingsExportFormat->show ();
2775 } else {
2776 DlgRequiresTransform dlg ("Export settings");
2777 dlg.exec();
2778 }
2779}
2780
2781void MainWindow::slotSettingsGeneral ()
2782{
2783 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsGeneral";
2784
2785 m_dlgSettingsGeneral->load (*m_cmdMediator);
2786 m_dlgSettingsGeneral->show ();
2787}
2788
2789void MainWindow::slotSettingsGridDisplay()
2790{
2791 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsGridDisplay";
2792
2793 m_dlgSettingsGridDisplay->load (*m_cmdMediator);
2794 m_dlgSettingsGridDisplay->show ();
2795}
2796
2797void MainWindow::slotSettingsGridRemoval ()
2798{
2799 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsGridRemoval";
2800
2801 m_dlgSettingsGridRemoval->load (*m_cmdMediator);
2802 m_dlgSettingsGridRemoval->show ();
2803}
2804
2805void MainWindow::slotSettingsPointMatch ()
2806{
2807 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsPointMatch";
2808
2809 m_dlgSettingsPointMatch->load (*m_cmdMediator);
2810 m_dlgSettingsPointMatch->show ();
2811}
2812
2813void MainWindow::slotSettingsSegments ()
2814{
2815 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsSegments";
2816
2817 m_dlgSettingsSegments->load (*m_cmdMediator);
2818 m_dlgSettingsSegments->show ();
2819}
2820
2821void MainWindow::slotTableStatusChange ()
2822{
2823 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotTableStatusChange";
2824
2825 // This slot is called when either window in FittingWindow or GeometryWindow loses/gains focus. This is
2826 // so the Copy menu item can be updated
2827 updateControls ();
2828}
2829
2830void MainWindow::slotSettingsMainWindow ()
2831{
2832 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotSettingsMainWindow";
2833
2834 m_dlgSettingsMainWindow->loadMainWindowModel (*m_cmdMediator,
2835 m_modelMainWindow);
2836 m_dlgSettingsMainWindow->show ();
2837}
2838
2839void MainWindow::slotTimeoutRegressionErrorReport ()
2840{
2841 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotTimeoutRegressionErrorReport"
2842 << " cmdStackIndex=" << m_cmdMediator->index()
2843 << " cmdStackCount=" << m_cmdMediator->count();
2844
2845 if (m_cmdStackShadow->canRedo()) {
2846
2847 // Always reset current directory before the command. This guarantees the upcoming redo step will work
2848 QDir::setCurrent (m_startupDirectory);
2849
2850 m_cmdStackShadow->slotRedo();
2851
2852 // Always reset current directory after the command. This guarantees the final export to file will work
2853 QDir::setCurrent (m_startupDirectory);
2854
2855 } else {
2856
2857#if !defined(OSX_DEBUG) && !defined(OSX_RELEASE)
2858 exportAllCoordinateSystemsAfterRegressionTests ();
2859#endif
2860
2861 // Regression test has finished so exit. We unset the dirty flag so there is no prompt
2862 m_cmdMediator->setClean();
2863 close();
2864
2865 }
2866}
2867
2868void MainWindow::slotTimeoutRegressionFileCmdScript ()
2869{
2870 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotTimeoutRegressionFileCmdScript";
2871
2872 if (m_fileCmdScript->canRedo()) {
2873
2874 // Always reset current directory before the command. This guarantees the upcoming redo step will work
2875 QDir::setCurrent (m_startupDirectory);
2876
2877 m_fileCmdScript->redo(*this);
2878
2879 // Always reset current directory after the command. This guarantees the final export to file will work
2880 QDir::setCurrent (m_startupDirectory);
2881
2882 } else {
2883
2884 // Script file might already have closed the Document so export only if last was not closed
2885 if (m_cmdMediator != nullptr) {
2886
2887#if !defined(OSX_DEBUG) && !defined(OSX_RELEASE)
2888 exportAllCoordinateSystemsAfterRegressionTests ();
2889#endif
2890
2891 // We unset the dirty flag so there is no "Save changes?" prompt
2892 m_cmdMediator->setClean();
2893
2894 }
2895
2896 // Regression test has finished so exit
2897 close();
2898
2899 }
2900}
2901
2902void MainWindow::slotUndoTextChanged (const QString &text)
2903{
2904 LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotUndoTextChanged";
2905
2906 QString completeText ("Undo");
2907 if (!text.isEmpty ()) {
2908 completeText += QString (" \"%1\"").arg (text);
2909 }
2910 m_actionEditUndo->setText (completeText);
2911}
2912
2913void MainWindow::slotViewGridLines ()
2914{
2915 LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::slotViewGridLines";
2916
2917 updateGridLines ();
2918}
2919
2920void MainWindow::slotViewGroupBackground(QAction *action)
2921{
2922 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewGroupBackground";
2923
2924 // Set the combobox
2926 int indexBackground;
2927 if (action == m_actionViewBackgroundNone) {
2928 indexBackground = m_cmbBackground->findData (QVariant (BACKGROUND_IMAGE_NONE));
2930 } else if (action == m_actionViewBackgroundOriginal) {
2931 indexBackground = m_cmbBackground->findData (QVariant (BACKGROUND_IMAGE_ORIGINAL));
2933 } else if (action == m_actionViewBackgroundFiltered) {
2934 indexBackground = m_cmbBackground->findData (QVariant (BACKGROUND_IMAGE_FILTERED));
2936 } else {
2937 ENGAUGE_ASSERT (false);
2938
2939 // Defaults if assert is disabled so execution continues
2940 indexBackground = m_cmbBackground->findData (QVariant (BACKGROUND_IMAGE_ORIGINAL));
2942 }
2943
2944 m_cmbBackground->setCurrentIndex (indexBackground);
2945 m_backgroundStateContext->setBackgroundImage (backgroundImage);
2946}
2947
2948void MainWindow::slotViewGroupCurves(QAction * /* action */)
2949{
2950 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewGroupCurves";
2951
2952 updateViewedCurves ();
2953}
2954
2955void MainWindow::slotViewGroupStatus(QAction *action)
2956{
2957 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewGroupStatus";
2958
2959 ENGAUGE_CHECK_PTR (m_statusBar); // At startup, make sure status bar is already set up when View menu gets initialized
2960
2961 if (action == m_actionStatusNever) {
2963 } else if (action == m_actionStatusTemporary) {
2965 } else {
2967 }
2968}
2969
2970void MainWindow::slotViewToolBarBackground ()
2971{
2972 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarBackground";
2973
2974 if (m_actionViewBackground->isChecked ()) {
2975 m_toolBackground->show();
2976 } else {
2977 m_toolBackground->hide();
2978 }
2979}
2980
2981void MainWindow::slotViewToolBarChecklistGuide ()
2982{
2983 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarChecklistGuide";
2984
2985 if (m_actionViewChecklistGuide->isChecked ()) {
2986 m_dockChecklistGuide->show();
2987 } else {
2988 m_dockChecklistGuide->hide();
2989 }
2990}
2991
2992void MainWindow::slotViewToolBarCoordSystem ()
2993{
2994 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarCoordSystem";
2995
2996 if (m_actionViewCoordSystem->isChecked ()) {
2997 m_toolCoordSystem->show();
2998 } else {
2999 m_toolCoordSystem->hide();
3000 }
3001}
3002
3003void MainWindow::slotViewToolBarDigitize ()
3004{
3005 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarDigitize";
3006
3007 if (m_actionViewDigitize->isChecked ()) {
3008 m_toolDigitize->show();
3009 } else {
3010 m_toolDigitize->hide();
3011 }
3012}
3013
3014void MainWindow::slotViewToolBarFittingWindow()
3015{
3016 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarFittingWindow";
3017
3018 if (m_actionViewFittingWindow->isChecked()) {
3019 m_dockFittingWindow->show ();
3020 if (m_fittingCurve != nullptr) {
3021 m_fittingCurve->setVisible (true);
3022 }
3023 } else {
3024 m_dockFittingWindow->hide ();
3025 if (m_fittingCurve != nullptr) {
3026 m_fittingCurve->setVisible (false);
3027 }
3028 }
3029}
3030
3031void MainWindow::slotViewToolBarGeometryWindow ()
3032{
3033 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarGeometryWindow";
3034
3035 if (m_actionViewGeometryWindow->isChecked ()) {
3036 m_dockGeometryWindow->show();
3037 } else {
3038 m_dockGeometryWindow->hide();
3039 }
3040}
3041
3042void MainWindow::slotViewToolBarSettingsViews ()
3043{
3044 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolBarSettingsViews";
3045
3046 if (m_actionViewSettingsViews->isChecked ()) {
3047 m_toolSettingsViews->show();
3048 } else {
3049 m_toolSettingsViews->hide();
3050 }
3051}
3052
3053void MainWindow::slotViewToolTips ()
3054{
3055 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewToolTips";
3056
3057 loadToolTips();
3058}
3059
3060void MainWindow::slotViewZoom (int zoom)
3061{
3062 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoom";
3063
3064 // Update zoom controls and apply the zoom factor
3065 ZoomFactor zoomFactor = static_cast<ZoomFactor> (zoom);
3066 m_zoomMapToAction [zoomFactor]->setChecked (true);
3067 slotViewZoomFactor (static_cast<ZoomFactor> (zoom));
3068}
3069
3070void MainWindow::slotViewZoomFactor (ZoomFactor zoomFactor)
3071{
3072 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoomFactor";
3073
3074 if (zoomFactor == ZOOM_FILL) {
3075 m_backgroundStateContext->fitInView (*m_view);
3076 } else {
3077
3080
3082 transform.scale (factor, factor);
3083 m_view->setTransform (transform);
3084 }
3085
3087}
3088
3089void MainWindow::slotViewZoomFactorInt (int zoom)
3090{
3091 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoomFactorInt";
3092
3093 slotViewZoomFactor (static_cast<ZoomFactor> (zoom));
3094}
3095
3096void MainWindow::slotViewZoomIn ()
3097{
3098 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoomIn";
3099
3101 ZoomFactor zoomFactorNew = zoomTransition.zoomIn (currentZoomFactor (),
3102 m_view->transform ().m11 (),
3103 m_view->transform ().m22 (),
3104 m_actionZoomFill->isChecked ());
3105 setNonFillZoomFactor (zoomFactorNew);
3106}
3107
3108
3109void MainWindow::slotViewZoomInFromWheelEvent ()
3110{
3111 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoomInFromWheelEvent";
3112
3113 if ((m_modelMainWindow.zoomControl() == ZOOM_CONTROL_MENU_WHEEL) ||
3114 (m_modelMainWindow.zoomControl() == ZOOM_CONTROL_MENU_WHEEL_PLUSMINUS)) {
3115
3116 // Anchor the zoom to the cursor position
3117 m_view->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
3118
3119 // Forward this event
3120 slotViewZoomIn ();
3121
3122 m_view->setTransformationAnchor(QGraphicsView::NoAnchor);
3123 }
3124}
3125
3126void MainWindow::slotViewZoomOut ()
3127{
3128 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoomOut";
3129
3130 // Try to zoom out
3132 ZoomFactor zoomFactorNew = zoomTransition.zoomOut (currentZoomFactor (),
3133 m_view->transform ().m11 (),
3134 m_view->transform ().m22 (),
3135 m_actionZoomFill->isChecked ());
3136 setNonFillZoomFactor (zoomFactorNew);
3137}
3138
3139void MainWindow::slotViewZoomOutFromWheelEvent ()
3140{
3141 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::slotViewZoomOutFromWheelEvent";
3142
3143 if ((m_modelMainWindow.zoomControl() == ZOOM_CONTROL_MENU_WHEEL) ||
3144 (m_modelMainWindow.zoomControl() == ZOOM_CONTROL_MENU_WHEEL_PLUSMINUS)) {
3145
3146 // Anchor the zoom to the cursor position
3147 m_view->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
3148
3149 // Forward this event
3150 slotViewZoomOut ();
3151
3152 m_view->setTransformationAnchor(QGraphicsView::NoAnchor);
3153 }
3154}
3155
3156void MainWindow::startRegressionDropTest (const QStringList &loadStartupFiles)
3157{
3158 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::startRegressionTestErrorReport";
3159
3160 // Regression testing of drag and drop has some constraints:
3161 // 1) Need graphics window (GraphicsView) or else its events will not work. This is why
3162 // drag and drop testing is not done as one of the cli tests, which do not show the gui
3163 // 2) Drag and drop by itself does not produce the csv file, so this code will output theupdateTransformFromMatrices
3164 // x,y dimensions of the imported image instead of a normal csv file
3165 connect (this, SIGNAL (signalDropRegression (QString)), m_view, SLOT (slotDropRegression (QString)));
3166
3167 for (int counter = 0; counter < loadStartupFiles.size (); counter++) {
3169
3170 // Trigger drop part of drag and drop operation
3172
3173 QSize siz = m_view->size();
3174
3176 if (filenameDrop.startsWith ("http")) {
3177
3178 // Internet url is not useful for computing local file name. Only regression tests reach this branch
3179 // so filename is hardcoded
3180 filenameCsv = "../test/drag_and_drop_http.csv_actual_1";
3181
3182 } else {
3183
3184 // Local file
3185 filenameCsv = QString ("%1_%2")
3186 .arg (exportRegressionFilenameFromInputFilename (filenameDrop))
3187 .arg (counter + 1);
3188 }
3189
3191 file.open (QIODevice::WriteOnly);
3192 QTextStream str (&file);
3193 str << siz.width() << "x" << siz.height() << "\n";
3194 file.close ();
3195 }
3196
3197 exit (0);
3198}
3199
3200void MainWindow::startRegressionTestErrorReport(const QString &regressionInputFile)
3201{
3202 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::startRegressionTestErrorReport";
3203
3204 // In order for point-deleting commands to work (CmdCut, CmdDelete) in the regression tests, we need to
3205 // reset the Point identifier index here:
3206 // 1) after loading of the file which has increased the index value to greater than 0
3207 // 2) before running any commands since those commands implicitly assume the index is zero
3209
3210 // Save output/export file name
3211 m_regressionFile = exportRegressionFilenameFromInputFilename (regressionInputFile);
3212
3213 m_timerRegressionErrorReport = new QTimer();
3214 m_timerRegressionErrorReport->setSingleShot(false);
3215 connect (m_timerRegressionErrorReport, SIGNAL (timeout()), this, SLOT (slotTimeoutRegressionErrorReport()));
3216
3217 m_timerRegressionErrorReport->start(REGRESSION_INTERVAL);
3218}
3219
3220void MainWindow::startRegressionTestFileCmdScript()
3221{
3222 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::startRegressionTestFileCmdScript";
3223
3224 m_timerRegressionFileCmdScript = new QTimer();
3225 m_timerRegressionFileCmdScript->setSingleShot(false);
3226 connect (m_timerRegressionFileCmdScript, SIGNAL (timeout()), this, SLOT (slotTimeoutRegressionFileCmdScript()));
3227
3228 m_timerRegressionFileCmdScript->start(REGRESSION_INTERVAL);
3229}
3230
3232{
3233 return m_transformation;
3234}
3235
3237{
3238 return m_transformation.transformIsDefined();
3239}
3240
3242{
3243 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateAfterCommand";
3244
3245 ENGAUGE_CHECK_PTR (m_cmdMediator);
3246
3247 // Update transformation stuff, including the graph coordinates of every point in the Document, so coordinates in
3248 // status bar are up to date. Point coordinates in Document are also updated
3249 updateAfterCommandStatusBarCoords ();
3250
3251 updateHighlightOpacity ();
3252
3253 // Update graphics. Effectively, these steps do very little (just needed for highlight opacity)
3254 m_digitizeStateContext->updateAfterPointAddition (); // May or may not be needed due to point addition
3255
3256 updateControls ();
3257 updateChecklistGuide ();
3258 updateFittingWindow ();
3259 updateGeometryWindow();
3260
3261 // Final actions at the end of a redo/undo are:
3262 // 1) checkpoint the Document and GraphicsScene to log files so proper state can be verified
3263 // 2) run sanity check on state
3264 writeCheckpointToLogFile ();
3266 docScrub.check (*this,
3267 m_cmdMediator->document ());
3268
3269 // Since focus may have drifted over to Geometry Window or some other control we se focus on the GraphicsView
3270 // so the cursor is appropriate for the current state (otherwise it often ends up as default arrow)
3271 m_view->setFocus ();
3272}
3273
3274void MainWindow::updateAfterCommandStatusBarCoords ()
3275{
3276 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateAfterCommandStatusBarCoords";
3277
3278 // For some reason, mapFromGlobal(QCursor::pos) differs from event->pos by a little bit. We must compensate for
3279 // this so cursor coordinates in status bar match the DlgEditPointAxis inputs initially. After the mouse moves
3280 // the problem disappears since event->pos is available and QCursor::pos is no longer needed
3282
3283 Transformation m_transformationBefore (m_transformation);
3284
3285 updateTransformationAndItsDependencies();
3286
3287 // Trigger state transitions for transformation if appropriate
3288 if (!m_transformationBefore.transformIsDefined() && m_transformation.transformIsDefined()) {
3289
3290 // Transition from undefined to defined
3291 m_transformationStateContext->triggerStateTransition(m_isGnuplot,
3293 *m_cmdMediator,
3294 m_transformation,
3296
3297 } else if (m_transformationBefore.transformIsDefined() && !m_transformation.transformIsDefined()) {
3298
3299 // Transition from defined to undefined
3300 m_transformationStateContext->triggerStateTransition(m_isGnuplot,
3302 *m_cmdMediator,
3303 m_transformation,
3305
3306 } else if (m_transformation.transformIsDefined() && (m_transformationBefore != m_transformation)) {
3307
3308 // There was not a define/undefined or undefined/defined transition, but the transformation changed so we
3309 // need to update the Checker
3310 m_transformationStateContext->updateAxesChecker(*m_cmdMediator,
3311 m_transformation);
3312
3313 }
3314
3315 QPoint posLocal = m_view->mapFromGlobal (QCursor::pos ()) - HACK_SO_GRAPH_COORDINATE_MATCHES_INPUT;
3316 QPointF posScreen = m_view->mapToScene (posLocal);
3317
3318 slotMouseMove (posScreen); // Update the status bar coordinates to reflect the newly updated transformation
3319}
3320
3322{
3323 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateAfterMouseRelease";
3324
3325 updateControls ();
3326}
3327
3328void MainWindow::updateChecklistGuide ()
3329{
3330 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateChecklistGuide";
3331
3332 m_dockChecklistGuide->update (*m_cmdMediator,
3333 m_isDocumentExported);
3334}
3335
3336void MainWindow::updateControls ()
3337{
3338 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateControls"
3339 << " selectedItems=" << m_scene->selectedItems().count();
3340
3341 m_cmbBackground->setEnabled (!m_currentFile.isEmpty ());
3342
3343 m_actionImportImageReplace->setEnabled (m_cmdMediator != nullptr);
3344#if !defined(OSX_DEBUG) && !defined(OSX_RELEASE)
3345 m_menuFileOpenRecent->setEnabled ((m_actionRecentFiles.count () > 0) &&
3346 (m_actionRecentFiles.at(0)->isVisible ())); // Need at least one visible recent file entry
3347#endif
3348 m_actionClose->setEnabled (!m_currentFile.isEmpty ());
3349 m_actionSave->setEnabled (!m_currentFile.isEmpty ());
3350 m_actionSaveAs->setEnabled (!m_currentFile.isEmpty ());
3351 m_actionExport->setEnabled (!m_currentFile.isEmpty ());
3352 m_actionPrint->setEnabled (!m_currentFile.isEmpty ());
3353
3354 if (m_cmdMediator == nullptr) {
3355 m_actionEditUndo->setEnabled (false);
3356 m_actionEditRedo->setEnabled (false);
3357 } else {
3358 m_actionEditUndo->setEnabled (m_cmdMediator->canUndo ());
3359 m_actionEditRedo->setEnabled (m_cmdMediator->canRedo () || m_cmdStackShadow->canRedo ());
3360 }
3363 m_dockFittingWindow->getTableStatus (tableFittingIsActive, tableFittingIsCopyable); // Fitting window status
3364 m_dockGeometryWindow->getTableStatus (tableGeometryIsActive, tableGeometryIsCopyable); // Geometry window status
3365 m_actionEditCut->setEnabled (!tableFittingIsActive &&
3367 m_scene->selectedItems().count () > 0);
3368 m_actionEditCopy->setEnabled ((!tableFittingIsActive && !tableGeometryIsActive && m_scene->selectedItems().count () > 0) ||
3371 m_actionEditPaste->setEnabled (m_digitizeStateContext->canPaste (m_transformation,
3372 m_view->size ()));
3373 m_actionEditDelete->setEnabled (!tableFittingIsActive &&
3375 m_scene->selectedItems().count () > 0);
3376 // m_actionEditPasteAsNew and m_actionEditPasteAsNewAdvanced are updated when m_menuEdit is about to be shown
3377
3378 m_actionDigitizeAxis->setEnabled (modeGraph ());
3379 m_actionDigitizeScale->setEnabled (modeMap ());
3380 m_actionDigitizeCurve ->setEnabled (!m_currentFile.isEmpty ());
3381 m_actionDigitizePointMatch->setEnabled (!m_currentFile.isEmpty ());
3382 m_actionDigitizeColorPicker->setEnabled (!m_currentFile.isEmpty ());
3383 m_actionDigitizeSegment->setEnabled (!m_currentFile.isEmpty ());
3384 m_actionDigitizeSelect->setEnabled (!m_currentFile.isEmpty ());
3385 if (m_transformation.transformIsDefined()) {
3386 m_actionViewGridLines->setEnabled (true);
3387 } else {
3388 m_actionViewGridLines->setEnabled (false);
3389 m_actionViewGridLines->setChecked (false);
3390 }
3391 m_actionViewBackground->setEnabled (!m_currentFile.isEmpty());
3392 m_actionViewChecklistGuide->setEnabled (!m_dockChecklistGuide->browserIsEmpty());
3393 m_actionViewDigitize->setEnabled (!m_currentFile.isEmpty ());
3394 m_actionViewSettingsViews->setEnabled (!m_currentFile.isEmpty ());
3395
3396 m_actionSettingsCoords->setEnabled (!m_currentFile.isEmpty ());
3397 m_actionSettingsCurveList->setEnabled (!m_currentFile.isEmpty ());
3398 m_actionSettingsCurveProperties->setEnabled (!m_currentFile.isEmpty ());
3399 m_actionSettingsDigitizeCurve->setEnabled (!m_currentFile.isEmpty ());
3400 m_actionSettingsExport->setEnabled (!m_currentFile.isEmpty ());
3401 m_actionSettingsColorFilter->setEnabled (!m_currentFile.isEmpty ());
3402 m_actionSettingsAxesChecker->setEnabled (!m_currentFile.isEmpty ());
3403 m_actionSettingsGridDisplay->setEnabled (!m_currentFile.isEmpty () && m_transformation.transformIsDefined());
3404 m_actionSettingsGridRemoval->setEnabled (!m_currentFile.isEmpty ());
3405 m_actionSettingsPointMatch->setEnabled (!m_currentFile.isEmpty ());
3406 m_actionSettingsSegments->setEnabled (!m_currentFile.isEmpty ());
3407 m_actionSettingsGeneral->setEnabled (!m_currentFile.isEmpty ());
3408
3409 m_groupBackground->setEnabled (!m_currentFile.isEmpty ());
3410 m_groupCurves->setEnabled (!m_currentFile.isEmpty ());
3411 m_groupZoom->setEnabled (!m_currentFile.isEmpty ());
3412
3413 m_actionZoomIn->setEnabled (!m_currentFile.isEmpty ()); // Disable at startup so shortcut has no effect
3414 m_actionZoomOut->setEnabled (!m_currentFile.isEmpty ()); // Disable at startup so shortcut has no effect
3415}
3416
3418{
3419 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateCoordSystem";
3420
3421 // Set current curve in the Document and in the MainWindow combobox together so they are in sync. Setting
3422 // the selected curve prevents a crash in updateTransformationAndItsDependencies
3423 m_cmdMediator->document().setCoordSystemIndex (coordSystemIndex);
3424 loadCurveListFromCmdMediator ();
3425
3426 updateTransformationAndItsDependencies(); // Transformation state may have changed
3427 updateSettingsAxesChecker(m_cmdMediator->document().modelAxesChecker()); // Axes checker dependes on transformation state
3428
3429 // Nice trick for showing that a new coordinate system is in effect is to show the axes checker
3430 m_transformationStateContext->updateAxesChecker (*m_cmdMediator,
3431 m_transformation);
3432
3434}
3435
3437{
3438 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateDigitizeStateIfSoftwareTriggered";
3439
3440 switch (digitizeState) {
3442 m_actionDigitizeAxis->setChecked(true);
3443 slotDigitizeAxis(); // Call the slot that the setChecked call fails to trigger
3444 break;
3445
3447 m_actionDigitizeColorPicker->setChecked(true);
3448 slotDigitizeColorPicker(); // Call the slot that the setChecked call fails to trigger
3449 break;
3450
3452 m_actionDigitizeCurve->setChecked(true);
3453 slotDigitizeCurve(); // Call the slot that the setChecked call fails to trigger
3454 break;
3455
3457 break;
3458
3460 m_actionDigitizePointMatch->setChecked(true);
3461 slotDigitizePointMatch(); // Call the slot that the setChecked call fails to trigger
3462 break;
3463
3465 m_actionDigitizeScale->setChecked(true);
3466 slotDigitizeScale(); // Call the slot that the setChecked call fails to trigger
3467 break;
3468
3470 m_actionDigitizeSegment->setChecked(true);
3471 slotDigitizeSegment(); // Call the slot that the setChecked call fails to trigger
3472 break;
3473
3475 m_actionDigitizeSelect->setChecked(true);
3476 slotDigitizeSelect(); // Call the slot that the setChecked call fails to trigger
3477 break;
3478
3479 default:
3480 LOG4CPP_ERROR_S ((*mainCat)) << "MainWindow::updateDigitizeStateIfSoftwareTriggered";
3481 break;
3482 }
3483}
3484
3485void MainWindow::updateFittingWindow ()
3486{
3487 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateFittingWindow";
3488
3489 if (m_cmdMediator != nullptr &&
3490 m_cmbCurve != nullptr) {
3491
3492 // Update fitting window
3493 m_dockFittingWindow->update (*m_cmdMediator,
3494 m_modelMainWindow,
3495 m_cmbCurve->currentText (),
3496 m_transformation);
3497 }
3498}
3499
3500void MainWindow::updateGeometryWindow ()
3501{
3502 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateGeometryWindow";
3503
3504 if (m_cmdMediator != nullptr &&
3505 m_cmbCurve != nullptr) {
3506
3507 // Update geometry window
3508 m_dockGeometryWindow->update (*m_cmdMediator,
3509 m_modelMainWindow,
3510 m_cmbCurve->currentText (),
3511 m_transformation);
3512 }
3513}
3514
3516{
3517 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateGraphicsLinesToMatchGraphicsPoints";
3518
3520 m_transformation);
3521}
3522
3523void MainWindow::updateGridLines ()
3524{
3525 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateGridLines";
3526
3527 // Remove old grid lines
3528 m_gridLines.clear ();
3529
3530 // Create new grid lines
3531 GridLineFactory factory (*m_scene,
3532 m_cmdMediator->document().modelCoords());
3533 factory.createGridLinesForEvenlySpacedGrid (m_cmdMediator->document().modelGridDisplay(),
3534 m_cmdMediator->document(),
3535 m_modelMainWindow,
3536 m_transformation,
3537 m_gridLines);
3538
3539 m_gridLines.setVisible (m_actionViewGridLines->isChecked());
3540}
3541
3542void MainWindow::updateHighlightOpacity ()
3543{
3544 if (m_cmdMediator != nullptr) {
3545
3546 // Update the QGraphicsScene with the populated Curves. This requires the points in the Document to be already updated
3547 // by updateAfterCommandStatusBarCoords
3548 m_scene->updateAfterCommand (*m_cmdMediator,
3549 m_modelMainWindow.highlightOpacity(),
3550 m_dockGeometryWindow,
3551 m_transformation);
3552 }
3553}
3554
3555void MainWindow::updateRecentFileList()
3556{
3557 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateRecentFileList";
3558
3559#if !defined(OSX_DEBUG) && !defined(OSX_RELEASE)
3562
3563 // Determine the desired size of the path list
3564 unsigned int count = unsigned (recentFilePaths.size());
3565 if (count > MAX_RECENT_FILE_LIST_SIZE) {
3567 }
3568
3569 // Add visible entries
3570 int i;
3571 for (i = 0; i < signed (count); i++) {
3572 QString strippedName = QFileInfo (recentFilePaths.at(i)).fileName();
3573 m_actionRecentFiles.at (i)->setText (strippedName);
3574 m_actionRecentFiles.at (i)->setData (recentFilePaths.at (i));
3575 m_actionRecentFiles.at (i)->setVisible (true);
3576 }
3577
3578 // Hide any extra entries
3579 for (i = signed (count); i < signed (MAX_RECENT_FILE_LIST_SIZE); i++) {
3580 m_actionRecentFiles.at (i)->setVisible (false);
3581 }
3582#endif
3583}
3584
3586{
3587 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsAxesChecker";
3588
3589 m_cmdMediator->document().setModelAxesChecker(modelAxesChecker);
3590 if (m_transformation.transformIsDefined()) {
3591 m_transformationStateContext->triggerStateTransition(m_isGnuplot,
3593 *m_cmdMediator,
3594 m_transformation,
3595 m_cmbCurve->currentText());
3596 } else {
3597 m_transformationStateContext->triggerStateTransition(m_isGnuplot,
3599 *m_cmdMediator,
3600 m_transformation,
3601 m_cmbCurve->currentText());
3602 }
3603}
3604
3606{
3607 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsColorFilter";
3608
3609 m_cmdMediator->document().setModelColorFilter(modelColorFilter);
3610 m_backgroundStateContext->updateColorFilter (m_isGnuplot,
3611 m_transformation,
3612 m_cmdMediator->document().modelGridRemoval(),
3613 modelColorFilter,
3614 m_cmbCurve->currentText());
3615 m_digitizeStateContext->handleCurveChange (m_cmdMediator);
3617}
3618
3620{
3621 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsCoords";
3622
3623 m_cmdMediator->document().setModelCoords(modelCoords);
3624}
3625
3627{
3628 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsCurveList";
3629
3630 m_cmdMediator->document().setCurvesGraphs (curvesGraphs);
3631 loadCurveListFromCmdMediator();
3633}
3634
3636{
3637 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsCurveStyles";
3638
3639 m_scene->updateCurveStyles(modelCurveStyles);
3640 m_cmdMediator->document().setModelCurveStyles(modelCurveStyles);
3642}
3643
3645{
3646 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsDigitizeCurve";
3647
3648 m_cmdMediator->document().setModelDigitizeCurve(modelDigitizeCurve);
3649 m_digitizeStateContext->updateModelDigitizeCurve (m_cmdMediator,
3650 modelDigitizeCurve);
3651}
3652
3654{
3655 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsExportFormat";
3656
3657 m_cmdMediator->document().setModelExport (modelExport);
3658}
3659
3661{
3662 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsGeneral";
3663
3664 m_cmdMediator->document().setModelGeneral(modelGeneral);
3665}
3666
3668{
3669 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsGridDisplay";
3670
3671 m_cmdMediator->document().setModelGridDisplay(modelGridDisplay);
3672 updateGridLines ();
3673}
3674
3676{
3677 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsGridRemoval";
3678
3679 m_cmdMediator->document().setModelGridRemoval(modelGridRemoval);
3680}
3681
3682void MainWindow::updateSettingsMainWindow()
3683{
3684 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsMainWindow";
3685
3686 if (m_modelMainWindow.zoomControl() == ZOOM_CONTROL_MENU_ONLY ||
3687 m_modelMainWindow.zoomControl() == ZOOM_CONTROL_MENU_WHEEL) {
3688
3689 m_actionZoomIn->setShortcut (tr (""));
3690 m_actionZoomOut->setShortcut (tr (""));
3691
3692 } else {
3693
3694 m_actionZoomIn->setShortcut (tr ("+"));
3695 m_actionZoomOut->setShortcut (tr ("-"));
3696
3697 }
3698
3699 if ((m_scene != nullptr) &&
3700 (m_cmdMediator != nullptr)) {
3701 m_scene->updateCurveStyles(m_cmdMediator->document().modelCurveStyles());
3702 }
3703
3704 updateHighlightOpacity();
3705 updateWindowTitle();
3706 updateFittingWindow(); // Forward the drag and drop choice
3707 updateGeometryWindow(); // Forward the drag and drop choice
3708}
3709
3711{
3712 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsMainWindow";
3713
3714 m_modelMainWindow = modelMainWindow;
3716}
3717
3719{
3720 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsPointMatch";
3721
3722 m_cmdMediator->document().setModelPointMatch(modelPointMatch);
3723}
3724
3726{
3727 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateSettingsSegments";
3728
3729 m_cmdMediator->document().setModelSegments(modelSegments);
3730 m_digitizeStateContext->updateModelSegments(modelSegments);
3731}
3732
3733void MainWindow::updateSmallDialogs ()
3734{
3735 m_dlgSettingsAxesChecker->setSmallDialogs (m_modelMainWindow.smallDialogs ());
3736 m_dlgSettingsColorFilter->setSmallDialogs (m_modelMainWindow.smallDialogs ());
3737 m_dlgSettingsCoords->setSmallDialogs (m_modelMainWindow.smallDialogs ());
3738 m_dlgSettingsCurveList->setSmallDialogs (m_modelMainWindow.smallDialogs ());
3739 m_dlgSettingsCurveProperties->setSmallDialogs (m_modelMainWindow.smallDialogs ());
3740 m_dlgSettingsDigitizeCurve->setSmallDialogs (m_modelMainWindow.smallDialogs ());
3741 m_dlgSettingsExportFormat->setSmallDialogs (m_modelMainWindow.smallDialogs ());
3742 m_dlgSettingsGeneral->setSmallDialogs (m_modelMainWindow.smallDialogs ());
3743 m_dlgSettingsGridDisplay->setSmallDialogs (m_modelMainWindow.smallDialogs ());
3744 m_dlgSettingsGridRemoval->setSmallDialogs (m_modelMainWindow.smallDialogs ());
3745 m_dlgSettingsMainWindow->setSmallDialogs (m_modelMainWindow.smallDialogs ());
3746 m_dlgSettingsPointMatch->setSmallDialogs (m_modelMainWindow.smallDialogs ());
3747 m_dlgSettingsSegments->setSmallDialogs (m_modelMainWindow.smallDialogs ());
3748}
3749
3750void MainWindow::updateTransformationAndItsDependencies()
3751{
3752 m_transformation.update (!m_currentFile.isEmpty (),
3753 *m_cmdMediator,
3754 m_modelMainWindow);
3755
3756 // Grid removal is affected by new transformation above
3757 m_backgroundStateContext->setCurveSelected (m_isGnuplot,
3758 m_transformation,
3759 m_cmdMediator->document().modelGridRemoval(),
3760 m_cmdMediator->document().modelColorFilter(),
3761 m_cmbCurve->currentText ());
3762
3763 // Grid display is also affected by new transformation above, if there was a transition into defined state
3764 // in which case that transition triggered the initialization of the grid display parameters
3765 updateGridLines();
3766}
3767
3768void MainWindow::updateViewedCurves ()
3769{
3770 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateViewedCurves";
3771
3772 if (m_actionViewCurvesAll->isChecked ()) {
3773
3774 m_scene->showCurves (true, true);
3775
3776 } else if (m_actionViewCurvesSelected->isChecked ()) {
3777
3778 m_scene->showCurves (true, false, selectedGraphCurve ());
3779
3780 } else if (m_actionViewCurvesNone->isChecked ()) {
3781
3782 m_scene->showCurves (false);
3783
3784 } else {
3785 ENGAUGE_ASSERT (false);
3786 }
3787}
3788
3790{
3791 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateViewsOfSettings";
3792
3793 QString activeCurve = m_digitizeStateContext->activeCurve ();
3794
3795 updateViewsOfSettings (activeCurve);
3796}
3797
3799{
3800 if (activeCurve.isEmpty ()) {
3801
3802 m_viewPointStyle->unsetPointStyle ();
3803 m_viewSegmentFilter->unsetColorFilterSettings ();
3804
3805
3806 } else {
3807
3808 PointStyle pointStyle = m_cmdMediator->document().modelCurveStyles().curveStyle(activeCurve).pointStyle();
3809 m_viewPointStyle->setPointStyle (pointStyle);
3810
3811 ColorFilterSettings colorFilterSettings = m_cmdMediator->document().modelColorFilter().colorFilterSettings(activeCurve);
3812 m_viewSegmentFilter->setColorFilterSettings (colorFilterSettings,
3813 m_cmdMediator->pixmap ());
3814
3815 }
3816}
3817
3818void MainWindow::updateWindowTitle ()
3819{
3820 LOG4CPP_INFO_S ((*mainCat)) << "MainWindow::updateWindowTitle";
3821
3822 const QString PLACEHOLDER ("[*]");
3823
3824 QString title = QString ("%1 %2")
3825 .arg (tr ("Engauge Digitizer"))
3826 .arg (VERSION_NUMBER);
3827
3829 if (!m_currentFileWithPathAndFileExtension.isEmpty()) {
3830
3831 QFileInfo fileInfo (m_currentFileWithPathAndFileExtension);
3832
3833 switch (m_modelMainWindow.mainTitleBarFormat())
3834 {
3836 // Remove file extension and path for "clean look". We use completeBaseName rather than baseName so
3837 // files with multiple periods are handled correctly - all but last suffix gets kept
3838 fileNameMaybeStripped = fileInfo.completeBaseName();
3839 break;
3840
3842 fileNameMaybeStripped = m_currentFileWithPathAndFileExtension;
3843 break;
3844 }
3845
3846 title += QString (": %1")
3847 .arg (fileNameMaybeStripped);
3848 }
3849
3850 // To prevent "QWidget::setWindowModified: The window title does not contain a [*] placeholder" warnings,
3851 // we always append a placeholder
3852 title += PLACEHOLDER;
3853
3855}
3856
3858{
3859 ENGAUGE_CHECK_PTR (m_view);
3860 return *m_view;
3861}
3862
3864{
3865 ENGAUGE_CHECK_PTR (m_view);
3866 return *m_view;
3867}
3868
3869void MainWindow::writeCheckpointToLogFile ()
3870{
3871 // Document
3875 strDoc);
3876
3877 // Scene
3881 strScene);
3882
3883 // Skip slow string manipulation if BEFORE call to LOG4CPP_DEBUG_S
3885
3886 LOG4CPP_DEBUG_S ((*mainCat)) << "MainWindow::writeCheckpointToLogFile\n"
3887 << "--------------DOCUMENT CHECKPOINT START----------" << "\n"
3888 << checkpointDoc.toLatin1().data()
3889 << "---------------DOCUMENT CHECKPOINT END-----------" << "\n"
3890 << "----------------SCENE CHECKPOINT START-----------" << "\n"
3891 << checkpointScene.toLatin1().data()
3892 << "-----------------SCENE CHECKPOINT END------------" ;
3893 }
3894}
BackgroundImage
Background selection.
@ BACKGROUND_IMAGE_ORIGINAL
@ BACKGROUND_IMAGE_FILTERED
@ BACKGROUND_IMAGE_NONE
unsigned int CoordSystemIndex
Zero-based index for identifying CoordSystem instantiations.
DigitizeState
Set of possible states of Digitize toolbar.
@ DIGITIZE_STATE_POINT_MATCH
@ DIGITIZE_STATE_SELECT
@ DIGITIZE_STATE_COLOR_PICKER
@ DIGITIZE_STATE_SEGMENT
const int INNER_RADIUS_MIN
@ DOCUMENT_AXES_POINTS_REQUIRED_2
const QString DOCUMENT_SERIALIZE_ERROR
const QString DOCUMENT_SERIALIZE_APPLICATION
const QString DOCUMENT_SERIALIZE_ERROR_CONTEXT
const QString DOCUMENT_SERIALIZE_OPERATING_SYSTEM_WORD_SIZE
const QString DOCUMENT_SERIALIZE_FILE
const QString DOCUMENT_SERIALIZE_ERROR_COMMENT
const QString DOCUMENT_SERIALIZE_IMAGE
const QString DOCUMENT_SERIALIZE_IMAGE_HEIGHT
const QString DOCUMENT_SERIALIZE_ERROR_LINE
const QString DOCUMENT_SERIALIZE_IMAGE_WIDTH
const QString DOCUMENT_SERIALIZE_ERROR_FILE
const QString DOCUMENT_SERIALIZE_DOCUMENT
const QString DOCUMENT_SERIALIZE_OPERATING_SYSTEM_ENDIAN
const QString DOCUMENT_SERIALIZE_APPLICATION_VERSION_NUMBER
const QString DOCUMENT_SERIALIZE_FILE_IMPORTED
const QString DOCUMENT_SERIALIZE_OPERATING_SYSTEM
const QString DOCUMENT_SERIALIZE_ERROR_REPORT
const QString DOCUMENT_SERIALIZE_BOOL_TRUE
const QString DOCUMENT_SERIALIZE_BOOL_FALSE
#define ENGAUGE_ASSERT(cond)
Drop in replacement for Q_ASSERT if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS) define ENGAUGE...
#define ENGAUGE_CHECK_PTR(ptr)
#endif
QString EndianToString(QSysInfo::Endian endian)
Definition EnumsToQt.cpp:43
@ EXPORT_DELIMITER_COMMA
@ EXPORT_DELIMITER_TAB
QVector< double > FittingCurveCoefficients
Coefficients x0, x1, ... in y = a0 + a1 * x + a2 * x^2 + ...
const double DEFAULT_HIGHLIGHT_OPACITY
const int DEFAULT_MAXIMUM_GRID_LINES
Default for maximum number of grid lines.
const ImportCropping DEFAULT_IMPORT_CROPPING
ImportCropping
log4cpp::Category * mainCat
Definition Logger.cpp:14
const QString INDENTATION_PAST_TIMESTAMP
MainTitleBarFormat
Format format in MainWindow title bar.
@ MAIN_TITLE_BAR_FORMAT_NO_PATH
@ MAIN_TITLE_BAR_FORMAT_PATH
Filename without path.
bool DEFAULT_DRAG_DROP_EXPORT
bool DEFAULT_IMAGE_REPLACE_RENAMES_DOCUMENT
int DEFAULT_SIGNIFICANT_DIGITS
bool DEFAULT_SMALL_DIALOGS
const int REGRESSION_INTERVAL
const unsigned int MAX_RECENT_FILE_LIST_SIZE
const QString ENGAUGE_FILENAME_EXTENSION("dig")
const QString EMPTY_FILENAME("")
const unsigned int MAX_RECENT_FILE_LIST_SIZE
NonPdfReturn
Return values from load operation.
Definition NonPdf.h:19
@ NON_PDF_RETURN_CANCELED
Definition NonPdf.h:20
@ NON_PDF_RETURN_SUCCESS
Definition NonPdf.h:22
int DEFAULT_IMPORT_PDF_RESOLUTION
PdfReturn
Return values from load operation.
Definition Pdf.h:19
@ PDF_RETURN_CANCELED
Definition Pdf.h:20
@ PDF_RETURN_SUCCESS
Definition Pdf.h:22
const QString SETTINGS_ZOOM_FACTOR
const QString SETTINGS_SMALL_DIALOGS
const QString SETTINGS_IMPORT_PDF_RESOLUTION
const QString SETTINGS_ENGAUGE
const QString SETTINGS_CHECKLIST_GUIDE_DOCK_AREA
const QString SETTINGS_FITTING_WINDOW_DOCK_AREA
const QString SETTINGS_MAIN_TITLE_BAR_FORMAT
const QString SETTINGS_MAIN_DIRECTORY_EXPORT_SAVE
const QString SETTINGS_MAXIMUM_GRID_LINES
const QString SETTINGS_IMAGE_REPLACE_RENAMES_DOCUMENT
const QString SETTINGS_MAIN_DIRECTORY_IMPORT_LOAD
const QString SETTINGS_GROUP_ENVIRONMENT
const QString SETTINGS_HELP_SIZE
const QString SETTINGS_HIGHLIGHT_OPACITY
const QString SETTINGS_CHECKLIST_GUIDE_DOCK_GEOMETRY
const QString SETTINGS_LOCALE_LANGUAGE
const QString SETTINGS_SIZE
const QString SETTINGS_IMPORT_CROPPING
const QString SETTINGS_RECENT_FILE_LIST
const QString SETTINGS_HELP_POS
const QString SETTINGS_VIEW_COORD_SYSTEM_TOOLBAR
const QString SETTINGS_VIEW_DIGITIZE_TOOLBAR
const QString SETTINGS_ZOOM_FACTOR_INITIAL
const QString SETTINGS_SIGNIFICANT_DIGITS
const QString SETTINGS_VIEW_BACKGROUND_TOOLBAR
const QString SETTINGS_VIEW_SETTINGS_VIEWS_TOOLBAR
const QString SETTINGS_CHECKLIST_GUIDE_WIZARD
const QString SETTINGS_DRAG_DROP_EXPORT
const QString SETTINGS_VIEW_STATUS_BAR
const QString SETTINGS_ZOOM_CONTROL
const QString SETTINGS_GROUP_MAIN_WINDOW
const QString SETTINGS_VIEW_TOOL_TIPS
const QString SETTINGS_BACKGROUND_IMAGE
const QString SETTINGS_GEOMETRY_WINDOW_DOCK_GEOMETRY
const QString SETTINGS_POS
const QString SETTINGS_DIGITIZER
const QString SETTINGS_CURRENT_DIRECTORY
const QString SETTINGS_FITTING_WINDOW_DOCK_GEOMETRY
const QString SETTINGS_LOCALE_COUNTRY
const QString SETTINGS_GEOMETRY_WINDOW_DOCK_AREA
StatusBarMode
@ STATUS_BAR_MODE_TEMPORARY
@ STATUS_BAR_MODE_ALWAYS
@ STATUS_BAR_MODE_NEVER
QString engaugeWindowTitle()
Text for title bars of dialogs.
Definition Version.cpp:14
const char * VERSION_NUMBER
Definition Version.cpp:12
ZoomControl
Definition ZoomControl.h:10
@ ZOOM_CONTROL_MENU_WHEEL_PLUSMINUS
Definition ZoomControl.h:14
@ ZOOM_CONTROL_MENU_WHEEL
Definition ZoomControl.h:12
@ ZOOM_CONTROL_MENU_ONLY
Definition ZoomControl.h:11
const ZoomFactorInitial DEFAULT_ZOOM_FACTOR_INITIAL
ZoomFactorInitial
@ ZOOM_INITIAL_PREVIOUS
ZoomFactor
Zoom factors ordered by zoom level so next one above/below is the next zoom level.
Definition ZoomFactor.h:11
@ NUMBER_ZOOM_FACTORS
Definition ZoomFactor.h:38
@ ZOOM_FILL
Definition ZoomFactor.h:37
@ ZOOM_1_TO_1
Definition ZoomFactor.h:24
void setPixmap(bool isGnuplot, const Transformation &transformation, const DocumentModelGridRemoval &modelGridRemoval, const DocumentModelColorFilter &modelColorFilter, const QPixmap &pixmapOriginal, const QString &curveSelected)
Update the images of all states, rather than just the current state.
void setBackgroundImage(BackgroundImage backgroundImage)
Transition to the specified state. This method is used by classes outside of the state machine to tri...
QImage imageForCurveState() const
Image for the Curve state, even if the current state is different.
void fitInView(GraphicsView &view)
Zoom so background fills the window.
void updateColorFilter(bool isGnuplot, const Transformation &transformation, const DocumentModelGridRemoval &modelGridRemoval, const DocumentModelColorFilter &colorFilter, const QString &curveSelected)
Apply color filter settings.
void close()
Open Document is being closed so remove the background.
void setCurveSelected(bool isGnuplot, const Transformation &transformation, const DocumentModelGridRemoval &modelGridRemoval, const DocumentModelColorFilter &modelColorFilter, const QString &curveSelected)
Update the selected curve.
Wizard for setting up the checklist guide.
bool browserIsEmpty() const
When browser is empty, it is pointless to show it.
void setTemplateHtml(const QString &html, const QStringList &curveNames)
Populate the browser with template html.
void update(const CmdMediator &cmdMediator, bool documentIsExported)
Update using current CmdMediator/Document state.
Command for adding one or more graph points. This is for Segment Fill mode.
Command for moving all selected Points by a specified translation.
Definition CmdCopy.h:19
Command for cutting all selected Points.
Definition CmdCut.h:19
Command for deleting all selected Points.
Definition CmdDelete.h:19
Command queue stack.
Definition CmdMediator.h:24
QString selectedCurveName() const
Currently selected curve name. This is used to set the selected curve combobox in MainWindow.
QString reasonForUnsuccessfulRead() const
See Document::reasonForUnsuccessfulRead.
QPixmap pixmap() const
See Document::pixmap.
bool isModified() const
Dirty flag.
void saveXml(QXmlStreamWriter &writer) const
Serialize to xml.
void setSelectedCurveName(const QString &selectedCurveName)
Save curve name that is selected for the current coordinate system, for the next time the coordinate ...
QStringList curvesGraphsNames() const
See CurvesGraphs::curvesGraphsNames.
bool successfulRead() const
Wrapper for Document::successfulRead.
void setDocumentAxesPointsRequired(DocumentAxesPointsRequired documentAxesPointsRequired)
Set the number of axes points required.
Document & document()
Provide the Document to commands, primarily for undo/redo processing.
Command for changing the currently selected CoordSystem.
bool canRedo() const
Return true if there is a command available.
void slotRedo()
Move next command from list to CmdMediator. Noop if there are no more commands.
void loadCommands(MainWindow &mainWindow, Document &document, QXmlStreamReader &reader)
Load commands from serialized xml.
Color filter parameters for one curve. For a class, this is handled the same as LineStyle and PointSt...
Facade class that wraps around all of the create classes for MainWindow.
void create(MainWindow &mw)
Create QAction facade.
PointStyle pointStyle() const
Get method for PointStyle.
Model for DlgSettingsCurveProperties and CmdSettingsCurveProperties.
Definition CurveStyles.h:23
CurveStyle curveStyle(const QString &curveName) const
CurveStyle in specified curve.
Container for all graph curves. The axes point curve is external to this class.
void resetOnLoad(CmdMediator *cmdMediator)
Resetting makes re-initializes for documents after the first.
void handleMouseRelease(CmdMediator *cmdMediator, QPointF pos)
See DigitizeStateAbstractBase::handleMouseRelease.
bool canPaste(const Transformation &transformation, const QSize &viewSize) const
Return true if there is good data in the clipboard for pasting, and that operation is compatible with...
void handleMouseMove(CmdMediator *cmdMediator, QPointF pos)
See DigitizeStateAbstractBase::handleMouseMove.
void requestImmediateStateTransition(CmdMediator *cmdMediator, DigitizeState digitizeState)
Perform immediate state transition. Called from outside state machine.
void updateModelDigitizeCurve(CmdMediator *cmdMediator, const DocumentModelDigitizeCurve &modelDigitizeCurve)
Update the digitize curve settings.
void handleContextMenuEventGraph(CmdMediator *cmdMediator, const QStringList &pointIdentifiers)
See DigitizeStateAbstractBase::handleContextMenuEventGraph.
void handleMousePress(CmdMediator *cmdMediator, QPointF pos)
See DigitizeStateAbstractBase::handleMousePress.
void appendNewCmd(CmdMediator *cmdMediator, QUndoCommand *cmd)
Append just-created QUndoCommand to command stack. This is called from DigitizeStateAbstractBase subc...
void setImageIsLoaded(CmdMediator *cmdMediator, bool imageIsLoaded)
Set the image so QGraphicsView cursor and drag mode are accessible.
QString activeCurve() const
Curve name for active Curve. This can include AXIS_CURVE_NAME, and empty string.
void handleKeyPress(CmdMediator *cmdMediator, Qt::Key key, bool atLeastOneSelectedItem)
See DigitizeStateAbstractBase::handleKeyPress.
void updateModelSegments(const DocumentModelSegments &modelSegments)
Update the segments given the new settings.
void updateAfterPointAddition()
Update the graphics attributes.
void handleCurveChange(CmdMediator *cmdMediator)
See DigitizeStateAbstractBase::handleCurveChange.
void handleContextMenuEventAxis(CmdMediator *cmdMediator, const QString &pointIdentifier)
See DigitizeStateAbstractBase::handleContextMenuEventAxis.
About Engauge dialog. This provides a hidden shortcut for triggering ENGAUGE_ASSERT.
Definition DlgAbout.h:16
Dialog for saving error report for later transmission to the developers.
Dialog for setting the advanced parameters in a newly imported Document.
Dialog to be displayed whenever some operation or processing cannot be performed since the axis point...
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
virtual void setSmallDialogs(bool smallDialogs)
If false then dialogs have a minimum size so all controls are visible.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
virtual void setSmallDialogs(bool smallDialogs)
If false then dialogs have a minimum size so all controls are visible.
virtual void setSmallDialogs(bool smallDialogs)
If false then dialogs have a minimum size so all controls are visible.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
void load(CmdMediator &cmdMediator)
Load settings from Document.
virtual void setSmallDialogs(bool smallDialogs)
If false then dialogs have a minimum size so all controls are visible.
virtual void setSmallDialogs(bool smallDialogs)
If false then dialogs have a minimum size so all controls are visible.
void setCurveName(const QString &curveName)
Load information for the specified curve name. When called externally, the load method must have been...
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
virtual void setSmallDialogs(bool smallDialogs)
If false then dialogs have a minimum size so all controls are visible.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
virtual void setSmallDialogs(bool smallDialogs)
If false then dialogs have a minimum size so all controls are visible.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
virtual void setSmallDialogs(bool smallDialogs)
If false then dialogs have a minimum size so all controls are visible.
virtual void setSmallDialogs(bool smallDialogs)
If false then dialogs have a minimum size so all controls are visible.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
virtual void setSmallDialogs(bool smallDialogs)
If false then dialogs have a minimum size so all controls are visible.
void loadMainWindowModel(CmdMediator &cmdMediator, const MainWindowModel &modelMainWindow)
Replaced load method since the main window settings are independent of document, unlike other DlgSett...
virtual void setSmallDialogs(bool smallDialogs)
If false then dialogs have a minimum size so all controls are visible.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
virtual void setSmallDialogs(bool smallDialogs)
If false then dialogs have a minimum size so all controls are visible.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
virtual void setSmallDialogs(bool smallDialogs)
If false then dialogs have a minimum size so all controls are visible.
Model for DlgSettingsAxesChecker and CmdSettingsAxesChecker.
Model for DlgSettingsColorFilter and CmdSettingsColorFilter.
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...
Model for DlgSettingsCoords and CmdSettingsCoords.
Model for DlgSettingsDigitizeCurve and CmdSettingsDigitizeCurve.
Model for DlgSettingsExportFormat and CmdSettingsExportFormat.
void setDelimiter(ExportDelimiter exportDelimiter)
Set method for delimiter.
Model for DlgSettingsGeneral and CmdSettingsGeneral.
Model for DlgSettingsGridDisplay and CmdSettingsGridDisplay.
Model for DlgSettingsGridRemoval and CmdSettingsGridRemoval. The settings are unstable until the user...
Model for DlgSettingsPointMatch and CmdSettingsPointMatch.
Model for DlgSettingsSegments and CmdSettingsSegments.
Check Document state.
void check(MainWindow &mainWindow, const Document &document) const
Check document state.
unsigned int coordSystemCount() const
Number of CoordSystem.
Definition Document.cpp:307
void setModelGridRemoval(const DocumentModelGridRemoval &modelGridRemoval)
Set method for DocumentModelGridRemoval.
void setCoordSystemIndex(CoordSystemIndex coordSystemIndex)
Set the index of current active CoordSystem.
Definition Document.cpp:918
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:842
CoordSystemIndex coordSystemIndex() const
Index of current active CoordSystem.
Definition Document.cpp:314
QStringList curvesGraphsNames() const
See CurvesGraphs::curvesGraphsNames.
Definition Document.cpp:349
void setModelPointMatch(const DocumentModelPointMatch &modelPointMatch)
Set method for DocumentModelPointMatch.
void setModelCurveStyles(const CurveStyles &modelCurveStyles)
Set method for CurveStyles.
Definition Document.cpp:983
void setModelGridDisplay(const DocumentModelGridDisplay &modelGridDisplay)
Set method for DocumentModelGridDisplay.
void addCoordSystems(unsigned int numberCoordSystemToAdd)
Add some number (0 or more) of additional coordinate systems.
Definition Document.cpp:150
void setModelColorFilter(const DocumentModelColorFilter &modelColorFilter)
Set method for DocumentModelColorFilter.
Definition Document.cpp:958
void setModelDigitizeCurve(const DocumentModelDigitizeCurve &modelDigitizeCurve)
Set method for DocumentModelDigitizeCurve.
void saveXml(QXmlStreamWriter &writer) const
Save document to xml.
Definition Document.cpp:884
DocumentModelAxesChecker modelAxesChecker() const
Get method for DocumentModelAxesChecker.
Definition Document.cpp:681
DocumentModelCoords modelCoords() const
Get method for DocumentModelCoords.
Definition Document.cpp:695
DocumentModelColorFilter modelColorFilter() const
Get method for DocumentModelColorFilter.
Definition Document.cpp:688
void setCurvesGraphs(const CurvesGraphs &curvesGraphs)
Let CmdAbstract classes overwrite CurvesGraphs.
Definition Document.cpp:932
CurveStyles modelCurveStyles() const
Get method for CurveStyles.
Definition Document.cpp:702
void setModelCoords(const DocumentModelCoords &modelCoords)
Set method for DocumentModelCoords.
Definition Document.cpp:976
void setModelAxesChecker(const DocumentModelAxesChecker &modelAxesChecker)
Set method for DocumentModelAxesChecker.
Definition Document.cpp:951
DocumentAxesPointsRequired documentAxesPointsRequired() const
Get method for DocumentAxesPointsRequired.
Definition Document.cpp:363
void setModelSegments(const DocumentModelSegments &modelSegments)
Set method for DocumentModelSegments.
void setModelGeneral(const DocumentModelGeneral &modelGeneral)
Set method for DocumentModelGeneral.
void setModelExport(const DocumentModelExportFormat &modelExport)
Set method for DocumentModelExportFormat.
DocumentModelGridRemoval modelGridRemoval() const
Get method for DocumentModelGridRemoval.
Definition Document.cpp:737
DocumentModelGridDisplay modelGridDisplay() const
Get method for DocumentModelGridDisplay.
Definition Document.cpp:730
DocumentModelExportFormat modelExport() const
Get method for DocumentModelExportFormat.
Definition Document.cpp:716
void setPixmap(const QImage &image)
Set method for the background pixmap.
Class for exporting during regression, when the Transformation has not yet been defined.
Strategy class for exporting to a file. This strategy is external to the Document class so that class...
File that manages a command stack for regression testing of file import/open/export/close.
bool canRedo() const
Returns true if there is at least one command on the stack.
void redo(MainWindow &mainWindow)
Apply the next command. Requires non-empty stack.
Curve that overlays the current scene so the regression-fitted curve is visible.
virtual void clear()
Clear stale information.
virtual void doCopy()
Copy the current selection to the clipboard.
virtual void update(const CmdMediator &cmdMediator, const MainWindowModel &modelMainWindow, const QString &curveSelected, const Transformation &transformation)
Populate the table with the specified Curve.
virtual void update(const CmdMediator &cmdMediator, const MainWindowModel &modelMainWindow, const QString &curveSelected, const Transformation &transformation)
Populate the table with the specified Curve.
virtual void clear()
Clear stale information.
virtual void doCopy()
Copy the current selection to the clipboard.
Class for showing points and lines for all coordinate systems simultaneously, even though the code no...
Definition Ghosts.h:27
unsigned int coordSystemIndexToBeRestored() const
Coordinate system index that was active before the ghosts.
Definition Ghosts.cpp:73
void createGhosts(QGraphicsScene &scene)
Create ghosts from the path/rect/polygon lists.
Definition Ghosts.cpp:78
void captureGraphicsItems(QGraphicsScene &scene)
Take a snapshot of the graphics items.
Definition Ghosts.cpp:26
void destroyGhosts(QGraphicsScene &scene)
Destory ghosts. Called at end of algorithm.
Definition Ghosts.cpp:119
This class consolidates utility routines that deal with graphics items that are getting extracted fro...
Add point and line handling to generic QGraphicsScene.
void updateGraphicsLinesToMatchGraphicsPoints(const CurveStyles &modelCurveStyles, const Transformation &transformation)
A mouse move has just occurred so move the selected points, since they were dragged.
void resetOnLoad()
Reset, when loading a document after the first, to same state that first document was at when loaded.
void updateAfterCommand(CmdMediator &cmdMediator, double highlightOpacity, GeometryWindow *geometryWindow, const Transformation &transformation)
Update the Points and their Curves after executing a command.
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);.
void resetPositionHasChangedFlags()
Reset positionHasChanged flag for all items. Typically this is done as part of mousePressEvent.
void printStream(QString indentation, QTextStream &str)
Debugging method that supports print method of this class and printStream method of some other class(...
void updateCurveStyles(const CurveStyles &modelCurveStyles)
Update curve styles after settings changed.
QGraphicsView class with event handling added. Typically the events are sent to the active digitizing...
Factory class for generating the points, composed of QGraphicsItem objects, along a GridLine.
void setVisible(bool visible)
Make all grid lines visible or hidden.
Definition GridLines.cpp:41
void clear()
Deallocate and remove all grid lines.
Definition GridLines.cpp:24
Provides list of file extensions for import.
QStringList fileExtensionsWithAsterisks() const
File extensions for use in file dialogs.
Wrapper around OpenJPEG library, in C, for opening jpeg2000 files.
Definition Jpeg2000.h:27
bool load(const QString &filename, QImage &image) const
Load image from jpeg2000 file.
Definition Jpeg2000.cpp:192
Returns information about files.
void startLoadImage(const QUrl &url)
Start the asynchronous loading of an image from the specified url.
static void bindToMainWindow(MainWindow *mainWindow)
Bind to MainWindow so this class can access the command stack.
Persist the directory between successive Import/Open operations, or successive Export/Save operations...
void setDirectoryExportSaveFromSavedPath(const QString &path)
Set the current Export/Save directory at startup to path from previous execution.
void setDirectoryExportSaveFromFilename(const QString &fileName)
Save the current Export/Save directory, after user has accepted the Export/Save dialog.
Model for DlgSettingsMainWindow.
void setSmallDialogs(bool smallDialogs)
Set method for small dialogs flag.
QLocale locale() const
Get method for locale.
void setImageReplaceRenamesDocument(bool imageReplaceRenamesDocument)
Set method for image replace renames document.
bool dragDropExport() const
Get method for drag and drop export.
bool imageReplaceRenamesDocument() const
Get method for image replaces renames document.
ZoomFactorInitial zoomFactorInitial() const
Get method for initial zoom factor.
void setImportCropping(ImportCropping importCropping)
Set method for import cropping.
ImportCropping importCropping() const
Get method for import cropping.
bool smallDialogs() const
Get method for small dialogs flag.
void setMainTitleBarFormat(MainTitleBarFormat mainTitleBarFormat)
Set method for MainWindow titlebar filename format.
void setDragDropExport(bool dragDropExport)
Set method for drag and drop export.
double highlightOpacity() const
Get method for highlight opacity.
void setZoomControl(ZoomControl zoomControl)
Set method for zoom control.
void setMaximumGridLines(int maximumGridLines)
Set method for maximum number of grid lines.
ZoomControl zoomControl() const
Get method for zoom control.
void setPdfResolution(int resolution)
Set method for resolution of imported PDF files, in dots per inch.
int maximumGridLines() const
Maximum number of grid lines.
void setZoomFactorInitial(ZoomFactorInitial zoomFactorInitial)
Set method for initial zoom factor.
MainTitleBarFormat mainTitleBarFormat() const
Get method for MainWindow titlebar filename format.
void setHighlightOpacity(double highlightOpacity)
Set method for highlight opacity.
void setLocale(QLocale::Language language, QLocale::Country country)
Set method for locale given attributes.
int pdfResolution() const
Get method for resolution of imported PDF files, in dots per inch.
void setSignificantDigits(int significantDigits)
Set method for significant digits.
void saveErrorReportFileAndExit(const char *comment, const char *file, int line, const char *context)
Save error report and exit.
void updateSettingsGridRemoval(const DocumentModelGridRemoval &modelGridRemoval)
Update with new grid removal properties.
void showTemporaryMessage(const QString &temporaryMessage)
Show temporary message in status bar.
CmdMediator * cmdMediator()
Accessor for commands to process the Document.
void updateSettingsGridDisplay(const DocumentModelGridDisplay &modelGridDisplay)
Update with new grid display properties.
virtual bool eventFilter(QObject *, QEvent *)
Catch secret keypresses.
void updateSettingsAxesChecker(const DocumentModelAxesChecker &modelAxesChecker)
Update with new axes indicator properties.
virtual void showEvent(QShowEvent *)
Processing performed after gui becomes available.
void updateSettingsDigitizeCurve(const DocumentModelDigitizeCurve &modelDigitizeCurve)
Update with new curve digitization styles.
bool isGnuplot() const
Get method for gnuplot flag.
void updateSettingsCurveStyles(const CurveStyles &modelCurveStyles)
Update with new curve styles.
bool transformIsDefined() const
Return true if all three axis points have been defined.
MainWindowModel modelMainWindow() const
Get method for main window model.
void cmdFileOpen(const QString &fileName)
Open file. This is called from a file script command.
void updateSettingsCurveList(const CurvesGraphs &curvesGraphs)
Update with new curves.
void updateAfterCommand()
See GraphicsScene::updateAfterCommand.
void updateSettingsExportFormat(const DocumentModelExportFormat &modelExport)
Update with new export properties.
void updateSettingsSegments(const DocumentModelSegments &modelSegments)
Update with new segments properties.
BackgroundImage selectOriginal(BackgroundImage backgroundImage)
Make original background visible, for DigitizeStateColorPicker.
void cmdFileExport(const QString &fileName)
Export file. This is called from a file script command.
void updateViewsOfSettings(const QString &activeCurve)
Update curve-specific view of settings. Private version gets active curve name from DigitizeStateCont...
void updateSettingsMainWindow(const MainWindowModel &modelMainWindow)
Update with new main window properties.
void cmdFileClose()
Close file. This is called from a file script command.
void updateDigitizeStateIfSoftwareTriggered(DigitizeState digitizeState)
After software-triggered state transition, this method manually triggers the action as if user had cl...
bool modeMap() const
True if document scale is set using a scale bar, otherwise using axis points.
void signalDropRegression(QString)
Send drag and drop regression test url.
void updateSettingsGeneral(const DocumentModelGeneral &modelGeneral)
Update with new general properties.
void signalZoom(int)
Send zoom selection, picked from menu or keystroke, to StatusBar.
void updateSettingsPointMatch(const DocumentModelPointMatch &modelPointMatch)
Update with new point match properties.
MainWindow(const QString &errorReportFile, const QString &fileCmdScriptFile, bool isDropRegression, bool isRegressionTest, bool isGnuplot, bool isReset, bool isExportOnly, bool isExtractImageOnly, const QString &extractImageOnlyExtension, const QStringList &loadStartupFiles, const QStringList &commandLineWithoutLoadStartupFiles, QWidget *parent=nullptr)
Single constructor.
void cmdFileImport(const QString &fileName)
Import file. This is called from a file script command.
void updateGraphicsLinesToMatchGraphicsPoints()
Update the graphics lines so they follow the graphics points, after a drag, addition,...
QImage imageFiltered() const
Background image that has been filtered for the current curve. This asserts if a curve-specific image...
QString selectedGraphCurve() const
Curve name that is currently selected in m_cmbCurve.
GraphicsScene & scene()
Scene container for the QImage and QGraphicsItems.
void updateAfterMouseRelease()
Call MainWindow::updateControls (which is private) after the very specific case - a mouse press/relea...
void resizeEvent(QResizeEvent *event)
Intercept resize event so graphics scene can be appropriately resized when in Fill mode.
Transformation transformation() const
Return read-only copy of transformation.
void updateSettingsColorFilter(const DocumentModelColorFilter &modelColorFilter)
Update with new color filter properties.
void updateCoordSystem(CoordSystemIndex coordSystemIndex)
Select a different CoordSystem.
void updateSettingsCoords(const DocumentModelCoords &modelCoords)
Update with new coordinate properties.
GraphicsView & view()
View for the QImage and QGraphicsItems, without const.
Import of point data from clipboard.
void retrievePoints(const Transformation &transformation, QList< QPoint > &points, QList< double > &ordinals) const
Retrieve points from clipboard.
Wrapper around the QImage class for read and importing non-PDF files.
Definition NonPdf.h:27
NonPdfReturn load(const QString &fileName, QImage &image, ImportCropping importCropping, bool isErrorReportRegressionTest) const
Try to load the specified file. Success is indicated in the function return value.
Definition NonPdf.cpp:18
Wrapper around the Poppler library.
Definition Pdf.h:29
PdfReturn load(const QString &fileName, QImage &image, int resolution, ImportCropping importCropping, bool isErrorReportRegressionTest) const
Try to load the specified file. Success is indicated in the function return value.
Definition Pdf.cpp:25
Details for a specific Point.
Definition PointStyle.h:21
static void setIdentifierIndex(unsigned int identifierIndex)
Reset the current index while performing a Redo.
Definition Point.cpp:478
Given a set of point identifiers, if a map is in effect (with its two axis endpoints) then both axis ...
void wakeUp()
Enable all widgets in the status bar. This is called just after a Document becomes active.
void setStatusBarMode(StatusBarMode statusBarMode)
Set the status bar visibility mode.
StatusBarMode statusBarMode() const
Current mode for status bar visibility. This is tracked locally so this class knows when to hide/show...
Definition StatusBar.h:45
void showTemporaryMessage(const QString &message)
Show temporary message in status bar. After a short interval the message will disappear.
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...
void triggerStateTransition(bool isGnuplot, TransformationState transformationState, CmdMediator &cmdMediator, const Transformation &transformation, const QString &selectedGraphCurve)
Trigger a state transition to be performed immediately.
void resetOnLoad()
Reset, when loading a document after the first, to same state that first document was at when loaded.
void updateAxesChecker(CmdMediator &cmdMediator, const Transformation &transformation)
Apply the new DocumentModelAxesChecker.
Affine transformation between screen and graph coordinates, based on digitized axis points.
void coordTextForStatusBar(QPointF cursorScreen, QString &coordsScreen, QString &coordsGraph, QString &resolutionGraph, bool usingScaleBar)
Return string descriptions of cursor coordinates for status bar.
void resetOnLoad()
Reset, when loading a document after the first, to same state that first document was at when loaded.
bool transformIsDefined() const
Transform is defined when at least three axis points have been digitized.
void update(bool fileIsLoaded, const CmdMediator &cmdMediator, const MainWindowModel &modelMainWindow)
Update transform by iterating through the axis points.
void unsetPointStyle()
Apply no PointStyle.
void setPointStyle(const PointStyle &pointStyle)
Apply the PointStyle of the currently selected curve.
void setEnabled(bool enabled)
Show the style with semi-transparency or full-transparency to indicate if associated Curve is active ...
void unsetColorFilterSettings()
Apply no color filter.
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 setEnabled(bool enabled)
Show the style with semi-transparency or full-transparency to indicate if associated Curve is active ...
void getTableStatus(bool &tableIsActive, bool &tableIsCopyable) const
Give table status so MainWindow can determine if table can be copied.
Perform calculations to determine the next zoom setting given the current zoom setting,...
double mapToFactor(ZoomFactor zoomFactor) const
Return the floating precision zoom factor given the enum value.
ZoomFactor zoomOut(ZoomFactor currentZoomFactor, double m11, double m22, bool actionZoomFillIsChecked) const
Zoom out.
ZoomFactor zoomIn(ZoomFactor currentZoomFactor, double m11, double m22, bool actionZoomFillIsChecked) const
Zoom in.
Priority::Value getPriority() const
Returns unused priority.
Definition Category.cpp:19
#define LOG4CPP_INFO_S(logger)
Definition convenience.h:18
#define LOG4CPP_DEBUG_S(logger)
Definition convenience.h:20
#define LOG4CPP_ERROR_S(logger)
Definition convenience.h:12