]> vaikene.ee Git - evaf/blob - src/main/CLI/main.cpp
Warning fixes and copyright update.
[evaf] / src / main / CLI / main.cpp
1 /**
2 * @file main/CLI/main.cpp
3 * @brief The main eVaf CLI application class
4 *
5 * Copyright (c) 2011-2019 Enar Vaikene
6 *
7 * This file is part of the eVaf C++ cross-platform application development framework.
8 *
9 * This file can be used under the terms of the GNU General Public License
10 * version 3.0 as published by the Free Software Foundation and appearing in
11 * the file LICENSE included in the packaging of this file. Please review the
12 * the following information to ensure the GNU General Public License version
13 * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
14 *
15 * Alternatively, this file may be used in accordance with the Commercial License
16 * Agreement provided with the Software.
17 */
18
19 #include "main.h"
20 #include "exithandler.h"
21 //#include "version_p.h"
22 #include "version.h"
23
24 #include <Common/Globals>
25 #include <Common/iLogger>
26 #include <Common/iApp>
27
28 #include <Plugins/PluginManager>
29
30 #include <QtCore>
31
32 #ifdef Q_OS_LINUX
33 # include <sys/types.h>
34 # include <unistd.h>
35 #endif
36
37 using namespace eVaf;
38
39 //-------------------------------------------------------------------
40
41 namespace eVaf {
42 namespace CLI {
43 namespace Internal {
44
45 /**
46 * Qt message handler replacement.
47 * @param type Type of the message
48 * @param msg The message
49 *
50 * This function outputs messages to the console and to the log file.
51 */
52 static void messageOutput(QtMsgType type, QMessageLogContext const &, QString const & msg)
53 {
54 static bool inHandler = false;
55
56 // Avoid recursions in case outputting a message causes another message to be output
57 if (inHandler)
58 return;
59 inHandler = true;
60
61 // Qt message type conversion to eVaf logger severity levels
62 Common::iLogger::Severity v;
63 switch (type) {
64 case QtWarningMsg:
65 v = Common::iLogger::Warning;
66 break;
67 case QtCriticalMsg:
68 v = Common::iLogger::Error;
69 break;
70 case QtFatalMsg:
71 v = Common::iLogger::Fatal;
72 break;
73 default:
74 v = Common::iLogger::Debug;
75 }
76
77 // Output to the log file and console
78 Common::iLogger::instance()->write(v, msg);
79
80 inHandler = false;
81 }
82
83 /**
84 * Fatal error message handler
85 * @param msg The error message
86 * @param source Source of the message
87 * @param where Where the error occurred
88 *
89 * This function shows a critical error message box on the screen if needed and then terminates
90 * the application.
91 *
92 * If the critical error message is shown, then the user has an option to ignore the error. In this
93 * case the application is not terminated.
94 */
95 [[noreturn]] static void fatalMsgHandler(QString const & msg, QString const & source, QString const & where)
96 {
97 Q_UNUSED(msg)
98 Q_UNUSED(source)
99 Q_UNUSED(where)
100 exit(1);
101 }
102
103 } // namespace eVaf::CLI::Internal
104 } // namespace eVaf::CLI
105 } // namespace eVaf
106
107 //-------------------------------------------------------------------
108
109 using namespace eVaf::CLI;
110
111 Application::Application(int & argc, char ** argv)
112 : QCoreApplication(argc, argv)
113 {
114 setObjectName(QString("%1-%2").arg(VER_MODULE_NAME_STR).arg(__FUNCTION__));
115 }
116
117 Application::~Application()
118 {
119 }
120
121 bool Application::processCommandLine(int argc, char ** argv)
122 {
123 Common::iLogger::Severity consoleSeverityLevel = Common::iLogger::Fatal;
124
125 QStringList args;
126 for (int i = 1; i < argc; ++i)
127 args += argv[i];
128
129 for (int i = 0; i < args.size(); ++i) {
130 // Get the argument and optional value
131 QStringList arg = args.at(i).simplified().split(QChar('='));
132
133 if (QRegExp("(-[-]?version)|([-//]V)").exactMatch(arg.at(0))) {
134 printVersion();
135 return false;
136 }
137 else if (QRegExp("(-[-]?help)|([-//][h/?])").exactMatch(arg.at(0))) {
138 printHelp();
139 return false;
140 }
141 else if (QRegExp("-[-]?verbose").exactMatch(arg.at(0)) && arg.size() > 1) {
142 QString v = arg.at(1).toLower();
143 if (v == "debug")
144 consoleSeverityLevel = Common::iLogger::Debug;
145 else if (v == "info")
146 consoleSeverityLevel = Common::iLogger::Info;
147 else if (v == "warning")
148 consoleSeverityLevel = Common::iLogger::Warning;
149 else if (v == "error")
150 consoleSeverityLevel = Common::iLogger::Error;
151 else if (v == "fatal")
152 consoleSeverityLevel = Common::iLogger::Fatal;
153 else if (v == "none") {
154 consoleSeverityLevel = Common::iLogger::None;
155 }
156 else {
157 printHelp();
158 return false;
159 }
160 }
161 else if (QRegExp("-[v]+").exactMatch(arg.at(0)) && arg.size() == 1) {
162 // The number of 'v's increases the verbosity
163 for (int j = 1; j < arg.at(0).size(); ++j) {
164 switch (consoleSeverityLevel) {
165 case Common::iLogger::None:
166 consoleSeverityLevel = Common::iLogger::Fatal;
167 break;
168 case Common::iLogger::Fatal:
169 consoleSeverityLevel = Common::iLogger::Error;
170 break;
171 case Common::iLogger::Error:
172 consoleSeverityLevel = Common::iLogger::Warning;
173 break;
174 case Common::iLogger::Warning:
175 consoleSeverityLevel = Common::iLogger::Info;
176 break;
177 case Common::iLogger::Info:
178 consoleSeverityLevel = Common::iLogger::Debug;
179 break;
180 default:
181 break;
182 }
183 }
184 }
185 }
186
187 // Set the console severity
188 Common::iLogger::instance()->setConsoleSeverity(consoleSeverityLevel);
189
190 return true;
191 }
192
193 void Application::printHelp()
194 {
195 char const * const txt = QT_TR_NOOP(
196 "Usage: eVafCLI [options]\n"
197 "\n"
198 // General options
199 " -help Shows this help and quits.\n"
200 " -version Shows version information and quits.\n"
201 " -verbose=LEVEL Specifies the verbose level. LEVEL can be one of the\n"
202 " following: NONE, FATAL, ERROR, WARNING, INFO, DEBUG.\n"
203 " -v Makes the application more verbose. Can be repeated for\n"
204 " more verbosity.\n"
205 // Handled by the iApp interface implementation
206 " -appl[ication]=NAME Specifies the name of the application.\n"
207 " -lang[uage]=xx[_CC] Specifies the language, where xx is the ISO 639\n"
208 " language code followed by an optional ISO 3166 country\n"
209 " code.\n"
210 " -root[dir]=DIR Specifies the application's root directory.\n"
211 " -dataroot[dir]=DIR Specifies the data root directory.\n"
212 " -etc[dir]=DIR Specifies the configuration files directory.\n"
213 " -log[dir]=DIR Specifies the log files directory.\n"
214 " -doc[dir]=DIR Specifies the documentation directory.\n"
215 " -qtplugins[dir]=DIR Specifies the Qt plugins directory.\n"
216 );
217 ::fputs(tr(txt).toLocal8Bit().constData(), stdout);
218 }
219
220 void Application::printVersion()
221 {
222 ::printf("%s version %s release date %s, %s version %s\n",
223 VER_PRODUCT_NAME_STR,
224 VER_PRODUCT_VERSION_STR,
225 VER_PRODUCT_DATE_STR,
226 VER_MODULE_NAME_STR,
227 VER_FILE_VERSION_STR
228 );
229 }
230
231
232 //-------------------------------------------------------------------
233
234 int main(int argc, char ** argv)
235 {
236 Common::iLogger::instance()->setSeverity(Common::iLogger::Warning);
237
238 // Install our onw message handlers
239 Common::iLogger::instance()->installFatalMsgHandler(Internal::fatalMsgHandler);
240 qInstallMessageHandler(Internal::messageOutput);
241
242 // Process command-line arguments
243 if (!Application::processCommandLine(argc, argv))
244 return 1;
245
246 EVAF_INFO("%s version %s release date %s, %s version %s",
247 VER_PRODUCT_NAME_STR,
248 VER_PRODUCT_VERSION_STR,
249 VER_PRODUCT_DATE_STR,
250 VER_MODULE_NAME_STR,
251 VER_FILE_VERSION_STR);
252
253 #ifdef Q_OS_LINUX
254 EVAF_INFO("%s application pid = %d", VER_MODULE_NAME_STR, getpid());
255 #endif
256
257 Application app(argc, argv);
258
259 // Install the exit handler
260 if (!Internal::installExitHandler())
261 return 1;
262
263 // Plugin manager
264 Plugins::PluginManager pluginManager;
265
266 // The main run loop
267 bool quit = false;
268 int rval = 0;
269 while (!quit) {
270
271 EVAF_INFO("%s is starting up", VER_MODULE_NAME_STR);
272
273 // Initialize the common library
274 if (!Common::init())
275 return 1;
276
277 // Initialize the plugin manager and load plugins
278 if (!pluginManager.init())
279 return 1;
280
281 // Run the application
282 EVAF_INFO("Running %s", VER_MODULE_NAME_STR);
283 rval = Common::iApp::instance()->exec();
284
285 quit = rval != Common::iApp::RC_Restart;
286
287 EVAF_INFO("%s is %s", VER_MODULE_NAME_STR, quit ? "exiting" : "restarting");
288
289 // Unload plugins and finalize the plugin manager
290 pluginManager.done();
291 }
292
293 EVAF_INFO("%s exit with code %d", VER_MODULE_NAME_STR, rval);
294
295 return rval;
296 }