[Simulator] Asynchronous SimulatorInterface & a few new features. (#4738)
[opentx.git] / companion / src / appdebugmessagehandler.cpp
blobab2ee3858c6f2db169c01a3dcbda566ad6cce7bf
1 /*
2 * Copyright (C) OpenTX
4 * Based on code named
5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
21 #include "appdebugmessagehandler.h"
23 AppDebugMessageHandler::AppDebugMessageHandler(QObject * parent) :
24 QObject(parent),
25 m_appDebugOutputLevel(APP_DBG_HANDLER_DEFAULT_LEVEL),
26 m_showSourcePath(APP_DBG_HANDLER_SHOW_SRC_PATH),
27 m_showFunctionDeclarations(APP_DBG_HANDLER_SHOW_FUNCTION_DECL)
29 m_srcPathFilter = QRegularExpression("^" APP_DBG_HANDLER_SRC_PATH "[\\\\\\/](.*?)$", QRegularExpression::InvertedGreedinessOption);
30 m_functionFilter = QRegularExpression("^.+?(\\w+\\().+$");
33 AppDebugMessageHandler * AppDebugMessageHandler::instance()
35 static AppDebugMessageHandler * _instance = NULL;
36 #if APP_DBG_HANDLER_ENABLE
37 if(_instance == NULL && !qApp->closingDown())
38 _instance = new AppDebugMessageHandler(qApp); // Ensure this object is cleaned up when the QApplication exits.
39 #endif
40 return _instance;
43 void AppDebugMessageHandler::setAppDebugOutputLevel(const quint8 & appDebugOutputLevel)
45 m_appDebugOutputLevel = appDebugOutputLevel;
48 void AppDebugMessageHandler::setShowSourcePath(bool showSourcePath)
50 m_showSourcePath = showSourcePath;
53 void AppDebugMessageHandler::setShowFunctionDeclarations(bool showFunctionDeclarations)
55 m_showFunctionDeclarations = showFunctionDeclarations;
58 void AppDebugMessageHandler::installAppMessageHandler()
60 m_defaultHandler = qInstallMessageHandler(g_appDebugMessageHandler);
63 void AppDebugMessageHandler::messageHandler(QtMsgType type, const QMessageLogContext & context, const QString & msg)
65 static const char symbols[] = { 'D', 'W', 'E', 'X', 'I' }; // correspond to QtMsgType enum
66 // normalize types, QtDebugMsg stays 0, QtInfoMsg becomes 1, rest are QtMsgType + 1
67 quint8 lvl = type;
68 if (type == QtInfoMsg)
69 lvl = 1;
70 else if (type > QtDebugMsg)
71 ++lvl;
73 if (lvl < m_appDebugOutputLevel && type != QtFatalMsg)
74 return;
76 #if defined(Q_OS_LINUX) && (QT_VERSION < QT_VERSION_CHECK(5, 3, 0))
77 // Filter out lots of QPainter warnings from undocked QDockWidgets... hackish but effective (only workaround found so far)
78 if (lvl == 2 && QString(context.function).contains("QPainter::"))
79 return;
80 #endif
82 QString msgPattern = QString("[%1] ").arg(symbols[type]);
84 if (m_showSourcePath) {
85 QString file = QString("%1::").arg(context.file);
86 file.replace(m_srcPathFilter, "\\1");
87 msgPattern.append(file);
89 if (m_showFunctionDeclarations)
90 msgPattern.append(context.function);
91 else
92 msgPattern.append("%{function}()");
94 msgPattern.append(":%{line} -%{if-category} [%{category}]%{endif} %{message}");
96 if (type == QtFatalMsg)
97 msgPattern.append("\nBACKTRACE:\n%{backtrace depth=12 separator=\"\n\"}");
99 qSetMessagePattern(msgPattern);
101 if (!m_defaultHandler || receivers(SIGNAL(messageOutput(quint8, const QString &)))) {
102 #if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
103 msgPattern = qFormatLogMessage(type, context, msg);
104 #else
105 msgPattern.replace("%{line}", QString::number(context.line));
106 msgPattern.replace("%{if-category} [%{category}]%{endif}", QString(context.category));
107 msgPattern.replace("%{message}", msg);
108 if (!m_showFunctionDeclarations) {
109 QString func = context.function;
110 msgPattern.replace("%{function}", func.replace(m_functionFilter, "\\1)"));
112 #endif
114 emit messageOutput(lvl, msgPattern);
117 // if (QThread::currentThread() == qApp->thread()) // gui thread
119 if (m_defaultHandler) {
120 m_defaultHandler(type, context, msg);
122 else {
123 fprintf(stderr, "%s", qPrintable(msgPattern));
124 if (type == QtFatalMsg)
125 abort();
129 // Message handler which is installed using qInstallMessageHandler. This needs to be global.
130 void g_appDebugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
132 if (AppDebugMessageHandler::instance())
133 AppDebugMessageHandler::instance()->messageHandler(type, context, msg);