[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 b12bd7d7be)
This commit is contained in:
committed by
Bertrand Songis
parent
620094e358
commit
00b2799427
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#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 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
|
||||
+11
-12
@@ -26,20 +26,15 @@
|
||||
#include <SDL.h>
|
||||
#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 <windows.h>
|
||||
#define sleep(x) Sleep(x*1000)
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <QProxyStyle>
|
||||
#include <QProxyStyle>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -61,12 +61,6 @@
|
||||
#define COMPANION_INSTALLER "companion-windows-%1.exe"
|
||||
#endif
|
||||
|
||||
#if defined _MSC_VER || !defined __GNUC__
|
||||
#include <windows.h>
|
||||
#define sleep(x) Sleep(x*1000)
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
#define OPENTX_NIGHT_COMPANION_DOWNLOADS "http://downloads-22.open-tx.org/nightly/companion/windows"
|
||||
#else
|
||||
|
||||
@@ -33,13 +33,6 @@
|
||||
#include "storage.h"
|
||||
#include "radiointerface.h"
|
||||
|
||||
#if defined _MSC_VER || !defined __GNUC__
|
||||
#include <windows.h>
|
||||
#define sleep(x) Sleep(x*1000)
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
MdiChild::MdiChild(MainWindow * parent):
|
||||
QWidget(),
|
||||
parent(parent),
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 <QDebug>
|
||||
#include <QFile>
|
||||
#include <iostream>
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -26,8 +26,9 @@
|
||||
#include <QPainter>
|
||||
#include <QClipboard>
|
||||
#include <QDir>
|
||||
#include <QDebug>
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <QLocale>
|
||||
#include <QString>
|
||||
#include <QDir>
|
||||
#include <QDebug>
|
||||
#include <QTextStream>
|
||||
#include <QMessageBox>
|
||||
#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 <windows.h>
|
||||
#ifdef _MSC_VER
|
||||
#define sleep(x) Sleep(x*1000)
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(_MSC_VER) || defined(__GNUC__)
|
||||
#include <unistd.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user