diff --git a/src/QmlControls/AppMessages.cc b/src/QmlControls/AppMessages.cc index 1c8ae7ae2510ad354f7f0644a69f86ce9f016b9a..9c0826946ee1ec2c8831e0ff71d6000663fc09c2 100644 --- a/src/QmlControls/AppMessages.cc +++ b/src/QmlControls/AppMessages.cc @@ -21,15 +21,18 @@ This file is part of the QGROUNDCONTROL project ======================================================================*/ + +// Allows QGlobalStatic to work on this translation unit +#define _LOG_CTOR_ACCESS_ public #include "AppMessages.h" #include #include #include #include -AppLogModel AppLogModel::instance; +Q_GLOBAL_STATIC(AppLogModel, debug_model) + static QtMessageHandler old_handler; -static AppLogModel &debug_strings = AppLogModel::getModel(); static void msgHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { @@ -38,9 +41,7 @@ static void msgHandler(QtMsgType type, const QMessageLogContext &context, const // Avoid recursion if (!QString(context.category).startsWith("qt.quick")) { - const int line = debug_strings.rowCount(); - debug_strings.insertRows(line, 1); - debug_strings.setData(debug_strings.index(line), output, Qt::DisplayRole); + debug_model->log(output); } if (old_handler != nullptr) { @@ -52,20 +53,24 @@ static void msgHandler(QtMsgType type, const QMessageLogContext &context, const void AppMessages::installHandler() { old_handler = qInstallMessageHandler(msgHandler); -} -AppLogModel *AppMessages::getModel() -{ - return &AppLogModel::getModel(); + // Force creation of debug model on installing thread + Q_UNUSED(*debug_model); } -AppLogModel& AppLogModel::getModel() +AppLogModel *AppMessages::getModel() { - return instance; + return debug_model; } AppLogModel::AppLogModel() : QStringListModel() { +#ifdef __mobile__ + Qt::ConnectionType contype = Qt::QueuedConnection; +#else + Qt::ConnectionType contype = Qt::AutoConnection; +#endif + connect(this, &AppLogModel::emitLog, this, &AppLogModel::threadsafeLog, contype); } void AppLogModel::writeMessages(const QUrl dest_file) @@ -73,7 +78,7 @@ void AppLogModel::writeMessages(const QUrl dest_file) const QString writebuffer(stringList().join('\n').append('\n')); QtConcurrent::run([dest_file, writebuffer] { - emit instance.writeStarted(); + emit debug_model->writeStarted(); bool success = false; QFile file(dest_file.toLocalFile()); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { @@ -81,6 +86,18 @@ void AppLogModel::writeMessages(const QUrl dest_file) out << writebuffer; success = out.status() == QTextStream::Ok; } - emit instance.writeFinished(success); + emit debug_model->writeFinished(success); }); } + +void AppLogModel::log(const QString message) +{ + emit debug_model->emitLog(message); +} + +void AppLogModel::threadsafeLog(const QString message) +{ + const int line = rowCount(); + insertRows(line, 1); + setData(index(line), message, Qt::DisplayRole); +} diff --git a/src/QmlControls/AppMessages.h b/src/QmlControls/AppMessages.h index e9b998705ae706af2ade63116a04c7423feaa9f4..08da2fd063b41241fe2e29c1942783d8fa54e5c2 100644 --- a/src/QmlControls/AppMessages.h +++ b/src/QmlControls/AppMessages.h @@ -27,21 +27,28 @@ This file is part of the QGROUNDCONTROL project #include #include +// Hackish way to force only this translation unit to have public ctor access +#ifndef _LOG_CTOR_ACCESS_ +#define _LOG_CTOR_ACCESS_ private +#endif + class AppLogModel : public QStringListModel { Q_OBJECT public: - static AppLogModel& getModel(); - Q_INVOKABLE void writeMessages(const QUrl dest_file); + static void log(const QString message); signals: + void emitLog(const QString message); void writeStarted(); void writeFinished(bool success); -private: +private slots: + void threadsafeLog(const QString message); + +_LOG_CTOR_ACCESS_: AppLogModel(); - static AppLogModel instance; };