diff --git a/qgcresources.qrc b/qgcresources.qrc index cc3b28fba4f74d078fdc496b3989fc31b6bc950f..52a88814a471f89efd37d2fcea09f71e680eb33d 100644 --- a/qgcresources.qrc +++ b/qgcresources.qrc @@ -208,6 +208,9 @@ src/AutoPilotPlugins/PX4/AirframeFactMetaData.xml src/AutoPilotPlugins/PX4/ParameterFactMetaData.xml + + src/AutoPilotPlugins/APM/AirframeFactMetaData.xml + src/FirmwarePlugin/APM/apm.pdef.xml diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 4156b72224ad910db1072a6f1274c349e7fafab5..1b793463915ed04127e7d95941b4a54b7f179332 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -282,7 +282,9 @@ HEADERS += \ src/uas/UASMessageHandler.h \ src/ui/toolbar/MainToolBarController.h \ src/AutoPilotPlugins/PX4/PX4AirframeLoader.h \ + src/AutoPilotPlugins/APM/APMAirframeLoader.h \ src/QmlControls/QGCImageProvider.h \ + src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.h DebugBuild { HEADERS += \ @@ -398,7 +400,9 @@ SOURCES += \ src/uas/UASMessageHandler.cc \ src/ui/toolbar/MainToolBarController.cc \ src/AutoPilotPlugins/PX4/PX4AirframeLoader.cc \ + src/AutoPilotPlugins/APM/APMAirframeLoader.cc \ src/QmlControls/QGCImageProvider.cc \ + src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.cc DebugBuild { SOURCES += \ @@ -550,6 +554,8 @@ HEADERS+= \ src/AutoPilotPlugins/AutoPilotPluginManager.h \ src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h \ src/AutoPilotPlugins/APM/APMAirframeComponent.h \ + src/AutoPilotPlugins/APM/APMAirframeComponentController.h \ + src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.h \ src/AutoPilotPlugins/APM/APMComponent.h \ src/AutoPilotPlugins/APM/APMRadioComponent.h \ src/AutoPilotPlugins/APM/APMFlightModesComponent.h \ @@ -601,6 +607,7 @@ SOURCES += \ src/AutoPilotPlugins/AutoPilotPluginManager.cc \ src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc \ src/AutoPilotPlugins/APM/APMAirframeComponent.cc \ + src/AutoPilotPlugins/APM/APMAirframeComponentController.cc \ src/AutoPilotPlugins/APM/APMComponent.cc \ src/AutoPilotPlugins/APM/APMRadioComponent.cc \ src/AutoPilotPlugins/APM/APMFlightModesComponent.cc \ @@ -610,6 +617,7 @@ SOURCES += \ src/AutoPilotPlugins/APM/APMSensorsComponentController.cc \ src/AutoPilotPlugins/APM/APMTuningComponent.cc \ src/AutoPilotPlugins/Common/RadioComponentController.cc \ + src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.cc \ src/AutoPilotPlugins/Generic/GenericAutoPilotPlugin.cc \ src/AutoPilotPlugins/PX4/AirframeComponent.cc \ src/AutoPilotPlugins/PX4/AirframeComponentAirframes.cc \ @@ -654,19 +662,21 @@ INCLUDEPATH += \ HEADERS += \ src/FactSystem/Fact.h \ + src/FactSystem/FactControls/FactPanelController.h \ src/FactSystem/FactMetaData.h \ src/FactSystem/FactSystem.h \ src/FactSystem/FactValidator.h \ src/FactSystem/ParameterLoader.h \ - src/FactSystem/FactControls/FactPanelController.h \ + src/FactSystem/SettingsFact.h \ SOURCES += \ src/FactSystem/Fact.cc \ + src/FactSystem/FactControls/FactPanelController.cc \ src/FactSystem/FactMetaData.cc \ src/FactSystem/FactSystem.cc \ src/FactSystem/FactValidator.cc \ src/FactSystem/ParameterLoader.cc \ - src/FactSystem/FactControls/FactPanelController.cc \ + src/FactSystem/SettingsFact.cc \ #------------------------------------------------------------------------------------- # Video Streaming diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponent.cc b/src/AutoPilotPlugins/APM/APMAirframeComponent.cc index 1c90064d80b68d4ed5de33eba714fe236adb82b8..19899f11f903a068faccf89db10feea733f76082 100644 --- a/src/AutoPilotPlugins/APM/APMAirframeComponent.cc +++ b/src/AutoPilotPlugins/APM/APMAirframeComponent.cc @@ -57,22 +57,13 @@ bool APMAirframeComponent::requiresSetup(void) const bool APMAirframeComponent::setupComplete(void) const { - // You'll need to figure out which parameters trigger setup complete -#if 0 - return _autopilot->getParameterFact(FactSystem::defaultComponentId, "SYS_AUTOSTART")->rawValue().toInt() != 0; -#else - return true; -#endif + //: Not the correct one, but it works for the moment. + return _autopilot->getParameterFact(FactSystem::defaultComponentId, "FRAME")->rawValue().toInt() != -1; } QStringList APMAirframeComponent::setupCompleteChangedTriggerList(void) const { - // You'll need to figure out which parameters trigger setup complete -#if 0 - return QStringList("SYS_AUTOSTART"); -#else return QStringList(); -#endif } QUrl APMAirframeComponent::setupSource(void) const diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponent.qml b/src/AutoPilotPlugins/APM/APMAirframeComponent.qml index e03e3e95084c396b4a52459cacec680d7616463c..1a6551e51caca5f8a8358407a8fda8b5827c5094 100644 --- a/src/AutoPilotPlugins/APM/APMAirframeComponent.qml +++ b/src/AutoPilotPlugins/APM/APMAirframeComponent.qml @@ -21,7 +21,7 @@ ======================================================================*/ -import QtQuick 2.2 +import QtQuick 2.5 import QtQuick.Controls 1.2 import QtQuick.Controls.Styles 1.2 import QtQuick.Dialogs 1.2 @@ -39,13 +39,214 @@ QGCView { QGCPalette { id: qgcPal; colorGroupEnabled: panel.enabled } + property real _minW: ScreenTools.defaultFontPixelWidth * 30 + property real _boxWidth: _minW + property real _boxSpace: ScreenTools.defaultFontPixelWidth + property Fact sysIdFact: controller.getParameterFact(-1, "FRAME") + + function computeDimensions() { + var sw = 0 + var rw = 0 + var idx = Math.floor(scroll.width / (_minW + ScreenTools.defaultFontPixelWidth)) + if(idx < 1) { + _boxWidth = scroll.width + _boxSpace = 0 + } else { + _boxSpace = 0 + if(idx > 1) { + _boxSpace = ScreenTools.defaultFontPixelWidth + sw = _boxSpace * (idx - 1) + } + rw = scroll.width - sw + _boxWidth = rw / idx + } + } + + APMAirframeComponentController { + id: controller + factPanel: panel + } + + Component { + id: applyRestartDialogComponent + + QGCViewDialog { + id: applyRestartDialog + + Connections { + target: controller + onCurrentAirframeTypeChanged: { + airframePicker.model = controller.currentAirframeType.airframes; + } + onCurrentAirframeChanged : { + hideDialog(); + } + } + + QGCLabel { + id: applyParamsText + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: _boxSpace + wrapMode: Text.WordWrap + text: "Select you drone to load the default parameters for it. " + } + + Flow { + anchors.top : applyParamsText.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + spacing : _boxSpace + layoutDirection: Qt.Vertical; + anchors.margins : _boxSpace + Repeater { + id : airframePicker + model : controller.currentAirframeType.airframes; + + delegate: QGCButton { + id: btnParams + width: parent.width / 2.1 + height: (ScreenTools.defaultFontPixelHeight * 14) / 5 + text: controller.currentAirframeType.airframes[index].name; + + onClicked : { + controller.currentAirframe = controller.currentAirframeType.airframes[index] + } + } + } + } + } + } + QGCViewPanel { id: panel anchors.fill: parent - QGCLabel { - text: "Work in progress"; + readonly property real spacerHeight: ScreenTools.defaultFontPixelHeight + + onWidthChanged: { + computeDimensions() + } + + Item { + id: helpApplyRow + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + height: Math.max(helpText.contentHeight, applyButton.height) + + QGCLabel { + id: helpText + width: parent.width - applyButton.width - 5 + text: qsTr("Please select your airframe type") + font.pixelSize: ScreenTools.mediumFontPixelSize + wrapMode: Text.WordWrap + } + + QGCButton { + id: applyButton + anchors.right: parent.right + text: qsTr("Load common parameters") + + onClicked: showDialog(applyRestartDialogComponent, qsTr("Load common parameters"), 50, StandardButton.Close) + } + } + + Item { + id: lastSpacer + anchors.top: helpApplyRow.bottom + height: parent.spacerHeight + width: 10 } + Flickable { + id: scroll + anchors.top: lastSpacer.bottom + width: parent.width; + height: parent.height; + clip: true + boundsBehavior: Flickable.StopAtBounds + flickableDirection: Flickable.VerticalFlick + + onWidthChanged: { + computeDimensions() + } + + Flow { + id: flowView + width: scroll.width + spacing: _boxSpace + + ExclusiveGroup { + id: airframeTypeExclusive + } + + Repeater { + model: controller.airframeTypesModel + + // Outer summary item rectangle + delegate : Rectangle { + id: airframeBackground + width: _boxWidth + height: ScreenTools.defaultFontPixelHeight * 14 + color: qgcPal.windowShade; + + readonly property real titleHeight: ScreenTools.defaultFontPixelHeight * 1.75 + readonly property real innerMargin: ScreenTools.defaultFontPixelWidth + + MouseArea { + anchors.fill: parent + onClicked: airframeCheckBox.checked = true; + } + + Rectangle { + id: nameRect; + width: parent.width + height: parent.titleHeight + color: qgcPal.windowShadeDark + + QGCLabel { + anchors.fill: parent + color: qgcPal.buttonText + verticalAlignment: TextEdit.AlignVCenter + horizontalAlignment: TextEdit.AlignHCenter + text: object.name + } + } + + Image { + id: imageRect + anchors.topMargin: innerMargin + anchors.top: nameRect.bottom + width: parent.width * 0.75 + height: parent.height - nameRect.height - (innerMargin * 3) + fillMode: Image.PreserveAspectFit + smooth: true + mipmap: true + source: object.imageResource + anchors.horizontalCenter: parent.horizontalCenter + } + + QGCCheckBox { + id: airframeCheckBox + checked: object.type == sysIdFact.value + exclusiveGroup: airframeTypeExclusive + anchors.bottom: imageRect.bottom + anchors.right: parent.right + anchors.rightMargin: innerMargin + + onCheckedChanged: { + if (checked) { + controller.currentAirframeType = object + } + airframeBackground.color = checked ? qgcPal.buttonHighlight : qgcPal.windowShade; + } + } + } + } + } + } // Scroll View - summary boxes } // QGCViewPanel } // QGCView diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.cc b/src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.cc new file mode 100644 index 0000000000000000000000000000000000000000..ca356f2fc60427557a726918a2ba3063597433ea --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.cc @@ -0,0 +1,60 @@ +/*===================================================================== + + 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 +/// @author Don Gagne + +#include "APMAirframeComponentAirframes.h" +#include "APMAirframeComponentController.h" + +QMap APMAirframeComponentAirframes::rgAirframeTypes; + +QMap& APMAirframeComponentAirframes::get() { + return rgAirframeTypes; +} + +void APMAirframeComponentAirframes::insert(const QString& group, int groupId, const QString& image,const QString& name, const QString& file) +{ + AirframeType_t *g; + if (!rgAirframeTypes.contains(group)) { + g = new AirframeType_t; + g->name = group; + g->type = groupId; + g->imageResource = QString("qrc:/qmlimages/") + (!image.isEmpty() ? image : QString("AirframeStandardPlane.png")); + rgAirframeTypes.insert(group, g); + } else { + g = rgAirframeTypes.value(group); + } + + if (!name.isEmpty() && !file.isEmpty()) + g->rgAirframeInfo.append(new APMAirframe(name, file, g->type)); +} + +void APMAirframeComponentAirframes::clear() { + QList valueList = get().values(); + foreach(AirframeType_t *pType, valueList) { + qDeleteAll(pType->rgAirframeInfo); + delete pType; + } + rgAirframeTypes.clear(); +} diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.h b/src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.h new file mode 100644 index 0000000000000000000000000000000000000000..7d33de2e20211500b2aa6d1b591c47fb6cfdb07d --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.h @@ -0,0 +1,62 @@ +/*===================================================================== + + 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 +/// @author Don Gagne + +#ifndef APMAirframeComponentAirframes_H +#define APMAirframeComponentAirframes_H + +#include +#include +#include +#include + +#include "UASInterface.h" +#include "AutoPilotPlugin.h" + +class APMAirframe; + +/// MVC Controller for AirframeComponent.qml. +class APMAirframeComponentAirframes +{ +public: + typedef struct { + QString name; + QString imageResource; + int type; + QList rgAirframeInfo; + } AirframeType_t; + typedef QMap AirframeTypeMap; + + static AirframeTypeMap& get(); + static void clear(); + static void insert(const QString& group, int groupId, const QString& image,const QString& name = QString(), const QString& file = QString()); + +protected: + static AirframeTypeMap rgAirframeTypes; + +private: +}; + +#endif diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponentController.cc b/src/AutoPilotPlugins/APM/APMAirframeComponentController.cc new file mode 100644 index 0000000000000000000000000000000000000000..26ff996dc7c841383e086884b41ec8fb87bb04cf --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMAirframeComponentController.cc @@ -0,0 +1,208 @@ +/*===================================================================== + + 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 +/// @author Don Gagne + +#include "APMAirframeComponentController.h" +#include "APMAirframeComponentAirframes.h" +#include "APMRemoteParamsDownloader.h" +#include "QGCMAVLink.h" +#include "MultiVehicleManager.h" +#include "AutoPilotPluginManager.h" +#include "QGCApplication.h" + +#include +#include + +bool APMAirframeComponentController::_typesRegistered = false; + +APMAirframeComponentController::APMAirframeComponentController(void) : + _airframeTypesModel(new QmlObjectListModel(this)) +{ + if (!_typesRegistered) { + _typesRegistered = true; + qmlRegisterUncreatableType("QGroundControl.Controllers", 1, 0, "APMAiframeType", "Can only reference APMAirframeType"); + qmlRegisterUncreatableType("QGroundControl.Controllers", 1, 0, "APMAiframe", "Can only reference APMAirframe"); + } + _fillAirFrames(); + + Fact *frame = getParameterFact(FactSystem::defaultComponentId, "FRAME"); + connect(frame, &Fact::vehicleUpdated, this, &APMAirframeComponentController::_factFrameChanged); + _factFrameChanged(frame->rawValue()); +} + +APMAirframeComponentController::~APMAirframeComponentController() +{ + +} + +void APMAirframeComponentController::_factFrameChanged(QVariant value) +{ + FrameId v = (FrameId) value.toInt(); + + for(int i = 0, size = _airframeTypesModel->count(); i < size; i++ ) { + APMAirframeType *airframeType = qobject_cast(_airframeTypesModel->get(i)); + Q_ASSERT(airframeType); + if (airframeType->type() == v) { + _currentAirframeType = airframeType; + break; + } + } + emit currentAirframeTypeChanged(_currentAirframeType); +} + +void APMAirframeComponentController::_fillAirFrames() +{ + for (int tindex = 0; tindex < APMAirframeComponentAirframes::get().count(); tindex++) { + const APMAirframeComponentAirframes::AirframeType_t* pType = APMAirframeComponentAirframes::get().values().at(tindex); + + APMAirframeType* airframeType = new APMAirframeType(pType->name, pType->imageResource, pType->type, this); + Q_CHECK_PTR(airframeType); + + for (int index = 0; index < pType->rgAirframeInfo.count(); index++) { + const APMAirframe* pInfo = pType->rgAirframeInfo.at(index); + Q_CHECK_PTR(pInfo); + + airframeType->addAirframe(pInfo->name(), pInfo->params(), pInfo->type()); + } + _airframeTypesModel->append(airframeType); + } + + emit loadAirframesCompleted(); +} + +void APMAirframeComponentController::_finishVehicleSetup() { + QDir dataLocation = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).at(0) + + QDir::separator() + qApp->applicationName(); + + QFile parametersFile(dataLocation.absoluteFilePath(_currentAirframe->params())); + parametersFile.open(QIODevice::ReadOnly); + + QTextStream reader(¶metersFile); + + while (!reader.atEnd()) { + QString line = reader.readLine().trimmed(); + if (line.isEmpty() || line.at(0) == QChar('#')) { + continue; + } + + QStringList aux = line.split(','); + if (parameterExists(-1, aux.at(0))) { + Fact *param = getParameterFact(-1, aux.at(0)); + param->setRawValue(QVariant::fromValue(aux.at(1))); + } + } + qgcApp()->setOverrideCursor(Qt::ArrowCursor); + sender()->deleteLater(); + emit currentAirframeChanged(_currentAirframe); +} + +APMAirframeType::APMAirframeType(const QString& name, const QString& imageResource, int type, QObject* parent) : + QObject(parent), + _name(name), + _imageResource(imageResource), + _type(type), + _dirty(false) +{ +} + +APMAirframeType::~APMAirframeType() +{ +} + +void APMAirframeType::addAirframe(const QString& name, const QString& file, int type) +{ + APMAirframe* airframe = new APMAirframe(name, file, type); + Q_CHECK_PTR(airframe); + + _airframes.append(QVariant::fromValue(airframe)); +} + +APMAirframe::APMAirframe(const QString& name, const QString& paramsFile, int type, QObject* parent) : + QObject(parent), + _name(name), + _paramsFile(paramsFile), + _type(type) +{ +} + +QString APMAirframe::name() const +{ + return _name; +} + +QString APMAirframe::params() const +{ + return _paramsFile; +} + +int APMAirframe::type() const +{ + return _type; +} + +APMAirframe::~APMAirframe() +{ +} + +QString APMAirframeType::imageResource() const +{ + return _imageResource; +} + +QString APMAirframeType::name() const +{ + return _name; +} + +int APMAirframeType::type() const +{ + return _type; +} + +APMAirframeType *APMAirframeComponentController::currentAirframeType() const +{ + return _currentAirframeType; +} + +APMAirframe *APMAirframeComponentController::currentAirframe() const +{ + return _currentAirframe; +} + +void APMAirframeComponentController::setCurrentAirframe(APMAirframe *t) +{ + _currentAirframe = t; + qgcApp()->setOverrideCursor(Qt::WaitCursor); + APMRemoteParamsDownloader *paramDownloader = new APMRemoteParamsDownloader(_currentAirframe->params()); + connect(paramDownloader, &APMRemoteParamsDownloader::finished, this, &APMAirframeComponentController::_finishVehicleSetup); +} + +void APMAirframeComponentController::setCurrentAirframeType(APMAirframeType *t) +{ + Fact *param = getParameterFact(-1, "FRAME"); + Q_ASSERT(param); + param->setRawValue(t->type()); +} + diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponentController.h b/src/AutoPilotPlugins/APM/APMAirframeComponentController.h new file mode 100644 index 0000000000000000000000000000000000000000..ef799ab5246960d144e73658ebb296ca5ddc5e6b --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMAirframeComponentController.h @@ -0,0 +1,138 @@ +/*===================================================================== + + 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 +/// @author Don Gagne + +#ifndef APMAirframeComponentController_H +#define APMAirframeComponentController_H + +#include +#include +#include +#include + +#include "UASInterface.h" +#include "AutoPilotPlugin.h" +#include "FactPanelController.h" +#include "APMAirframeComponentAirframes.h" + +class APMAirframeModel; +class APMAirframeType; + +/// MVC Controller for APMAirframeComponent.qml. +class APMAirframeComponentController : public FactPanelController +{ + Q_OBJECT + +public: + enum FrameId{FRAME_TYPE_PLUS = 0, + FRAME_TYPE_X = 1, + FRAME_TYPE_V = 2, + FRAME_TYPE_H = 3, + FRAME_TYPE_NEWY6 = 10}; + Q_ENUM(FrameId) + + APMAirframeComponentController(void); + ~APMAirframeComponentController(); + + Q_PROPERTY(QmlObjectListModel* airframeTypesModel MEMBER _airframeTypesModel CONSTANT) + Q_PROPERTY(APMAirframeType* currentAirframeType READ currentAirframeType WRITE setCurrentAirframeType NOTIFY currentAirframeTypeChanged) + Q_PROPERTY(APMAirframe* currentAirframe READ currentAirframe WRITE setCurrentAirframe NOTIFY currentAirframeChanged) + + int currentAirframeIndex(void); + void setCurrentAirframeIndex(int newIndex); + +signals: + void loadAirframesCompleted(); + void currentAirframeTypeChanged(APMAirframeType* airframeType); + void currentAirframeChanged(APMAirframe* airframe); + +public slots: + APMAirframeType *currentAirframeType() const; + APMAirframe *currentAirframe() const; + void setCurrentAirframeType(APMAirframeType *t); + void setCurrentAirframe(APMAirframe *t); + +private slots: + void _fillAirFrames(void); + void _finishVehicleSetup(void); + void _factFrameChanged(QVariant v); + +private: + static bool _typesRegistered; + APMAirframeType *_currentAirframeType; + APMAirframe *_currentAirframe; + int _waitParamWriteSignalCount; + QmlObjectListModel *_airframeTypesModel; +}; + +class APMAirframe : public QObject +{ + Q_OBJECT + +public: + APMAirframe(const QString& name, const QString& paramsFile, int type, QObject* parent = NULL); + ~APMAirframe(); + + Q_PROPERTY(QString name MEMBER _name CONSTANT) + Q_PROPERTY(int type MEMBER _type CONSTANT) + Q_PROPERTY(QString params MEMBER _paramsFile CONSTANT) + + QString name() const; + QString params() const; + int type() const; + +private: + QString _name; + QString _paramsFile; + int _type; +}; + +class APMAirframeType : public QObject +{ + Q_OBJECT + +public: + APMAirframeType(const QString& name, const QString& imageResource, int type, QObject* parent = NULL); + ~APMAirframeType(); + + Q_PROPERTY(QString name MEMBER _name CONSTANT) + Q_PROPERTY(QString imageResource MEMBER _imageResource CONSTANT) + Q_PROPERTY(QVariantList airframes MEMBER _airframes CONSTANT) + Q_PROPERTY(int type MEMBER _type CONSTANT) + Q_PROPERTY(bool dirty MEMBER _dirty CONSTANT) + void addAirframe(const QString& name, const QString& paramsFile, int type); + + QString name() const; + QString imageResource() const; + int type() const; +private: + QString _name; + QString _imageResource; + QVariantList _airframes; + int _type; + bool _dirty; +}; + +#endif diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml b/src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml index 975a6f8254bd010dddd228e40db2a3cc306d7a9c..3e697b1b1ba96cb498628e0c380fd21fbdc8d72e 100644 --- a/src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml +++ b/src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml @@ -13,33 +13,27 @@ FactPanel { color: qgcPal.windowShadeDark QGCPalette { id: qgcPal; colorGroupEnabled: enabled } + APMAirframeComponentController { + id: controller + factPanel: panel + } -/* - property Fact sysIdFact: controller.getParameterFact(-1, "MAV_SYS_ID") - property Fact sysAutoStartFact: controller.getParameterFact(-1, "SYS_AUTOSTART") + property Fact sysIdFact: controller.getParameterFact(-1, "FRAME") - property bool autoStartSet: sysAutoStartFact.value != 0 -*/ Column { anchors.fill: parent anchors.margins: 8 -/* - VehicleSummaryRow { - labelText: "System ID:" - valueText: sysIdFact.valueString - } - VehicleSummaryRow { - labelText: "Airframe type:" - valueText: autoStartSet ? controller.currentAirframeType : "Setup required" - } + id: nameRow; + labelText: "Frame Type:" + valueText: sysIdFact.valueString === "0" ? "Plus" + : sysIdFact.valueString === "1" ? "X" + : sysIdFact.valueString === "2" ? "V" + : sysIdFact.valueString == "3" ? "H" + :/* Fact.value == 10 */ "New Y6"; - VehicleSummaryRow { - labelText: "Vehicle:" - valueText: autoStartSet ? controller.currentVehicleName : "Setup required" } -*/ } } diff --git a/src/AutoPilotPlugins/APM/APMAirframeLoader.cc b/src/AutoPilotPlugins/APM/APMAirframeLoader.cc new file mode 100644 index 0000000000000000000000000000000000000000..1a189ebd2002ebf4161e1883c1c0ab30c525dc87 --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMAirframeLoader.cc @@ -0,0 +1,100 @@ +/*===================================================================== + + 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 +/// @author Don Gagne + +#include "APMAirframeLoader.h" +#include "QGCApplication.h" +#include "QGCLoggingCategory.h" +#include "APMAirframeComponentAirframes.h" + +#include +#include +#include +#include + +QGC_LOGGING_CATEGORY(APMAirframeLoaderLog, "APMAirframeLoaderLog") + +bool APMAirframeLoader::_airframeMetaDataLoaded = false; + +APMAirframeLoader::APMAirframeLoader(AutoPilotPlugin* autopilot, UASInterface* uas, QObject* parent) +{ + Q_UNUSED(autopilot); + Q_UNUSED(uas); + Q_UNUSED(parent); + Q_ASSERT(uas); +} + +/// Load Airframe Fact meta data +void APMAirframeLoader::loadAirframeFactMetaData(void) +{ + if (_airframeMetaDataLoaded) { + return; + } + + qCDebug(APMAirframeLoaderLog) << "Loading APM airframe fact meta data"; + + Q_ASSERT(APMAirframeComponentAirframes::get().count() == 0); + + QString airframeFilename = ":/AutoPilotPlugins/APM/AirframeFactMetaData.xml"; + + qCDebug(APMAirframeLoaderLog) << "Loading meta data file:" << airframeFilename; + + QFile xmlFile(airframeFilename); + Q_ASSERT(xmlFile.exists()); + + bool success = xmlFile.open(QIODevice::ReadOnly); + Q_UNUSED(success); + Q_ASSERT(success); + + QXmlStreamReader xml(xmlFile.readAll()); + xmlFile.close(); + if (xml.hasError()) { + qCWarning(APMAirframeLoaderLog) << "Badly formed XML" << xml.errorString(); + return; + } + + QString airframeGroup; + QString image; + int groupId = 0; + while (!xml.atEnd()) { + if (xml.isStartElement()) { + QString elementName = xml.name().toString(); + QXmlStreamAttributes attr = xml.attributes(); + if (elementName == "airframe_group") { + airframeGroup = attr.value("name").toString(); + image = attr.value("image").toString(); + groupId = attr.value("id").toInt(); + APMAirframeComponentAirframes::insert(airframeGroup, groupId, image); + } else if (elementName == "airframe") { + QString name = attr.value("name").toString(); + QString file = attr.value("file").toString(); + APMAirframeComponentAirframes::insert(airframeGroup, groupId, image, name, file); + } + } + xml.readNext(); + } + + _airframeMetaDataLoaded = true; +} diff --git a/src/AutoPilotPlugins/APM/APMAirframeLoader.h b/src/AutoPilotPlugins/APM/APMAirframeLoader.h new file mode 100644 index 0000000000000000000000000000000000000000..5d8d4e6dac9132a217688ab039b7740b4d755664 --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMAirframeLoader.h @@ -0,0 +1,59 @@ +/*===================================================================== + + 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 APMAirframeLoader_H +#define APMAirframeLoader_H + +#include +#include +#include +#include + +#include "ParameterLoader.h" +#include "FactSystem.h" +#include "UASInterface.h" +#include "AutoPilotPlugin.h" + +/// @file APMAirframeLoader.h +/// @author Lorenz Meier + +Q_DECLARE_LOGGING_CATEGORY(APMAirframeLoaderLog) + +/// Collection of Parameter Facts for PX4 AutoPilot + +class APMAirframeLoader : QObject +{ + Q_OBJECT + +public: + /// @param uas Uas which this set of facts is associated with + APMAirframeLoader(AutoPilotPlugin* autpilot,UASInterface* uas, QObject* parent = NULL); + + static void loadAirframeFactMetaData(void); + +private: + static bool _airframeMetaDataLoaded; ///< true: parameter meta data already loaded + static QMap _mapParameterName2FactMetaData; ///< Maps from a parameter name to FactMetaData +}; + +#endif // APMAirframeLoader_H diff --git a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc index b04d522c8c70cef108206b79007768a33921dc84..d8254a3f0790f724518cfc8ae1b392e3e3882a04 100644 --- a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc +++ b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc @@ -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 . - + ======================================================================*/ #include "APMAutoPilotPlugin.h" @@ -26,6 +26,18 @@ #include "UAS.h" #include "FirmwarePlugin/APM/APMParameterMetaData.h" // FIXME: Hack #include "FirmwarePlugin/APM/APMFirmwarePlugin.h" // FIXME: Hack +#include "FirmwarePlugin/APM/ArduCopterFirmwarePlugin.h" +#include "APMComponent.h" +#include "APMAirframeComponent.h" +#include "APMAirframeComponentAirframes.h" +#include "APMAirframeComponentController.h" +#include "APMAirframeLoader.h" +#include "APMRemoteParamsDownloader.h" +#include "APMFlightModesComponent.h" +#include "APMRadioComponent.h" +#include "APMSafetyComponent.h" +#include "APMTuningComponent.h" +#include "APMSensorsComponent.h" /// This is the AutoPilotPlugin implementatin for the MAV_AUTOPILOT_ARDUPILOT type. APMAutoPilotPlugin::APMAutoPilotPlugin(Vehicle* vehicle, QObject* parent) @@ -37,8 +49,9 @@ APMAutoPilotPlugin::APMAutoPilotPlugin(Vehicle* vehicle, QObject* parent) , _safetyComponent(NULL) , _sensorsComponent(NULL) , _tuningComponent(NULL) + , _airframeFacts(new APMAirframeLoader(this, vehicle->uas(), this)) { - Q_ASSERT(vehicle); + APMAirframeLoader::loadAirframeFactMetaData(); } APMAutoPilotPlugin::~APMAutoPilotPlugin() @@ -52,12 +65,14 @@ const QVariantList& APMAutoPilotPlugin::vehicleComponents(void) Q_ASSERT(_vehicle); if (parametersReady()) { - _airframeComponent = new APMAirframeComponent(_vehicle, this); - if (_airframeComponent) { - _airframeComponent->setupTriggerSignals(); - _components.append(QVariant::fromValue((VehicleComponent*)_airframeComponent)); - } else { - qWarning() << "new APMAirframeComponent failed"; + if (dynamic_cast(_vehicle->firmwarePlugin())){ + _airframeComponent = new APMAirframeComponent(_vehicle, this); + if(_airframeComponent) { + _airframeComponent->setupTriggerSignals(); + _components.append(QVariant::fromValue((VehicleComponent*)_airframeComponent)); + } else { + qWarning() << "new APMAirframeComponent failed"; + } } _flightModesComponent = new APMFlightModesComponent(_vehicle, this); @@ -122,9 +137,9 @@ void APMAutoPilotPlugin::_parametersReadyPreChecks(bool missingParameters) "Please perform a Firmware Upgrade if you wish to use Vehicle Setup."); } #endif - + Q_UNUSED(missingParameters); _parametersReady = true; - _missingParameters = missingParameters; + _missingParameters = false; // we apply only the parameters that do exists on the FactSystem. emit missingParametersChanged(_missingParameters); emit parametersReadyChanged(_parametersReady); } diff --git a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h index c26dee7c07cd816a5774993be547bec8f7363ad5..1102cf1e77fb9f2e7b9f60c9eae75e61d668b17b 100644 --- a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h +++ b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h @@ -26,12 +26,14 @@ #include "AutoPilotPlugin.h" #include "Vehicle.h" -#include "APMAirframeComponent.h" -#include "APMFlightModesComponent.h" -#include "APMRadioComponent.h" -#include "APMSafetyComponent.h" -#include "APMSensorsComponent.h" -#include "APMTuningComponent.h" + +class APMAirframeComponent; +class APMAirframeLoader; +class APMFlightModesComponent; +class APMRadioComponent; +class APMTuningComponent; +class APMSafetyComponent; +class APMSensorsComponent; /// This is the APM specific implementation of the AutoPilot class. class APMAutoPilotPlugin : public AutoPilotPlugin @@ -66,6 +68,7 @@ private: APMSafetyComponent* _safetyComponent; APMSensorsComponent* _sensorsComponent; APMTuningComponent* _tuningComponent; + APMAirframeLoader* _airframeFacts; }; #endif diff --git a/src/AutoPilotPlugins/APM/APMComponent.cc b/src/AutoPilotPlugins/APM/APMComponent.cc index ec3cbf9b6e91fe989b8c5c8fb445cd5698274479..e5b745b31c61477d3b33825a1ae1069f22f97f84 100644 --- a/src/AutoPilotPlugins/APM/APMComponent.cc +++ b/src/AutoPilotPlugins/APM/APMComponent.cc @@ -37,10 +37,8 @@ APMComponent::APMComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject void APMComponent::setupTriggerSignals(void) { - // Watch for changed on trigger list params - foreach (QString paramName, setupCompleteChangedTriggerList()) { + foreach (const QString& paramName, setupCompleteChangedTriggerList()) { Fact* fact = _autopilot->getParameterFact(FactSystem::defaultComponentId, paramName); - connect(fact, &Fact::valueChanged, this, &APMComponent::_triggerUpdated); } } diff --git a/src/AutoPilotPlugins/APM/APMFlightModesComponent.cc b/src/AutoPilotPlugins/APM/APMFlightModesComponent.cc index 77456548006c472c8bd2b01852c89527d346b81c..80b9baa6d86c44e269df27999a8ce5f184f48088 100644 --- a/src/AutoPilotPlugins/APM/APMFlightModesComponent.cc +++ b/src/AutoPilotPlugins/APM/APMFlightModesComponent.cc @@ -23,6 +23,8 @@ #include "APMFlightModesComponent.h" #include "APMAutoPilotPlugin.h" +#include "APMAirframeComponent.h" +#include "APMRadioComponent.h" APMFlightModesComponent::APMFlightModesComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent) : APMComponent(vehicle, autopilot, parent), diff --git a/src/AutoPilotPlugins/APM/APMRadioComponent.cc b/src/AutoPilotPlugins/APM/APMRadioComponent.cc index c42a1d553b99be47d23e2660385e50ce96caf89a..5cbed197ae29d864427d7f3eaf67548546ef56f1 100644 --- a/src/AutoPilotPlugins/APM/APMRadioComponent.cc +++ b/src/AutoPilotPlugins/APM/APMRadioComponent.cc @@ -23,6 +23,7 @@ #include "APMRadioComponent.h" #include "APMAutoPilotPlugin.h" +#include "APMAirframeComponent.h" APMRadioComponent::APMRadioComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent) : APMComponent(vehicle, autopilot, parent), diff --git a/src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.cc b/src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.cc new file mode 100644 index 0000000000000000000000000000000000000000..8b4834dbc4b3b1d909973b21020e6d2cf3df6a31 --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.cc @@ -0,0 +1,181 @@ +/*===================================================================== + + 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 "APMRemoteParamsDownloader.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "APMRemoteParamsDownloader.h" + +#define FRAME_PARAMS_LIST QUrl("https://api.github.com/repos/diydrones/ardupilot/contents/Tools/Frame_params") +#define FRAME_PARAMS_URL "https://raw.github.com/diydrones/ardupilot/master/Tools/Frame_params/" + +static QString dataLocation; + +APMRemoteParamsDownloader::APMRemoteParamsDownloader(const QString& file) : + m_fileToDownload(file), + m_networkReply(NULL), + m_downloadedParamFile(NULL) +{ + dataLocation = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).at(0) + + QDir::separator() + qApp->applicationName(); + refreshParamList(); +} + +QString APMRemoteParamsDownloader::statusText() const +{ + return m_statusText; +} +void APMRemoteParamsDownloader::setStatusText(const QString& text) +{ + m_statusText = text; +} + +void APMRemoteParamsDownloader::refreshParamList() +{ + setStatusText(tr("Refresh Param file list")); + + QUrl url = FRAME_PARAMS_LIST; + m_networkReply->deleteLater(); + m_networkReply = m_networkAccessManager.get(QNetworkRequest(url)); + connect(m_networkReply, SIGNAL(finished()), this, SLOT(httpParamListFinished())); + connect(m_networkReply, SIGNAL(downloadProgress(qint64,qint64)), + this, SLOT(updateDataReadProgress(qint64,qint64))); +} + +/* Returned Json Example + "_links": { + "git":"https://api.github.com/repos/diydrones/ardupilot/git/blobs/a7074e606d695566f9a8c87724ad52e5e3baba7d", + "html":"https://github.com/diydrones/ardupilot/blob/master/Tools/Frame_params/Parrot_Bebop.param", + "self":"https://api.github.com/repos/diydrones/ardupilot/contents/Tools/Frame_params/Parrot_Bebop.param?ref=master" + }, + "download_url":"https://raw.githubusercontent.com/diydrones/ardupilot/master/Tools/Frame_params/Parrot_Bebop.param", + "git_url":"https://api.github.com/repos/diydrones/ardupilot/git/blobs/a7074e606d695566f9a8c87724ad52e5e3baba7d", + "html_url":"https://github.com/diydrones/ardupilot/blob/master/Tools/Frame_params/Parrot_Bebop.param", + "name":"Parrot_Bebop.param","path":"Tools/Frame_params/Parrot_Bebop.param","" + "sha":"a7074e606d695566f9a8c87724ad52e5e3baba7d", + "size":533, + "type":"file", + "url":"https://api.github.com/repos/diydrones/ardupilot/contents/Tools/Frame_params/Parrot_Bebop.param?ref=master" +*/ +void APMRemoteParamsDownloader::startFileDownloadRequest() +{ + QUrl url; + + QJsonObject obj; + + // Find the correct file from the json file list. + while(curr != end) { + obj = (*curr).toObject(); + url = QUrl(obj["download_url"].toString()); + QString name = obj["name"].toString(); + if (name == m_fileToDownload) { + break; + } + curr++; + } + if (curr == end) + return; + + QDir parameterDir(dataLocation); + if (!parameterDir.exists()) + parameterDir.mkpath(dataLocation); + + QString filename = parameterDir.absoluteFilePath(obj["name"].toString()); + + if(m_downloadedParamFile) + m_downloadedParamFile->deleteLater(); + m_downloadedParamFile = new QFile(filename); + m_downloadedParamFile->open(QIODevice::WriteOnly); + + m_networkReply = m_networkAccessManager.get(QNetworkRequest(url)); + connect(m_networkReply, SIGNAL(finished()), this, SLOT(httpFinished())); + connect(m_networkReply, SIGNAL(readyRead()), this, SLOT(httpReadyRead())); + connect(m_networkReply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(updateDataReadProgress(qint64,qint64))); + curr++; +} + +void APMRemoteParamsDownloader::httpFinished() +{ + m_downloadedParamFile->flush(); + m_downloadedParamFile->close(); + + if (m_networkReply->error()) { + m_downloadedParamFile->remove(); + setStatusText(tr("Download failed: %1.").arg(m_networkReply->errorString())); + } + + m_networkReply->deleteLater(); + m_networkReply = NULL; + delete m_downloadedParamFile; + m_downloadedParamFile = NULL; + + emit finished(); +} + +void APMRemoteParamsDownloader::httpReadyRead() +{ + if (m_downloadedParamFile) + m_downloadedParamFile->write(m_networkReply->readAll()); +} + +void APMRemoteParamsDownloader::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes) +{ + Q_UNUSED(bytesRead); + Q_UNUSED(totalBytes); +} + +void APMRemoteParamsDownloader::httpParamListFinished() +{ + if (m_networkReply->error()) { + qDebug() << "Download failed:" << m_networkReply->errorString(); + return; + } + processDownloadedVersionObject(m_networkReply->readAll()); + startFileDownloadRequest(); +} + +void APMRemoteParamsDownloader::processDownloadedVersionObject(const QByteArray &listObject) +{ + QJsonParseError jsonErrorChecker; + QJsonDocument jsonDocument = QJsonDocument::fromJson(listObject, &jsonErrorChecker); + if (jsonErrorChecker.error != QJsonParseError::NoError) { + qDebug() << "Json error while parsing document:" << jsonErrorChecker.errorString(); + return; + } + + m_documentArray = jsonDocument.array(); + curr = m_documentArray.constBegin(); + end = m_documentArray.constEnd(); +} diff --git a/src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.h b/src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.h new file mode 100644 index 0000000000000000000000000000000000000000..b635cc77e4ab743f2f448d64267a81c0aa64e7d8 --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.h @@ -0,0 +1,47 @@ +#ifndef APMREMOTEPARAMSCONTROLLER_H +#define APMREMOTEPARAMSCONTROLLER_H + +#include +#include +#include +#include + +class QNetworkReply; +class QFile; +class QUrl; + +class APMRemoteParamsDownloader : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString statusText READ statusText) +public: + explicit APMRemoteParamsDownloader(const QString& file); + QString statusText() const; +public slots: + void refreshParamList(); + void httpParamListFinished(); + void httpFinished(); + void httpReadyRead(); + void updateDataReadProgress(qint64 bytesRead, qint64 totalBytes); +private: + void setStatusText(const QString& text); + void startFileDownloadRequest(); + void manualListSetup(); + void processDownloadedVersionObject(const QByteArray& listObject); + void startDownloadingRemoteParams(); +signals: + void finished(); +private: + QString m_fileToDownload; + QString m_statusText; + QNetworkAccessManager m_networkAccessManager; + QNetworkReply* m_networkReply; + QFile* m_downloadedParamFile; + + // the list of needed documents. + QJsonArray m_documentArray; + QJsonArray::const_iterator curr; + QJsonArray::const_iterator end; +}; + +#endif // APMREMOTEPARAMSCONTROLLER_H diff --git a/src/AutoPilotPlugins/APM/APMSafetyComponent.cc b/src/AutoPilotPlugins/APM/APMSafetyComponent.cc index 1346fa6e138172913a12da3d9a8ec09e8b29079a..805c02c24af88ba74df3b4ff28fe2e4874a3e3dc 100644 --- a/src/AutoPilotPlugins/APM/APMSafetyComponent.cc +++ b/src/AutoPilotPlugins/APM/APMSafetyComponent.cc @@ -27,6 +27,7 @@ #include "APMSafetyComponent.h" #include "QGCQmlWidgetHolder.h" #include "APMAutoPilotPlugin.h" +#include "APMAirframeComponent.h" APMSafetyComponent::APMSafetyComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent) : APMComponent(vehicle, autopilot, parent) diff --git a/src/AutoPilotPlugins/APM/APMSensorsComponent.cc b/src/AutoPilotPlugins/APM/APMSensorsComponent.cc index 49f4b599fe3db6326037e8feb4649943937355e8..4b1e088d8bd3f908d7e9dad1e9db72d753b192b4 100644 --- a/src/AutoPilotPlugins/APM/APMSensorsComponent.cc +++ b/src/AutoPilotPlugins/APM/APMSensorsComponent.cc @@ -24,6 +24,7 @@ #include "APMSensorsComponent.h" #include "APMAutoPilotPlugin.h" #include "APMSensorsComponentController.h" +#include "APMAirframeComponent.h" // These two list must be kept in sync diff --git a/src/AutoPilotPlugins/APM/APMTuningComponent.cc b/src/AutoPilotPlugins/APM/APMTuningComponent.cc index ca61ec1d599568d9d0ee8a2d74c52e0c36a46d45..7275d9829a98d771b201a287993715678f9b69f0 100644 --- a/src/AutoPilotPlugins/APM/APMTuningComponent.cc +++ b/src/AutoPilotPlugins/APM/APMTuningComponent.cc @@ -23,6 +23,7 @@ #include "APMTuningComponent.h" #include "APMAutoPilotPlugin.h" +#include "APMAirframeComponent.h" APMTuningComponent::APMTuningComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent) : APMComponent(vehicle, autopilot, parent) diff --git a/src/AutoPilotPlugins/APM/AirframeFactMetaData.xml b/src/AutoPilotPlugins/APM/AirframeFactMetaData.xml new file mode 100644 index 0000000000000000000000000000000000000000..b41926c02ffa0d4dd09607997ee020d52ae42656 --- /dev/null +++ b/src/AutoPilotPlugins/APM/AirframeFactMetaData.xml @@ -0,0 +1,30 @@ + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/AutoPilotPlugins/AutoPilotPlugin.h b/src/AutoPilotPlugins/AutoPilotPlugin.h index 8e24bb5c6f82f508dca8e2380dcd84d36eca8fd1..649542ae9df79e8d3512a6e720b325cc79cc404d 100644 --- a/src/AutoPilotPlugins/AutoPilotPlugin.h +++ b/src/AutoPilotPlugins/AutoPilotPlugin.h @@ -1,148 +1,148 @@ -/*===================================================================== - - 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 -/// @author Don Gagne - -#ifndef AUTOPILOTPLUGIN_H -#define AUTOPILOTPLUGIN_H - -#include -#include -#include -#include - -#include "VehicleComponent.h" -#include "FactSystem.h" -#include "Vehicle.h" - -class ParameterLoader; -class Vehicle; -class FirmwarePlugin; - -/// This is the base class for AutoPilot plugins -/// -/// The AutoPilotPlugin class is an abstract base class which represent the methods and objects -/// which are specific to a certain AutoPilot. This is the only place where AutoPilot specific -/// code should reside in QGroundControl. The remainder of the QGroundControl source is -/// generic to a common mavlink implementation. - -class AutoPilotPlugin : public QObject -{ - Q_OBJECT - -public: - AutoPilotPlugin(Vehicle* vehicle, QObject* parent); - ~AutoPilotPlugin(); - - /// true: parameters are ready for use - Q_PROPERTY(bool parametersReady READ parametersReady NOTIFY parametersReadyChanged) - - /// true: parameters are missing from firmware response, false: all parameters received from firmware - Q_PROPERTY(bool missingParameters READ missingParameters NOTIFY missingParametersChanged) - - /// List of VehicleComponent objects - Q_PROPERTY(QVariantList vehicleComponents READ vehicleComponents CONSTANT) - - /// false: One or more vehicle components require setup - Q_PROPERTY(bool setupComplete READ setupComplete NOTIFY setupCompleteChanged) - - /// Reset all parameters to their default values - Q_INVOKABLE void resetAllParametersToDefaults(void); - - /// Re-request the full set of parameters from the autopilot - Q_INVOKABLE void refreshAllParameters(void); - - /// Request a refresh on the specific parameter - Q_INVOKABLE void refreshParameter(int componentId, const QString& name); - - /// Request a refresh on all parameters that begin with the specified prefix - Q_INVOKABLE void refreshParametersPrefix(int componentId, const QString& namePrefix); - - /// Returns true if the specifed parameter exists from the default component - Q_INVOKABLE bool parameterExists(int componentId, const QString& name); - - /// Returns all parameter names - QStringList parameterNames(int componentId); - - /// Returns the specified parameter Fact from the default component - /// WARNING: Returns a default Fact if parameter does not exists. If that possibility exists, check for existince first with - /// parameterExists. - Fact* getParameterFact(int componentId, const QString& name); - - /// Writes the parameter facts to the specified stream - void writeParametersToStream(QTextStream &stream); - - /// Reads the parameters from the stream and updates values - /// @return Errors during load. Empty string for no errors - QString readParametersFromStream(QTextStream &stream); - - /// Returns true if the specifed fact exists - Q_INVOKABLE bool factExists(FactSystem::Provider_t provider, ///< fact provider - int componentId, ///< fact component, -1=default component - const QString& name); ///< fact name - - /// Returns the specified Fact. - /// WARNING: Will assert if fact does not exists. If that possibility exists, check for existince first with - /// factExists. - Fact* getFact(FactSystem::Provider_t provider, ///< fact provider - int componentId, ///< fact component, -1=default component - const QString& name); ///< fact name - - const QMap >& getGroupMap(void); - - // Must be implemented by derived class - virtual const QVariantList& vehicleComponents(void) = 0; - - // Property accessors - bool parametersReady(void) { return _parametersReady; } - bool missingParameters(void) { return _missingParameters; } - bool setupComplete(void); - - Vehicle* vehicle(void) { return _vehicle; } - -signals: - void parametersReadyChanged(bool parametersReady); - void missingParametersChanged(bool missingParameters); - void setupCompleteChanged(bool setupComplete); - void parameterListProgress(float value); - -protected: - /// All access to AutoPilotPugin objects is through getInstanceForAutoPilotPlugin - AutoPilotPlugin(QObject* parent = NULL) : QObject(parent) { } - - Vehicle* _vehicle; - FirmwarePlugin* _firmwarePlugin; - bool _parametersReady; - bool _missingParameters; - bool _setupComplete; - -private slots: - void _uasDisconnected(void); - void _parametersReadyChanged(bool parametersReady); - -private: - void _recalcSetupComplete(void); -}; - -#endif + /*===================================================================== + + 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 + /// @author Don Gagne + + #ifndef AUTOPILOTPLUGIN_H + #define AUTOPILOTPLUGIN_H + + #include + #include + #include + #include + + #include "VehicleComponent.h" + #include "FactSystem.h" + #include "Vehicle.h" + + class ParameterLoader; + class Vehicle; + class FirmwarePlugin; + + /// This is the base class for AutoPilot plugins + /// + /// The AutoPilotPlugin class is an abstract base class which represent the methods and objects + /// which are specific to a certain AutoPilot. This is the only place where AutoPilot specific + /// code should reside in QGroundControl. The remainder of the QGroundControl source is + /// generic to a common mavlink implementation. + + class AutoPilotPlugin : public QObject + { + Q_OBJECT + + public: + AutoPilotPlugin(Vehicle* vehicle, QObject* parent); + ~AutoPilotPlugin(); + + /// true: parameters are ready for use + Q_PROPERTY(bool parametersReady READ parametersReady NOTIFY parametersReadyChanged) + + /// true: parameters are missing from firmware response, false: all parameters received from firmware + Q_PROPERTY(bool missingParameters READ missingParameters NOTIFY missingParametersChanged) + + /// List of VehicleComponent objects + Q_PROPERTY(QVariantList vehicleComponents READ vehicleComponents CONSTANT) + + /// false: One or more vehicle components require setup + Q_PROPERTY(bool setupComplete READ setupComplete NOTIFY setupCompleteChanged) + + /// Reset all parameters to their default values + Q_INVOKABLE void resetAllParametersToDefaults(void); + + /// Re-request the full set of parameters from the autopilot + Q_INVOKABLE void refreshAllParameters(void); + + /// Request a refresh on the specific parameter + Q_INVOKABLE void refreshParameter(int componentId, const QString& name); + + /// Request a refresh on all parameters that begin with the specified prefix + Q_INVOKABLE void refreshParametersPrefix(int componentId, const QString& namePrefix); + + /// Returns true if the specifed parameter exists from the default component + Q_INVOKABLE bool parameterExists(int componentId, const QString& name); + + /// Returns all parameter names + QStringList parameterNames(int componentId); + + /// Returns the specified parameter Fact from the default component + /// WARNING: Returns a default Fact if parameter does not exists. If that possibility exists, check for existince first with + /// parameterExists. + Fact* getParameterFact(int componentId, const QString& name); + + /// Writes the parameter facts to the specified stream + void writeParametersToStream(QTextStream &stream); + + /// Reads the parameters from the stream and updates values + /// @return Errors during load. Empty string for no errors + QString readParametersFromStream(QTextStream &stream); + + /// Returns true if the specifed fact exists + Q_INVOKABLE bool factExists(FactSystem::Provider_t provider, ///< fact provider + int componentId, ///< fact component, -1=default component + const QString& name); ///< fact name + + /// Returns the specified Fact. + /// WARNING: Will assert if fact does not exists. If that possibility exists, check for existince first with + /// factExists. + Fact* getFact(FactSystem::Provider_t provider, ///< fact provider + int componentId, ///< fact component, -1=default component + const QString& name); ///< fact name + + const QMap >& getGroupMap(void); + + // Must be implemented by derived class + virtual const QVariantList& vehicleComponents(void) = 0; + + // Property accessors + bool parametersReady(void) { return _parametersReady; } + bool missingParameters(void) { return _missingParameters; } + bool setupComplete(void); + + Vehicle* vehicle(void) { return _vehicle; } + + signals: + void parametersReadyChanged(bool parametersReady); + void missingParametersChanged(bool missingParameters); + void setupCompleteChanged(bool setupComplete); + void parameterListProgress(float value); + + protected: + /// All access to AutoPilotPugin objects is through getInstanceForAutoPilotPlugin + AutoPilotPlugin(QObject* parent = NULL) : QObject(parent) { } + + Vehicle* _vehicle; + FirmwarePlugin* _firmwarePlugin; + bool _parametersReady; + bool _missingParameters; + bool _setupComplete; + + private slots: + void _uasDisconnected(void); + void _parametersReadyChanged(bool parametersReady); + + private: + void _recalcSetupComplete(void); + }; + + #endif diff --git a/src/AutoPilotPlugins/PX4/SafetyComponent.qml b/src/AutoPilotPlugins/PX4/SafetyComponent.qml index 8f04839ef20fe35cd07de6369fa15043cbba5168..695dab48947f2b5d7c54a486973fc57592aecbea 100644 --- a/src/AutoPilotPlugins/PX4/SafetyComponent.qml +++ b/src/AutoPilotPlugins/PX4/SafetyComponent.qml @@ -56,7 +56,7 @@ QGCView { Flickable { clip: true anchors.fill: parent - contentHeight: 7000 //rtlSettings.height + contentHeight: screenBottom.y + screenBottom.height contentWidth: parent.width boundsBehavior: Flickable.StopAtBounds flickableDirection: Flickable.VerticalFlick @@ -287,27 +287,40 @@ QGCView { } } - /* QGCLabel { - width: parent.width - font.pixelSize: ScreenTools.mediumFontPixelSize - text: "Warning: You have an advanced safety configuration set using the NAV_RCL_OBC parameter. The above settings may not apply."; - visible: fact.value !== 0 - wrapMode: Text.Wrap + id: navRclObc + anchors.topMargin: _margins + anchors.top: rtlSettings.bottom + anchors.left: parent.left + anchors.right: parent.right + font.pixelSize: ScreenTools.mediumFontPixelSize + text: "Warning: You have an advanced safety configuration set using the NAV_RCL_OBC parameter. The above settings may not apply."; + visible: fact.value !== 0 + wrapMode: Text.Wrap property Fact fact: controller.getParameterFact(-1, "NAV_RCL_OBC") } QGCLabel { - width: parent.width - font.pixelSize: ScreenTools.mediumFontPixelSize - text: "Warning: You have an advanced safety configuration set using the NAV_DLL_OBC parameter. The above settings may not apply."; - visible: fact.value !== 0 - wrapMode: Text.Wrap + id: navDllObc + anchors.topMargin: _margins / 2 + anchors.top: navRclObc.bottom + anchors.left: parent.left + anchors.right: parent.right + font.pixelSize: ScreenTools.mediumFontPixelSize + text: "Warning: You have an advanced safety configuration set using the NAV_DLL_OBC parameter. The above settings may not apply."; + visible: fact.value !== 0 + wrapMode: Text.Wrap property Fact fact: controller.getParameterFact(-1, "NAV_DLL_OBC") } - */ - } // Flickable - } // QGCViewPanel - } // QGCView + + Item { + id: screenBottom + anchors.top: navDllObc.bottom + width: 1 + height: 1 + } + } // Flickable + } // QGCViewPanel +} // QGCView diff --git a/src/AutoPilotPlugins/PX4/SensorsComponent.qml b/src/AutoPilotPlugins/PX4/SensorsComponent.qml index 8147775e4778e6a677dd40a8527faed1498edb66..750a9005e4da171c81ce9c8a5efba1146b458f98 100644 --- a/src/AutoPilotPlugins/PX4/SensorsComponent.qml +++ b/src/AutoPilotPlugins/PX4/SensorsComponent.qml @@ -90,7 +90,8 @@ QGCView { "ROTATION_PITCH_270", "ROTATION_ROLL_270_YAW_270", "ROTATION_ROLL_180_PITCH_270", - "ROTATION_PITCH_90_YAW_180" + "ROTATION_PITCH_90_YAW_180", + "ROTATION_ROLL_90_PITCH_90" ] property Fact cal_mag0_id: controller.getParameterFact(-1, "CAL_MAG0_ID") diff --git a/src/FactSystem/Fact.h b/src/FactSystem/Fact.h index f2e311c8f59eafc3d2dd3c2ca539dab4163444dd..0c6e55fdf8bcb912acf68acf231b2a9bf56b512e 100644 --- a/src/FactSystem/Fact.h +++ b/src/FactSystem/Fact.h @@ -136,7 +136,7 @@ signals: /// This signal is meant for use by Fact container implementations. void _containerRawValueChanged(const QVariant& value); -private: +protected: QString _variantToString(const QVariant& variant) const; QString _name; diff --git a/src/FactSystem/SettingsFact.cc b/src/FactSystem/SettingsFact.cc new file mode 100644 index 0000000000000000000000000000000000000000..de31cb7ea3af98bc0d832d8057d10921b8ce04cd --- /dev/null +++ b/src/FactSystem/SettingsFact.cc @@ -0,0 +1,73 @@ +/*===================================================================== + + 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 "SettingsFact.h" + +#include + +SettingsFact::SettingsFact(QObject* parent) + : Fact(parent) +{ + +} + +SettingsFact::SettingsFact(QString settingGroup, QString settingName, FactMetaData::ValueType_t type, const QVariant& defaultValue, QObject* parent) + : Fact(0, settingName, type, parent) + , _settingGroup(settingGroup) +{ + QSettings settings; + + if (!_settingGroup.isEmpty()) { + settings.beginGroup(_settingGroup); + } + + _rawValue = settings.value(_name, defaultValue); + + connect(this, &Fact::valueChanged, this, &SettingsFact::_valueChanged); +} + +SettingsFact::SettingsFact(const SettingsFact& other, QObject* parent) + : Fact(other, parent) +{ + *this = other; +} + +const SettingsFact& SettingsFact::operator=(const SettingsFact& other) +{ + Fact::operator=(other); + + _settingGroup = other._settingGroup; + + return *this; +} + +void SettingsFact::_valueChanged(QVariant value) +{ + QSettings settings; + + if (!_settingGroup.isEmpty()) { + settings.beginGroup(_settingGroup); + } + + settings.setValue(_name, value); +} diff --git a/src/FactSystem/SettingsFact.h b/src/FactSystem/SettingsFact.h new file mode 100644 index 0000000000000000000000000000000000000000..eb8a6b897ca2ac4febaeaa67acdabcb1558ba664 --- /dev/null +++ b/src/FactSystem/SettingsFact.h @@ -0,0 +1,51 @@ +/*===================================================================== + + 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 +/// @author Don Gagne + +#ifndef SettingsFact_H +#define SettingsFact_H + +#include "Fact.h" + +/// @brief A SettingsFact is Fact which holds a QSettings value. +class SettingsFact : public Fact +{ + Q_OBJECT + +public: + SettingsFact(QObject* parent = NULL); + SettingsFact(QString settingGroup, QString settingName, FactMetaData::ValueType_t type, const QVariant& defaultValue, QObject* parent = NULL); + SettingsFact(const SettingsFact& other, QObject* parent = NULL); + + const SettingsFact& operator=(const SettingsFact& other); + +private slots: + void _valueChanged(QVariant value); + +private: + QString _settingGroup; +}; + +#endif diff --git a/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.cc b/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.cc index 946f7cda7aa55666234edf9ca67d2ff54ec961d1..7808b3c045471e944fa3af1430822d2dcd7fd613 100644 --- a/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.cc +++ b/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.cc @@ -216,12 +216,7 @@ QList PX4FirmwarePlugin::supportedMissionCommands(void) << MAV_CMD_NAV_LOITER_UNLIM << MAV_CMD_NAV_LOITER_TURNS << MAV_CMD_NAV_LOITER_TIME << MAV_CMD_NAV_RETURN_TO_LAUNCH << MAV_CMD_NAV_LAND << MAV_CMD_NAV_TAKEOFF << MAV_CMD_NAV_ROI - << MAV_CMD_NAV_GUIDED_ENABLE - << MAV_CMD_DO_SET_ROI << MAV_CMD_DO_GUIDED_LIMITS << MAV_CMD_DO_JUMP << MAV_CMD_DO_CHANGE_SPEED << MAV_CMD_DO_SET_CAM_TRIGG_DIST - << MAV_CMD_DO_SET_RELAY << MAV_CMD_DO_REPEAT_RELAY - << MAV_CMD_DO_SET_SERVO << MAV_CMD_DO_REPEAT_SERVO - << MAV_CMD_DO_DIGICAM_CONFIGURE << MAV_CMD_DO_DIGICAM_CONTROL - << MAV_CMD_DO_MOUNT_CONTROL - << MAV_CMD_CONDITION_DELAY << MAV_CMD_CONDITION_CHANGE_ALT << MAV_CMD_CONDITION_DISTANCE << MAV_CMD_CONDITION_YAW; + << MAV_CMD_DO_JUMP + << MAV_CMD_CONDITION_DELAY; return list; } diff --git a/src/MissionManager/MissionCommands.cc b/src/MissionManager/MissionCommands.cc index 0f6a1e14fc49cfaf1718bed24e949d274b8b966e..dbbc0c05b81d9acb5307cfa8864e42d0d9953e9b 100644 --- a/src/MissionManager/MissionCommands.cc +++ b/src/MissionManager/MissionCommands.cc @@ -22,6 +22,10 @@ This file is part of the QGROUNDCONTROL project #include "MissionCommands.h" #include "FactMetaData.h" +#include "Vehicle.h" +#include "FirmwarePluginManager.h" +#include "QGCApplication.h" +#include "QGroundControlQmlGlobal.h" #include #include @@ -60,7 +64,14 @@ const QString MissionCommands::_degreesUnits (QStringLiteral("deg MissionCommands::MissionCommands(QGCApplication* app) : QGCTool(app) { + +} + +void MissionCommands::setToolbox(QGCToolbox* toolbox) +{ + QGCTool::setToolbox(toolbox); _loadMavCmdInfoJson(); + _createFirmwareSpecificLists(); } bool MissionCommands::_validateKeyTypes(QJsonObject& jsonObject, const QStringList& keys, const QList& types) @@ -165,7 +176,6 @@ void MissionCommands::_loadMavCmdInfoJson(void) } _mavCmdInfoMap[mavCmdInfo->_command] = mavCmdInfo; - _commandList.append(mavCmdInfo); // Read params @@ -234,16 +244,13 @@ void MissionCommands::_loadMavCmdInfoJson(void) if (mavCmdInfo->_command != MAV_CMD_NAV_LAST) { // Don't add fake home postion command to categories - if (!_categories.contains(mavCmdInfo->category()) && mavCmdInfo->friendlyEdit()) { - // Only friendly edit commands go in category list - qCDebug(MissionCommandsLog) << "Adding new category"; - _categories.append(mavCmdInfo->category()); - _categoryToMavCmdInfoListMap[mavCmdInfo->category()] = new QmlObjectListModel(this); - } - if (mavCmdInfo->friendlyEdit()) { - // Only friendly edit commands go in category list - _categoryToMavCmdInfoListMap[mavCmdInfo->category()]->append(mavCmdInfo); + // Only friendly edit commands go in category list. We use MAV_AUTOPILOT_GENERIC key to store full list. + if (!_categoryToMavCmdInfoListMap.contains(MAV_AUTOPILOT_GENERIC) || !_categoryToMavCmdInfoListMap[MAV_AUTOPILOT_GENERIC].contains(mavCmdInfo->category())) { + qCDebug(MissionCommandsLog) << "Adding new category"; + _categoryToMavCmdInfoListMap[MAV_AUTOPILOT_GENERIC][mavCmdInfo->category()] = new QmlObjectListModel(this); + } + _categoryToMavCmdInfoListMap[MAV_AUTOPILOT_GENERIC][mavCmdInfo->category()]->append(mavCmdInfo); } } @@ -259,3 +266,64 @@ void MissionCommands::_loadMavCmdInfoJson(void) } } } + +MAV_AUTOPILOT MissionCommands::_firmwareTypeFromVehicle(Vehicle* vehicle) const +{ + if (vehicle) { + return vehicle->firmwareType(); + } else { + QSettings settings; + + // FIXME: Hack duplicated code from QGroundControlQmlGlobal. Had to do this for now since + // QGroundControlQmlGlobal is not available from C++ side. + + return (MAV_AUTOPILOT)settings.value("OfflineEditingFirmwareType", MAV_AUTOPILOT_ARDUPILOTMEGA).toInt(); + } +} + +QString MissionCommands::categoryFromCommand(MavlinkQmlSingleton::Qml_MAV_CMD command) const +{ + return _mavCmdInfoMap[(MAV_CMD)command]->category(); +} + +QVariant MissionCommands::getCommandsForCategory(Vehicle* vehicle, const QString& category) const +{ + return QVariant::fromValue(_categoryToMavCmdInfoListMap[_firmwareTypeFromVehicle(vehicle)][category]); +} + +const QStringList MissionCommands::categories(Vehicle* vehicle) const +{ + QStringList list; + + foreach (QString category, _categoryToMavCmdInfoListMap[_firmwareTypeFromVehicle(vehicle)].keys()) { + list << category; + } + + return list; +} + +void MissionCommands::_createFirmwareSpecificLists(void) +{ + QList firmwareList; + + firmwareList << MAV_AUTOPILOT_PX4 << MAV_AUTOPILOT_ARDUPILOTMEGA; + + foreach (MAV_AUTOPILOT firmwareType, firmwareList) { + FirmwarePlugin* plugin = _toolbox->firmwarePluginManager()->firmwarePluginForAutopilot(firmwareType, MAV_TYPE_QUADROTOR); + + QList cmdList = plugin->supportedMissionCommands(); + foreach (MAV_CMD command, cmdList) { + MavCmdInfo* mavCmdInfo = _mavCmdInfoMap[command]; + + if (mavCmdInfo->friendlyEdit()) { + if (!_categoryToMavCmdInfoListMap.contains(firmwareType) || !_categoryToMavCmdInfoListMap[firmwareType].contains(mavCmdInfo->category())) { + qCDebug(MissionCommandsLog) << "Adding new category" << firmwareType; + _categoryToMavCmdInfoListMap[firmwareType][mavCmdInfo->category()] = new QmlObjectListModel(this); + } + _categoryToMavCmdInfoListMap[firmwareType][mavCmdInfo->category()]->append(mavCmdInfo); + } else { + qWarning() << "Attempt to add non friendly edit supported command"; + } + } + } +} diff --git a/src/MissionManager/MissionCommands.h b/src/MissionManager/MissionCommands.h index ce2f214f1c9378e390d1e6e7363700df6ba4e74b..200b3e584235834ff0543bacc220cd1715a857d4 100644 --- a/src/MissionManager/MissionCommands.h +++ b/src/MissionManager/MissionCommands.h @@ -38,6 +38,7 @@ Q_DECLARE_LOGGING_CATEGORY(MissionCommandsLog) class MissionCommands; +class Vehicle; class MavCmdParamInfo : public QObject { @@ -129,17 +130,15 @@ class MissionCommands : public QGCTool public: MissionCommands(QGCApplication* app); - Q_PROPERTY(QStringList categories READ categories CONSTANT) - Q_PROPERTY(const QmlObjectListModel* commands READ commands CONSTANT) - - Q_INVOKABLE QString categoryFromCommand(MavlinkQmlSingleton::Qml_MAV_CMD command) { return _mavCmdInfoMap[(MAV_CMD)command]->category(); } - Q_INVOKABLE const QVariant getCommandsForCategory(const QString& category) const { return QVariant::fromValue(_categoryToMavCmdInfoListMap[category]); } - - const QStringList categories (void) const { return _categories; } - const QmlObjectListModel* commands (void) const { return &_commandList; } + Q_INVOKABLE const QStringList categories (Vehicle* vehicle) const; + Q_INVOKABLE QString categoryFromCommand (MavlinkQmlSingleton::Qml_MAV_CMD command) const; + Q_INVOKABLE QVariant getCommandsForCategory (Vehicle* vehicle, const QString& category) const; const QMap& commandInfoMap(void) const { return _mavCmdInfoMap; }; + // Overrides from QGCTool + virtual void setToolbox(QGCToolbox* toolbox); + static const QString _degreesUnits; static const QString _degreesConvertUnits; @@ -147,14 +146,14 @@ signals: private: void _loadMavCmdInfoJson(void); + void _createFirmwareSpecificLists(void); void _setupMetaData(void); bool _validateKeyTypes(QJsonObject& jsonObject, const QStringList& keys, const QList& types); + MAV_AUTOPILOT _firmwareTypeFromVehicle(Vehicle* vehicle) const; private: - QStringList _categories; - QMap _categoryToMavCmdInfoListMap; - QmlObjectListModel _commandList; - QMap _mavCmdInfoMap; + QMap > _categoryToMavCmdInfoListMap; + QMap _mavCmdInfoMap; static const QString _categoryJsonKey; static const QString _decimalPlacesJsonKey; diff --git a/src/MissionManager/MissionItem.cc b/src/MissionManager/MissionItem.cc index 8f477f21c4ef9ac2a81b0e577715faba3fb7a353..2cd3c699e66a1ac42bdc791abaaf21ecba051449 100644 --- a/src/MissionManager/MissionItem.cc +++ b/src/MissionManager/MissionItem.cc @@ -37,7 +37,6 @@ FactMetaData* MissionItem::_defaultParamMetaData = NULL; FactMetaData* MissionItem::_frameMetaData = NULL; FactMetaData* MissionItem::_latitudeMetaData = NULL; FactMetaData* MissionItem::_longitudeMetaData = NULL; -FactMetaData* MissionItem::_supportedCommandMetaData = NULL; struct EnumInfo_s { const char * label; @@ -108,7 +107,6 @@ MissionItem::MissionItem(QObject* parent) , _param7MetaData(FactMetaData::valueTypeDouble) , _syncingAltitudeRelativeToHomeAndFrame (false) , _syncingHeadingDegreesAndParam4 (false) - , _syncingSupportedCommandAndCommand (false) , _mavCmdInfoMap(qgcApp()->toolbox()->missionCommands()->commandInfoMap()) { // Need a good command and frame before we start passing signals around @@ -167,7 +165,6 @@ MissionItem::MissionItem(int sequenceNumber, , _param7MetaData(FactMetaData::valueTypeDouble) , _syncingAltitudeRelativeToHomeAndFrame (false) , _syncingHeadingDegreesAndParam4 (false) - , _syncingSupportedCommandAndCommand (false) , _mavCmdInfoMap(qgcApp()->toolbox()->missionCommands()->commandInfoMap()) { // Need a good command and frame before we start passing signals around @@ -183,7 +180,6 @@ MissionItem::MissionItem(int sequenceNumber, setAutoContinue(autoContinue); _syncFrameToAltitudeRelativeToHome(); - _syncCommandToSupportedCommand(QVariant(this->command())); _param1Fact.setRawValue(param1); _param2Fact.setRawValue(param2); @@ -223,7 +219,6 @@ MissionItem::MissionItem(const MissionItem& other, QObject* parent) , _param4MetaData(FactMetaData::valueTypeDouble) , _syncingAltitudeRelativeToHomeAndFrame (false) , _syncingHeadingDegreesAndParam4 (false) - , _syncingSupportedCommandAndCommand (false) , _mavCmdInfoMap(qgcApp()->toolbox()->missionCommands()->commandInfoMap()) { // Need a good command and frame before we start passing signals around @@ -254,7 +249,6 @@ const MissionItem& MissionItem::operator=(const MissionItem& other) setHomePositionValid(other._homePositionValid); _syncFrameToAltitudeRelativeToHome(); - _syncCommandToSupportedCommand(QVariant(this->command())); _param1Fact.setRawValue(other._param1Fact.rawValue()); _param2Fact.setRawValue(other._param2Fact.rawValue()); @@ -282,8 +276,6 @@ void MissionItem::_connectSignals(void) connect(this, &MissionItem::sequenceNumberChanged, this, &MissionItem::_setDirtyFromSignal); // Values from these facts must propogate back and forth between the real object storage - connect(&_supportedCommandFact, &Fact::valueChanged, this, &MissionItem::_syncSupportedCommandToCommand); - connect(&_commandFact, &Fact::valueChanged, this, &MissionItem::_syncCommandToSupportedCommand); connect(&_altitudeRelativeToHomeFact, &Fact::valueChanged, this, &MissionItem::_syncAltitudeRelativeToHomeToFrame); connect(this, &MissionItem::frameChanged, this, &MissionItem::_syncFrameToAltitudeRelativeToHome); @@ -351,28 +343,10 @@ void MissionItem::_setupMetaData(void) _longitudeMetaData->setUnits("deg"); _longitudeMetaData->setDecimalPlaces(7); - enumStrings.clear(); - enumValues.clear(); - // FIXME: Hack hardcode to PX4 - QList supportedCommands = qgcApp()->toolbox()->firmwarePluginManager()->firmwarePluginForAutopilot(MAV_AUTOPILOT_PX4, MAV_TYPE_QUADROTOR)->supportedMissionCommands(); - if (supportedCommands.count()) { - foreach (MAV_CMD command, supportedCommands) { - enumStrings.append(_mavCmdInfoMap[command]->friendlyName()); - enumValues.append(QVariant(command)); - } - } else { - foreach (const MavCmdInfo* mavCmdInfo, _mavCmdInfoMap) { - enumStrings.append(mavCmdInfo->friendlyName()); - enumValues.append(QVariant(mavCmdInfo->command())); - } - } - _supportedCommandMetaData = new FactMetaData(FactMetaData::valueTypeUint32); - _supportedCommandMetaData->setEnumInfo(enumStrings, enumValues); } _commandFact.setMetaData(_commandMetaData); _frameFact.setMetaData(_frameMetaData); - _supportedCommandFact.setMetaData(_supportedCommandMetaData); } MissionItem::~MissionItem() @@ -787,24 +761,6 @@ void MissionItem::_syncFrameToAltitudeRelativeToHome(void) } } -void MissionItem::_syncSupportedCommandToCommand(const QVariant& value) -{ - if (!_syncingSupportedCommandAndCommand) { - _syncingSupportedCommandAndCommand = true; - _commandFact.setRawValue(value.toInt()); - _syncingSupportedCommandAndCommand = false; - } -} - -void MissionItem::_syncCommandToSupportedCommand(const QVariant& value) -{ - if (!_syncingSupportedCommandAndCommand) { - _syncingSupportedCommandAndCommand = true; - _supportedCommandFact.setRawValue(value.toInt()); - _syncingSupportedCommandAndCommand = false; - } -} - void MissionItem::setDefaultsForCommand(void) { // We set these global defaults first, then if there are param defaults they will get reset diff --git a/src/MissionManager/MissionItem.h b/src/MissionManager/MissionItem.h index a0e7c832691afce9e1f66fe3c8f97d65548c52fb..31446d8cdfc3a24c459c10433481fdeddcf5e4ec 100644 --- a/src/MissionManager/MissionItem.h +++ b/src/MissionManager/MissionItem.h @@ -87,7 +87,6 @@ public: Q_PROPERTY(int sequenceNumber READ sequenceNumber WRITE setSequenceNumber NOTIFY sequenceNumberChanged) Q_PROPERTY(bool standaloneCoordinate READ standaloneCoordinate NOTIFY commandChanged) Q_PROPERTY(bool specifiesCoordinate READ specifiesCoordinate NOTIFY commandChanged) - Q_PROPERTY(Fact* supportedCommand READ supportedCommand NOTIFY commandChanged) // These properties are used to display the editing ui Q_PROPERTY(QmlObjectListModel* checkboxFacts READ checkboxFacts NOTIFY uiModelChanged) @@ -118,7 +117,6 @@ public: int sequenceNumber (void) const { return _sequenceNumber; } bool standaloneCoordinate(void) const; bool specifiesCoordinate (void) const; - Fact* supportedCommand (void) { return &_supportedCommandFact; } QmlObjectListModel* textFieldFacts (void); @@ -206,9 +204,7 @@ private slots: void _sendFriendlyEditAllowedChanged(void); void _sendUiModelChanged(void); void _syncAltitudeRelativeToHomeToFrame(const QVariant& value); - void _syncCommandToSupportedCommand(const QVariant& value); void _syncFrameToAltitudeRelativeToHome(void); - void _syncSupportedCommandToCommand(const QVariant& value); private: void _clearParamMetaData(void); @@ -249,7 +245,6 @@ private: static FactMetaData* _frameMetaData; static FactMetaData* _latitudeMetaData; static FactMetaData* _longitudeMetaData; - static FactMetaData* _supportedCommandMetaData; FactMetaData _param1MetaData; FactMetaData _param2MetaData; @@ -264,7 +259,6 @@ private: bool _syncingAltitudeRelativeToHomeAndFrame; ///< true: already in a sync signal, prevents signal loop bool _syncingHeadingDegreesAndParam4; ///< true: already in a sync signal, prevents signal loop - bool _syncingSupportedCommandAndCommand; ///< true: already in a sync signal, prevents signal loop const QMap& _mavCmdInfoMap; }; diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index 5dc5193e93b06f674215ab302ae8480a7b3b9ae6..d5215220b6b6de0dfe09bf87c9096e3a1307d218 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -77,6 +77,7 @@ #include "APM/ArduCopterFirmwarePlugin.h" #include "APM/ArduPlaneFirmwarePlugin.h" #include "APM/ArduRoverFirmwarePlugin.h" +#include "APM/APMAirframeComponentController.h" #include "PX4/PX4FirmwarePlugin.h" #include "Vehicle.h" #include "MavlinkQmlSingleton.h" @@ -144,7 +145,11 @@ static QObject* mavlinkQmlSingletonFactory(QQmlEngine*, QJSEngine*) static QObject* qgroundcontrolQmlGlobalSingletonFactory(QQmlEngine*, QJSEngine*) { - return new QGroundControlQmlGlobal(qgcApp()->toolbox()); + // We create this object as a QGCTool even though it isn't int he toolbox + QGroundControlQmlGlobal* qmlGlobal = new QGroundControlQmlGlobal(qgcApp()); + qmlGlobal->setToolbox(qgcApp()->toolbox()); + + return qmlGlobal; } /** @@ -378,9 +383,10 @@ void QGCApplication::_initCommon(void) qmlRegisterUncreatableType ("QGroundControl.JoystickManager", 1, 0, "JoystickManager", "Reference only"); qmlRegisterUncreatableType ("QGroundControl.JoystickManager", 1, 0, "Joystick", "Reference only"); - qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ParameterEditorController"); + qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ParameterEditorController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "APMFlightModesComponentController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "FlightModesComponentController"); + qmlRegisterType ("QGroundControl.Controllers", 1, 0, "APMAirframeComponentController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "AirframeComponentController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "APMSensorsComponentController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "SensorsComponentController"); diff --git a/src/QmlControls/MissionCommandDialog.qml b/src/QmlControls/MissionCommandDialog.qml index d41004f7e3660ddcc9ff793b2f1e147b9647b4e2..fc7f4f3942c6f30dd5f29d3b8da1fb40008f8189 100644 --- a/src/QmlControls/MissionCommandDialog.qml +++ b/src/QmlControls/MissionCommandDialog.qml @@ -32,6 +32,8 @@ import QGroundControl.Palette 1.0 QGCViewDialog { property var missionItem + property var _vehicle: QGroundControl.multiVehicleManager.activeVehicle + QGCPalette { id: qgcPal } QGCLabel { @@ -45,10 +47,10 @@ QGCViewDialog { anchors.margins: ScreenTools.defaultFontPixelWidth anchors.left: categoryLabel.right anchors.right: parent.right - model: QGroundControl.missionCommands.categories + model: QGroundControl.missionCommands.categories(_vehicle) function categorySelected(category) { - commandList.model = QGroundControl.missionCommands.getCommandsForCategory(category) + commandList.model = QGroundControl.missionCommands.getCommandsForCategory(_vehicle, category) } Component.onCompleted: { @@ -109,5 +111,4 @@ QGCViewDialog { } } } // ListView - } // QGCViewDialog diff --git a/src/QmlControls/QGCView.qml b/src/QmlControls/QGCView.qml index 1536effc22393a6733df29dd25d399d3d6bf233b..359d4fc5615cab47c59ae75c6ea53c7c6a4efc0c 100644 --- a/src/QmlControls/QGCView.qml +++ b/src/QmlControls/QGCView.qml @@ -96,7 +96,7 @@ FactPanel { __rejectButton.text = "Cancel" __rejectButton.visible = true } else if (buttons & StandardButton.Close) { - __rejectButton.text = "Cancel" + __rejectButton.text = "Close" __rejectButton.visible = true } else if (buttons & StandardButton.No) { __rejectButton.text = "No" diff --git a/src/QmlControls/QGroundControlQmlGlobal.cc b/src/QmlControls/QGroundControlQmlGlobal.cc index e5270782df5ba173282c3d6b613757c2ce693bc9..ca0348a9d76299c54c70a882708d8bc2088e9475 100644 --- a/src/QmlControls/QGroundControlQmlGlobal.cc +++ b/src/QmlControls/QGroundControlQmlGlobal.cc @@ -25,7 +25,6 @@ /// @author Don Gagne #include "QGroundControlQmlGlobal.h" -#include "QGCApplication.h" #include @@ -33,19 +32,49 @@ static const char* kQmlGlobalKeyName = "QGCQml"; const char* QGroundControlQmlGlobal::_virtualTabletJoystickKey = "VirtualTabletJoystick"; -QGroundControlQmlGlobal::QGroundControlQmlGlobal(QGCToolbox* toolbox, QObject* parent) - : QObject(parent) - , _flightMapSettings(toolbox->flightMapSettings()) - , _homePositionManager(toolbox->homePositionManager()) - , _linkManager(toolbox->linkManager()) - , _missionCommands(toolbox->missionCommands()) - , _multiVehicleManager(toolbox->multiVehicleManager()) +QGroundControlQmlGlobal::QGroundControlQmlGlobal(QGCApplication* app) + : QGCTool(app) + , _flightMapSettings(NULL) + , _homePositionManager(NULL) + , _linkManager(NULL) + , _missionCommands(NULL) + , _multiVehicleManager(NULL) , _virtualTabletJoystick(false) + , _offlineEditingFirmwareTypeFact(QString(), "OfflineEditingFirmwareType", FactMetaData::valueTypeUint32, (uint32_t)MAV_AUTOPILOT_ARDUPILOTMEGA) + , _offlineEditingFirmwareTypeMetaData(FactMetaData::valueTypeUint32) + { QSettings settings; _virtualTabletJoystick = settings.value(_virtualTabletJoystickKey, false). toBool(); + + QStringList firmwareEnumStrings; + QVariantList firmwareEnumValues; + + firmwareEnumStrings << "APM Flight Stack" << "PX4 Flight Stack" << "Mavlink Generic Flight Stack"; + firmwareEnumValues << QVariant::fromValue((uint32_t)MAV_AUTOPILOT_ARDUPILOTMEGA) << QVariant::fromValue((uint32_t)MAV_AUTOPILOT_PX4) << QVariant::fromValue((uint32_t)MAV_AUTOPILOT_GENERIC); + + _offlineEditingFirmwareTypeMetaData.setEnumInfo(firmwareEnumStrings, firmwareEnumValues); + _offlineEditingFirmwareTypeFact.setMetaData(&_offlineEditingFirmwareTypeMetaData); +} + +QGroundControlQmlGlobal::~QGroundControlQmlGlobal() +{ + } + +void QGroundControlQmlGlobal::setToolbox(QGCToolbox* toolbox) +{ + QGCTool::setToolbox(toolbox); + + _flightMapSettings = toolbox->flightMapSettings(); + _homePositionManager = toolbox->homePositionManager(); + _linkManager = toolbox->linkManager(); + _missionCommands = toolbox->missionCommands(); + _multiVehicleManager = toolbox->multiVehicleManager(); +} + + void QGroundControlQmlGlobal::saveGlobalSetting (const QString& key, const QString& value) { QSettings settings; diff --git a/src/QmlControls/QGroundControlQmlGlobal.h b/src/QmlControls/QGroundControlQmlGlobal.h index 599474cae5f24ee5f81e326bd6642c60fbffdd0b..ff4403052e5ac349742ef5933409022bd4d2d5f0 100644 --- a/src/QmlControls/QGroundControlQmlGlobal.h +++ b/src/QmlControls/QGroundControlQmlGlobal.h @@ -27,13 +27,13 @@ #ifndef QGroundControlQmlGlobal_H #define QGroundControlQmlGlobal_H -#include - +#include "QGCToolbox.h" #include "QGCApplication.h" #include "LinkManager.h" #include "HomePositionManager.h" #include "FlightMapSettings.h" #include "MissionCommands.h" +#include "SettingsFact.h" #ifdef QT_DEBUG #include "MockLink.h" @@ -41,12 +41,14 @@ class QGCToolbox; -class QGroundControlQmlGlobal : public QObject +class QGroundControlQmlGlobal : public QGCTool { Q_OBJECT public: - QGroundControlQmlGlobal(QGCToolbox* toolbox, QObject* parent = NULL); + QGroundControlQmlGlobal(QGCApplication* app); + ~QGroundControlQmlGlobal(); + Q_PROPERTY(FlightMapSettings* flightMapSettings READ flightMapSettings CONSTANT) Q_PROPERTY(HomePositionManager* homePositionManager READ homePositionManager CONSTANT) @@ -72,13 +74,15 @@ public: Q_PROPERTY(bool isVersionCheckEnabled READ isVersionCheckEnabled WRITE setIsVersionCheckEnabled NOTIFY isVersionCheckEnabledChanged) Q_PROPERTY(int mavlinkSystemID READ mavlinkSystemID WRITE setMavlinkSystemID NOTIFY mavlinkSystemIDChanged) + Q_PROPERTY(Fact* offlineEditingFirmwareType READ offlineEditingFirmwareType CONSTANT) + Q_INVOKABLE void saveGlobalSetting (const QString& key, const QString& value); Q_INVOKABLE QString loadGlobalSetting (const QString& key, const QString& defaultValue); Q_INVOKABLE void saveBoolGlobalSetting (const QString& key, bool value); Q_INVOKABLE bool loadBoolGlobalSetting (const QString& key, bool defaultValue); - Q_INVOKABLE void deleteAllSettingsNextBoot () { qgcApp()->deleteAllSettingsNextBoot(); } - Q_INVOKABLE void clearDeleteAllSettingsNextBoot () { qgcApp()->clearDeleteAllSettingsNextBoot(); } + Q_INVOKABLE void deleteAllSettingsNextBoot () { _app->deleteAllSettingsNextBoot(); } + Q_INVOKABLE void clearDeleteAllSettingsNextBoot () { _app->clearDeleteAllSettingsNextBoot(); } Q_INVOKABLE void startPX4MockLink (bool sendStatusText); Q_INVOKABLE void startGenericMockLink (bool sendStatusText); @@ -98,16 +102,18 @@ public: qreal zOrderWidgets () { return 100; } qreal zOrderMapItems () { return 50; } - bool isDarkStyle () { return qgcApp()->styleIsDark(); } - bool isAudioMuted () { return qgcApp()->toolbox()->audioOutput()->isMuted(); } - bool isSaveLogPrompt () { return qgcApp()->promptFlightDataSave(); } - bool isSaveLogPromptNotArmed () { return qgcApp()->promptFlightDataSaveNotArmed(); } + bool isDarkStyle () { return _app->styleIsDark(); } + bool isAudioMuted () { return _toolbox->audioOutput()->isMuted(); } + bool isSaveLogPrompt () { return _app->promptFlightDataSave(); } + bool isSaveLogPromptNotArmed () { return _app->promptFlightDataSaveNotArmed(); } bool virtualTabletJoystick () { return _virtualTabletJoystick; } - bool isHeartBeatEnabled () { return qgcApp()->toolbox()->mavlinkProtocol()->heartbeatsEnabled(); } - bool isMultiplexingEnabled () { return qgcApp()->toolbox()->mavlinkProtocol()->multiplexingEnabled(); } - bool isVersionCheckEnabled () { return qgcApp()->toolbox()->mavlinkProtocol()->versionCheckEnabled(); } - int mavlinkSystemID () { return qgcApp()->toolbox()->mavlinkProtocol()->getSystemId(); } + bool isHeartBeatEnabled () { return _toolbox->mavlinkProtocol()->heartbeatsEnabled(); } + bool isMultiplexingEnabled () { return _toolbox->mavlinkProtocol()->multiplexingEnabled(); } + bool isVersionCheckEnabled () { return _toolbox->mavlinkProtocol()->versionCheckEnabled(); } + int mavlinkSystemID () { return _toolbox->mavlinkProtocol()->getSystemId(); } + + Fact* offlineEditingFirmwareType () { return &_offlineEditingFirmwareTypeFact; } //-- TODO: Make this into an actual preference. bool isAdvancedMode () { return false; } @@ -123,6 +129,9 @@ public: void setIsVersionCheckEnabled (bool enable); void setMavlinkSystemID (int id); + // Overrides from QGCTool + virtual void setToolbox(QGCToolbox* toolbox); + signals: void isDarkStyleChanged (bool dark); void isAudioMutedChanged (bool muted); @@ -144,6 +153,9 @@ private: bool _virtualTabletJoystick; + SettingsFact _offlineEditingFirmwareTypeFact; + FactMetaData _offlineEditingFirmwareTypeMetaData; + static const char* _virtualTabletJoystickKey; }; diff --git a/src/QmlControls/SubMenuButton.qml b/src/QmlControls/SubMenuButton.qml index 05533114dbd267df9348abd948e411128d4e2216..4d4538b13205b3f06d330ce2c93b98c89894ec92 100644 --- a/src/QmlControls/SubMenuButton.qml +++ b/src/QmlControls/SubMenuButton.qml @@ -13,8 +13,8 @@ Button { text: "Button" ///< Pass in your own button text - checkable: true - height: ScreenTools.defaultFontPixelHeight * 2.5 + checkable: true + implicitHeight: ScreenTools.defaultFontPixelHeight * 2.5 style: ButtonStyle { id: buttonStyle @@ -30,6 +30,8 @@ Button { id: innerRect color: showHighlight ? qgcPal.buttonHighlight : qgcPal.windowShade + implicitWidth: titleBar.x + titleBar.contentWidth + ScreenTools.defaultFontPixelWidth + QGCColoredImage { id: image anchors.leftMargin: ScreenTools.defaultFontPixelWidth diff --git a/src/VehicleSetup/SetupView.qml b/src/VehicleSetup/SetupView.qml index 1a782466098b6f24b9072a3d470a4d1decd7f7d3..27e8c33a131e69f4cd1650d530799dba793e4f8b 100644 --- a/src/VehicleSetup/SetupView.qml +++ b/src/VehicleSetup/SetupView.qml @@ -213,24 +213,42 @@ Rectangle { Flickable { id: buttonScroll - width: mainWindow.menuButtonWidth + width: buttonColumn.width anchors.topMargin: _defaultTextHeight / 2 anchors.top: parent.top anchors.bottom: parent.bottom clip: true contentHeight: buttonColumn.height - contentWidth: parent.width + contentWidth: buttonColumn.width boundsBehavior: Flickable.StopAtBounds flickableDirection: Flickable.VerticalFlick Column { id: buttonColumn - width: mainWindow.menuButtonWidth + width: _maxButtonWidth spacing: _defaultTextHeight / 2 + property real _maxButtonWidth: 0 + + Component.onCompleted: reflowWidths() + + Connections { + target: componentRepeater + + onModelChanged: buttonColumn.reflowWidths() + } + + function reflowWidths() { + for (var i=0; i