From 2ab8cd3d68a55773240c9424aa0e14d678fd2dbb Mon Sep 17 00:00:00 2001 From: =?utf8?q?Enar=20V=C3=A4ikene?= Date: Thu, 19 May 2011 15:16:28 +0300 Subject: [PATCH] Added eVaf Command Line Interface application. --- src/main/CLI/CMakeLists.txt | 4 +- src/main/CLI/main.cpp | 267 ++++++++++++++++++++++++++++++++++-- src/main/CLI/main.h | 62 ++++++++- src/main/CMakeLists.txt | 2 +- 4 files changed, 314 insertions(+), 21 deletions(-) diff --git a/src/main/CLI/CMakeLists.txt b/src/main/CLI/CMakeLists.txt index f27ec1f..d6a5b14 100644 --- a/src/main/CLI/CMakeLists.txt +++ b/src/main/CLI/CMakeLists.txt @@ -9,19 +9,17 @@ include(${QT_USE_FILE}) include_directories(${eVaf_INCLUDE}) # Required eVaf libraries -set(eVaf_LIBRARIES) +set(eVaf_LIBRARIES CommonLib PluginsLib) # Source files set(SRCS main.cpp exithandler.cpp - version.cpp ) # Header files for the meta-object compiler set(MOC_HDRS main.h - version_p.h ) # Version info resource file for Windows builds diff --git a/src/main/CLI/main.cpp b/src/main/CLI/main.cpp index 4c57084..3c1ec3b 100644 --- a/src/main/CLI/main.cpp +++ b/src/main/CLI/main.cpp @@ -1,6 +1,6 @@ /** - * @file main/gui/main.cpp - * @brief The main eVaf GUI application class + * @file main/CLI/main.cpp + * @brief The main eVaf CLI application class * * Copyright (c) 2011 Enar Vaikene * @@ -18,39 +18,282 @@ #include "main.h" #include "exithandler.h" -#include "fatalerr.h" -#include "version_p.h" +//#include "version_p.h" #include "version.h" -#ifdef Q_OS_WIN32 -#include "winconsole.h" +#include +#include +#include +#include + +#include + +#include + +#ifdef Q_OS_LINUX +# include +# include #endif -#include +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, char const * 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. + */ +static void fatalMsgHandler(QString const & msg, QString const & source, QString const & where) +{ +#ifdef Q_OS_LINUX + abort(); +#else + exit(1); +#endif +} + +} // namespace eVaf::CLI::Internal +} // namespace eVaf::CLI +} // namespace eVaf //------------------------------------------------------------------- -using namespace eVafGUI; +using namespace eVaf::CLI; Application::Application(int & argc, char ** argv) - : QApplication(argc, argv) + : QCoreApplication(argc, argv) { - setObjectName(QString("%1-%2").arg(VER_MODULENAME_STR).arg(__FUNCTION__)); - - setWindowIcon(QIcon(":/eVafGUI/Icon")); + 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; + case Common::iLogger::Debug: + 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" + // Handled by the iEnv interface implementation + " -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); + qInstallMsgHandler(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 = app.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; } diff --git a/src/main/CLI/main.h b/src/main/CLI/main.h index 41ec6b5..97a1237 100644 --- a/src/main/CLI/main.h +++ b/src/main/CLI/main.h @@ -1,5 +1,5 @@ /** - * @file main/cli/main.h + * @file main/CLI/main.h * @brief The main eVaf CLI application class * * Copyright (c) 2011 Enar Vaikene @@ -17,19 +17,71 @@ */ #ifndef __CLI_MAIN_H -#define __CLI_MAIN_H +# define __CLI_MAIN_H #include +namespace eVaf { /** - * The main eVaf CLI application. + * The main eVaf command line interface (CLI) application. * * eVafGUI is the main CLI executable. It provides an empty CLI application * that is used to load other eVaf modules. */ -namespace eVafCLI { +namespace CLI { -} // namespace eVafCLI +/** + * Internal implementation of the main eVaf CLI application. + */ +namespace Internal { +} // namespace eVaf::CLI::Internal + +/** + * The main eVaf CLI application class + */ +class Application : public QCoreApplication +{ + Q_OBJECT + +public: + + Application(int & argc, char ** argv); + + virtual ~Application(); + + +public: // Static methods + + /** + * Processes command-line arguments + * @param argc Number of command-line arguments + * @param argv List of command-line arguments + * @return True if ok; false if the application should terminate + * + * This function processes command-line arguments and should be called before running + * the application. + */ + static bool processCommandLine(int argc, char ** argv); + + /** + * Prints out help for command-line arguments. + */ + static void printHelp(); + + /** + * Prints out help for Qt command-line arguments. + */ + static void printQtHelp(); + + /** + * Prints out version information. + */ + static void printVersion(); + +}; + +} // namespace eVaf::CLI +} // namespace eVaf #endif // main.h diff --git a/src/main/CMakeLists.txt b/src/main/CMakeLists.txt index a5b8305..362aba6 100644 --- a/src/main/CMakeLists.txt +++ b/src/main/CMakeLists.txt @@ -1,2 +1,2 @@ add_subdirectory(GUI) -#add_subdirectory(CLI) +add_subdirectory(CLI) -- 2.45.1