Commit c51a1a6e authored by Nate Weibley's avatar Nate Weibley

Add optional qml-based console to view debugging messages. For #3121

parent e6648c06
...@@ -94,7 +94,10 @@ QT += \ ...@@ -94,7 +94,10 @@ QT += \
# testlib is needed even in release flavor for QSignalSpy support # testlib is needed even in release flavor for QSignalSpy support
QT += testlib QT += testlib
ReleaseBuild {
# We don't need the testlib console in release mode
QT.testlib.CONFIG -= console
}
# #
# OS Specific settings # OS Specific settings
# #
...@@ -295,6 +298,7 @@ HEADERS += \ ...@@ -295,6 +298,7 @@ HEADERS += \
src/QmlControls/QGCImageProvider.h \ src/QmlControls/QGCImageProvider.h \
src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.h \ src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.h \
src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h \ src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h \
src/ViewWidgets/AppMessagesDialog.h
DebugBuild { DebugBuild {
HEADERS += \ HEADERS += \
...@@ -434,6 +438,7 @@ SOURCES += \ ...@@ -434,6 +438,7 @@ SOURCES += \
src/QmlControls/QGCImageProvider.cc \ src/QmlControls/QGCImageProvider.cc \
src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.cc \ src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.cc \
src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc \ src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc \
src/ViewWidgets/AppMessagesDialog.cc
DebugBuild { DebugBuild {
SOURCES += \ SOURCES += \
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
<file alias="APMAirframeComponentSummary.qml">src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml</file> <file alias="APMAirframeComponentSummary.qml">src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml</file>
<file alias="CustomCommandWidget.qml">src/ViewWidgets/CustomCommandWidget.qml</file> <file alias="CustomCommandWidget.qml">src/ViewWidgets/CustomCommandWidget.qml</file>
<file alias="LogDownload.qml">src/ViewWidgets/LogDownload.qml</file> <file alias="LogDownload.qml">src/ViewWidgets/LogDownload.qml</file>
<file alias="AppMessagesDialog.qml">src/ViewWidgets/AppMessagesDialog.qml</file>
<file alias="FirmwareUpgrade.qml">src/VehicleSetup/FirmwareUpgrade.qml</file> <file alias="FirmwareUpgrade.qml">src/VehicleSetup/FirmwareUpgrade.qml</file>
<file alias="FlightDisplayView.qml">src/FlightDisplay/FlightDisplayView.qml</file> <file alias="FlightDisplayView.qml">src/FlightDisplay/FlightDisplayView.qml</file>
<file alias="PX4FlightModes.qml">src/AutoPilotPlugins/PX4/PX4FlightModes.qml</file> <file alias="PX4FlightModes.qml">src/AutoPilotPlugins/PX4/PX4FlightModes.qml</file>
......
...@@ -47,6 +47,8 @@ void QGCDockWidget::closeEvent(QCloseEvent* event) ...@@ -47,6 +47,8 @@ void QGCDockWidget::closeEvent(QCloseEvent* event)
saveSettings(); saveSettings();
event->ignore(); event->ignore();
_action->trigger(); _action->trigger();
} else {
QWidget::closeEvent(event);
} }
} }
......
...@@ -41,7 +41,7 @@ public: ...@@ -41,7 +41,7 @@ public:
protected: protected:
QString _title; QString _title;
QAction* _action; QPointer<QAction> _action;
static const char* _settingsGroup; static const char* _settingsGroup;
}; };
......
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
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 <http://www.gnu.org/licenses/>.
======================================================================*/
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();
}
}
}
}
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
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 <http://www.gnu.org/licenses/>.
======================================================================*/
#include "AppMessagesDialog.h"
#include <QStringListModel>
#include <iostream>
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);
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
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 <http://www.gnu.org/licenses/>.
======================================================================*/
#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();
};
...@@ -35,7 +35,8 @@ This file is part of the QGROUNDCONTROL project ...@@ -35,7 +35,8 @@ This file is part of the QGROUNDCONTROL project
#include <QHostAddress> #include <QHostAddress>
#include <QUdpSocket> #include <QUdpSocket>
#include <QtPlugin> #include <QtPlugin>
#include <QStringListModel>
#include "AppMessagesDialog.h"
#include "QGCApplication.h" #include "QGCApplication.h"
#define SINGLE_INSTANCE_PORT 14499 #define SINGLE_INSTANCE_PORT 14499
...@@ -71,17 +72,6 @@ This file is part of the QGROUNDCONTROL project ...@@ -71,17 +72,6 @@ This file is part of the QGROUNDCONTROL project
#endif #endif
#ifdef Q_OS_WIN #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 /// @brief CRT Report Hook installed using _CrtSetReportHook. We install this hook when
/// we don't want asserts to pop a dialog on windows. /// we don't want asserts to pop a dialog on windows.
int WindowsCrtReportHook(int reportType, char* message, int* returnValue) int WindowsCrtReportHook(int reportType, char* message, int* returnValue)
...@@ -143,10 +133,9 @@ int main(int argc, char *argv[]) ...@@ -143,10 +133,9 @@ int main(int argc, char *argv[])
#endif #endif
#endif #endif
#ifdef Q_OS_WIN
// install the message handler // install the message handler
qInstallMessageHandler(msgHandler); AppMessagesDialog::installHandler();
#ifdef Q_OS_WIN
// Set our own OpenGL buglist // Set our own OpenGL buglist
qputenv("QT_OPENGL_BUGLIST", ":/opengl/resources/opengl/buglist.json"); qputenv("QT_OPENGL_BUGLIST", ":/opengl/resources/opengl/buglist.json");
......
...@@ -66,6 +66,7 @@ This file is part of the QGROUNDCONTROL project ...@@ -66,6 +66,7 @@ This file is part of the QGROUNDCONTROL project
#include "UASInfoWidget.h" #include "UASInfoWidget.h"
#include "HILDockWidget.h" #include "HILDockWidget.h"
#include "LogDownload.h" #include "LogDownload.h"
#include "AppMessagesDialog.h"
#endif #endif
#ifndef __ios__ #ifndef __ios__
...@@ -88,7 +89,8 @@ enum DockWidgetTypes { ...@@ -88,7 +89,8 @@ enum DockWidgetTypes {
INFO_VIEW, INFO_VIEW,
HIL_CONFIG, HIL_CONFIG,
ANALYZE, ANALYZE,
LOG_DOWNLOAD LOG_DOWNLOAD,
DEBUG_MESSAGES
}; };
static const char *rgDockWidgetNames[] = { static const char *rgDockWidgetNames[] = {
...@@ -99,7 +101,8 @@ static const char *rgDockWidgetNames[] = { ...@@ -99,7 +101,8 @@ static const char *rgDockWidgetNames[] = {
"Info View", "Info View",
"HIL Config", "HIL Config",
"Analyze", "Analyze",
"Log Download" "Log Download",
"Debug Messages"
}; };
#define ARRAY_SIZE(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0])) #define ARRAY_SIZE(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0]))
...@@ -306,7 +309,7 @@ void MainWindow::_buildCommonWidgets(void) ...@@ -306,7 +309,7 @@ void MainWindow::_buildCommonWidgets(void)
const char* pDockWidgetName = rgDockWidgetNames[i]; const char* pDockWidgetName = rgDockWidgetNames[i];
// Add to menu // Add to menu
QAction* action = new QAction(tr(pDockWidgetName), NULL); QAction* action = new QAction(tr(pDockWidgetName), this);
action->setCheckable(true); action->setCheckable(true);
action->setData(i); action->setData(i);
connect(action, &QAction::triggered, this, &MainWindow::_showDockWidgetAction); connect(action, &QAction::triggered, this, &MainWindow::_showDockWidgetAction);
...@@ -352,6 +355,9 @@ bool MainWindow::_createInnerDockWidget(const QString& widgetName) ...@@ -352,6 +355,9 @@ bool MainWindow::_createInnerDockWidget(const QString& widgetName)
case LOG_DOWNLOAD: case LOG_DOWNLOAD:
widget = new LogDownload(widgetName, action, this); widget = new LogDownload(widgetName, action, this);
break; break;
case DEBUG_MESSAGES:
widget = new AppMessagesDialog(widgetName, action, this);
break;
case STATUS_DETAILS: case STATUS_DETAILS:
widget = new UASInfoWidget(widgetName, action, this); widget = new UASInfoWidget(widgetName, action, this);
break; break;
...@@ -419,10 +425,6 @@ void MainWindow::closeEvent(QCloseEvent *event) ...@@ -419,10 +425,6 @@ void MainWindow::closeEvent(QCloseEvent *event)
_storeCurrentViewState(); _storeCurrentViewState();
storeSettings(); 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(); emit mainWindowClosed();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment