diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 9dd7fb8dca561eb9321b18190f7f3d392b4b4d11..f61044ca6ddf76c166633b77f3b4882737a94fdd 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -94,7 +94,10 @@ QT += \ # testlib is needed even in release flavor for QSignalSpy support QT += testlib - +ReleaseBuild { + # We don't need the testlib console in release mode + QT.testlib.CONFIG -= console +} # # OS Specific settings # @@ -295,6 +298,7 @@ HEADERS += \ src/QmlControls/QGCImageProvider.h \ src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.h \ src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h \ + src/ViewWidgets/AppMessagesDialog.h DebugBuild { HEADERS += \ @@ -434,6 +438,7 @@ SOURCES += \ src/QmlControls/QGCImageProvider.cc \ src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.cc \ src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc \ + src/ViewWidgets/AppMessagesDialog.cc DebugBuild { SOURCES += \ diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index a87759717d864aa53495ac29c8dd88c19add6fb6..1e00af6bb08e47504e72b738fda2c0647041c274 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -12,6 +12,7 @@ src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml src/ViewWidgets/CustomCommandWidget.qml src/ViewWidgets/LogDownload.qml + src/ViewWidgets/AppMessagesDialog.qml src/VehicleSetup/FirmwareUpgrade.qml src/FlightDisplay/FlightDisplayView.qml src/AutoPilotPlugins/PX4/PX4FlightModes.qml diff --git a/src/QGCDockWidget.cc b/src/QGCDockWidget.cc index 2d21ed74b6a2563ed6dc2ce6492cdd6fdfdbdd1c..cc368b9af38a7507f694639f8fefc896f6619731 100644 --- a/src/QGCDockWidget.cc +++ b/src/QGCDockWidget.cc @@ -47,6 +47,8 @@ void QGCDockWidget::closeEvent(QCloseEvent* event) saveSettings(); event->ignore(); _action->trigger(); + } else { + QWidget::closeEvent(event); } } diff --git a/src/QGCDockWidget.h b/src/QGCDockWidget.h index 5452d19973bcba2ac67c0147469a21fd819a20f1..e8fde455888c328bd7c708a8e6e9bb01ce9d4c67 100644 --- a/src/QGCDockWidget.h +++ b/src/QGCDockWidget.h @@ -41,7 +41,7 @@ public: protected: QString _title; - QAction* _action; + QPointer _action; static const char* _settingsGroup; }; diff --git a/src/ViewWidgets/AppMessagesDialog.qml b/src/ViewWidgets/AppMessagesDialog.qml new file mode 100644 index 0000000000000000000000000000000000000000..22c7175c4eef23d77d3a99d39289cf7bde337d08 --- /dev/null +++ b/src/ViewWidgets/AppMessagesDialog.qml @@ -0,0 +1,112 @@ +/*===================================================================== + +QGroundControl Open Source Ground Control Station + +(c) 2009, 2016 QGROUNDCONTROL PROJECT + +This file is part of the QGROUNDCONTROL project + +QGROUNDCONTROL is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +QGROUNDCONTROL 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. + +You should have received a copy of the GNU General Public License +along with QGROUNDCONTROL. If not, see . + +======================================================================*/ + +import QtQuick 2.5 +import QtQuick.Controls 1.2 +import QtQuick.Controls.Styles 1.2 +import QtQuick.Dialogs 1.2 + +import QGroundControl.Palette 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.Controllers 1.0 +import QGroundControl.ScreenTools 1.0 + +QGCView { + viewPanel: panel + id: logwindow + property bool loaded: false + + QGCPalette { id: qgcPal } + + + Connections { + target: debugMessageModel + + onDataChanged: { + // Keep the view in sync if the button is checked + if (loaded) { + if (followTail.checked) { + listview.positionViewAtEnd(); + } + } + } + } + + Component { + id: delegateItem + Rectangle { + color: index % 2 == 0 ? qgcPal.window : qgcPal.windowShade + height: Math.round(ScreenTools.defaultFontPixelHeight * 0.5 + field.height) + width: listview.width + + Text { + anchors.verticalCenter: parent.verticalCenter + id: field + text: display + color: qgcPal.text + width: parent.width + wrapMode: Text.Wrap + } + } + } + + QGCViewPanel { + id: panel + anchors.fill: parent + + Rectangle { + anchors.fill: parent + color: qgcPal.window + } + + ListView { + Component.onCompleted: { + loaded = true + } + anchors.margins: ScreenTools.defaultFontPixelHeight + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: followTail.top + id: listview + model: debugMessageModel + delegate: delegateItem + } + + Button { + id: followTail + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.margins: ScreenTools.defaultFontPixelWidth + text: "Show Latest" + checkable: true + checked: true + + onCheckedChanged: { + if (checked && loaded) { + listview.positionViewAtEnd(); + } + } + } + } +} diff --git a/src/ViewWidgets/appmessagesdialog.cc b/src/ViewWidgets/appmessagesdialog.cc new file mode 100644 index 0000000000000000000000000000000000000000..4b908fd51b7d00b790bcf42c67e747d419c955f6 --- /dev/null +++ b/src/ViewWidgets/appmessagesdialog.cc @@ -0,0 +1,63 @@ +/*===================================================================== + +QGroundControl Open Source Ground Control Station + +(c) 2009, 2016 QGROUNDCONTROL PROJECT + +This file is part of the QGROUNDCONTROL project + + QGROUNDCONTROL is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + QGROUNDCONTROL 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. + + You should have received a copy of the GNU General Public License + along with QGROUNDCONTROL. If not, see . + +======================================================================*/ + +#include "AppMessagesDialog.h" +#include +#include + +static QtMessageHandler old_handler; +static QStringListModel debug_strings; + +static void msgHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + const char symbols[] = { 'D', 'E', '!', 'X', 'I' }; + QString output = QString("[%1] at %2:%3 - \"%4\"").arg(symbols[type]).arg(context.file).arg(context.line).arg(msg); + + // 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); + } + + if (old_handler != nullptr) { + old_handler(type, context, msg); + } + if( type == QtFatalMsg ) abort(); +} + + +AppMessagesDialog::AppMessagesDialog(const QString &title, QAction *action, QWidget *parent) : + QGCQmlWidgetHolder(title, action, parent) +{ + resize(800, 600); + setContextPropertyObject("debugMessageModel", &debug_strings); + setSource(QUrl::fromUserInput("qrc:/qml/AppMessagesDialog.qml")); + loadSettings(); +} + +void AppMessagesDialog::installHandler() +{ + old_handler = qInstallMessageHandler(msgHandler); +} + diff --git a/src/ViewWidgets/appmessagesdialog.h b/src/ViewWidgets/appmessagesdialog.h new file mode 100644 index 0000000000000000000000000000000000000000..e43b9f130683b6ea5a98b961d249fcb2a367f3b6 --- /dev/null +++ b/src/ViewWidgets/appmessagesdialog.h @@ -0,0 +1,37 @@ +/*===================================================================== + +QGroundControl Open Source Ground Control Station + +(c) 2009, 2016 QGROUNDCONTROL PROJECT + +This file is part of the QGROUNDCONTROL project + + QGROUNDCONTROL is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + QGROUNDCONTROL 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. + + You should have received a copy of the GNU General Public License + along with QGROUNDCONTROL. If not, see . + +======================================================================*/ + +#pragma once + +#include "QGCQmlWidgetHolder.h" + +class QStringListModel; + +class AppMessagesDialog : public QGCQmlWidgetHolder +{ + Q_OBJECT +public: + AppMessagesDialog(const QString& title, QAction* action, QWidget *parent = 0); + + static void installHandler(); +}; diff --git a/src/main.cc b/src/main.cc index c6276a586ae97df248acf96ba75278ec25166fda..7ccdab5361f9f12b47a046b07c8e8fcb81af7de5 100644 --- a/src/main.cc +++ b/src/main.cc @@ -35,7 +35,8 @@ This file is part of the QGROUNDCONTROL project #include #include #include - +#include +#include "AppMessagesDialog.h" #include "QGCApplication.h" #define SINGLE_INSTANCE_PORT 14499 @@ -71,17 +72,6 @@ This file is part of the QGROUNDCONTROL project #endif #ifdef Q_OS_WIN - -/// @brief Message handler which is installed using qInstallMsgHandler so you do not need -/// the MSFT debug tools installed to see qDebug(), qWarning(), qCritical and qAbort -void msgHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) -{ - const char symbols[] = { 'I', 'E', '!', 'X' }; - QString output = QString("[%1] at %2:%3 - \"%4\"").arg(symbols[type]).arg(context.file).arg(context.line).arg(msg); - std::cerr << output.toStdString() << std::endl; - if( type == QtFatalMsg ) abort(); -} - /// @brief CRT Report Hook installed using _CrtSetReportHook. We install this hook when /// we don't want asserts to pop a dialog on windows. int WindowsCrtReportHook(int reportType, char* message, int* returnValue) @@ -143,10 +133,9 @@ int main(int argc, char *argv[]) #endif #endif -#ifdef Q_OS_WIN // install the message handler - qInstallMessageHandler(msgHandler); - + AppMessagesDialog::installHandler(); +#ifdef Q_OS_WIN // Set our own OpenGL buglist qputenv("QT_OPENGL_BUGLIST", ":/opengl/resources/opengl/buglist.json"); diff --git a/src/ui/MainWindow.cc b/src/ui/MainWindow.cc index fe17f8ef00390814d36495f5e63ff0827ae69972..e6f42e6fffec0fb288a000a53aa814fad8c87305 100644 --- a/src/ui/MainWindow.cc +++ b/src/ui/MainWindow.cc @@ -66,6 +66,7 @@ This file is part of the QGROUNDCONTROL project #include "UASInfoWidget.h" #include "HILDockWidget.h" #include "LogDownload.h" +#include "AppMessagesDialog.h" #endif #ifndef __ios__ @@ -88,7 +89,8 @@ enum DockWidgetTypes { INFO_VIEW, HIL_CONFIG, ANALYZE, - LOG_DOWNLOAD + LOG_DOWNLOAD, + DEBUG_MESSAGES }; static const char *rgDockWidgetNames[] = { @@ -99,7 +101,8 @@ static const char *rgDockWidgetNames[] = { "Info View", "HIL Config", "Analyze", - "Log Download" + "Log Download", + "Debug Messages" }; #define ARRAY_SIZE(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0])) @@ -306,7 +309,7 @@ void MainWindow::_buildCommonWidgets(void) const char* pDockWidgetName = rgDockWidgetNames[i]; // Add to menu - QAction* action = new QAction(tr(pDockWidgetName), NULL); + QAction* action = new QAction(tr(pDockWidgetName), this); action->setCheckable(true); action->setData(i); connect(action, &QAction::triggered, this, &MainWindow::_showDockWidgetAction); @@ -352,6 +355,9 @@ bool MainWindow::_createInnerDockWidget(const QString& widgetName) case LOG_DOWNLOAD: widget = new LogDownload(widgetName, action, this); break; + case DEBUG_MESSAGES: + widget = new AppMessagesDialog(widgetName, action, this); + break; case STATUS_DETAILS: widget = new UASInfoWidget(widgetName, action, this); break; @@ -419,10 +425,6 @@ void MainWindow::closeEvent(QCloseEvent *event) _storeCurrentViewState(); storeSettings(); - //-- TODO: This effectively causes the QGCApplication destructor to not being able - // to access the pointer it is trying to delete. - _instance = NULL; - emit mainWindowClosed(); }