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