diff --git a/src/librssguard/definitions/definitions.h b/src/librssguard/definitions/definitions.h index 7cba5e9a9..fc727e1ef 100755 --- a/src/librssguard/definitions/definitions.h +++ b/src/librssguard/definitions/definitions.h @@ -270,6 +270,7 @@ #define qInfoNN qInfo().noquote().nospace() #endif +#define NONQUOTE_W_SPACE_DOT(x) " " << (x) << "." #define QUOTE_W_SPACE_DOT(x) " '" << (x) << "'." #define QUOTE_W_SPACE(x) " '" << (x) << "' " #define QUOTE_NO_SPACE(x) "'" << (x) << "'" diff --git a/src/librssguard/miscellaneous/application.cpp b/src/librssguard/miscellaneous/application.cpp index 714cc28d4..b28a50520 100755 --- a/src/librssguard/miscellaneous/application.cpp +++ b/src/librssguard/miscellaneous/application.cpp @@ -21,6 +21,8 @@ #include "services/standard/standardserviceroot.h" #include "services/tt-rss/ttrssserviceentrypoint.h" +#include + #include #include @@ -53,8 +55,10 @@ Application::Application(const QString& id, int& argc, char** argv) m_localization(new Localization(this)), m_icons(new IconFactory(this)), m_database(new DatabaseFactory(this)), m_downloadManager(nullptr), m_shouldRestart(false) { + parseCmdArguments(); + // Setup debug output system. - qSetMessagePattern(QSL("time=\"%{time process}\" type=\"%{type}\" -> %{message}")); + qInstallMessageHandler(performLogging); determineFirstRuns(); //: Abbreviation of language, e.g. en. @@ -102,6 +106,33 @@ Application::~Application() { qDebugNN << LOGSEC_CORE << "Destroying Application instance."; } +QString s_customLogFile = QString(); + +void Application::performLogging(QtMsgType type, const QMessageLogContext& context, const QString& msg) { +#ifndef QT_NO_DEBUG_OUTPUT + QString console_message = qFormatLogMessage(type, context, msg); + std::wcout << console_message.toStdWString() << std::endl; + + if (!s_customLogFile.isEmpty()) { + QFile log_file(s_customLogFile); + + if (log_file.open(QFile::OpenModeFlag::Append | QFile::OpenModeFlag::Unbuffered)) { + log_file.write(console_message.toUtf8()); + log_file.write(QSL("\r\n").toUtf8()); + log_file.close(); + } + } + + if (type == QtMsgType::QtFatalMsg) { + qApp->exit(EXIT_FAILURE); + } +#else + Q_UNUSED(type) + Q_UNUSED(context) + Q_UNUSED(msg) +#endif +} + void Application::reactOnForeignNotifications() { connect(this, &Application::messageReceived, this, &Application::processExecutionMessage); } @@ -166,6 +197,10 @@ bool Application::isFirstRunCurrentVersion() const { return m_firstRunCurrentVersion; } +QCommandLineParser* Application::cmdParser() { + return &m_cmdParser; +} + WebFactory* Application::web() const { return m_webFactory; } @@ -519,3 +554,16 @@ void Application::determineFirstRuns() { eliminateFirstRuns(); } + +void Application::parseCmdArguments() { + QCommandLineOption log_file(QStringList() << "l" << "log", "Write application debug log to file.", "log-file"); + + m_cmdParser.addOption(log_file); + m_cmdParser.addHelpOption(); + m_cmdParser.addVersionOption(); + m_cmdParser.setApplicationDescription(APP_NAME); + + m_cmdParser.process(*this); + + s_customLogFile = m_cmdParser.value(QSL("l")); +} diff --git a/src/librssguard/miscellaneous/application.h b/src/librssguard/miscellaneous/application.h index 1409b3530..23b025cff 100755 --- a/src/librssguard/miscellaneous/application.h +++ b/src/librssguard/miscellaneous/application.h @@ -17,6 +17,7 @@ #include "miscellaneous/systemfactory.h" #include "network-web/downloadmanager.h" +#include #include #include @@ -66,6 +67,7 @@ class RSSGUARD_DLLSPEC Application : public QtSingleApplication { // Check whether CURRENT VERSION of the application starts for the first time. bool isFirstRunCurrentVersion() const; + QCommandLineParser* cmdParser(); WebFactory* web() const; SystemFactory* system(); SkinFactory* skins(); @@ -116,6 +118,11 @@ class RSSGUARD_DLLSPEC Application : public QtSingleApplication { // Returns pointer to "GOD" application singleton. static Application* instance(); + // Custom debug/console log handler. + static void performLogging(QtMsgType type, const QMessageLogContext& context, const QString& msg); + + //static QString s_customLogFile; + public slots: // Restarts the application. @@ -138,6 +145,10 @@ class RSSGUARD_DLLSPEC Application : public QtSingleApplication { private: void determineFirstRuns(); void eliminateFirstRuns(); + void parseCmdArguments(); + + private: + QCommandLineParser m_cmdParser; #if defined(USE_WEBENGINE) NetworkUrlInterceptor* m_urlInterceptor; diff --git a/src/librssguard/miscellaneous/iconfactory.cpp b/src/librssguard/miscellaneous/iconfactory.cpp index 6ff9cbd62..094580627 100755 --- a/src/librssguard/miscellaneous/iconfactory.cpp +++ b/src/librssguard/miscellaneous/iconfactory.cpp @@ -77,23 +77,23 @@ void IconFactory::loadCurrentIconTheme() { } // Display list of installed themes. - qDebug("Installed icon themes are: %s.", - qPrintable(QStringList(installed_themes) - .replaceInStrings(QRegularExpression(QSL("^|$")), QSL("\'")) - .replaceInStrings(QRegularExpression(QSL("^\\'$")), QSL("\'\'")).join(QSL(", ")))); + qDebugNN << LOGSEC_GUI << "Installed icon themes are: %s.", + qPrintable(QStringList(installed_themes) + .replaceInStrings(QRegularExpression(QSL("^|$")), QSL("\'")) + .replaceInStrings(QRegularExpression(QSL("^\\'$")), QSL("\'\'")).join(QSL(", "))); if (installed_themes.contains(theme_name_from_settings)) { // Desired icon theme is installed and can be loaded. #if defined(Q_OS_LINUX) if (theme_name_from_settings.isEmpty()) { - qDebug("Loading default system icon theme."); + qDebugNN << LOGSEC_GUI << "Loading default system icon theme."; } else { - qDebug("Loading icon theme '%s'.", qPrintable(theme_name_from_settings)); + qDebugNN << LOGSEC_GUI << "Loading icon theme" << QUOTE_W_SPACE_DOT(theme_name_from_settings); QIcon::setThemeName(theme_name_from_settings); } #else - qDebug("Loading icon theme '%s'.", qPrintable(theme_name_from_settings)); + qDebugNN << LOGSEC_GUI << "Loading icon theme" << QUOTE_W_SPACE_DOT(theme_name_from_settings); QIcon::setThemeName(theme_name_from_settings); #endif } @@ -101,11 +101,13 @@ void IconFactory::loadCurrentIconTheme() { // Desired icon theme is not currently available. // Activate "default" or "no" icon theme instead. #if defined(Q_OS_LINUX) - qWarning("Icon theme '%s' cannot be loaded. Activating \"system default\" icon theme.", - qPrintable(theme_name_from_settings)); + qWarningNN << "Icon theme" + << QUOTE_W_SPACE(theme_name_from_settings) + << "cannot be loaded because it is not installed. Activating \"no\" icon theme."; #else - qWarning("Icon theme '%s' cannot be loaded because it is not installed. Activating \"no\" icon theme.", - qPrintable(theme_name_from_settings)); + qWarningNN << "Icon theme" + << QUOTE_W_SPACE(theme_name_from_settings) + << "cannot be loaded because it is not installed. Activating \"no\" icon theme."; QIcon::setThemeName(APP_NO_THEME); #endif } diff --git a/src/rssguard/main.cpp b/src/rssguard/main.cpp index 78ee4c473..0274d95e5 100755 --- a/src/rssguard/main.cpp +++ b/src/rssguard/main.cpp @@ -14,16 +14,7 @@ extern void disableWindowTabbing(); #endif int main(int argc, char* argv[]) { - for (int i = 0; i < argc; i++) { - const QString str = QString::fromLocal8Bit(argv[i]); - - if (str == "-h") { - qDebug("Usage: rssguard [OPTIONS]\n\n" - "Option\t\tMeaning\n" - "-h\t\tDisplays this help."); - return EXIT_SUCCESS; - } - } + qSetMessagePattern(QSL("time=\"%{time process}\" type=\"%{type}\" -> %{message}")); QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); @@ -43,12 +34,12 @@ int main(int argc, char* argv[]) { // Instantiate base application object. Application application(APP_LOW_NAME, argc, argv); - qDebug("Starting %s.", qPrintable(QSL(APP_LONG_NAME))); - qDebug("Instantiated Application class."); + qDebugNN << LOGSEC_CORE << "Starting" << NONQUOTE_W_SPACE_DOT(APP_LONG_NAME); + qDebugNN << LOGSEC_CORE << "Instantiated class " << QUOTE_W_SPACE_DOT(application.metaObject()->className()); // Check if another instance is running. if (application.isAlreadyRunning()) { - qWarning("Another instance of the application is already running. Notifying it."); + qWarningNN << LOGSEC_CORE << "Another instance of the application is already running. Notifying it."; return EXIT_FAILURE; }