From 1b0e2576029a3a58d789c4ab6be14552eefe8a8b Mon Sep 17 00:00:00 2001 From: Bent Witthold Date: Thu, 2 Oct 2025 16:46:50 +0200 Subject: [PATCH] Added a message handler to have colored console output in debug mode. --- CMakeLists.txt | 1 + main.cpp | 34 +++++---- utils/messagehandler.h | 164 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 185 insertions(+), 14 deletions(-) create mode 100644 utils/messagehandler.h diff --git a/CMakeLists.txt b/CMakeLists.txt index dfa00ba..7e14778 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) qt_add_executable(${TARGET_APP} MANUAL_FINALIZATION ${PROJECT_SOURCES} + utils/messagehandler.h ) # Define target properties for Android with Qt 6 as: # set_property(TARGET ${TARGET_APP} APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR diff --git a/main.cpp b/main.cpp index 4721a41..7910b30 100644 --- a/main.cpp +++ b/main.cpp @@ -4,20 +4,26 @@ #include #include -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); +#ifdef QT_DEBUG +#include "utils/messagehandler.h" +#endif - QTranslator translator; - const QStringList uiLanguages = QLocale::system().uiLanguages(); - for (const QString &locale : uiLanguages) { - const QString baseName = "GenericWidgets_" + QLocale(locale).name(); - if (translator.load(":/i18n/" + baseName)) { - a.installTranslator(&translator); - break; - } +int main(int argc, char* argv[]) { +#ifdef QT_DEBUG + qInstallMessageHandler(consoleHandlerColoredVerboseInDarkTheme); +#endif + QApplication a(argc, argv); + + QTranslator translator; + const QStringList uiLanguages = QLocale::system().uiLanguages(); + for (const QString& locale : uiLanguages) { + const QString baseName = "GenericWidgets_" + QLocale(locale).name(); + if (translator.load(":/i18n/" + baseName)) { + a.installTranslator(&translator); + break; } - MainWindow w; - w.show(); - return a.exec(); + } + MainWindow w; + w.show(); + return a.exec(); } diff --git a/utils/messagehandler.h b/utils/messagehandler.h new file mode 100644 index 0000000..955fb7c --- /dev/null +++ b/utils/messagehandler.h @@ -0,0 +1,164 @@ +#ifndef MESSAGEHANDLER_H +#define MESSAGEHANDLER_H +/** + * Color and formatting codes + * @see: http://misc.flogisoft.com/bash/tip_colors_and_formatting + */ + +#include + +// qSetMessagePattern("%{file}(%{line}): %{message}"); +// qSetMessagePattern("%{type}(%{line}):\t%{message}"); +// qSetMessagePattern("%{type}%{file}(%{line}):\t%{message}"); + +void consoleHandlerColoredVerbose(QtMsgType type, + const QMessageLogContext& context, + const QString& msg) { + QByteArray localMsg = msg.toLocal8Bit(); + switch (type) { + case QtDebugMsg: + // fprintf(stderr, "\033[1;30mDebug: (%s:%u, %s) \t%s\n\033[0m", context.file, + // context.line, context.function, localMsg.constData()); // bold + fprintf(stderr, "\033[107;30mDebug: (%s:%u, %s) \t%s\n\033[0m", context.file, context.line, + context.function, localMsg.constData()); + break; + case QtInfoMsg: + fprintf(stderr, "\033[107;32mInfo: (%s:%u) \t%s\n\033[0m", context.file, context.line, + localMsg.constData()); + break; + case QtWarningMsg: + fprintf(stderr, "\033[43;30mWarning: (%s:%u, %s) \t%s\n\033[0m", context.file, context.line, + context.function, localMsg.constData()); + break; + case QtCriticalMsg: + fprintf(stderr, "\033[41;30mCritical: (%s:%u, %s) \t%s\n\033[0m", context.file, context.line, + context.function, localMsg.constData()); + break; + case QtFatalMsg: + fprintf(stderr, "\033[41;30mFatal: (%s:%u, %s) \t%s\n\033[0m", context.file, context.line, + context.function, localMsg.constData()); + abort(); + } +} + +void consoleHandlerColoredVerboseInDarkTheme(QtMsgType type, + const QMessageLogContext& context, + const QString& msg) { + QByteArray localMsg = msg.toLocal8Bit(); + switch (type) { + case QtDebugMsg: + // fprintf(stderr, "\033[1;30mDebug: (%s:%u, %s) \t%s\n\033[0m", context.file, + // context.line, context.function, localMsg.constData()); // bold + fprintf(stderr, "\033[107;37mDebug: (%s:%u, %s) \t%s\n\033[0m", context.file, context.line, + context.function, localMsg.constData()); + break; + case QtInfoMsg: + fprintf(stderr, "\033[107;32mInfo: (%s:%u) \t%s\n\033[0m", context.file, context.line, + localMsg.constData()); + break; + case QtWarningMsg: + fprintf(stderr, "\033[43;30mWarning: (%s:%u, %s) \t%s\n\033[0m", context.file, context.line, + context.function, localMsg.constData()); + break; + case QtCriticalMsg: + fprintf(stderr, "\033[41;30mCritical: (%s:%u, %s) \t%s\n\033[0m", context.file, context.line, + context.function, localMsg.constData()); + break; + case QtFatalMsg: + fprintf(stderr, "\033[41;30mFatal: (%s:%u, %s) \t%s\n\033[0m", context.file, context.line, + context.function, localMsg.constData()); + abort(); + } +} + +void consoleHandlerColored(QtMsgType type, const QMessageLogContext& context, const QString& msg) { + QByteArray localMsg = msg.toLocal8Bit(); + switch (type) { + case QtDebugMsg: + fprintf(stderr, "\033[1;30mDebug: (%s:%u) \t%s\n\033[0m", context.file, context.line, + localMsg.constData()); + break; + case QtInfoMsg: + fprintf(stderr, "\033[0;30mInfo: (%s:%u) \t%s\n\033[0m", context.file, context.line, + localMsg.constData()); + break; + case QtWarningMsg: + fprintf(stderr, "\033[1;33mWarning: (%s:%u) \t%s\n\033[0m", context.file, context.line, + localMsg.constData()); + break; + case QtCriticalMsg: + fprintf(stderr, "\033[31mCritical: (%s:%u) \t%s\n\033[0m", context.file, context.line, + localMsg.constData()); + break; + case QtFatalMsg: + fprintf(stderr, "\033[31mFatal: (%s:%u) \t%s\n\033[0m", context.file, context.line, + localMsg.constData()); + abort(); + } +} + +void myMessageOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg) { + QByteArray localMsg = msg.toLocal8Bit(); + switch (type) { + case QtDebugMsg: + fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, + context.function); + break; + case QtInfoMsg: + fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, + context.function); + break; + case QtWarningMsg: + fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, + context.function); + break; + case QtCriticalMsg: + fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, + context.line, context.function); + break; + case QtFatalMsg: + fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, + context.function); + abort(); + } +} + +#ifdef Q_OS_ANDROID +#include + +const char* const applicationName = "Pensieve"; +void androidMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) { + QString report = msg; + if (context.file && !QString(context.file).isEmpty()) { + report += " in file "; + report += QString(context.file); + report += " line "; + report += QString::number(context.line); + } + if (context.function && !QString(context.function).isEmpty()) { + report += +" function "; + report += QString(context.function); + } + const char* const local = report.toLocal8Bit().constData(); + switch (type) { + case QtDebugMsg: + __android_log_write(ANDROID_LOG_DEBUG, applicationName, local); + break; + case QtInfoMsg: + __android_log_write(ANDROID_LOG_INFO, applicationName, local); + break; + case QtWarningMsg: + __android_log_write(ANDROID_LOG_WARN, applicationName, local); + break; + case QtCriticalMsg: + __android_log_write(ANDROID_LOG_ERROR, applicationName, local); + break; + case QtFatalMsg: + default: + __android_log_write(ANDROID_LOG_FATAL, applicationName, local); + abort(); + } +} +#endif + +#endif // MESSAGEHANDLER_H