* [AppDebugMessageHandler] Add ability to write debug output to any number of QIODevices. * [Simulator][DebugOutput] Use new QIODevice hook in AppDebugMessageHandler instead of signal/slot. * [AppData] Add new settings for debug logging; Refactor property creation macro to work with any data type and add varName_init() method to set default; Refactor all boolean settings to use new macro (others to be migrated later). * [AppPreferencesDialog] Add UI for appDebugLog, fwTraceLog, & appLogsDir settings; Clean up layout on application prefs. tab, move and re-label a couple items. * [Companion][Simulator] Enable optional application debug output logging. * [Simulator] Enable optional logging of firmware debug output to file. * [EEPROMInterface] Use qDebug() instead of std::cout so that now all debug output can be routed via custom message handler/logger. * [Companion][Simulator] Add missing #include.
143 lines
5.1 KiB
C++
143 lines
5.1 KiB
C++
/*
|
|
* Copyright (C) OpenTX
|
|
*
|
|
* Based on code named
|
|
* th9x - http://code.google.com/p/th9x
|
|
* er9x - http://code.google.com/p/er9x
|
|
* gruvin9x - http://code.google.com/p/gruvin9x
|
|
*
|
|
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#ifndef APPDEBUGMESSAGEHANDLER_H
|
|
#define APPDEBUGMESSAGEHANDLER_H
|
|
|
|
#include <cstdlib>
|
|
#include <iostream>
|
|
|
|
#include <QApplication>
|
|
#include <QDebug>
|
|
#include <QIODevice>
|
|
#include <QMessageLogContext>
|
|
#include <QObject>
|
|
#include <QRegularExpression>
|
|
#include <QString>
|
|
|
|
/*
|
|
* Custom debug/message handler class to work in conjunction with qDebug() family of functions.
|
|
* Formats all stderr output generated by the application in a consistent manner.
|
|
* It can also be used by other event listeners to intercept messages they may be interested in (connect to messageOutput() signal).
|
|
*
|
|
* Include this header to use qInfo() safely with Qt < v5.5 (qInfo becomes alias for qDebug).
|
|
*
|
|
* Note that the default message format can still be overriden by setting QT_MESSAGE_PATTERN environment variable at _runtime_.
|
|
* see: https://doc.qt.io/qt-5/qtglobal.html#qSetMessagePattern
|
|
*
|
|
* This is an app-wide "global" thread-safe singleton class, use it with AppDebugMessageHandler::instance().
|
|
* For example, at start of application:
|
|
*
|
|
* QApplication app(argc, argv);
|
|
* AppDebugMessageHandler::instance()->installAppMessageHandler();
|
|
*
|
|
* To connect to a signal:
|
|
*
|
|
* connect(AppDebugMessageHandler::instance(), &AppDebugMessageHandler::messageOutput, this, &DebugOutput::onAppDebugMessage);
|
|
*
|
|
* This singleton will self-destruct upon QApplication termination.
|
|
*
|
|
*/
|
|
|
|
#if defined(QT_DEBUG) || defined(DEBUG)
|
|
#define APP_DBG_HANDLER_IS_DBG_BUILD 1
|
|
#else
|
|
#define APP_DBG_HANDLER_IS_DBG_BUILD 0
|
|
#endif
|
|
|
|
// Enable/disable this custom handler handler entirely
|
|
#ifndef APP_DBG_HANDLER_ENABLE
|
|
#define APP_DBG_HANDLER_ENABLE 1
|
|
#endif
|
|
|
|
// Default log level (can also be set with setAppDebugOutputLevel()):
|
|
// 0 = debug+; 1 = info+; 2 = warn+; 3 = critical+; 4 = fatal only
|
|
#ifndef APP_DBG_HANDLER_DEFAULT_LEVEL
|
|
#define APP_DBG_HANDLER_DEFAULT_LEVEL 0
|
|
#endif
|
|
|
|
// Include source file path/name in output (filtered with APP_DBG_HANDLER_SRC_PATH)
|
|
#ifndef APP_DBG_HANDLER_SHOW_SRC_PATH
|
|
#define APP_DBG_HANDLER_SHOW_SRC_PATH APP_DBG_HANDLER_IS_DBG_BUILD
|
|
#endif
|
|
|
|
// Show just the function Class::name vs. full declaration with return and param types
|
|
#ifndef APP_DBG_HANDLER_SHOW_FUNCTION_DECL
|
|
#define APP_DBG_HANDLER_SHOW_FUNCTION_DECL 0
|
|
#endif
|
|
|
|
// base path for source file name filter, everything after this is kept; RegEx, non-greedy
|
|
#ifndef APP_DBG_HANDLER_SRC_PATH
|
|
#define APP_DBG_HANDLER_SRC_PATH ".*src"
|
|
#endif
|
|
|
|
// Make sure to include this header if using qInfo()
|
|
#if (QT_VERSION < QT_VERSION_CHECK(5, 5, 0))
|
|
#if defined(QT_NO_INFO_OUTPUT)
|
|
#define qInfo QT_NO_QDEBUG_MACRO
|
|
#else
|
|
#define qInfo qDebug
|
|
#endif
|
|
#define QtInfoMsg QtMsgType(4)
|
|
#endif
|
|
|
|
class AppDebugMessageHandler : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
// This class implements the singleton design pattern and is therefore publicly accessible only through instance().
|
|
static AppDebugMessageHandler * instance();
|
|
AppDebugMessageHandler(AppDebugMessageHandler const &) = delete;
|
|
void operator = (AppDebugMessageHandler const &) = delete;
|
|
|
|
void setAppDebugOutputLevel(const quint8 & appDebugOutputLevel);
|
|
void setShowSourcePath(bool showSourcePath);
|
|
void setShowFunctionDeclarations(bool showFunctionDeclarations);
|
|
void addOutputDevice(QIODevice * device);
|
|
void removeOutputDevice(QIODevice * device);
|
|
|
|
void installAppMessageHandler();
|
|
void messageHandler(QtMsgType type, const QMessageLogContext & context, const QString & msg);
|
|
|
|
private:
|
|
// This class implements the singleton design pattern and therefore has only a private constructor.
|
|
explicit AppDebugMessageHandler(QObject * parent = Q_NULLPTR);
|
|
~AppDebugMessageHandler() { }
|
|
|
|
QtMessageHandler m_defaultHandler;
|
|
QRegularExpression m_srcPathFilter;
|
|
QRegularExpression m_functionFilter;
|
|
quint8 m_appDebugOutputLevel;
|
|
QVector<QIODevice *> m_outputDevices;
|
|
bool m_showSourcePath;
|
|
bool m_showFunctionDeclarations;
|
|
|
|
signals:
|
|
void messageOutput(quint8 level, const QString & msg);
|
|
};
|
|
|
|
// Message handler which is installed using qInstallMessageHandler. This needs to be global.
|
|
// Use AppDebugMessageHandler::instance()->installAppMessageHandler();
|
|
// instead of installing this function directly (it will verify this handler is enabled, etc).
|
|
void g_appDebugMessageHandler(QtMsgType, const QMessageLogContext &, const QString &);
|
|
|
|
#endif // APPDEBUGMESSAGEHANDLER_H
|