2 * @file main/GUI/main.cpp
3 * @brief The main eVaf GUI application class
6 * Copyright (c) 2011 Enar Vaikene
8 * This file is part of the eVaf C++ cross-platform application development framework.
10 * This file can be used under the terms of the GNU General Public License
11 * version 3.0 as published by the Free Software Foundation and appearing in
12 * the file LICENSE included in the packaging of this file. Please review the
13 * the following information to ensure the GNU General Public License version
14 * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
16 * Alternatively, this file may be used in accordance with the Commercial License
17 * Agreement provided with the Software.
21 #include "exithandler.h"
23 //#include "version_p.h"
27 #include "winconsole.h"
30 #include <Common/Globals>
31 #include <Common/iLogger>
32 #include <Common/iApp>
34 #include <Plugins/PluginManager>
39 # include <sys/types.h>
44 //-------------------------------------------------------------------
51 * Flag indicating that the application should be more verbose when dealing with fatal errors.
53 * If this flag is set, then shows fatal errors on the screen as dialog boxes and
54 * the user has to close them before terminating the application.
56 * If this flag is not set, then no messages are shown and the application terminates
57 * silently. Error messages are written only into the log file.
59 static bool BeVerbose
= true;
63 * Flag indicating that the application needs a console window.
65 * If this flag is set, opens an extra console window for message output.
67 static bool NeedsConsole
= false;
71 * Console severity level.
73 * This variable is used to set the console severity level. The severity level is changed
74 * with command-line arguments.
76 static eVaf::Common::iLogger::Severity ConsoleSeverityLevel
= eVaf::Common::iLogger::Fatal
;
79 * Qt message handler replacement.
80 * @param type Type of the message
81 * @param msg The message
83 * This function outputs messages to the console and to the log file.
85 static void messageOutput(QtMsgType type
, QMessageLogContext
const &, QString
const & msg
)
87 static bool inHandler
= false;
89 // Avoid recursions in case outputting a message causes another message to be output
94 // Qt message type conversion to eVaf logger severity levels
95 eVaf::Common::iLogger::Severity v
;
98 v
= eVaf::Common::iLogger::Warning
;
101 v
= eVaf::Common::iLogger::Error
;
104 v
= eVaf::Common::iLogger::Fatal
;
107 v
= eVaf::Common::iLogger::Debug
;
110 // Output to the log file and console
111 eVaf::Common::iLogger::instance()->write(v
, msg
);
117 * Fatal error message handler
118 * @param msg The error message
119 * @param source Source of the message
120 * @param where Where the error occurred
122 * This function shows a critical error message box on the screen if needed and then terminates
125 * If the critical error message is shown, then the user has an option to ignore the error. In this
126 * case the application is not terminated.
128 static void fatalMsgHandler(QString
const & msg
, QString
const & source
, QString
const & where
)
132 // Show the message on the screen
134 if (FatalErr::message(QObject::tr("Fatal Error"),
135 QObject::tr("%1\n\nOccurred in '%2'")
138 nullptr) == FatalErr::Ignore
)
144 } // namespace eVaf::GUI::Internal
145 } // namespace eVaf::GUI
149 //-------------------------------------------------------------------
151 using namespace eVaf
;
152 using namespace eVaf::GUI
;
154 Application::Application(int & argc
, char ** argv
)
155 : QApplication(argc
, argv
)
157 setObjectName(QString("%1-%2").arg(VER_MODULE_NAME_STR
).arg(__FUNCTION__
));
159 EVAF_INFO("%s version %s created", qPrintable(objectName()), VER_FILE_VERSION_STR
);
162 Application::~Application()
164 EVAF_INFO("%s destroyed", qPrintable(objectName()));
167 bool Application::processCommandLine(int argc
, char ** argv
)
170 for (int i
= 1; i
< argc
; ++i
)
173 for (int i
= 0; i
< args
.size(); ++i
) {
174 // Get the argument and optional value
175 QStringList arg
= args
.at(i
).simplified().split(QChar('='));
177 if (QRegExp("(-[-]?version)|([-//]V)").exactMatch(arg
.at(0))) {
181 else if (QRegExp("(-[-]?help)|([-//][h/?])").exactMatch(arg
.at(0))) {
185 else if (QRegExp("-[-]?help-qt").exactMatch(arg
.at(0))) {
189 else if (QRegExp("-[-]?verbose").exactMatch(arg
.at(0)) && arg
.size() > 1) {
191 Internal::NeedsConsole
= true;
193 QString v
= arg
.at(1).toLower();
195 Internal::ConsoleSeverityLevel
= Common::iLogger::Debug
;
196 else if (v
== "info")
197 Internal::ConsoleSeverityLevel
= Common::iLogger::Info
;
198 else if (v
== "warning")
199 Internal::ConsoleSeverityLevel
= Common::iLogger::Warning
;
200 else if (v
== "error")
201 Internal::ConsoleSeverityLevel
= Common::iLogger::Error
;
202 else if (v
== "fatal")
203 Internal::ConsoleSeverityLevel
= Common::iLogger::Fatal
;
204 else if (v
== "none") {
205 Internal::ConsoleSeverityLevel
= Common::iLogger::None
;
206 Internal::BeVerbose
= false;
208 Internal::NeedsConsole
= false;
216 else if (QRegExp("-[v]+").exactMatch(arg
.at(0)) && arg
.size() == 1) {
217 // The number of 'v's increases the verbosity
218 for (int j
= 1; j
< arg
.at(0).size(); ++j
) {
219 switch (Internal::ConsoleSeverityLevel
) {
220 case Common::iLogger::None
:
221 Internal::ConsoleSeverityLevel
= Common::iLogger::Fatal
;
223 case Common::iLogger::Fatal
:
224 Internal::ConsoleSeverityLevel
= Common::iLogger::Error
;
226 case Common::iLogger::Error
:
227 Internal::ConsoleSeverityLevel
= Common::iLogger::Warning
;
229 case Common::iLogger::Warning
:
230 Internal::ConsoleSeverityLevel
= Common::iLogger::Info
;
232 case Common::iLogger::Info
:
233 Internal::ConsoleSeverityLevel
= Common::iLogger::Debug
;
245 void Application::printHelp()
247 char const * const txt
= QT_TR_NOOP(
248 "Usage: eVafGUI [options]\n"
251 " -help Shows this help and quits.\n"
252 " -help-qt Shows Qt command line options and quits.\n"
253 " -version Shows version information and quits.\n"
254 " -verbose=LEVEL Specifies the verbose level. LEVEL can be one of the\n"
255 " following: NONE, FATAL, ERROR, WARNING, INFO, DEBUG.\n"
256 " -v Makes the application more verbose. Can be repeated for\n"
258 // Handled by the iApp interface implementation
259 " -appl[ication]=NAME Specifies the name of the application.\n"
260 " -lang[uage]=xx[_CC] Specifies the language, where xx is the ISO 639\n"
261 " language code followed by an optional ISO 3166 country\n"
263 " -root[dir]=DIR Specifies the application's root directory.\n"
264 " -dataroot[dir]=DIR Specifies the data root directory.\n"
265 " -etc[dir]=DIR Specifies the configuration files directory.\n"
266 " -log[dir]=DIR Specifies the log files directory.\n"
267 " -doc[dir]=DIR Specifies the documentation directory.\n"
268 " -qtplugins[dir]=DIR Specifies the Qt plugins directory.\n"
270 ::fputs(tr(txt
).toLocal8Bit().constData(), stdout
);
273 void Application::printQtHelp()
275 // Cannot translate this text as QT_TR_NOOP() is not able to process #ifdef parts.
276 char const * const txt
=
278 "Qt debugging options:\n"
279 " -nograb tells Qt that it must never grab the mouse or the keyboard.\n"
281 " -dograb running under a debugger can cause an implicit -nograb,\n"
282 " use -dograb to override.\n"
283 " -sync switches to synchronous mode for debugging.\n\n"
286 "Qt common options:\n"
287 " -style=STYLE sets the application GUI style. Possible values are motif,\n"
288 " windows, and platinum.\n"
289 " -style STYLE is the same as listed above.\n"
290 " -stylesheet=STYLESHEET sets the application style sheet.\n"
291 " -stylesheet STYLESHEET is the same as listed above.\n"
292 " -session=SESSION restores the application from an earlier session.\n"
293 " -session SESSION is the same as listed above.\n"
294 " -widgetcount prints debug message at the end about number of widgets\n"
295 " left undestroyed and maximum number of widgets existed at\n"
297 " -reverse sets the application's layout direction to Qt::RightToLeft\n\n"
299 "Qt options on Windows:\n"
300 " -direct3d will make the Direct3D paint engine the default widget\n"
301 " paint engine in Qt.\n\n"
304 "Qt options on X11:\n"
305 " -display DISPLAY sets the X display.\n"
306 " -geometry GEOMETRY sets the client geometry of the first window that is\n"
308 " -fn or -font FONT defines the application font.\n"
309 " -bg or -background COLOR sets the default background color and an\n"
310 " application palette.\n"
311 " -fg or -foreground COLOR sets the default foreground color.\n"
312 " -btn or -button COLOR sets the default button color.\n"
313 " -name NAME sets the application name.\n"
314 " -title TITLE sets the application title.\n"
315 " -visual TrueColor forces the application to use a TrueColor visual on an\n"
317 " -ncols COUNT limits the number of colors allocated in the color cube on\n"
318 " an 8-bit display, if the application is using the\n"
319 " QApplication::ManyColor color specification. If COUNT is\n"
320 " 216 then a 6x6x6 color cube is used (i.e. 6 levels of red,\n"
321 " 6 of green, and 6 of blue); for other values, a cube\n"
322 " approximately proportional to a 2x3x1 cube is used.\n"
323 " -cmap causes the application to install a private color map on an\n"
325 " -im sets the input method server (equivalent to setting the\n"
326 " XMODIFIERS environment variable).\n"
327 " -noxim disables the input method framework (\"no X input method\").\n"
328 " -inputstyle defines how the input is inserted into the given widget.\n"
329 " E.g., onTheSpot makes the input appear directly in the\n"
330 " widget, while overTheSpot makes the input appear in a box\n"
331 " floating over the widget and is not inserted until the\n"
332 " editing is done.\n"
335 ::fputs(txt
, stdout
);
338 void Application::printVersion()
340 ::printf("%s version %s release date %s, %s version %s\n",
341 VER_PRODUCT_NAME_STR
,
342 VER_PRODUCT_VERSION_STR
,
343 VER_PRODUCT_DATE_STR
,
350 //-------------------------------------------------------------------
352 int main(int argc
, char ** argv
)
354 Common::iLogger::instance()->setSeverity(Common::iLogger::Warning
);
356 // Install our own message handlers
357 Common::iLogger::instance()->installFatalMsgHandler(Internal::fatalMsgHandler
);
358 qInstallMessageHandler(Internal::messageOutput
);
360 // Process command-line arguments
361 if (!Application::processCommandLine(argc
, argv
))
364 // Set the console severity
365 Common::iLogger::instance()->setConsoleSeverity(Internal::ConsoleSeverityLevel
);
368 // Enable the extra message console on Windows
369 if (Internal::NeedsConsole
)
370 Internal::enableWinConsole();
373 EVAF_INFO("%s version %s release date %s, %s version %s",
374 VER_PRODUCT_NAME_STR
,
375 VER_PRODUCT_VERSION_STR
,
376 VER_PRODUCT_DATE_STR
,
378 VER_FILE_VERSION_STR
);
381 EVAF_INFO("%s application pid = %d", VER_MODULE_NAME_STR
, getpid());
384 Application
app(argc
, argv
);
386 // Install the exit handler
387 if (!Internal::installExitHandler())
393 Plugins::PluginManager pluginManager
;
399 EVAF_INFO("%s is starting up", VER_MODULE_NAME_STR
);
401 // Initialize the common library
405 // Initialize the plugin manager and load plugins
406 if (!pluginManager
.init())
409 // Run the application
410 EVAF_INFO("Running %s", VER_MODULE_NAME_STR
);
411 rval
= Common::iApp::instance()->exec();
413 quit
= rval
!= Common::iApp::RC_Restart
;
415 EVAF_INFO("%s is %s", VER_MODULE_NAME_STR
, quit
? "exiting" : "restarting");
417 // Unload plugins and finalize the plugin manager
418 pluginManager
.done();
420 // Finalize the common library
425 EVAF_INFO("%s exit with code %d", VER_MODULE_NAME_STR
, rval
);