From 00b2799427a454478b379bef275498166f5f1f10 Mon Sep 17 00:00:00 2001 From: Max Paperno Date: Thu, 2 Mar 2017 12:35:00 -0500 Subject: [PATCH] [Companion][Simulator] Add custom qDebug message handler/formatter (#4475) * [Companion][Simulator] Add custom qDebug message handler/formatter as an option. Keeps support for QT_MESSAGE_PATTERN env. var. * [Simulator] Show system messages of level qInfo and above in debug console. * [Simulator] Still capture screenshot to clipboard if path is not accessible (and screenshot results now print to simulator debug console). * Fix for older CMake. * [Companion] Do not start debug message handler if app is shutting down, and add null checks before using it; Increase backtrace report depth; Add OTx headers; Add Companion exit status debug; Clean up unused code. * [Simulator] Add asynchronous FIFO buffer for handling debug output/display more efficiently. (#4488) (cherry-picked from b12bd7d7be78df9900e26ed5ea8bf29d1636cc3b) --- CMakeLists.txt | 24 +++ companion/src/CMakeLists.txt | 10 +- companion/src/appdebugmessagehandler.cpp | 128 ++++++++++++++++ companion/src/appdebugmessagehandler.h | 138 ++++++++++++++++++ companion/src/companion.cpp | 23 ++- companion/src/mainwindow.cpp | 6 - companion/src/mdichild.cpp | 7 - companion/src/simulation/debugoutput.cpp | 14 ++ companion/src/simulation/debugoutput.h | 2 + .../src/simulation/simulateduiwidget.cpp | 18 +-- companion/src/simulation/simulatorwidget.cpp | 10 +- companion/src/simulation/widgets/lcdwidget.h | 7 +- companion/src/simulator.cpp | 29 +--- radio/src/targets/simu/CMakeLists.txt | 8 +- 14 files changed, 352 insertions(+), 72 deletions(-) create mode 100644 companion/src/appdebugmessagehandler.cpp create mode 100644 companion/src/appdebugmessagehandler.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 119c598f7..022086459 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,8 +43,16 @@ git_id(GIT_STR) message(STATUS "OpenTX ${VERSION} @${GIT_STR}") # options shared by all targets + +option(APP_CUSTOM_DBG_HANDLER "Use custom message handler for debug output in all Qt apps." ON) +set(APP_CUSTOM_DBG_LEVEL "0" CACHE STRING + "Debug output level: 0=debug+; 1=info+; 2=warn+; 3=critical+; 4=fatal only.") +set(APP_CUSTOM_DBG_SHOW_FILE "DEFAULT" CACHE STRING + "Show source file names in debug output. 1/0/DEFAULT (default is ON with DEBUG builds).") + option(VERBOSE_CMAKELISTS "Show extra information while processing CMakeLists.txt files." OFF) option(WARNINGS_AS_ERRORS "Treat any compiler warning as an error (adds -Werror flag)." OFF) + if(WIN32) set(WIN_EXTRA_LIBS_PATH "C:/Programs" CACHE PATH "Base path to extra libs/headers on Windows (SDL & pthreads folders should be in here).") @@ -60,6 +68,22 @@ find_package(Qt5Svg) if(Qt5Widgets_FOUND) message(STATUS "Qt Version: ${Qt5Widgets_VERSION}") + list(APPEND APP_COMMON_DEFINES -DSIMU) + list(APPEND APP_COMMON_DEFINES -DQXT_STATIC) + list(APPEND APP_COMMON_DEFINES -DQT_USE_QSTRINGBUILDER) # more efficient QString construction using % operator + if(APP_CUSTOM_DBG_HANDLER) + # provide full qDebug log context to our custom handler. This may also affect libsimulator, which is why it is here + list(APPEND APP_COMMON_DEFINES -DQT_MESSAGELOGCONTEXT) + list(APPEND APP_COMMON_DEFINES -DAPP_DBG_HANDLER_ENABLE=1) + if(APP_CUSTOM_DBG_LEVEL GREATER -1 AND APP_CUSTOM_DBG_LEVEL LESS 5) + list(APPEND APP_COMMON_DEFINES -DAPP_DBG_HANDLER_DEFAULT_LEVEL=${APP_CUSTOM_DBG_LEVEL}) + endif() + if(NOT APP_CUSTOM_DBG_SHOW_FILE STREQUAL "DEFAULT" AND (APP_CUSTOM_DBG_SHOW_FILE STREQUAL "1" OR APP_CUSTOM_DBG_SHOW_FILE STREQUAL "0")) + list(APPEND APP_COMMON_DEFINES -DAPP_DBG_HANDLER_SHOW_SRC_PATH=${APP_CUSTOM_DBG_SHOW_FILE}) + endif() + else() + list(APPEND APP_COMMON_DEFINES -DAPP_DBG_HANDLER_ENABLE=0) + endif() else() message(WARNING "Qt not found! Companion and Simulator builds disabled.") endif() diff --git a/companion/src/CMakeLists.txt b/companion/src/CMakeLists.txt index ebc6ed137..34b8ca442 100644 --- a/companion/src/CMakeLists.txt +++ b/companion/src/CMakeLists.txt @@ -51,8 +51,7 @@ if(SDL_FOUND) add_definitions(-DJOYSTICKS) endif() -add_definitions(-DSIMU) -add_definitions(-DQXT_STATIC) +add_definitions(${APP_COMMON_DEFINES}) # set in top-level CMakeLists if(NOT MSVC) set(WARNING_FLAGS "${WARNING_FLAGS} -Wall") @@ -115,6 +114,7 @@ add_subdirectory(thirdparty/qxtcommandoptions) ############# Common lib ############### set(common_SRCS + appdebugmessagehandler.cpp boards.cpp eeprominterface.cpp radiodata.cpp @@ -126,7 +126,11 @@ set(common_SRCS firmwares/opentx/opentxinterface.cpp ) -qt5_wrap_cpp(common_SRCS) +set(common_MOC_HDRS + appdebugmessagehandler.h + ) + +qt5_wrap_cpp(common_SRCS ${common_MOC_HDRS}) add_library(common ${common_SRCS}) qt5_use_modules(common Core Xml Widgets) diff --git a/companion/src/appdebugmessagehandler.cpp b/companion/src/appdebugmessagehandler.cpp new file mode 100644 index 000000000..bf817191c --- /dev/null +++ b/companion/src/appdebugmessagehandler.cpp @@ -0,0 +1,128 @@ +/* + * 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. + */ + +#include "appdebugmessagehandler.h" + +AppDebugMessageHandler::AppDebugMessageHandler(QObject * parent) : + QObject(parent), + m_appDebugOutputLevel(APP_DBG_HANDLER_DEFAULT_LEVEL), + m_showSourcePath(APP_DBG_HANDLER_SHOW_SRC_PATH), + m_showFunctionDeclarations(APP_DBG_HANDLER_SHOW_FUNCTION_DECL) +{ + m_srcPathFilter = QRegularExpression("^" APP_DBG_HANDLER_SRC_PATH "[\\\\\\/](.*?)$", QRegularExpression::InvertedGreedinessOption); + m_functionFilter = QRegularExpression("^.+?(\\w+\\().+$"); +} + +AppDebugMessageHandler * AppDebugMessageHandler::instance() +{ + static AppDebugMessageHandler * _instance = NULL; + if(_instance == NULL && !qApp->closingDown()) + _instance = new AppDebugMessageHandler(qApp); // Ensure this object is cleaned up when the QApplication exits. + return _instance; +} + +void AppDebugMessageHandler::setAppDebugOutputLevel(const quint8 & appDebugOutputLevel) +{ + m_appDebugOutputLevel = appDebugOutputLevel; +} + +void AppDebugMessageHandler::setShowSourcePath(bool showSourcePath) +{ + m_showSourcePath = showSourcePath; +} + +void AppDebugMessageHandler::setShowFunctionDeclarations(bool showFunctionDeclarations) +{ + m_showFunctionDeclarations = showFunctionDeclarations; +} + +void AppDebugMessageHandler::installAppMessageHandler() +{ +#if APP_DBG_HANDLER_ENABLE + m_defaultHandler = qInstallMessageHandler(g_appDebugMessageHandler); +#endif +} + +void AppDebugMessageHandler::messageHandler(QtMsgType type, const QMessageLogContext & context, const QString & msg) +{ + static const char symbols[] = { 'D', 'W', 'E', 'X', 'I' }; // correspond to QtMsgType enum + // normalize types, QtDebugMsg stays 0, QtInfoMsg becomes 1, rest are QtMsgType + 1 + quint8 lvl = type; + if (type == QtInfoMsg) + lvl = 1; + else if (type > QtDebugMsg) + ++lvl; + + if (lvl < m_appDebugOutputLevel && type != QtFatalMsg) + return; + + QString msgPattern = QString("[%1] ").arg(symbols[type]); + + if (m_showSourcePath) { + QString file = QString("%1::").arg(context.file); + file.replace(m_srcPathFilter, "\\1"); + msgPattern.append(file); + } + if (m_showFunctionDeclarations) + msgPattern.append(context.function); + else + msgPattern.append("%{function}()"); + + msgPattern.append(":%{line} -%{if-category} [%{category}]%{endif} %{message}"); + + if (type == QtFatalMsg) + msgPattern.append("\nBACKTRACE:\n%{backtrace depth=12 separator=\"\n\"}"); + + qSetMessagePattern(msgPattern); + + if (!m_defaultHandler || receivers(SIGNAL(messageOutput(quint8, const QString &, const QMessageLogContext &)))) { +#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)) + msgPattern = qFormatLogMessage(type, context, msg); +#else + msgPattern.replace("%{line}", QString::number(context.line)); + msgPattern.replace("%{if-category} [%{category}]%{endif}", QString(context.category)); + msgPattern.replace("%{message}", msg); + if (!m_showFunctionDeclarations) { + QString func = context.function; + msgPattern.replace(QString("%{function}"), func.replace(m_functionFilter, "\\1)")); + } +#endif + + emit messageOutput(lvl, msgPattern, context); + } + + // if (QThread::currentThread() == qApp->thread()) // gui thread + + if (m_defaultHandler) { + m_defaultHandler(type, context, msg); + } + else { + fprintf(stderr, "%s", qPrintable(msgPattern)); + if (type == QtFatalMsg) + abort(); + } +} + +// Message handler which is installed using qInstallMessageHandler. This needs to be global. +void g_appDebugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + if (AppDebugMessageHandler::instance()) + AppDebugMessageHandler::instance()->messageHandler(type, context, msg); +} diff --git a/companion/src/appdebugmessagehandler.h b/companion/src/appdebugmessagehandler.h new file mode 100644 index 000000000..1e79ef63e --- /dev/null +++ b/companion/src/appdebugmessagehandler.h @@ -0,0 +1,138 @@ +/* + * 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 +#include + +#include +#include +#include +#include +#include +#include + +/* + * 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 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 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; + bool m_showSourcePath; + bool m_showFunctionDeclarations; + + signals: + void messageOutput(quint8 level, const QString & msg, const QMessageLogContext & context); +}; + +// 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 diff --git a/companion/src/companion.cpp b/companion/src/companion.cpp index e4f5d6418..6f58684f1 100644 --- a/companion/src/companion.cpp +++ b/companion/src/companion.cpp @@ -26,20 +26,15 @@ #include #undef main #endif + +#include "appdebugmessagehandler.h" #include "mainwindow.h" #include "version.h" #include "appdata.h" #include "storage.h" -#if defined _MSC_VER || !defined __GNUC__ -#include -#define sleep(x) Sleep(x*1000) -#else -#include -#endif - #ifdef __APPLE__ -#include +#include class MyProxyStyle : public QProxyStyle { @@ -62,11 +57,14 @@ int main(int argc, char *argv[]) #endif QApplication app(argc, argv); - app.setApplicationName("OpenTX Companion"); - app.setOrganizationName("OpenTX"); - app.setOrganizationDomain("open-tx.org"); + app.setApplicationName(APP_COMPANION); + app.setOrganizationName(COMPANY); + app.setOrganizationDomain(COMPANY_DOMAIN); app.setAttribute(Qt::AA_DontShowIconsInMenus, false); + if (AppDebugMessageHandler::instance()) + AppDebugMessageHandler::instance()->installAppMessageHandler(); + g.init(); QStringList strl = QApplication::arguments(); @@ -101,7 +99,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "ERROR: couldn't initialize SDL: %s\n", SDL_GetError()); } #endif - + registerStorageFactories(); registerOpenTxFirmwares(); registerSimulators(); @@ -142,5 +140,6 @@ int main(int argc, char *argv[]) SDL_Quit(); #endif + qDebug() << "COMPANION EXIT" << result; return result; } diff --git a/companion/src/mainwindow.cpp b/companion/src/mainwindow.cpp index c7694494a..4579d342a 100644 --- a/companion/src/mainwindow.cpp +++ b/companion/src/mainwindow.cpp @@ -61,12 +61,6 @@ #define COMPANION_INSTALLER "companion-windows-%1.exe" #endif -#if defined _MSC_VER || !defined __GNUC__ - #include - #define sleep(x) Sleep(x*1000) -#else - #include -#endif #ifdef WIN32 #define OPENTX_NIGHT_COMPANION_DOWNLOADS "http://downloads-22.open-tx.org/nightly/companion/windows" #else diff --git a/companion/src/mdichild.cpp b/companion/src/mdichild.cpp index 6d103f6ff..aacec7cdd 100644 --- a/companion/src/mdichild.cpp +++ b/companion/src/mdichild.cpp @@ -33,13 +33,6 @@ #include "storage.h" #include "radiointerface.h" -#if defined _MSC_VER || !defined __GNUC__ -#include -#define sleep(x) Sleep(x*1000) -#else -#include -#endif - MdiChild::MdiChild(MainWindow * parent): QWidget(), parent(parent), diff --git a/companion/src/simulation/debugoutput.cpp b/companion/src/simulation/debugoutput.cpp index 66c5e43d6..1bd08b936 100644 --- a/companion/src/simulation/debugoutput.cpp +++ b/companion/src/simulation/debugoutput.cpp @@ -21,6 +21,7 @@ #include "debugoutput.h" #include "ui_debugoutput.h" +#include "appdebugmessagehandler.h" #include "appdata.h" #include "filteredtextbuffer.h" @@ -100,6 +101,9 @@ DebugOutput::DebugOutput(QWidget * parent, SimulatorInterface *simulator): connect(ui->actionToggleFilter, &QAction::toggled, this, &DebugOutput::onFilterToggled); connect(ui->filterText, &QComboBox::currentTextChanged, this, &DebugOutput::onFilterTextChanged); + if (AppDebugMessageHandler::instance()) + connect(AppDebugMessageHandler::instance(), &AppDebugMessageHandler::messageOutput, this, &DebugOutput::onAppDebugMessage); + // send firmware TRACE events to our data collector m_simulator->installTraceHook(firmwareTraceCb); } @@ -108,6 +112,8 @@ DebugOutput::~DebugOutput() { saveState(); + if (AppDebugMessageHandler::instance()) + disconnect(AppDebugMessageHandler::instance(), 0, this, 0); if (m_dataBufferDevice) { disconnect(m_dataBufferDevice, 0, this, 0); @@ -198,6 +204,14 @@ void DebugOutput::onDataBufferOverflow(const qint64 len) } } +void DebugOutput::onAppDebugMessage(quint8 level, const QString & msg, const QMessageLogContext & context) +{ + if (level > 0) { + firmwareTraceCb(qPrintable(msg)); + firmwareTraceCb("\n"); + } +} + /* * UI handlers */ diff --git a/companion/src/simulation/debugoutput.h b/companion/src/simulation/debugoutput.h index 33dd4e635..72b51b9b4 100644 --- a/companion/src/simulation/debugoutput.h +++ b/companion/src/simulation/debugoutput.h @@ -44,6 +44,7 @@ namespace Ui { } class QAbstractButton; +class QMessageLogContext; class FilteredTextBuffer; using namespace Simulator; @@ -71,6 +72,7 @@ class DebugOutput : public QWidget void restoreState(); void processBytesReceived(); void onDataBufferOverflow(const qint64 len); + void onAppDebugMessage(quint8 level, const QString & msg, const QMessageLogContext & context); void onFilterStateChanged(); void onFilterTextChanged(const QString &); void onFilterToggled(bool enable); diff --git a/companion/src/simulation/simulateduiwidget.cpp b/companion/src/simulation/simulateduiwidget.cpp index 43895746b..fc4ed35bb 100644 --- a/companion/src/simulation/simulateduiwidget.cpp +++ b/companion/src/simulation/simulateduiwidget.cpp @@ -122,16 +122,16 @@ void SimulatedUIWidget::captureScreenshot() if (path.isEmpty()) path = "./"; QDir dir(path); - if (!dir.exists() || !dir.isReadable()) { - // m_simulator->traceCallback("SIMULATOR ERROR - Cannot open screenshot folder, check your settings.\n"); - qDebug() << "SIMULATOR ERROR - Cannot open screenshot folder, check your settings."; - return; + if (dir.exists() && dir.isReadable()) { + QStringList fwid = getCurrentFirmware()->getId().split("-", QString::SkipEmptyParts); + QString flavor = fwid.at(qMin(1, fwid.size())); + QString fnpfx = tr("screenshot", "Simulator LCD screenshot file name prefix"); + fileName = "%1/%2_%3_%4.png"; + fileName = fileName.arg(dir.absolutePath(), fnpfx, flavor, QDateTime::currentDateTime().toString("yy-MM-dd_HH-mm-ss")); + } + else { + qWarning() << "SIMULATOR ERROR - Cannot open screenshot folder, check your settings."; } - QStringList fwid = getCurrentFirmware()->getId().split("-", QString::SkipEmptyParts); - QString flavor = fwid.at(qMin(1, fwid.size())); - QString fnpfx = tr("screenshot", "Simulator LCD screenshot file name prefix"); - fileName = "%1/%2_%3_%4.png"; - fileName = fileName.arg(dir.absolutePath(), fnpfx, flavor, QDateTime::currentDateTime().toString("yy-MM-dd_HH-mm-ss")); } m_lcd->makeScreenshot(fileName); } diff --git a/companion/src/simulation/simulatorwidget.cpp b/companion/src/simulation/simulatorwidget.cpp index e6d489046..a673355d8 100644 --- a/companion/src/simulation/simulatorwidget.cpp +++ b/companion/src/simulation/simulatorwidget.cpp @@ -22,6 +22,7 @@ #include "ui_simulatorwidget.h" #include "appdata.h" +#include "appdebugmessagehandler.h" #include "radiofaderwidget.h" #include "radioknobwidget.h" #include "radioswitchwidget.h" @@ -36,7 +37,6 @@ #include "joystickdialog.h" #endif -#include #include #include @@ -332,11 +332,11 @@ bool SimulatorWidget::useTempDataPath(bool deleteOnClose) setDataPath(tmpDir.path()); tmpDir.setAutoRemove(false); deleteTempRadioData = deleteOnClose; - qDebug() << __FILE__ << __LINE__ << "Created temporary settings directory" << radioDataPath << "with delteOnClose:" << deleteOnClose; + qDebug() << "Created temporary settings directory" << radioDataPath << "with delteOnClose:" << deleteOnClose; return true; } else { - qDebug() << __FILE__ << __LINE__ << "ERROR : Failed to create temporary settings directory" << radioDataPath; + qCritical() << "ERROR : Failed to create temporary settings directory" << radioDataPath; return false; } } @@ -381,7 +381,7 @@ bool SimulatorWidget::saveTempData() if (!(ret = store.write(radioData))) error = store.error(); else - qDebug() << __FILE__ << __LINE__ << "Saved radio data to file" << file; + qInfo() << "Saved radio data to file" << file; } } @@ -398,7 +398,7 @@ void SimulatorWidget::deleteTempData() { if (!radioDataPath.isEmpty()) { QDir tpath(radioDataPath); - qDebug() << __FILE__ << __LINE__ << "Deleting temporary settings directory" << tpath.absolutePath(); + qDebug() << "Deleting temporary settings directory" << tpath.absolutePath(); tpath.removeRecursively(); tpath.rmdir(radioDataPath); // for some reason this is necessary to remove the base folder } diff --git a/companion/src/simulation/widgets/lcdwidget.h b/companion/src/simulation/widgets/lcdwidget.h index 50d396d61..355c9b5b5 100644 --- a/companion/src/simulation/widgets/lcdwidget.h +++ b/companion/src/simulation/widgets/lcdwidget.h @@ -26,8 +26,9 @@ #include #include #include -#include + #include "appdata.h" +#include "appdebugmessagehandler.h" class LcdWidget : public QWidget { @@ -90,12 +91,12 @@ class LcdWidget : public QWidget QPainter p(&buffer); doPaint(p); if (fileName.isEmpty()) { - qDebug() << "Screenshot saved to clipboard"; QApplication::clipboard()->setPixmap( buffer ); + qInfo() << "Screenshot saved to clipboard"; } else { - qDebug() << "Screenshot" << fileName; buffer.toImage().save(fileName); + qInfo() << "Screenshot saved to:" << fileName; } } diff --git a/companion/src/simulator.cpp b/companion/src/simulator.cpp index 1ef3bcbf5..3a767da7d 100644 --- a/companion/src/simulator.cpp +++ b/companion/src/simulator.cpp @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #if defined(JOYSTICKS) || defined(SIMU_AUDIO) @@ -33,6 +32,7 @@ #endif #include "appdata.h" +#include "appdebugmessagehandler.h" #include "constants.h" #include "eeprominterface.h" #include "simulator.h" @@ -42,16 +42,6 @@ #include "qxtcommandoptions.h" #include "version.h" -#ifdef WIN32 - #include - #ifdef _MSC_VER - #define sleep(x) Sleep(x*1000) - #endif -#endif -#if !defined(_MSC_VER) || defined(__GNUC__) -#include -#endif - using namespace Simulator; int finish(int exitCode); @@ -96,21 +86,15 @@ int main(int argc, char *argv[]) #if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif -#if defined(WIN32) && defined(WIN_USE_CONSOLE_STDIO) - if (!GetConsoleWindow()) { - AllocConsole(); - freopen("conin$", "r", stdin); - freopen("conout$", "w", stdout); - freopen("conout$", "w", stderr); - } - SetConsoleTitle(APP_SIMULATOR " Console"); -#endif QApplication app(argc, argv); app.setApplicationName(APP_SIMULATOR); app.setOrganizationName(COMPANY); app.setOrganizationDomain(COMPANY_DOMAIN); + if (AppDebugMessageHandler::instance()) + AppDebugMessageHandler::instance()->installAppMessageHandler(); + g.init(); QTranslator companionTranslator; @@ -219,7 +203,7 @@ int main(int argc, char *argv[]) return finish(0); } } - qDebug() << __FILE__ << __LINE__ << "profileId=" << profileId << simOptions; + qDebug() << "profileId=" << profileId << simOptions; if (profileId < 0 || simOptions.firmwareId.isEmpty() || (simOptions.dataFile.isEmpty() && simOptions.dataFolder.isEmpty())) { showMessage(QObject::tr("ERROR: Couldn't start simulator, missing radio/profile/data file/folder.\n Profile ID: [%1]; Radio ID: [%2];\nData File: [%3]") @@ -277,9 +261,6 @@ int finish(int exitCode) #if defined(JOYSTICKS) || defined(SIMU_AUDIO) SDL_Quit(); #endif -#if defined(WIN32) && defined(WIN_USE_CONSOLE_STDIO) - FreeConsole(); -#endif return exitCode; } diff --git a/radio/src/targets/simu/CMakeLists.txt b/radio/src/targets/simu/CMakeLists.txt index a1ae471f4..c72cdb85e 100644 --- a/radio/src/targets/simu/CMakeLists.txt +++ b/radio/src/targets/simu/CMakeLists.txt @@ -10,7 +10,6 @@ set(SIMU_SRC simudisk.cpp ) -add_definitions(-DSIMU) remove_definitions(-DCLI) if(SDL_FOUND) @@ -29,6 +28,7 @@ if(Qt5Widgets_FOUND) include_directories(${COMPANION_SRC_DIRECTORY} ${COMPANION_SRC_DIRECTORY}/simulation) add_library(${SIMULATOR_TARGET} SHARED ${SIMU_SRC} opentxsimulator.cpp) add_dependencies(${SIMULATOR_TARGET} ${FIRMWARE_DEPENDENCIES}) + target_compile_definitions(${SIMULATOR_TARGET} PUBLIC ${APP_COMMON_DEFINES}) # set in top-level CMakeLists target_link_libraries(${SIMULATOR_TARGET} ${SDL_LIBRARY}) qt5_use_modules(${SIMULATOR_TARGET} Core) add_custom_target(libsimulator DEPENDS ${SIMULATOR_TARGET}) @@ -57,14 +57,16 @@ use_cxx11() # ensure gnu++11 in CXX_FLAGS with CMake < 3.1 if(FOX_FOUND) if(SIMU_DISKIO) - add_definitions(-DSIMU_DISKIO) set(SIMU_SRC ${SIMU_SRC} ${FATFS_DIR}/FatFs/ff.c ${FATFS_DIR}/option/ccsbcs.c) endif() - add_executable(simu WIN32 ${SIMU_SRC} ${RADIO_SRC_DIRECTORY}/simu.cpp) add_dependencies(simu ${FIRMWARE_DEPENDENCIES}) target_include_directories(simu PUBLIC ${FOX_INCLUDE_DIR} ) target_link_libraries(simu ${FOX_LIBRARY} pthread ${SDL_LIBRARY}) + target_compile_definitions(simu PUBLIC -DSIMU) + if(SIMU_DISKIO) + target_compile_definitions(simu PUBLIC -DSIMU_DISKIO) + endif() endif() if(APPLE)