Engauge Digitizer  2
main.cpp
1 /******************************************************************************************************
2  * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
3  * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
4  * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
5  ******************************************************************************************************/
6 
7 #include "ColorFilterMode.h"
8 #include "FittingCurveCoefficients.h"
9 #include <iostream>
10 #include "Logger.h"
11 #include "MainWindow.h"
12 #include <QApplication>
13 #include <QCoreApplication>
14 #include <QDebug>
15 #include <QDir>
16 #include <QFileInfo>
17 #include <QObject>
18 #include <QProcessEnvironment>
19 #include <QStyleFactory>
20 #include "TranslatorContainer.h"
21 #include "ZoomFactor.h"
22 
23 using namespace std;
24 
25 const QString CMD_DEBUG ("debug");
26 const QString CMD_ERROR_REPORT ("errorreport");
27 const QString CMD_FILE_CMD_SCRIPT ("filecmdscript");
28 const QString CMD_GNUPLOT ("gnuplot");
29 const QString CMD_HELP ("help");
30 const QString CMD_REGRESSION ("regression");
31 const QString CMD_RESET ("reset");
32 const QString CMD_STYLES ("styles"); // Not to be confused with -style option that qt handles
33 const QString DASH ("-");
34 const QString DASH_DEBUG ("-" + CMD_DEBUG);
35 const QString DASH_ERROR_REPORT ("-" + CMD_ERROR_REPORT);
36 const QString DASH_FILE_CMD_SCRIPT ("-" + CMD_FILE_CMD_SCRIPT);
37 const QString DASH_GNUPLOT ("-" + CMD_GNUPLOT);
38 const QString DASH_HELP ("-" + CMD_HELP);
39 const QString DASH_REGRESSION ("-" + CMD_REGRESSION);
40 const QString DASH_RESET ("-" + CMD_RESET);
41 const QString DASH_STYLES ("-" + CMD_STYLES);
42 const QString ENGAUGE_LOG_FILE (".engauge.log");
43 
44 // Prototypes
45 bool checkFileExists (const QString &file);
46 QString engaugeLogFilename ();
47 bool engaugeLogFilenameAttempt (const QString &path,
48  QString &pathAndFile);
49 void parseCmdLine (int argc,
50  char **argv,
51  bool &isDebug,
52  bool &isReset,
53  QString &errorReportFile,
54  QString &fileCmdScriptFile,
55  bool &isErrorReportRegressionTest,
56  bool &isGnuplot,
57  QStringList &loadStartupFiles);
58 void showStylesAndExit ();
59 
60 // Functions
61 bool checkFileExists (const QString &file)
62 {
63  QFileInfo check (file);
64  return check.exists() && check.isFile();
65 }
66 
67 QString engaugeLogFilename()
68 {
69  QString pathAndFile; // Return empty value in OSX which is unused
70 
71 #if !defined(OSX_RELEASE) && !defined(WIN_RELEASE) && !defined(APPIMAGE_RELEASE)
72  QProcessEnvironment env;
73 
74  // Make multiple attempts until a directory is found where the log file can be written
75  if (!engaugeLogFilenameAttempt (QCoreApplication::applicationDirPath(), pathAndFile)) {
76  if (!engaugeLogFilenameAttempt (env.value ("HOME"), pathAndFile)) {
77  if (!engaugeLogFilenameAttempt (env.value ("TEMP"), pathAndFile)) {
78  pathAndFile = ENGAUGE_LOG_FILE; // Current directory will have to do
79  }
80  }
81  }
82 #endif
83 
84  return pathAndFile;
85 }
86 
87 bool engaugeLogFilenameAttempt (const QString &path,
88  QString &pathAndFile)
89 {
90  bool success = false;
91 
92  // Test if file can be opened. Checking permissions on directory is unreliable in Windows/OSX
93  pathAndFile = QString ("%1%2%3")
94  .arg (path)
95  .arg (QDir::separator())
96  .arg (ENGAUGE_LOG_FILE);
97  QFile file (pathAndFile);
98  if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
99  // Success
100  file.close();
101  file.remove(); // Cleanup
102  success = true;
103  }
104 
105  return success;
106 }
107 
108 int main(int argc, char *argv[])
109 {
110  qRegisterMetaType<ColorFilterMode> ("ColorFilterMode");
111  qRegisterMetaType<FittingCurveCoefficients> ("FilterCurveCoefficients");
112  qRegisterMetaType<ZoomFactor> ("ZoomFactor");
113 
114  QApplication app(argc, argv);
115 
116  // Translations
117  TranslatorContainer translatorContainer (app); // Must exist until execution terminates
118 
119  // Command line
120  bool isDebug, isReset, isGnuplot, isErrorReportRegressionTest;
121  QString errorReportFile, fileCmdScriptFile;
122  QStringList loadStartupFiles;
123  parseCmdLine (argc,
124  argv,
125  isDebug,
126  isReset,
127  errorReportFile,
128  fileCmdScriptFile,
129  isErrorReportRegressionTest,
130  isGnuplot,
131  loadStartupFiles);
132 
133  // Logging
134  initializeLogging ("engauge",
135  engaugeLogFilename(),
136  isDebug);
137  LOG4CPP_INFO_S ((*mainCat)) << "main args=" << QApplication::arguments().join (" ").toLatin1().data();
138 
139  // Create and show main window
140  MainWindow w (errorReportFile,
141  fileCmdScriptFile,
142  isErrorReportRegressionTest,
143  isGnuplot,
144  isReset,
145  loadStartupFiles);
146  w.show();
147 
148  // Event loop
149  return app.exec();
150 }
151 
152 void parseCmdLine (int argc,
153  char **argv,
154  bool &isDebug,
155  bool &isReset,
156  QString &errorReportFile,
157  QString &fileCmdScriptFile,
158  bool &isErrorReportRegressionTest,
159  bool &isGnuplot,
160  QStringList &loadStartupFiles)
161 {
162  const int COLUMN_WIDTH = 20;
163  bool showUsage = false;
164 
165  // State
166  bool nextIsErrorReportFile = false;
167  bool nextIsFileCmdScript = false;
168 
169  // Defaults
170  isDebug = false;
171  isReset = false;
172  errorReportFile = "";
173  fileCmdScriptFile = "";
174  isErrorReportRegressionTest = false;
175  isGnuplot = false;
176 
177  for (int i = 1; i < argc; i++) {
178 
179  if (nextIsErrorReportFile) {
180  errorReportFile = argv [i];
181  showUsage |= !checkFileExists (errorReportFile);
182  nextIsErrorReportFile = false;
183  } else if (nextIsFileCmdScript) {
184  fileCmdScriptFile = argv [i];
185  showUsage |= !checkFileExists (fileCmdScriptFile);
186  nextIsFileCmdScript = false;
187  } else if (strcmp (argv [i], DASH_DEBUG.toLatin1().data()) == 0) {
188  isDebug = true;
189  } else if (strcmp (argv [i], DASH_ERROR_REPORT.toLatin1().data()) == 0) {
190  nextIsErrorReportFile = true;
191  } else if (strcmp (argv [i], DASH_FILE_CMD_SCRIPT.toLatin1().data()) == 0) {
192  nextIsFileCmdScript = true;
193  } else if (strcmp (argv [i], DASH_GNUPLOT.toLatin1().data()) == 0) {
194  isGnuplot = true;
195  } else if (strcmp (argv [i], DASH_HELP.toLatin1().data()) == 0) {
196  showUsage = true; // User requested help
197  } else if (strcmp (argv [i], DASH_REGRESSION.toLatin1().data()) == 0) {
198  isErrorReportRegressionTest = true;
199  } else if (strcmp (argv [i], DASH_RESET.toLatin1().data()) == 0) {
200  isReset = true;
201  } else if (strcmp (argv [i], DASH_STYLES.toLatin1().data()) == 0) {
202  showStylesAndExit ();
203  } else if (strncmp (argv [i], DASH.toLatin1().data(), 1) == 0) {
204  showUsage = true; // User entered an unrecognized token
205  } else {
206  // MainWindow will change current directory (which is often some obscure application directory),
207  // so relative paths must be changed in advance to absolute so the files can still be found
208  QString fileName = argv [i];
209  QFileInfo fInfo (fileName);
210  if (fInfo.isRelative()) {
211  fileName = fInfo.absoluteFilePath();
212  }
213  loadStartupFiles << fileName; // Save file name
214  }
215  }
216 
217  if (showUsage || nextIsErrorReportFile) {
218 
219  cerr << "Usage: engauge "
220  << "[" << DASH_DEBUG.toLatin1().data() << "] "
221  << "[" << DASH_ERROR_REPORT.toLatin1().data() << " <file>] "
222  << "[" << DASH_FILE_CMD_SCRIPT.toLatin1().data() << " <file> "
223  << "[" << DASH_GNUPLOT.toLatin1().data() << "] "
224  << "[" << DASH_HELP.toLatin1().data() << "] "
225  << "[" << DASH_REGRESSION.toLatin1().data() << "] "
226  << "[" << DASH_RESET.toLatin1().data () << "] "
227  << "[" << DASH_STYLES.toLatin1().data () << "] "
228  << "[<load_file1>] [<load_file2>] ..." << endl
229  << " " << DASH_DEBUG.leftJustified(COLUMN_WIDTH, ' ').toLatin1().data()
230  << QObject::tr ("Enables extra debug information. Used for debugging").toLatin1().data() << endl
231  << " " << DASH_ERROR_REPORT.leftJustified(COLUMN_WIDTH, ' ').toLatin1().data()
232  << QObject::tr ("Specifies an error report file as input. Used for debugging and testing").toLatin1().data() << endl
233  << " " << DASH_FILE_CMD_SCRIPT.leftJustified(COLUMN_WIDTH, ' ').toLatin1().data()
234  << QObject::tr ("Specifies a file command script file as input. Used for debugging and testing").toLatin1().data() << endl
235  << " " << DASH_GNUPLOT.leftJustified(COLUMN_WIDTH, ' ').toLatin1().data()
236  << QObject::tr ("Output diagnostic gnuplot input files. Used for debugging").toLatin1().data() << endl
237  << " " << DASH_HELP.leftJustified(COLUMN_WIDTH, ' ').toLatin1().data()
238  << QObject::tr ("Show this help information").toLatin1().data() << endl
239  << " " << DASH_REGRESSION.leftJustified(COLUMN_WIDTH, ' ').toLatin1().data()
240  << QObject::tr ("Executes the error report file or file command script. Used for regression testing").toLatin1().data() << endl
241  << " " << DASH_RESET.leftJustified(COLUMN_WIDTH, ' ').toLatin1().data()
242  << QObject::tr ("Removes all stored settings, including window positions. Used when windows start up offscreen").toLatin1().data() << endl
243  << " " << DASH_STYLES.leftJustified(COLUMN_WIDTH, ' ').toLatin1().data()
244  << QObject::tr ("Show a list of available styles that can be used with the -style command").toLatin1().data() << endl
245  << " " << QString ("<load file> ").leftJustified(COLUMN_WIDTH, ' ').toLatin1().data()
246  << QObject::tr ("File(s) to be imported or opened at startup").toLatin1().data() << endl;
247 
248  exit (0);
249  }
250 }
251 
252 void showStylesAndExit ()
253 {
254  cout << "Available styles: " << QStyleFactory::keys ().join (", ").toLatin1().data() << endl;
255  exit (0);
256 }
Class that stores QTranslator objects for the duration of application execution.
Main window consisting of menu, graphics scene, status bar and optional toolbars as a Single Document...
Definition: MainWindow.h:89