From d33852c535d9ca47eef0fab4dddf8a2b7b448383 Mon Sep 17 00:00:00 2001 From: dogmaphobic Date: Sat, 7 Nov 2015 00:41:16 -0500 Subject: [PATCH] PX4FLOW Sensor Support. --- QGCApplication.pro | 4 +- qgroundcontrol.qrc | 145 ++++++++--------- src/QGCQmlWidgetHolder.cpp | 22 ++- src/QGCQmlWidgetHolder.h | 23 +-- src/QGCSettings.cpp | 39 ----- src/QGCToolbox.cc | 4 + src/QGCToolbox.h | 59 +++---- src/QmlControls/QGCImageProvider.cc | 97 ++++++++++++ .../QGCImageProvider.h} | 35 +++-- src/QmlControls/SubMenuButton.qml | 1 + src/Vehicle/MultiVehicleManager.cc | 63 ++++---- src/Vehicle/MultiVehicleManager.h | 61 ++++---- src/Vehicle/Vehicle.cc | 147 ++++++++++-------- src/Vehicle/Vehicle.h | 121 +++++++------- src/VehicleSetup/PX4FlowSensor.qml | 64 ++++++++ src/VehicleSetup/SetupView.qml | 15 ++ src/comm/MockLink.cc | 60 +++---- src/ui/MainWindow.cc | 11 ++ 18 files changed, 588 insertions(+), 383 deletions(-) delete mode 100644 src/QGCSettings.cpp create mode 100644 src/QmlControls/QGCImageProvider.cc rename src/{QGCSettings.h => QmlControls/QGCImageProvider.h} (51%) create mode 100644 src/VehicleSetup/PX4FlowSensor.qml diff --git a/QGCApplication.pro b/QGCApplication.pro index 56072babf..1b21e54ed 100644 --- a/QGCApplication.pro +++ b/QGCApplication.pro @@ -271,7 +271,7 @@ HEADERS += \ src/ui/uas/UASMessageView.h \ src/MissionItem.h \ src/AutoPilotPlugins/PX4/PX4AirframeLoader.h \ - src/QGCSettings.h + src/QmlControls/QGCImageProvider.h \ WindowsBuild { PRECOMPILED_HEADER += src/stable_headers.h @@ -383,7 +383,7 @@ SOURCES += \ src/ui/uas/UASMessageView.cc \ src/MissionItem.cc \ src/AutoPilotPlugins/PX4/PX4AirframeLoader.cc \ - src/QGCSettings.cpp + src/QmlControls/QGCImageProvider.cc \ !iOSBuild { SOURCES += \ diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index feb302b3b..3ce5ad56c 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -6,99 +6,104 @@ src/FactSystem/FactSystemTest.qml - src/test.qml - src/QmlControls/QmlTest.qml - src/FactSystem/FactControls/qmldir - src/FactSystem/FactControls/FactPanel.qml - src/FactSystem/FactControls/FactLabel.qml - src/FactSystem/FactControls/FactTextField.qml - src/FactSystem/FactControls/FactCheckBox.qml - src/FactSystem/FactControls/FactComboBox.qml - src/QmlControls/QGroundControl.Controls.qmldir + src/AutoPilotPlugins/PX4/AirframeComponent.qml + src/AutoPilotPlugins/PX4/AirframeComponentSummary.qml + src/AutoPilotPlugins/APM/APMAirframeComponent.qml + src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml + src/ViewWidgets/CustomCommandWidget.qml + src/ui/preferences/DebugWindow.qml + src/VehicleSetup/FirmwareUpgrade.qml + src/FlightDisplay/FlightDisplayView.qml + src/AutoPilotPlugins/PX4/FlightModesComponent.qml + src/AutoPilotPlugins/PX4/FlightModesComponentSummary.qml + src/ui/preferences/GeneralSettings.qml + src/VehicleSetup/JoystickConfig.qml + src/ui/toolbar/MainToolBar.qml + src/ui/MainWindow.qml + src/ui/MainWindowLeftPanel.qml + src/ui/preferences/MavlinkSettings.qml + src/MissionEditor/MissionEditor.qml + src/MissionEditor/MissionEditorHelp.qml + src/AutoPilotPlugins/PX4/PowerComponent.qml + src/AutoPilotPlugins/PX4/PowerComponentSummary.qml + src/VehicleSetup/PX4FlowSensor.qml + + src/QmlControls/ClickableColor.qml + src/QmlControls/DropButton.qml + src/QmlControls/ExclusiveGroupItem.qml + src/QmlControls/IndicatorButton.qml + src/ui/toolbar/MainToolBar.qml + src/ui/toolbar/MainToolBarIndicators.qml + src/QmlControls/MissionItemEditor.qml + src/QmlControls/MissionItemIndexLabel.qml + src/QmlControls/MissionItemSummary.qml + src/QmlControls/ModeSwitchDisplay.qml + src/QmlControls/ParameterEditor.qml + src/QmlControls/ParameterEditorDialog.qml src/QmlControls/QGCButton.qml - src/QmlControls/QGCRadioButton.qml + src/QmlControls/QGCCanvas.qml src/QmlControls/QGCCheckBox.qml + src/QmlControls/QGCColoredImage.qml + src/QmlControls/QGCComboBox.qml src/QmlControls/QGCLabel.qml + src/QmlControls/QGCMovableItem.qml + src/QmlControls/QGCRadioButton.qml src/QmlControls/QGCTextField.qml - src/QmlControls/QGCComboBox.qml - src/QmlControls/QGCColoredImage.qml src/QmlControls/QGCToolBarButton.qml - src/QmlControls/QGCMovableItem.qml - src/QmlControls/QGroundControl.ScreenTools.qmldir - src/QmlControls/ScreenTools.qml - src/QmlControls/SubMenuButton.qml - src/QmlControls/IndicatorButton.qml - src/QmlControls/VehicleRotationCal.qml - src/QmlControls/VehicleSummaryRow.qml - src/ViewWidgets/ViewWidget.qml src/QmlControls/QGCView.qml - src/QmlControls/QGCViewPanel.qml src/QmlControls/QGCViewDialog.qml src/QmlControls/QGCViewMessage.qml - src/QmlControls/ParameterEditor.qml - src/QmlControls/ParameterEditorDialog.qml - src/QmlControls/ModeSwitchDisplay.qml - src/QmlControls/MissionItemIndexLabel.qml - src/QmlControls/MissionItemSummary.qml - src/QmlControls/MissionItemEditor.qml - src/QmlControls/DropButton.qml + src/QmlControls/QGCViewPanel.qml + src/QmlControls/QGroundControl.Controls.qmldir src/QmlControls/RoundButton.qml - src/QmlControls/QGCCanvas.qml - src/QmlControls/ExclusiveGroupItem.qml - src/QmlControls/ClickableColor.qml - src/ui/MainWindow.qml - src/ui/MainWindowLeftPanel.qml - src/ui/toolbar/MainToolBar.qml - src/ui/toolbar/MainToolBarIndicators.qml src/ui/toolbar/SignalStrength.qml - src/VehicleSetup/SetupView.qml - src/VehicleSetup/VehicleSummary.qml - src/VehicleSetup/FirmwareUpgrade.qml - src/VehicleSetup/JoystickConfig.qml - src/VehicleSetup/SetupParameterEditor.qml - src/ViewWidgets/CustomCommandWidget.qml - src/AutoPilotPlugins/PX4/SafetyComponent.qml - src/AutoPilotPlugins/PX4/RadioComponent.qml - src/AutoPilotPlugins/PX4/PowerComponent.qml - src/AutoPilotPlugins/PX4/SensorsComponent.qml - src/AutoPilotPlugins/PX4/FlightModesComponent.qml - src/AutoPilotPlugins/PX4/SafetyComponentSummary.qml - src/AutoPilotPlugins/PX4/PowerComponentSummary.qml - src/AutoPilotPlugins/PX4/SensorsComponentSummary.qml - src/AutoPilotPlugins/PX4/SensorsComponentSummaryFixedWing.qml - src/AutoPilotPlugins/PX4/RadioComponentSummary.qml - src/AutoPilotPlugins/PX4/FlightModesComponentSummary.qml - src/AutoPilotPlugins/PX4/AirframeComponentSummary.qml - src/AutoPilotPlugins/PX4/AirframeComponent.qml - src/ui/toolbar/MainToolBar.qml - src/FlightDisplay/FlightDisplayView.qml - src/MissionEditor/MissionEditor.qml - src/MissionEditor/MissionEditorHelp.qml - src/AutoPilotPlugins/APM/APMAirframeComponent.qml - src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml - src/FlightDisplay/qmldir + src/QmlControls/SubMenuButton.qml + src/QmlControls/VehicleRotationCal.qml + src/QmlControls/VehicleSummaryRow.qml + src/ViewWidgets/ViewWidget.qml + + src/FactSystem/FactControls/FactCheckBox.qml + src/FactSystem/FactControls/FactComboBox.qml + src/FactSystem/FactControls/FactLabel.qml + src/FactSystem/FactControls/FactPanel.qml + src/FactSystem/FactControls/FactTextField.qml + src/FactSystem/FactControls/qmldir + src/FlightDisplay/FlightDisplayView.qml src/FlightDisplay/FlightDisplayViewMap.qml src/FlightDisplay/FlightDisplayViewVideo.qml src/FlightDisplay/FlightDisplayViewWidgets.qml - src/FlightMap/qmldir + src/FlightDisplay/qmldir + src/FlightMap/FlightMap.qml - src/FlightMap/QGCVideoBackground.qml + src/FlightMap/MapItems/MissionItemIndicator.qml + src/FlightMap/MapItems/MissionItemView.qml + src/FlightMap/MapItems/MissionLineView.qml src/FlightMap/Widgets/QGCArtificialHorizon.qml - src/FlightMap/Widgets/QGCAttitudeWidget.qml src/FlightMap/Widgets/QGCAttitudeHUD.qml + src/FlightMap/Widgets/QGCAttitudeWidget.qml src/FlightMap/Widgets/QGCCompassWidget.qml src/FlightMap/Widgets/QGCInstrumentWidget.qml src/FlightMap/Widgets/QGCPitchIndicator.qml src/FlightMap/Widgets/QGCSlider.qml - src/FlightMap/MapItems/MissionItemIndicator.qml + src/FlightMap/QGCVideoBackground.qml + src/FlightMap/qmldir src/FlightMap/MapItems/VehicleMapItem.qml - src/FlightMap/MapItems/MissionItemView.qml - src/FlightMap/MapItems/MissionLineView.qml - src/ui/preferences/DebugWindow.qml - src/ui/preferences/MavlinkSettings.qml - src/ui/preferences/GeneralSettings.qml + src/QmlControls/QGroundControl.ScreenTools.qmldir + src/QmlControls/ScreenTools.qml + src/QmlControls/QmlTest.qml + src/AutoPilotPlugins/PX4/RadioComponent.qml + src/AutoPilotPlugins/PX4/RadioComponentSummary.qml + src/AutoPilotPlugins/PX4/SafetyComponent.qml + src/AutoPilotPlugins/PX4/SafetyComponentSummary.qml + src/AutoPilotPlugins/PX4/SensorsComponent.qml + src/AutoPilotPlugins/PX4/SensorsComponentSummary.qml + src/AutoPilotPlugins/PX4/SensorsComponentSummaryFixedWing.qml + src/VehicleSetup/SetupParameterEditor.qml + src/VehicleSetup/SetupView.qml + src/test.qml + src/VehicleSetup/VehicleSummary.qml diff --git a/src/QGCQmlWidgetHolder.cpp b/src/QGCQmlWidgetHolder.cpp index 07a383f7c..26b72c730 100644 --- a/src/QGCQmlWidgetHolder.cpp +++ b/src/QGCQmlWidgetHolder.cpp @@ -1,24 +1,24 @@ /*===================================================================== - + QGroundControl Open Source Ground Control Station - + (c) 2009 - 2014 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 . - + ======================================================================*/ /// @file @@ -30,7 +30,7 @@ QGCQmlWidgetHolder::QGCQmlWidgetHolder(const QString& title, QAction* action, QW QGCDockWidget(title, action, parent) { _ui.setupUi(this); - + layout()->setContentsMargins(0,0,0,0); if (action) { @@ -69,6 +69,12 @@ QQuickItem* QGCQmlWidgetHolder::getRootObject(void) return _ui.qmlWidget->rootObject(); } +QQmlEngine* QGCQmlWidgetHolder::getEngine() +{ + return _ui.qmlWidget->engine(); +} + + void QGCQmlWidgetHolder::setResizeMode(QQuickWidget::ResizeMode resizeMode) { _ui.qmlWidget->setResizeMode(resizeMode); diff --git a/src/QGCQmlWidgetHolder.h b/src/QGCQmlWidgetHolder.h index fa9749082..ba2d6902e 100644 --- a/src/QGCQmlWidgetHolder.h +++ b/src/QGCQmlWidgetHolder.h @@ -1,24 +1,24 @@ /*===================================================================== - + QGroundControl Open Source Ground Control Station - + (c) 2009 - 2014 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 . - + ======================================================================*/ #ifndef QGCQmlWidgetHolder_h @@ -49,7 +49,7 @@ public: // action = NULL explicit QGCQmlWidgetHolder(const QString& title, QAction* action, QWidget *parent = 0); ~QGCQmlWidgetHolder(); - + /// Sets the UAS into the widget which in turn will load facts into the context void setAutoPilot(AutoPilotPlugin* autoPilot); @@ -58,13 +58,16 @@ public: /// Get Root Object QQuickItem* getRootObject(void); - + + /// Get QML Engine + QQmlEngine* getEngine(); + /// Sets the QML into the control. Will display errors message box if error occurs loading source. /// @return true: source loaded, false: source not loaded, errors occured bool setSource(const QUrl& qmlUrl); void setContextPropertyObject(const QString& name, QObject* object); - + /// Sets the resize mode for the QQuickWidget container void setResizeMode(QQuickWidget::ResizeMode resizeMode); diff --git a/src/QGCSettings.cpp b/src/QGCSettings.cpp deleted file mode 100644 index e8116080b..000000000 --- a/src/QGCSettings.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/*===================================================================== - -QGroundControl Open Source Ground Control Station - -(c) 2009 - 2015 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 . - -======================================================================*/ - -/** -* @file -* @brief Implementation of class QGCSettings -* -* @author Gus Grubba -* -*/ - - -#include "QGCSettings.h" - -QGCSettings::QGCSettings(QObject *parent) : QObject(parent) -{ - -} - diff --git a/src/QGCToolbox.cc b/src/QGCToolbox.cc index 659a21755..16041405f 100644 --- a/src/QGCToolbox.cc +++ b/src/QGCToolbox.cc @@ -32,6 +32,7 @@ #include "AutoPilotPluginManager.h" #include "UASMessageHandler.h" #include "FactSystem.h" +#include "QGCImageProvider.h" QGCToolbox::QGCToolbox(QGCApplication* app) : _firmwarePluginManager(NULL) @@ -45,6 +46,7 @@ QGCToolbox::QGCToolbox(QGCApplication* app) , _audioOutput(NULL) , _uasMessageHandler(NULL) , _factSystem(NULL) + , _imageProvider(NULL) { _firmwarePluginManager = new FirmwarePluginManager(app); _autopilotPluginManager = new AutoPilotPluginManager(app); @@ -57,6 +59,7 @@ QGCToolbox::QGCToolbox(QGCApplication* app) _joystickManager = new JoystickManager(app); _audioOutput = new GAudioOutput(app); _uasMessageHandler = new UASMessageHandler(app); + _imageProvider = new QGCImageProvider(app); _firmwarePluginManager->setToolbox(this); _autopilotPluginManager->setToolbox(this); @@ -69,6 +72,7 @@ QGCToolbox::QGCToolbox(QGCApplication* app) _joystickManager->setToolbox(this); _audioOutput->setToolbox(this); _uasMessageHandler->setToolbox(this); + _imageProvider->setToolbox(this); } QGCToolbox::~QGCToolbox() diff --git a/src/QGCToolbox.h b/src/QGCToolbox.h index 79ef8d715..3d1e03299 100644 --- a/src/QGCToolbox.h +++ b/src/QGCToolbox.h @@ -1,24 +1,24 @@ /*===================================================================== - + QGroundControl Open Source Ground Control Station - + (c) 2009 - 2015 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 . - + ======================================================================*/ #ifndef QGCToolbox_h @@ -38,6 +38,7 @@ class GAudioOutput; class FirmwarePluginManager; class AutoPilotPluginManager; class FactSystem; +class QGCImageProvider; /// This is used to manage all of our top level services/tools class QGCToolbox { @@ -46,29 +47,31 @@ public: QGCToolbox(QGCApplication* app); ~QGCToolbox(); - LinkManager* linkManager(void) { return _linkManager; } - MAVLinkProtocol* mavlinkProtocol(void) { return _mavlinkProtocol; } - MultiVehicleManager* multiVehicleManager(void) { return _multiVehicleManager; } - JoystickManager* joystickManager(void) { return _joystickManager; } - UASMessageHandler* uasMessageHandler(void) { return _uasMessageHandler; } - HomePositionManager* homePositionManager(void) { return _homePositionManager; } - FlightMapSettings* flightMapSettings(void) { return _flightMapSettings; } - GAudioOutput* audioOutput(void) { return _audioOutput; } - FirmwarePluginManager* firmwarePluginManager(void) { return _firmwarePluginManager; } - AutoPilotPluginManager* autopilotPluginManager(void) { return _autopilotPluginManager; } + LinkManager* linkManager(void) { return _linkManager; } + MAVLinkProtocol* mavlinkProtocol(void) { return _mavlinkProtocol; } + MultiVehicleManager* multiVehicleManager(void) { return _multiVehicleManager; } + JoystickManager* joystickManager(void) { return _joystickManager; } + UASMessageHandler* uasMessageHandler(void) { return _uasMessageHandler; } + HomePositionManager* homePositionManager(void) { return _homePositionManager; } + FlightMapSettings* flightMapSettings(void) { return _flightMapSettings; } + GAudioOutput* audioOutput(void) { return _audioOutput; } + FirmwarePluginManager* firmwarePluginManager(void) { return _firmwarePluginManager; } + AutoPilotPluginManager* autopilotPluginManager(void) { return _autopilotPluginManager; } + QGCImageProvider* imageProvider() { return _imageProvider; } private: - FirmwarePluginManager* _firmwarePluginManager; - AutoPilotPluginManager* _autopilotPluginManager; - LinkManager* _linkManager; - MultiVehicleManager* _multiVehicleManager; - MAVLinkProtocol* _mavlinkProtocol; - FlightMapSettings* _flightMapSettings; - HomePositionManager* _homePositionManager; - JoystickManager* _joystickManager; - GAudioOutput* _audioOutput; - UASMessageHandler* _uasMessageHandler; - FactSystem* _factSystem; + FirmwarePluginManager* _firmwarePluginManager; + AutoPilotPluginManager* _autopilotPluginManager; + LinkManager* _linkManager; + MultiVehicleManager* _multiVehicleManager; + MAVLinkProtocol* _mavlinkProtocol; + FlightMapSettings* _flightMapSettings; + HomePositionManager* _homePositionManager; + JoystickManager* _joystickManager; + GAudioOutput* _audioOutput; + UASMessageHandler* _uasMessageHandler; + FactSystem* _factSystem; + QGCImageProvider* _imageProvider; }; /// This is the base class for all tools diff --git a/src/QmlControls/QGCImageProvider.cc b/src/QmlControls/QGCImageProvider.cc new file mode 100644 index 000000000..9081898a4 --- /dev/null +++ b/src/QmlControls/QGCImageProvider.cc @@ -0,0 +1,97 @@ +/*===================================================================== + +QGroundControl Open Source Ground Control Station + +(c) 2009 - 2015 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 . + +======================================================================*/ + +/** +* @file +* @brief Image Provider +* +* @author Gus Grubba +* +*/ + + +#include "QGCImageProvider.h" + +#include +#include + +QGCImageProvider::QGCImageProvider(QGCApplication *app) + : QGCTool(app) + , QQuickImageProvider(QQmlImageProviderBase::Image) +{ +} + +QGCImageProvider::~QGCImageProvider() +{ + +} + +void QGCImageProvider::setToolbox(QGCToolbox *toolbox) +{ + QGCTool::setToolbox(toolbox); + //-- Dummy temporary image until something comes along + _pImage = QImage(320, 240, QImage::Format_RGBA8888); + _pImage.fill(Qt::black); + QPainter painter(&_pImage); + QFont f = painter.font(); + f.setPixelSize(20); + painter.setFont(f); + painter.setPen(Qt::white); + painter.drawText(QRectF(0, 0, 320, 240), Qt::AlignCenter, "Waiting..."); +} + +QImage QGCImageProvider::requestImage(const QString & /* image url with vehicle id*/, QSize *, const QSize &) +{ +/* + The QML side will request an image using a special URL, which we've registered as QGCImages. + The URL follows this format (or anything you want to make out of it after the "QGCImages" part): + + "image://QGCImages/vvv/iii" + + Where: + vvv: Some vehicle id + iii: An auto incremented index (which forces the Item to reload the image) + + The image index is incremented each time a new image arrives. A signal is emitted and the QML side + updates its contents automatically. + + Image { + source: "image://QGCImages/" + _activeVehicle.id + "/" + _activeVehicle.flowImageIndex + width: parent.width * 0.5 + height: width * 0.75 + cache: false + anchors.centerIn: parent + fillMode: Image.PreserveAspectFit + } + + For now, we don't even look at the URL. This will have to be fixed if we're to support multiple + vehicles transmitting flow images. +*/ + return _pImage; +} + +void QGCImageProvider::setImage(QImage* pImage, int /* vehicle id*/) +{ + _pImage = pImage->mirrored(); +} + diff --git a/src/QGCSettings.h b/src/QmlControls/QGCImageProvider.h similarity index 51% rename from src/QGCSettings.h rename to src/QmlControls/QGCImageProvider.h index fcbd969ea..59a5afee9 100644 --- a/src/QGCSettings.h +++ b/src/QmlControls/QGCImageProvider.h @@ -23,28 +23,37 @@ /** * @file - * @brief Definition of main class + * @brief Image Provider * -* @author Gus Grubba + * @author Gus Grubba * */ -#ifndef QGCSETTINGS_H -#define QGCSETTINGS_H +#ifndef QGCIMAGEPROVIDER_H +#define QGCIMAGEPROVIDER_H #include +#include +#include -class QGCSettings : public QObject +#include "QGCToolbox.h" + +class QGCImageProvider : public QGCTool, public QQuickImageProvider { - Q_OBJECT public: - explicit QGCSettings(QObject *parent = 0); - -signals: - -public slots: - + QGCImageProvider (QGCApplication* app); + ~QGCImageProvider (); + QImage requestImage (const QString & id, QSize * size, const QSize & requestedSize); + void setImage (QImage* pImage, int id = 0); + void setToolbox (QGCToolbox *toolbox); +private: + //-- TODO: For now this is holding a single image. If you happen to have two + // or more vehicles with flow, it will not work. To properly manage that condition + // this should be a map between each vehicle and its image. The URL provided + // for the image request would contain the vehicle identification. + QImage _pImage; }; -#endif // QGCSETTINGS_H + +#endif // QGCIMAGEPROVIDER_H diff --git a/src/QmlControls/SubMenuButton.qml b/src/QmlControls/SubMenuButton.qml index 64b0cb4fe..3b0074bf3 100644 --- a/src/QmlControls/SubMenuButton.qml +++ b/src/QmlControls/SubMenuButton.qml @@ -39,6 +39,7 @@ Button { verticalAlignment: TextEdit.AlignVCenter horizontalAlignment: TextEdit.AlignHCenter color: showHighlight ? qgcPal.buttonHighlightText : qgcPal.buttonText + font.pixelSize: ScreenTools.isMobile ? ScreenTools.defaultFontPixelSize * 0.65 : ScreenTools.defaultFontPixelSize text: control.text Rectangle { diff --git a/src/Vehicle/MultiVehicleManager.cc b/src/Vehicle/MultiVehicleManager.cc index 6ba5ac765..6e1630228 100644 --- a/src/Vehicle/MultiVehicleManager.cc +++ b/src/Vehicle/MultiVehicleManager.cc @@ -1,24 +1,24 @@ /*===================================================================== - + QGroundControl Open Source Ground Control Station - + (c) 2009 - 2014 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 . - + ======================================================================*/ /// @file @@ -56,6 +56,7 @@ void MultiVehicleManager::setToolbox(QGCToolbox *toolbox) QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); qmlRegisterUncreatableType("QGroundControl.MultiVehicleManager", 1, 0, "MultiVehicleManager", "Reference only"); + } bool MultiVehicleManager::notifyHeartbeatInfo(LinkInterface* link, int vehicleId, mavlink_heartbeat_t& heartbeat) @@ -64,7 +65,7 @@ bool MultiVehicleManager::notifyHeartbeatInfo(LinkInterface* link, int vehicleId if (vehicleId == _mavlinkProtocol->getSystemId()) { _app->showToolBarMessage(QString("Warning: A vehicle is using the same system id as QGroundControl: %1").arg(vehicleId)); } - + QSettings settings; bool mavlinkVersionCheck = settings.value("VERSION_CHECK_ENABLED", true).toBool(); if (mavlinkVersionCheck && heartbeat.mavlink_version != MAVLINK_VERSION) { @@ -74,24 +75,24 @@ bool MultiVehicleManager::notifyHeartbeatInfo(LinkInterface* link, int vehicleId "QGroundControl therefore refuses to connect to vehicle #%1, which sends MAVLink version %2 (QGroundControl uses version %3).").arg(vehicleId).arg(heartbeat.mavlink_version).arg(MAVLINK_VERSION)); return false; } - + Vehicle* vehicle = new Vehicle(link, vehicleId, (MAV_AUTOPILOT)heartbeat.autopilot, (MAV_TYPE)heartbeat.type, _firmwarePluginManager, _autopilotPluginManager, _joystickManager); - + if (!vehicle) { qWarning() << "New Vehicle allocation failed"; return false; } - + connect(vehicle, &Vehicle::allLinksDisconnected, this, &MultiVehicleManager::_deleteVehiclePhase1); connect(vehicle->autopilotPlugin(), &AutoPilotPlugin::parametersReadyChanged, this, &MultiVehicleManager::_autopilotParametersReadyChanged); _vehicles.append(vehicle); - + emit vehicleAdded(vehicle); - + setActiveVehicle(vehicle); } - + return true; } @@ -115,17 +116,17 @@ void MultiVehicleManager::_deleteVehiclePhase1(Vehicle* vehicle) if (!found) { qWarning() << "Vehicle not found in map!"; } - + vehicle->setActive(false); vehicle->uas()->clearVehicle(); - + // First we must signal that a vehicle is no longer available. _activeVehicleAvailable = false; _parameterReadyVehicleAvailable = false; emit activeVehicleAvailableChanged(false); emit parameterReadyVehicleAvailableChanged(false); emit vehicleRemoved(vehicle); - + // We must let the above signals flow through the system as well as get back to the main loop event queue // before we can actually delete the Vehicle. The reason is that Qml may be holding on the references to it. // Even though the above signals should unload any Qml which has references, that Qml will not be destroyed @@ -141,15 +142,15 @@ void MultiVehicleManager::_deleteVehiclePhase2 (void) /// Qml has been notified of vehicle about to go away and should be disconnected from it by now. /// This means we can now clear the active vehicle property and delete the Vehicle for real. - + Vehicle* newActiveVehicle = NULL; if (_vehicles.count()) { newActiveVehicle = qobject_cast(_vehicles[0]); } - + _activeVehicle = newActiveVehicle; emit activeVehicleChanged(newActiveVehicle); - + if (_activeVehicle) { _activeVehicle->setActive(true); emit activeVehicleAvailableChanged(true); @@ -157,7 +158,7 @@ void MultiVehicleManager::_deleteVehiclePhase2 (void) emit parameterReadyVehicleAvailableChanged(true); } } - + _vehicleBeingDeleted->deleteLater(); } @@ -168,10 +169,10 @@ void MultiVehicleManager::setActiveVehicle(Vehicle* vehicle) if (vehicle != _activeVehicle) { if (_activeVehicle) { _activeVehicle->setActive(false); - + // The sequence of signals is very important in order to not leave Qml elements connected // to a non-existent vehicle. - + // First we must signal that there is no active vehicle available. This will disconnect // any existing ui from the currently active vehicle. _activeVehicleAvailable = false; @@ -179,7 +180,7 @@ void MultiVehicleManager::setActiveVehicle(Vehicle* vehicle) emit activeVehicleAvailableChanged(false); emit parameterReadyVehicleAvailableChanged(false); } - + // See explanation in _deleteVehiclePhase1 _vehicleBeingSetActive = vehicle; QTimer::singleShot(20, this, &MultiVehicleManager::_setActiveVehiclePhase2); @@ -193,13 +194,13 @@ void MultiVehicleManager::_setActiveVehiclePhase2(void) // Now we signal the new active vehicle _activeVehicle = _vehicleBeingSetActive; emit activeVehicleChanged(_activeVehicle); - + // And finally vehicle availability if (_activeVehicle) { _activeVehicle->setActive(true); _activeVehicleAvailable = true; emit activeVehicleAvailableChanged(true); - + if (_activeVehicle->autopilotPlugin()->parametersReady()) { _parameterReadyVehicleAvailable = true; emit parameterReadyVehicleAvailableChanged(true); @@ -210,12 +211,12 @@ void MultiVehicleManager::_setActiveVehiclePhase2(void) void MultiVehicleManager::_autopilotParametersReadyChanged(bool parametersReady) { AutoPilotPlugin* autopilot = dynamic_cast(sender()); - + if (!autopilot) { qWarning() << "Dynamic cast failed!"; return; } - + if (autopilot->vehicle() == _activeVehicle) { _parameterReadyVehicleAvailable = parametersReady; emit parameterReadyVehicleAvailableChanged(parametersReady); @@ -249,10 +250,12 @@ Vehicle* MultiVehicleManager::getVehicleById(int vehicleId) QList MultiVehicleManager::vehicles(void) { QList list; - + for (int i=0; i< _vehicles.count(); i++) { list += qobject_cast(_vehicles[i]); } - + return list; } + + diff --git a/src/Vehicle/MultiVehicleManager.h b/src/Vehicle/MultiVehicleManager.h index b12c20024..bc3a42acb 100644 --- a/src/Vehicle/MultiVehicleManager.h +++ b/src/Vehicle/MultiVehicleManager.h @@ -1,24 +1,24 @@ /*===================================================================== - + QGroundControl Open Source Ground Control Station - + (c) 2009 - 2014 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 . - + ======================================================================*/ /// @file @@ -44,20 +44,20 @@ Q_DECLARE_LOGGING_CATEGORY(MultiVehicleManagerLog) class MultiVehicleManager : public QGCTool { Q_OBJECT - + public: MultiVehicleManager(QGCApplication* app); Q_INVOKABLE void saveSetting (const QString &key, const QString& value); Q_INVOKABLE QString loadSetting (const QString &key, const QString& defaultValue); - + Q_PROPERTY(bool activeVehicleAvailable READ activeVehicleAvailable NOTIFY activeVehicleAvailableChanged) Q_PROPERTY(bool parameterReadyVehicleAvailable READ parameterReadyVehicleAvailable NOTIFY parameterReadyVehicleAvailableChanged) Q_PROPERTY(Vehicle* activeVehicle READ activeVehicle WRITE setActiveVehicle NOTIFY activeVehicleChanged) Q_PROPERTY(QmlObjectListModel* vehicles READ vehiclesModel CONSTANT) - + // Methods - + /// Called to notify that a heartbeat was received with the specified information. MultiVehicleManager /// will create/update Vehicles as necessary. /// @param link Heartbeat came through on this link @@ -65,24 +65,24 @@ public: /// @param heartbeat Mavlink heartbeat message /// @return true: continue further processing of this message, false: disregard this message bool notifyHeartbeatInfo(LinkInterface* link, int vehicleId, mavlink_heartbeat_t& heartbeat); - + Q_INVOKABLE Vehicle* getVehicleById(int vehicleId); - + UAS* activeUas(void) { return _activeVehicle ? _activeVehicle->uas() : NULL; } - + QList vehicles(void); // Property accessors - + bool activeVehicleAvailable(void) { return _activeVehicleAvailable; } - + bool parameterReadyVehicleAvailable(void) { return _parameterReadyVehicleAvailable; } - + Vehicle* activeVehicle(void) { return _activeVehicle; } void setActiveVehicle(Vehicle* vehicle); - + QmlObjectListModel* vehiclesModel(void) { return &_vehicles; } - + // Override from QGCTool virtual void setToolbox(QGCToolbox *toolbox); @@ -92,33 +92,34 @@ signals: void activeVehicleAvailableChanged(bool activeVehicleAvailable); void parameterReadyVehicleAvailableChanged(bool parameterReadyVehicleAvailable); void activeVehicleChanged(Vehicle* activeVehicle); - + void _deleteVehiclePhase2Signal(void); - + private slots: void _deleteVehiclePhase1(Vehicle* vehicle); void _deleteVehiclePhase2(void); void _setActiveVehiclePhase2(void); void _autopilotParametersReadyChanged(bool parametersReady); - + private: bool _vehicleExists(int vehicleId); - + bool _activeVehicleAvailable; ///< true: An active vehicle is available bool _parameterReadyVehicleAvailable; ///< true: An active vehicle with ready parameters is available Vehicle* _activeVehicle; ///< Currently active vehicle from a ui perspective - + Vehicle* _vehicleBeingDeleted; ///< Vehicle being deleted in queued phases Vehicle* _vehicleBeingSetActive; ///< Vehicle being set active in queued phases - + QList _ignoreVehicleIds; ///< List of vehicle id for which we ignore further communication - + QmlObjectListModel _vehicles; - FirmwarePluginManager* _firmwarePluginManager; - AutoPilotPluginManager* _autopilotPluginManager; - JoystickManager* _joystickManager; - MAVLinkProtocol* _mavlinkProtocol; + FirmwarePluginManager* _firmwarePluginManager; + AutoPilotPluginManager* _autopilotPluginManager; + JoystickManager* _joystickManager; + MAVLinkProtocol* _mavlinkProtocol; + }; #endif diff --git a/src/Vehicle/Vehicle.cc b/src/Vehicle/Vehicle.cc index fd5b1709c..339006dad 100644 --- a/src/Vehicle/Vehicle.cc +++ b/src/Vehicle/Vehicle.cc @@ -1,24 +1,24 @@ /*===================================================================== - + QGroundControl Open Source Ground Control Station - + (c) 2009 - 2014 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 "Vehicle.h" @@ -34,6 +34,7 @@ #include "CoordinateVector.h" #include "ParameterLoader.h" #include "QGCApplication.h" +#include "QGCImageProvider.h" QGC_LOGGING_CATEGORY(VehicleLog, "VehicleLog") @@ -104,25 +105,27 @@ Vehicle::Vehicle(LinkInterface* link, , _firmwarePluginManager(firmwarePluginManager) , _autopilotPluginManager(autopilotPluginManager) , _joystickManager(joystickManager) + , _flowImageIndex(0) { _addLink(link); - + _mavlink = qgcApp()->toolbox()->mavlinkProtocol(); - + connect(_mavlink, &MAVLinkProtocol::messageReceived, this, &Vehicle::_mavlinkMessageReceived); connect(this, &Vehicle::_sendMessageOnThread, this, &Vehicle::_sendMessage, Qt::QueuedConnection); - + _uas = new UAS(_mavlink, this, _firmwarePluginManager); - + setLatitude(_uas->getLatitude()); setLongitude(_uas->getLongitude()); - - connect(_uas, &UAS::latitudeChanged, this, &Vehicle::setLatitude); - connect(_uas, &UAS::longitudeChanged, this, &Vehicle::setLongitude); - - _firmwarePlugin = _firmwarePluginManager->firmwarePluginForAutopilot(_firmwareType, _vehicleType); - _autopilotPlugin = _autopilotPluginManager->newAutopilotPluginForVehicle(this); - + + connect(_uas, &UAS::latitudeChanged, this, &Vehicle::setLatitude); + connect(_uas, &UAS::longitudeChanged, this, &Vehicle::setLongitude); + connect(_uas, &UAS::imageReady, this, &Vehicle::_imageReady); + + _firmwarePlugin = _firmwarePluginManager->firmwarePluginForAutopilot(_firmwareType, _vehicleType); + _autopilotPlugin = _autopilotPluginManager->newAutopilotPluginForVehicle(this); + connect(_autopilotPlugin, &AutoPilotPlugin::parametersReadyChanged, this, &Vehicle::_parametersReady); connect(_autopilotPlugin, &AutoPilotPlugin::missingParametersChanged, this, &Vehicle::missingParametersChanged); @@ -131,7 +134,7 @@ Vehicle::Vehicle(LinkInterface* link, _refreshTimer->setInterval(UPDATE_TIMER); _refreshTimer->start(UPDATE_TIMER); emit heartbeatTimeoutChanged(); - + _mav = uas(); // Reset satellite count (no GPS) _satelliteCount = -1; @@ -158,9 +161,9 @@ Vehicle::Vehicle(LinkInterface* link, _setSatelliteCount(pUas->getSatelliteCount(), QString("")); connect(pUas, &UAS::satelliteCountChanged, this, &Vehicle::_setSatelliteCount); } - + _loadSettings(); - + _missionManager = new MissionManager(this); connect(_missionManager, &MissionManager::error, this, &Vehicle::_missionManagerError); @@ -169,10 +172,10 @@ Vehicle::Vehicle(LinkInterface* link, connect(_parameterLoader, SIGNAL(parameterListProgress(float)), _autopilotPlugin, SIGNAL(parameterListProgress(float))); _firmwarePlugin->initializeVehicle(this); - + _sendMultipleTimer.start(_sendMessageMultipleIntraMessageDelay); connect(&_sendMultipleTimer, &QTimer::timeout, this, &Vehicle::_sendMessageMultipleNext); - + _mapTrajectoryTimer.setInterval(_mapTrajectoryMsecsBetweenPoints); connect(&_mapTrajectoryTimer, &QTimer::timeout, this, &Vehicle::_addNewMapTrajectoryPoint); @@ -191,6 +194,7 @@ Vehicle::~Vehicle() delete _mav; _mav = NULL; + } void Vehicle::_mavlinkMessageReceived(LinkInterface* link, mavlink_message_t message) @@ -200,14 +204,14 @@ void Vehicle::_mavlinkMessageReceived(LinkInterface* link, mavlink_message_t mes } _communicationInactivityTimer.start(); - + if (!_containsLink(link)) { _addLink(link); } - + // Give the plugin a change to adjust the message contents _firmwarePlugin->adjustMavlinkMessage(&message); - + switch (message.msgid) { case MAVLINK_MSG_ID_HOME_POSITION: _handleHomePosition(message); @@ -216,9 +220,9 @@ void Vehicle::_mavlinkMessageReceived(LinkInterface* link, mavlink_message_t mes _handleHeartbeat(message); break; } - + emit mavlinkMessageReceived(message); - + _uas->receiveMessage(message); } @@ -228,7 +232,7 @@ void Vehicle::_handleHomePosition(mavlink_message_t& message) bool emitHomePositionAvailableChanged = false; mavlink_home_position_t homePos; - + mavlink_msg_home_position_decode(&message, &homePos); QGeoCoordinate newHomePosition (homePos.latitude / 10000000.0, @@ -255,15 +259,15 @@ void Vehicle::_handleHomePosition(mavlink_message_t& message) void Vehicle::_handleHeartbeat(mavlink_message_t& message) { mavlink_heartbeat_t heartbeat; - + mavlink_msg_heartbeat_decode(&message, &heartbeat); - + bool newArmed = heartbeat.base_mode & MAV_MODE_FLAG_DECODE_POSITION_SAFETY; - + if (_armed != newArmed) { _armed = newArmed; emit armedChanged(_armed); - + // We are transitioning to the armed state, begin tracking trajectory points for the map if (_armed) { _mapTrajectoryStart(); @@ -286,7 +290,7 @@ bool Vehicle::_containsLink(LinkInterface* link) return true; } } - + return false; } @@ -303,14 +307,14 @@ void Vehicle::_linkDisconnected(LinkInterface* link) { qCDebug(VehicleLog) << "_linkDisconnected:" << link->getName(); qCDebug(VehicleLog) << "link count:" << _links.count(); - + for (int i=0; i<_links.count(); i++) { if (_links[i].data() == link) { _links.removeAt(i); break; } } - + if (_links.count() == 0) { emit allLinksDisconnected(this); } @@ -327,20 +331,20 @@ void Vehicle::_sendMessage(mavlink_message_t message) foreach (SharedLinkInterface sharedLink, _links) { LinkInterface* link = sharedLink.data(); Q_ASSERT(link); - + if (link->isConnected()) { MAVLinkProtocol* mavlink = _mavlink; - + // Give the plugin a chance to adjust _firmwarePlugin->adjustMavlinkMessage(&message); - + static const uint8_t messageKeys[256] = MAVLINK_MESSAGE_CRCS; mavlink_finalize_message_chan(&message, mavlink->getSystemId(), mavlink->getComponentId(), link->getMavlinkChannel(), message.len, messageKeys[message.msgid]); - + // Write message into buffer, prepending start sign uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; int len = mavlink_msg_to_send_buffer(buffer, &message); - + link->writeBytes((const char*)buffer, len); } } @@ -349,11 +353,11 @@ void Vehicle::_sendMessage(mavlink_message_t message) QList Vehicle::links(void) { QList list; - + foreach (SharedLinkInterface sharedLink, _links) { list += sharedLink.data(); } - + return list; } @@ -592,7 +596,7 @@ QString Vehicle::getMavIconColor() void Vehicle::_updateBatteryRemaining(UASInterface*, double voltage, double, double percent, int) { - + if(percent < 0.0) { percent = 0.0; } @@ -678,7 +682,7 @@ void Vehicle::_handleTextMessage(int newCount) emit messageCountChanged(); return; } - + UASMessageHandler* pMh = qgcApp()->toolbox()->uasMessageHandler(); Q_ASSERT(pMh); MessageType_t type = newCount ? _currentMessageType : MessageNone; @@ -755,16 +759,16 @@ int Vehicle::manualControlReservedButtonCount(void) void Vehicle::_loadSettings(void) { QSettings settings; - + settings.beginGroup(QString(_settingsGroup).arg(_id)); - + bool convertOk; - + _joystickMode = (JoystickMode_t)settings.value(_joystickModeSettingsKey, JoystickModeRC).toInt(&convertOk); if (!convertOk) { _joystickMode = JoystickModeRC; } - + _joystickEnabled = settings.value(_joystickEnabledSettingsKey, false).toBool(); _communicationInactivityTimeoutMSecs = settings.value(_communicationInactivityKey, _communicationInactivityTimeoutMSecsDefault).toInt(); } @@ -772,9 +776,9 @@ void Vehicle::_loadSettings(void) void Vehicle::_saveSettings(void) { QSettings settings; - + settings.beginGroup(QString(_settingsGroup).arg(_id)); - + settings.setValue(_joystickModeSettingsKey, _joystickMode); settings.setValue(_joystickEnabledSettingsKey, _joystickEnabled); settings.setValue(_communicationInactivityKey, _communicationInactivityTimeoutMSecs); @@ -791,7 +795,7 @@ void Vehicle::setJoystickMode(int mode) qCWarning(VehicleLog) << "Invalid joystick mode" << mode; return; } - + _joystickMode = (JoystickMode_t)mode; _saveSettings(); emit joystickModeChanged(mode); @@ -800,9 +804,9 @@ void Vehicle::setJoystickMode(int mode) QStringList Vehicle::joystickModes(void) { QStringList list; - + list << "Normal" << "Attitude" << "Position" << "Force" << "Velocity"; - + return list; } @@ -844,7 +848,7 @@ bool Vehicle::active(void) void Vehicle::setActive(bool active) { _active = active; - + _startJoystick(_active); } @@ -866,10 +870,10 @@ QGeoCoordinate Vehicle::homePosition(void) void Vehicle::setArmed(bool armed) { // We specifically use COMMAND_LONG:MAV_CMD_COMPONENT_ARM_DISARM since it is supported by more flight stacks. - + mavlink_message_t msg; mavlink_command_long_t cmd; - + cmd.command = (uint16_t)MAV_CMD_COMPONENT_ARM_DISARM; cmd.confirmation = 0; cmd.param1 = armed ? 1.0f : 0.0f; @@ -881,9 +885,9 @@ void Vehicle::setArmed(bool armed) cmd.param7 = 0.0f; cmd.target_system = id(); cmd.target_component = 0; - + mavlink_msg_command_long_encode(_mavlink->getSystemId(), _mavlink->getComponentId(), &msg, &cmd); - + sendMessage(msg); } @@ -948,13 +952,13 @@ void Vehicle::requestDataStream(MAV_DATA_STREAM stream, uint16_t rate) { mavlink_message_t msg; mavlink_request_data_stream_t dataStream; - + dataStream.req_stream_id = stream; dataStream.req_message_rate = rate; dataStream.start_stop = 1; // start dataStream.target_system = id(); dataStream.target_component = 0; - + mavlink_msg_request_data_stream_encode(_mavlink->getSystemId(), _mavlink->getComponentId(), &msg, &dataStream); // We use sendMessageMultiple since we really want these to make it to the vehicle @@ -965,16 +969,16 @@ void Vehicle::_sendMessageMultipleNext(void) { if (_nextSendMessageMultipleIndex < _sendMessageMultipleList.count()) { qCDebug(VehicleLog) << "_sendMessageMultipleNext:" << _sendMessageMultipleList[_nextSendMessageMultipleIndex].message.msgid; - + sendMessage(_sendMessageMultipleList[_nextSendMessageMultipleIndex].message); - + if (--_sendMessageMultipleList[_nextSendMessageMultipleIndex].retryCount <= 0) { _sendMessageMultipleList.removeAt(_nextSendMessageMultipleIndex); } else { _nextSendMessageMultipleIndex++; } } - + if (_nextSendMessageMultipleIndex >= _sendMessageMultipleList.count()) { _nextSendMessageMultipleIndex = 0; } @@ -983,10 +987,10 @@ void Vehicle::_sendMessageMultipleNext(void) void Vehicle::sendMessageMultiple(mavlink_message_t message) { SendMessageMultipleInfo_t info; - + info.message = message; info.retryCount = _sendMessageMultipleRetries; - + _sendMessageMultipleList.append(info); } @@ -1043,3 +1047,14 @@ ParameterLoader* Vehicle::getParameterLoader(void) { return _parameterLoader; } + +void Vehicle::_imageReady(UASInterface*) +{ + if(_uas) + { + QImage img = _uas->getImage(); + qgcApp()->toolbox()->imageProvider()->setImage(&img, _id); + _flowImageIndex++; + emit flowImageIndexChanged(); + } +} diff --git a/src/Vehicle/Vehicle.h b/src/Vehicle/Vehicle.h index 34f0b4b84..b41f86855 100644 --- a/src/Vehicle/Vehicle.h +++ b/src/Vehicle/Vehicle.h @@ -1,24 +1,24 @@ /*===================================================================== - + QGroundControl Open Source Ground Control Station - + (c) 2009 - 2014 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 . - + ======================================================================*/ /// @file @@ -29,7 +29,6 @@ #include #include -#include #include "LinkInterface.h" #include "QGCMAVLink.h" @@ -52,7 +51,7 @@ Q_DECLARE_LOGGING_CATEGORY(VehicleLog) class Vehicle : public QObject { Q_OBJECT - + public: Vehicle(LinkInterface* link, int vehicleId, @@ -62,7 +61,7 @@ public: AutoPilotPluginManager* autopilotPluginManager, JoystickManager* joystickManager); ~Vehicle(); - + Q_PROPERTY(int id READ id CONSTANT) Q_PROPERTY(AutoPilotPlugin* autopilot MEMBER _autopilotPlugin CONSTANT) Q_PROPERTY(QGeoCoordinate coordinate READ coordinate NOTIFY coordinateChanged) @@ -106,7 +105,8 @@ public: Q_PROPERTY(int joystickMode READ joystickMode WRITE setJoystickMode NOTIFY joystickModeChanged) Q_PROPERTY(QStringList joystickModes READ joystickModes CONSTANT) Q_PROPERTY(bool joystickEnabled READ joystickEnabled WRITE setJoystickEnabled NOTIFY joystickEnabledChanged) - Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged) + Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged) + Q_PROPERTY(int flowImageIndex READ flowImageIndex NOTIFY flowImageIndexChanged) /// Returns the number of buttons which are reserved for firmware use in the MANUAL_CONTROL mavlink /// message. For example PX4 Flight Stack reserves the first 8 buttons to simulate rc switches. @@ -121,8 +121,8 @@ public: QGeoCoordinate coordinate(void) { return _coordinate; } bool coordinateValid(void) { return _coordinateValid; } QmlObjectListModel* missionItemsModel(void); - - + + typedef enum { JoystickModeRC, ///< Joystick emulates an RC Transmitter JoystickModeAttitude, @@ -131,50 +131,50 @@ public: JoystickModeVelocity, JoystickModeMax } JoystickMode_t; - + int joystickMode(void); void setJoystickMode(int mode); - + /// List of joystick mode names QStringList joystickModes(void); - + bool joystickEnabled(void); void setJoystickEnabled(bool enabled); - + // Is vehicle active with respect to current active vehicle in QGC bool active(void); void setActive(bool active); - + // Property accesors int id(void) { return _id; } MAV_AUTOPILOT firmwareType(void) { return _firmwareType; } MAV_TYPE vehicleType(void) { return _vehicleType; } - + /// Sends this specified message to all links accociated with this vehicle void sendMessage(mavlink_message_t message); - + /// Sends the specified messages multiple times to the vehicle in order to attempt to /// guarantee that it makes it to the vehicle. void sendMessageMultiple(mavlink_message_t message); - + /// Provides access to uas from vehicle. Temporary workaround until UAS is fully phased out. UAS* uas(void) { return _uas; } - + /// Provides access to uas from vehicle. Temporary workaround until AutoPilotPlugin is fully phased out. AutoPilotPlugin* autopilotPlugin(void) { return _autopilotPlugin; } - + /// Provides access to the Firmware Plugin for this Vehicle FirmwarePlugin* firmwarePlugin(void) { return _firmwarePlugin; } - + QList links(void); - + int manualControlReservedButtonCount(void); - + MissionManager* missionManager(void) { return _missionManager; } - + bool homePositionAvailable(void); QGeoCoordinate homePosition(void); - + bool armed(void) { return _armed; } void setArmed(bool armed); @@ -185,23 +185,25 @@ public: bool hilMode(void); void setHilMode(bool hilMode); - + QmlObjectListModel* trajectoryPoints(void) { return &_mapTrajectoryList; } - + + int flowImageIndex() { return _flowImageIndex; } + /// Requests the specified data stream from the vehicle /// @param stream Stream which is being requested /// @param rate Rate at which to send stream in Hz void requestDataStream(MAV_DATA_STREAM stream, uint16_t rate); - + bool missingParameters(void); - + typedef enum { MessageNone, MessageNormal, MessageWarning, MessageError } MessageType_t; - + enum { ROLL_CHANGED, PITCH_CHANGED, @@ -213,10 +215,10 @@ public: ALTITUDEWGS84_CHANGED, ALTITUDEAMSL_CHANGED }; - + // Called when the message drop-down is invoked to clear current count void resetMessages(); - + bool messageTypeNone () { return _currentMessageType == MessageNone; } bool messageTypeNormal () { return _currentMessageType == MessageNormal; } bool messageTypeWarning () { return _currentMessageType == MessageWarning; } @@ -245,11 +247,11 @@ public: unsigned int heartbeatTimeout () { return _currentHeartbeatTimeout; } ParameterLoader* getParameterLoader(void); - + public slots: void setLatitude(double latitude); void setLongitude(double longitude); - + signals: void allLinksDisconnected(Vehicle* vehicle); void coordinateChanged(QGeoCoordinate coordinate); @@ -264,10 +266,10 @@ signals: void flightModeChanged(const QString& flightMode); void hilModeChanged(bool hilMode); void missingParametersChanged(bool missingParameters); - + /// Used internally to move sendMessage call to main thread void _sendMessageOnThread(mavlink_message_t message); - + void messageTypeChanged (); void newMessageCountChanged (); void messageCountChanged (); @@ -290,7 +292,8 @@ signals: void satelliteCountChanged (); void currentStateChanged (); void satelliteLockChanged (); - + void flowImageIndexChanged (); + private slots: void _mavlinkMessageReceived(LinkInterface* link, mavlink_message_t message); void _linkDisconnected(LinkInterface* link); @@ -316,6 +319,8 @@ private slots: void _heartbeatTimeout (bool timeout, unsigned int ms); void _setSatelliteCount (double val, QString name); void _setSatLoc (UASInterface* uas, int fix); + /** @brief A new camera image has arrived */ + void _imageReady (UASInterface* uas); private: bool _containsLink(LinkInterface* link); @@ -335,29 +340,29 @@ private: private: int _id; ///< Mavlink system id bool _active; - + MAV_AUTOPILOT _firmwareType; MAV_TYPE _vehicleType; FirmwarePlugin* _firmwarePlugin; AutoPilotPlugin* _autopilotPlugin; MAVLinkProtocol* _mavlink; - + /// List of all links associated with this vehicle. We keep SharedLinkInterface objects /// which are QSharedPointer's in order to maintain reference counts across threads. /// This way Link deletion works correctly. QList _links; - + JoystickMode_t _joystickMode; bool _joystickEnabled; - + UAS* _uas; - + QGeoCoordinate _coordinate; bool _coordinateValid; ///< true: vehicle has 3d lock and therefore valid location - + bool _homePositionAvailable; QGeoCoordinate _homePosition; - + UASInterface* _mav; int _currentMessageCount; int _messageCount; @@ -389,12 +394,12 @@ private: int _satelliteCount; int _satelliteLock; int _updateCount; - + MissionManager* _missionManager; bool _missionManagerInitialRequestComplete; ParameterLoader* _parameterLoader; - + bool _armed; ///< true: vehicle is armed uint8_t _base_mode; ///< base_mode from HEARTBEAT uint32_t _custom_mode; ///< custom_mode from HEARTBEAT @@ -404,15 +409,15 @@ private: mavlink_message_t message; ///< Message to send multiple times int retryCount; ///< Number of retries left } SendMessageMultipleInfo_t; - + QList _sendMessageMultipleList; ///< List of messages being sent multiple times - + static const int _sendMessageMultipleRetries = 5; static const int _sendMessageMultipleIntraMessageDelay = 500; - + QTimer _sendMultipleTimer; int _nextSendMessageMultipleIndex; - + QTimer _mapTrajectoryTimer; QmlObjectListModel _mapTrajectoryList; QGeoCoordinate _mapTrajectoryLastCoordinate; @@ -423,10 +428,12 @@ private: int _communicationInactivityTimeoutMSecs; static const int _communicationInactivityTimeoutMSecsDefault = 30 * 1000; - FirmwarePluginManager* _firmwarePluginManager; - AutoPilotPluginManager* _autopilotPluginManager; - JoystickManager* _joystickManager; - + FirmwarePluginManager* _firmwarePluginManager; + AutoPilotPluginManager* _autopilotPluginManager; + JoystickManager* _joystickManager; + + int _flowImageIndex; + // Settings keys static const char* _settingsGroup; static const char* _joystickModeSettingsKey; diff --git a/src/VehicleSetup/PX4FlowSensor.qml b/src/VehicleSetup/PX4FlowSensor.qml new file mode 100644 index 000000000..76858ba97 --- /dev/null +++ b/src/VehicleSetup/PX4FlowSensor.qml @@ -0,0 +1,64 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009 - 2015 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.3 +import QtQuick.Controls 1.2 +import QtQuick.Controls.Styles 1.2 +import QtQuick.Dialogs 1.2 + +import QGroundControl.Controls 1.0 +import QGroundControl.FactSystem 1.0 +import QGroundControl.FactControls 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Controllers 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.MultiVehicleManager 1.0 + +QGCView { + id: qgcView + viewPanel: panel + + property var _activeVehicle: multiVehicleManager.activeVehicle + + QGCPalette { id: qgcPal; colorGroupEnabled: panel.enabled } + + QGCViewPanel { + id: panel + anchors.fill: parent + + QGCLabel { + id: titleLabel + text: "PX4Flow Camera" + font.pixelSize: ScreenTools.mediumFontPixelSize + } + + Image { + source: _activeVehicle ? "image://QGCImages/" + _activeVehicle.id + "/" + _activeVehicle.flowImageIndex : "" + width: parent.width * 0.5 + height: width * 0.75 + cache: false + anchors.centerIn: parent + fillMode: Image.PreserveAspectFit + } + } +} diff --git a/src/VehicleSetup/SetupView.qml b/src/VehicleSetup/SetupView.qml index da7faf821..a39bd0f0e 100644 --- a/src/VehicleSetup/SetupView.qml +++ b/src/VehicleSetup/SetupView.qml @@ -94,6 +94,11 @@ Rectangle { panelLoader.source = "SetupParameterEditor.qml"; } + function showPX4FlowPanel() + { + panelLoader.source = "PX4FlowSensor.qml"; + } + function showVehicleComponentPanel(vehicleComponent) { if (multiVehicleManager.activeVehicle.armed) { @@ -247,6 +252,16 @@ Rectangle { onClicked: showFirmwarePanel() } + SubMenuButton { + id: px4FlowButton + width: mainWindow.menuButtonWidth + exclusiveGroup: setupButtonGroup + visible: _fullParameterVehicleAvailable + setupIndicator: false + text: "PX4FLOW" + onClicked: showPX4FlowPanel() + } + SubMenuButton { id: joystickButton width: mainWindow.menuButtonWidth diff --git a/src/comm/MockLink.cc b/src/comm/MockLink.cc index 1c0a89659..5d5f5c719 100644 --- a/src/comm/MockLink.cc +++ b/src/comm/MockLink.cc @@ -70,7 +70,7 @@ union px4_custom_mode { float MockLink::_vehicleLatitude = 47.633033f; float MockLink::_vehicleLongitude = -122.08794f; -float MockLink::_vehicleAltitude = 2.5f; +float MockLink::_vehicleAltitude = 9872.5f; const char* MockConfiguration::_firmwareTypeKey = "FirmwareType"; const char* MockConfiguration::_vehicleTypeKey = "VehicleType"; @@ -108,9 +108,9 @@ MockLink::MockLink(MockConfiguration* config) _fileServer = new MockLinkFileServer(_vehicleSystemId, _vehicleComponentId, this); Q_CHECK_PTR(_fileServer); - + moveToThread(this); - + _loadParams(); QObject::connect(this, &MockLink::_incomingBytes, this, &MockLink::_handleIncomingBytes); } @@ -154,7 +154,7 @@ void MockLink::run(void) QTimer _timer10HzTasks; QTimer _timer50HzTasks; - QObject::connect(&_timer1HzTasks, &QTimer::timeout, this, &MockLink::_run1HzTasks); + QObject::connect(&_timer1HzTasks, &QTimer::timeout, this, &MockLink::_run1HzTasks); QObject::connect(&_timer10HzTasks, &QTimer::timeout, this, &MockLink::_run10HzTasks); QObject::connect(&_timer50HzTasks, &QTimer::timeout, this, &MockLink::_run50HzTasks); @@ -164,10 +164,10 @@ void MockLink::run(void) exec(); - QObject::disconnect(&_timer1HzTasks, &QTimer::timeout, this, &MockLink::_run1HzTasks); + QObject::disconnect(&_timer1HzTasks, &QTimer::timeout, this, &MockLink::_run1HzTasks); QObject::disconnect(&_timer10HzTasks, &QTimer::timeout, this, &MockLink::_run10HzTasks); QObject::disconnect(&_timer50HzTasks, &QTimer::timeout, this, &MockLink::_run50HzTasks); - + _missionItemHandler.shutdown(); } @@ -285,14 +285,14 @@ void MockLink::_sendHeartBeat(void) _mavBaseMode, // MAV_MODE _mavCustomMode, // custom mode _mavState); // MAV_STATE - + respondWithMavlinkMessage(msg); } void MockLink::respondWithMavlinkMessage(const mavlink_message_t& msg) { uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; - + int cBuffer = mavlink_msg_to_send_buffer(buffer, &msg); QByteArray bytes((char *)buffer, cBuffer); emit bytesReceived(this, bytes); @@ -354,7 +354,7 @@ void MockLink::_handleIncomingMavlinkBytes(const uint8_t* bytes, int cBytes) if (!mavlink_parse_char(getMavlinkChannel(), bytes[i], &msg, &comm)) { continue; } - + if (_missionItemHandler.handleMessage(msg)) { continue; } @@ -379,11 +379,11 @@ void MockLink::_handleIncomingMavlinkBytes(const uint8_t* bytes, int cBytes) case MAVLINK_MSG_ID_PARAM_REQUEST_READ: _handleParamRequestRead(msg); break; - + case MAVLINK_MSG_ID_FILE_TRANSFER_PROTOCOL: _handleFTP(msg); break; - + case MAVLINK_MSG_ID_COMMAND_LONG: _handleCommandLong(msg); break; @@ -552,14 +552,14 @@ void MockLink::_handleParamRequestList(const mavlink_message_t& msg) Q_ASSERT(request.target_system == _vehicleSystemId); Q_ASSERT(request.target_component == MAV_COMP_ID_ALL); - + // We must send the first parameter for each component first. Otherwise system won't correctly know // when all parameters are loaded. foreach (int componentId, _mapParamName2Value.keys()) { uint16_t paramIndex = 0; int cParameters = _mapParamName2Value[componentId].count(); - + foreach(QString paramName, _mapParamName2Value[componentId].keys()) { char paramId[MAVLINK_MSG_ID_PARAM_VALUE_LEN]; mavlink_message_t responseMsg; @@ -583,17 +583,17 @@ void MockLink::_handleParamRequestList(const mavlink_message_t& msg) cParameters, // Total number of parameters paramIndex++); // Index of this parameter respondWithMavlinkMessage(responseMsg); - + // Only first parameter the first time through break; } } - + foreach (int componentId, _mapParamName2Value.keys()) { uint16_t paramIndex = 0; int cParameters = _mapParamName2Value[componentId].count(); bool skipParam = true; - + foreach(QString paramName, _mapParamName2Value[componentId].keys()) { if (skipParam) { // We've already sent the first param @@ -602,17 +602,17 @@ void MockLink::_handleParamRequestList(const mavlink_message_t& msg) } else { char paramId[MAVLINK_MSG_ID_PARAM_VALUE_LEN]; mavlink_message_t responseMsg; - + Q_ASSERT(_mapParamName2Value[componentId].contains(paramName)); Q_ASSERT(_mapParamName2MavParamType.contains(paramName)); - + MAV_PARAM_TYPE paramType = _mapParamName2MavParamType[paramName]; - + Q_ASSERT(paramName.length() <= MAVLINK_MSG_ID_PARAM_VALUE_LEN); strncpy(paramId, paramName.toLocal8Bit().constData(), MAVLINK_MSG_ID_PARAM_VALUE_LEN); - + qCDebug(MockLinkLog) << "Sending msg_param_value" << componentId << paramId << paramType << _mapParamName2Value[componentId][paramId]; - + mavlink_msg_param_value_pack(_vehicleSystemId, componentId, // component id &responseMsg, // Outgoing message @@ -634,14 +634,14 @@ void MockLink::_handleParamSet(const mavlink_message_t& msg) Q_ASSERT(request.target_system == _vehicleSystemId); int componentId = request.target_component; - + // Param may not be null terminated if exactly fits char paramId[MAVLINK_MSG_PARAM_SET_FIELD_PARAM_ID_LEN + 1]; paramId[MAVLINK_MSG_PARAM_SET_FIELD_PARAM_ID_LEN] = 0; strncpy(paramId, request.param_id, MAVLINK_MSG_PARAM_SET_FIELD_PARAM_ID_LEN); qCDebug(MockLinkLog) << "_handleParamSet" << componentId << paramId << request.param_type; - + Q_ASSERT(_mapParamName2Value.contains(componentId)); Q_ASSERT(_mapParamName2Value[componentId].contains(paramId)); Q_ASSERT(request.param_type == _mapParamName2MavParamType[paramId]); @@ -726,12 +726,12 @@ void MockLink::_handleParamRequestRead(const mavlink_message_t& msg) void MockLink::emitRemoteControlChannelRawChanged(int channel, uint16_t raw) { uint16_t chanRaw[18]; - + for (int i=0; i<18; i++) { chanRaw[i] = UINT16_MAX; } chanRaw[channel] = raw; - + mavlink_message_t responseMsg; mavlink_msg_rc_channels_pack(_vehicleSystemId, _vehicleComponentId, @@ -769,7 +769,7 @@ void MockLink::_handleFTP(const mavlink_message_t& msg) void MockLink::_handleCommandLong(const mavlink_message_t& msg) { mavlink_command_long_t request; - + mavlink_msg_command_long_decode(&msg, &request); if (request.command == MAV_CMD_COMPONENT_ARM_DISARM) { @@ -808,7 +808,7 @@ void MockLink::_sendHomePosition(void) (int32_t)(_vehicleAltitude * 1000), 0.0f, 0.0f, 0.0f, &bogus[0], - 0.0f, 0.0f, 0.0f); + 0.0f, 0.0f, 0.0f); respondWithMavlinkMessage(msg); } } @@ -823,9 +823,9 @@ void MockLink::_sendGpsRawInt(void) &msg, timeTick++, // time since boot 3, // 3D fix - (int32_t)(_vehicleLatitude * 1E7), + (int32_t)(_vehicleLatitude * 1E7), (int32_t)(_vehicleLongitude * 1E7), - (int32_t)(_vehicleAltitude * 1000), + (int32_t)(_vehicleAltitude * 1000), UINT16_MAX, UINT16_MAX, // HDOP/VDOP not known UINT16_MAX, // velocity not known UINT16_MAX, // course over ground not known @@ -878,7 +878,7 @@ MockConfiguration::MockConfiguration(MockConfiguration* source) : LinkConfiguration(source) { _firmwareType = source->_firmwareType; - _vehicleType = source->_vehicleType; + _vehicleType = source->_vehicleType; _sendStatusText = source->_sendStatusText; } diff --git a/src/ui/MainWindow.cc b/src/ui/MainWindow.cc index 1ed0015b9..b3d83c11b 100644 --- a/src/ui/MainWindow.cc +++ b/src/ui/MainWindow.cc @@ -53,6 +53,7 @@ This file is part of the QGROUNDCONTROL project #include "HomePositionManager.h" #include "LogCompressor.h" #include "UAS.h" +#include "QGCImageProvider.h" #ifndef __mobile__ #include "QGCDataPlot2D.h" @@ -166,6 +167,10 @@ MainWindow::MainWindow() _mainQmlWidgetHolder->setContextPropertyObject("controller", this); _mainQmlWidgetHolder->setSource(QUrl::fromUserInput("qrc:qml/MainWindow.qml")); + // Image provider + QQuickImageProvider* pImgProvider = dynamic_cast(qgcApp()->toolbox()->imageProvider()); + _mainQmlWidgetHolder->getEngine()->addImageProvider(QLatin1String("QGCImages"), pImgProvider); + // Set dock options setDockOptions(0); // Setup corners @@ -309,6 +314,7 @@ MainWindow::MainWindow() MainWindow::~MainWindow() { + _mainQmlWidgetHolder->getEngine()->removeImageProvider(QLatin1String("QGCImages")); _instance = NULL; } @@ -465,6 +471,8 @@ void MainWindow::closeEvent(QCloseEvent *event) // We have to pull out the QmlWidget from the main window and delete it here, before // the MainWindow ends up getting deleted. Otherwise the Qml has a reference to MainWindow // inside it which in turn causes a shutdown crash. + // Remove image provider + _mainQmlWidgetHolder->getEngine()->removeImageProvider(QLatin1String("QGCImages")); _centralLayout->removeWidget(_mainQmlWidgetHolder); delete _mainQmlWidgetHolder; _mainQmlWidgetHolder = NULL; @@ -474,7 +482,10 @@ void MainWindow::closeEvent(QCloseEvent *event) event->accept(); + //-- TODO: This effectively causes the QGCApplication destructor to not being able + // to access the pointer it is trying to delete. _instance = NULL; + emit mainWindowClosed(); } -- 2.22.0