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
) :
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.
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
68 if (type
== QtInfoMsg
)
70 else if (type
> QtDebugMsg
)
73 if (lvl
< m_appDebugOutputLevel
&& type
!= QtFatalMsg
)
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::"))
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
);
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
);
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)"));
114 emit
messageOutput(lvl
, msgPattern
);
117 // if (QThread::currentThread() == qApp->thread()) // gui thread
119 if (m_defaultHandler
) {
120 m_defaultHandler(type
, context
, msg
);
123 fprintf(stderr
, "%s", qPrintable(msgPattern
));
124 if (type
== QtFatalMsg
)
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
);