/** * @file main/CLI/main.cpp * @brief The main eVaf CLI application class * * Copyright (c) 2011 Enar Vaikene * * This file is part of the eVaf C++ cross-platform application development framework. * * This file can be used under the terms of the GNU General Public License * version 3.0 as published by the Free Software Foundation and appearing in * the file LICENSE included in the packaging of this file. Please review the * the following information to ensure the GNU General Public License version * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. * * Alternatively, this file may be used in accordance with the Commercial License * Agreement provided with the Software. */ #include "main.h" #include "exithandler.h" //#include "version_p.h" #include "version.h" #include #include #include #include #include #ifdef Q_OS_LINUX # include # include #endif using namespace eVaf; //------------------------------------------------------------------- namespace eVaf { namespace CLI { namespace Internal { /** * Qt message handler replacement. * @param type Type of the message * @param msg The message * * This function outputs messages to the console and to the log file. */ static void messageOutput(QtMsgType type, QMessageLogContext const &, QString const & msg) { static bool inHandler = false; // Avoid recursions in case outputting a message causes another message to be output if (inHandler) return; inHandler = true; // Qt message type conversion to eVaf logger severity levels Common::iLogger::Severity v; switch (type) { case QtWarningMsg: v = Common::iLogger::Warning; break; case QtCriticalMsg: v = Common::iLogger::Error; break; case QtFatalMsg: v = Common::iLogger::Fatal; break; default: v = Common::iLogger::Debug; } // Output to the log file and console Common::iLogger::instance()->write(v, msg); inHandler = false; } /** * Fatal error message handler * @param msg The error message * @param source Source of the message * @param where Where the error occurred * * This function shows a critical error message box on the screen if needed and then terminates * the application. * * If the critical error message is shown, then the user has an option to ignore the error. In this * case the application is not terminated. */ [[noreturn]] static void fatalMsgHandler(QString const & msg, QString const & source, QString const & where) { Q_UNUSED(msg); Q_UNUSED(source); Q_UNUSED(where); exit(1); } } // namespace eVaf::CLI::Internal } // namespace eVaf::CLI } // namespace eVaf //------------------------------------------------------------------- using namespace eVaf::CLI; Application::Application(int & argc, char ** argv) : QCoreApplication(argc, argv) { setObjectName(QString("%1-%2").arg(VER_MODULE_NAME_STR).arg(__FUNCTION__)); } Application::~Application() { } bool Application::processCommandLine(int argc, char ** argv) { Common::iLogger::Severity consoleSeverityLevel = Common::iLogger::Fatal; QStringList args; for (int i = 1; i < argc; ++i) args += argv[i]; for (int i = 0; i < args.size(); ++i) { // Get the argument and optional value QStringList arg = args.at(i).simplified().split(QChar('=')); if (QRegExp("(-[-]?version)|([-//]V)").exactMatch(arg.at(0))) { printVersion(); return false; } else if (QRegExp("(-[-]?help)|([-//][h/?])").exactMatch(arg.at(0))) { printHelp(); return false; } else if (QRegExp("-[-]?verbose").exactMatch(arg.at(0)) && arg.size() > 1) { QString v = arg.at(1).toLower(); if (v == "debug") consoleSeverityLevel = Common::iLogger::Debug; else if (v == "info") consoleSeverityLevel = Common::iLogger::Info; else if (v == "warning") consoleSeverityLevel = Common::iLogger::Warning; else if (v == "error") consoleSeverityLevel = Common::iLogger::Error; else if (v == "fatal") consoleSeverityLevel = Common::iLogger::Fatal; else if (v == "none") { consoleSeverityLevel = Common::iLogger::None; } else { printHelp(); return false; } } else if (QRegExp("-[v]+").exactMatch(arg.at(0)) && arg.size() == 1) { // The number of 'v's increases the verbosity for (int j = 1; j < arg.at(0).size(); ++j) { switch (consoleSeverityLevel) { case Common::iLogger::None: consoleSeverityLevel = Common::iLogger::Fatal; break; case Common::iLogger::Fatal: consoleSeverityLevel = Common::iLogger::Error; break; case Common::iLogger::Error: consoleSeverityLevel = Common::iLogger::Warning; break; case Common::iLogger::Warning: consoleSeverityLevel = Common::iLogger::Info; break; case Common::iLogger::Info: consoleSeverityLevel = Common::iLogger::Debug; break; default: break; } } } } // Set the console severity Common::iLogger::instance()->setConsoleSeverity(consoleSeverityLevel); return true; } void Application::printHelp() { char const * const txt = QT_TR_NOOP( "Usage: eVafCLI [options]\n" "\n" // General options " -help Shows this help and quits.\n" " -version Shows version information and quits.\n" " -verbose=LEVEL Specifies the verbose level. LEVEL can be one of the\n" " following: NONE, FATAL, ERROR, WARNING, INFO, DEBUG.\n" " -v Makes the application more verbose. Can be repeated for\n" " more verbosity.\n" // Handled by the iApp interface implementation " -appl[ication]=NAME Specifies the name of the application.\n" " -lang[uage]=xx[_CC] Specifies the language, where xx is the ISO 639\n" " language code followed by an optional ISO 3166 country\n" " code.\n" " -root[dir]=DIR Specifies the application's root directory.\n" " -dataroot[dir]=DIR Specifies the data root directory.\n" " -etc[dir]=DIR Specifies the configuration files directory.\n" " -log[dir]=DIR Specifies the log files directory.\n" " -doc[dir]=DIR Specifies the documentation directory.\n" " -qtplugins[dir]=DIR Specifies the Qt plugins directory.\n" ); ::fputs(tr(txt).toLocal8Bit().constData(), stdout); } void Application::printVersion() { ::printf("%s version %s release date %s, %s version %s\n", VER_PRODUCT_NAME_STR, VER_PRODUCT_VERSION_STR, VER_PRODUCT_DATE_STR, VER_MODULE_NAME_STR, VER_FILE_VERSION_STR ); } //------------------------------------------------------------------- int main(int argc, char ** argv) { Common::iLogger::instance()->setSeverity(Common::iLogger::Warning); // Install our onw message handlers Common::iLogger::instance()->installFatalMsgHandler(Internal::fatalMsgHandler); qInstallMessageHandler(Internal::messageOutput); // Process command-line arguments if (!Application::processCommandLine(argc, argv)) return 1; EVAF_INFO("%s version %s release date %s, %s version %s", VER_PRODUCT_NAME_STR, VER_PRODUCT_VERSION_STR, VER_PRODUCT_DATE_STR, VER_MODULE_NAME_STR, VER_FILE_VERSION_STR); #ifdef Q_OS_LINUX EVAF_INFO("%s application pid = %d", VER_MODULE_NAME_STR, getpid()); #endif Application app(argc, argv); // Install the exit handler if (!Internal::installExitHandler()) return 1; // Plugin manager Plugins::PluginManager pluginManager; // The main run loop bool quit = false; int rval; while (!quit) { EVAF_INFO("%s is starting up", VER_MODULE_NAME_STR); // Initialize the common library if (!Common::init()) return 1; // Initialize the plugin manager and load plugins if (!pluginManager.init()) return 1; // Run the application EVAF_INFO("Running %s", VER_MODULE_NAME_STR); rval = Common::iApp::instance()->exec(); quit = rval != Common::iApp::RC_Restart; EVAF_INFO("%s is %s", VER_MODULE_NAME_STR, quit ? "exiting" : "restarting"); // Unload plugins and finalize the plugin manager pluginManager.done(); } EVAF_INFO("%s exit with code %d", VER_MODULE_NAME_STR, rval); return rval; }