#include "message_handler.h" #include #include #define OUTPUT_LEN (512) static bool installedMsgHandler = false; static QtMsgType debugLevel = QtInfoMsg; QtMsgType getDebugLevel() { return debugLevel; } void setDebugLevel(QtMsgType newDebugLevel) { debugLevel = newDebugLevel; } bool messageHandlerInstalled() { return installedMsgHandler; } QtMessageHandler atbInstallMessageHandler(QtMessageHandler handler) { installedMsgHandler = (handler != 0); static QtMessageHandler prevHandler = nullptr; if (handler) { prevHandler = qInstallMessageHandler(handler); return prevHandler; } else { return qInstallMessageHandler(prevHandler); } } /// /// \brief Print message according to given debug level. /// /// \note Install this function using qInstallMsgHandler(). /// /// int main(int argc, char **argv) { /// installMsgHandler(atbDebugOutput); /// QApplication app(argc, argv); /// ... /// return app.exec(); /// } /// #if (QT_VERSION > QT_VERSION_CHECK(5, 0, 0) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) void atbDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) { static constexpr const char *format = "hh:mm:ss"; // static constexpr const char *format = "dd.MM.yyyy hh:mm:ss"; QByteArray localMsg = msg.toLocal8Bit(); const char *file = context.file ? context.file : ""; const char *function = context.function ? context.function : ""; const char *p = std::strstr(function, "::"); if (p) { function = p + 2; } char const* output = std::strrchr(file, '/'); if (output) { file = output + 1; } qint64 const currentMSecsSinceEpoch = QDateTime::currentMSecsSinceEpoch(); int const fractional_part = currentMSecsSinceEpoch % 1000; char buf[OUTPUT_LEN]{}; memset(buf, 0x00, sizeof(buf)); QDateTime const datetime = QDateTime::fromMSecsSinceEpoch(currentMSecsSinceEpoch); switch (type) { case QtDebugMsg: { if (debugLevel == QtDebugMsg) { snprintf(buf, sizeof(buf)-1, "%30.30s (%20.20s:%04u) %s.%03d DEBG %s", function, file, context.line, datetime.time().toString(format).toStdString().c_str(), fractional_part, localMsg.constData()); fprintf(stderr, "%s\n", buf); } } break; case QtInfoMsg: { if (debugLevel == QtInfoMsg || debugLevel == QtDebugMsg) { snprintf(buf, sizeof(buf)-1, "%30.30s (%20.20s:%04u) %s.%03d INFO %s", function, file, context.line, datetime.time().toString(format).toStdString().c_str(), fractional_part, localMsg.constData()); fprintf(stderr, "%s\n", buf); } } break; case QtWarningMsg: { if (debugLevel == QtInfoMsg || debugLevel == QtDebugMsg || debugLevel == QtWarningMsg) { snprintf(buf, sizeof(buf)-1, "%30.30s (%20.20s:%04u) %s.%03d WARN %s", function, file, context.line, datetime.time().toString(format).toStdString().c_str(), fractional_part, localMsg.constData()); fprintf(stderr, "%s\n", buf); } } break; case QtCriticalMsg: { if (debugLevel == QtInfoMsg || debugLevel == QtDebugMsg || debugLevel == QtWarningMsg || debugLevel == QtCriticalMsg) { snprintf(buf, sizeof(buf)-1, "%30.30s (%20.20s:%04u) %s.%03d CRIT %s", function, file, context.line, datetime.time().toString(format).toStdString().c_str(), fractional_part, localMsg.constData()); fprintf(stderr, "%s\n", buf); } } break; case QtFatalMsg: { if (debugLevel == QtInfoMsg || debugLevel == QtDebugMsg || debugLevel == QtWarningMsg || debugLevel == QtCriticalMsg || debugLevel == QtFatalMsg) { snprintf(buf, sizeof(buf)-1, "%30.30s (%20.20s:%04u) %s.%03d FATAL %s", function, file, context.line, datetime.time().toString(format).toStdString().c_str(), fractional_part, localMsg.constData()); fprintf(stderr, "%s\n", buf); } } break; default: { fprintf(stderr, "%*.*s.%03d No ErrorLevel defined! %s\n", OUTPUT_LEN, OUTPUT_LEN, datetime.time().toString(format).toStdString().c_str(), fractional_part, msg.toStdString().c_str()); } } } #endif