Commit 62285253 authored by Don Gagne's avatar Don Gagne

More work on complex mission items

- Load/Save working
- Entry point working
parent 17fee7a5
......@@ -42,9 +42,12 @@
<file alias="PowerComponent.qml">src/AutoPilotPlugins/PX4/PowerComponent.qml</file>
<file alias="PowerComponentSummary.qml">src/AutoPilotPlugins/PX4/PowerComponentSummary.qml</file>
<file alias="PX4FlowSensor.qml">src/VehicleSetup/PX4FlowSensor.qml</file>
<file alias="QGroundControl/Controls/qmldir">src/QmlControls/QGroundControl.Controls.qmldir</file>
<file alias="QGroundControl/Controls/ClickableColor.qml">src/QmlControls/ClickableColor.qml</file>
<file alias="QGroundControl/Controls/DropButton.qml">src/QmlControls/DropButton.qml</file>
<file alias="QGroundControl/Controls/ExclusiveGroupItem.qml">src/QmlControls/ExclusiveGroupItem.qml</file>
<file alias="QGroundControl/Controls/FactSliderPanel.qml">src/QmlControls/FactSliderPanel.qml</file>
<file alias="QGroundControl/Controls/IndicatorButton.qml">src/QmlControls/IndicatorButton.qml</file>
<file alias="QGroundControl/Controls/JoystickThumbPad.qml">src/QmlControls/JoystickThumbPad.qml</file>
<file alias="QGroundControl/Controls/MainToolBar.qml">src/ui/toolbar/MainToolBar.qml</file>
......@@ -73,14 +76,16 @@
<file alias="QGroundControl/Controls/QGCViewDialog.qml">src/QmlControls/QGCViewDialog.qml</file>
<file alias="QGroundControl/Controls/QGCViewMessage.qml">src/QmlControls/QGCViewMessage.qml</file>
<file alias="QGroundControl/Controls/QGCViewPanel.qml">src/QmlControls/QGCViewPanel.qml</file>
<file alias="QGroundControl/Controls/qmldir">src/QmlControls/QGroundControl.Controls.qmldir</file>
<file alias="QGroundControl/Controls/RoundButton.qml">src/QmlControls/RoundButton.qml</file>
<file alias="QGroundControl/Controls/SignalStrength.qml">src/ui/toolbar/SignalStrength.qml</file>
<file alias="QGroundControl/Controls/SubMenuButton.qml">src/QmlControls/SubMenuButton.qml</file>
<file alias="QGroundControl/Controls/VehicleRotationCal.qml">src/QmlControls/VehicleRotationCal.qml</file>
<file alias="QGroundControl/Controls/VehicleSummaryRow.qml">src/QmlControls/VehicleSummaryRow.qml</file>
<file alias="QGroundControl/Controls/ViewWidget.qml">src/ViewWidgets/ViewWidget.qml</file>
<file alias="QGroundControl/Controls/FactSliderPanel.qml">src/QmlControls/FactSliderPanel.qml</file>
<file alias="SimpleItemEditor.qml">src/MissionEditor/SimpleItemEditor.qml</file>
<file alias="SurveyItemEditor.qml">src/MissionEditor/SurveyItemEditor.qml</file>
<file alias="QGroundControl/FactControls/FactBitmask.qml">src/FactSystem/FactControls/FactBitmask.qml</file>
<file alias="QGroundControl/FactControls/FactCheckBox.qml">src/FactSystem/FactControls/FactCheckBox.qml</file>
<file alias="QGroundControl/FactControls/FactComboBox.qml">src/FactSystem/FactControls/FactComboBox.qml</file>
......
......@@ -82,7 +82,19 @@ bool JsonHelper::toQGeoCoordinate(const QJsonValue& jsonValue, QGeoCoordinate& c
return true;
}
bool JsonHelper::validateKeyTypes(QJsonObject& jsonObject, const QStringList& keys, const QList<QJsonValue::Type>& types, QString& errorString)
void JsonHelper::writeQGeoCoordinate(QJsonValue& jsonValue, const QGeoCoordinate& coordinate, bool writeAltitude)
{
QJsonArray coordinateArray;
coordinateArray << coordinate.latitude() << coordinate.longitude();
if (writeAltitude) {
coordinateArray << coordinate.altitude();
}
jsonValue = QJsonValue(coordinateArray);
}
bool JsonHelper::validateKeyTypes(const QJsonObject& jsonObject, const QStringList& keys, const QList<QJsonValue::Type>& types, QString& errorString)
{
for (int i=0; i<keys.count(); i++) {
if (jsonObject.contains(keys[i])) {
......
......@@ -31,10 +31,12 @@ class JsonHelper
{
public:
static bool validateRequiredKeys(const QJsonObject& jsonObject, const QStringList& keys, QString& errorString);
static bool validateKeyTypes(QJsonObject& jsonObject, const QStringList& keys, const QList<QJsonValue::Type>& types, QString& errorString);
static bool validateKeyTypes(const QJsonObject& jsonObject, const QStringList& keys, const QList<QJsonValue::Type>& types, QString& errorString);
static bool toQGeoCoordinate(const QJsonValue& jsonValue, QGeoCoordinate& coordinate, bool altitudeRequired, QString& errorString);
static bool parseEnum(QJsonObject& jsonObject, QStringList& enumStrings, QStringList& enumValues, QString& errorString);
static void writeQGeoCoordinate(QJsonValue& jsonValue, const QGeoCoordinate& coordinate, bool writeAltitude);
static const char* _enumStringsJsonKey;
static const char* _enumValuesJsonKey;
};
......
......@@ -552,6 +552,7 @@ QGCView {
var index = controller.insertComplexMissionItem(coordinate, controller.visualItems.count)
setCurrentItem(index)
checked = false
addMissionItemsButton.checked = false
}
}
......
......@@ -49,7 +49,6 @@ Rectangle {
property real _gradient: _statusValid ? Math.atan(_currentMissionItem.altDifference / _currentMissionItem.distance) : 0
property real _gradientPercent: isNaN(_gradient) ? 0 : _gradient * 100
property real _azimuth: _statusValid ? _currentMissionItem.azimuth : -1
property real _isHomePosition: _statusValid ? _currentMissionItem.homePosition : false
property bool _statusValid: currentMissionItem != undefined
property string _distanceText: _statusValid ? _distance.toFixed(2) + " m" : ""
property string _altText: _statusValid ? _altDifference.toFixed(2) + " m" : ""
......
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QtQuick.Dialogs 1.2
import QGroundControl.ScreenTools 1.0
import QGroundControl.Vehicle 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0
// Editor for Simple mission items
Rectangle {
id: valuesRect
width: availableWidth
height: valuesItem.height
color: qgcPal.windowShadeDark
visible: missionItem.isCurrentItem
radius: _radius
// The following properties must be available up the hierachy chain
//property real availableWidth ///< Width for control
//property var missionItem ///< Mission Item for editor
Item {
id: valuesItem
anchors.margins: _margin
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
height: valuesColumn.height + (_margin * 2)
Column {
id: valuesColumn
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
spacing: _margin
QGCLabel {
width: parent.width
wrapMode: Text.WordWrap
text: missionItem.sequenceNumber == 0 ?
"Planned home position." :
(missionItem.rawEdit ?
"Provides advanced access to all commands/parameters. Be very careful!" :
missionItem.commandDescription)
}
Repeater {
model: missionItem.comboboxFacts
Item {
width: valuesColumn.width
height: comboBoxFact.height
QGCLabel {
id: comboBoxLabel
anchors.baseline: comboBoxFact.baseline
text: object.name
visible: object.name != ""
}
FactComboBox {
id: comboBoxFact
anchors.right: parent.right
width: comboBoxLabel.visible ? _editFieldWidth : parent.width
indexModel: false
model: object.enumStrings
fact: object
}
}
}
Repeater {
model: missionItem.textFieldFacts
Item {
width: valuesColumn.width
height: textField.height
QGCLabel {
id: textFieldLabel
anchors.baseline: textField.baseline
text: object.name
}
FactTextField {
id: textField
anchors.right: parent.right
width: _editFieldWidth
showUnits: true
fact: object
visible: !_root.readOnly
}
FactLabel {
anchors.baseline: textFieldLabel.baseline
anchors.right: parent.right
fact: object
visible: _root.readOnly
}
}
}
Repeater {
model: missionItem.checkboxFacts
FactCheckBox {
text: object.name
fact: object
}
}
QGCButton {
text: "Move Home to map center"
visible: missionItem.homePosition
onClicked: editorRoot.moveHomeToMapCenter()
anchors.horizontalCenter: parent.horizontalCenter
}
} // Column
} // Item
} // Rectangle
import QtQuick 2.2
import QtQuick.Controls 1.2
import QGroundControl.ScreenTools 1.0
import QGroundControl.Vehicle 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0
// Editor for Survery mission items
Rectangle {
id: _root
height: editorColumn.height + (_margin * 2)
width: availableWidth
color: qgcPal.windowShadeDark
radius: _radius
// The following properties must be available up the hierachy chain
//property real availableWidth ///< Width for control
//property var missionItem ///< Mission Item for editor
property bool _addPointsMode: false
property real _margin: ScreenTools.defaultFontPixelWidth / 2
QGCPalette { id: qgcPal; colorGroupEnabled: true }
Column {
id: editorColumn
anchors.margins: _margin
anchors.top: parent.top
anchors.left: parent.left
width: availableWidth
spacing: _margin
Connections {
target: editorMap
onMapClicked: {
if (_addPointsMode) {
missionItem.addPolygonCoordinate(coordinate)
}
}
}
QGCLabel {
text: "Fly a grid pattern over a defined area."
wrapMode: Text.WordWrap
}
QGCButton {
text: _addPointsMode ? "Finished" : "Draw Polygon"
onClicked: {
if (_addPointsMode) {
_addPointsMode = false
} else {
missionItem.clearPolygon()
_addPointsMode = true
}
}
}
}
}
/*===================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2010 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
(c) 2009, 2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
......@@ -21,12 +21,25 @@ This file is part of the QGROUNDCONTROL project
======================================================================*/
#include "ComplexMissionItem.h"
#include "JsonHelper.h"
#include "MissionController.h"
const char* ComplexMissionItem::_jsonVersionKey = "version";
const char* ComplexMissionItem::_jsonTypeKey = "type";
const char* ComplexMissionItem::_jsonPolygonKey = "polygon";
const char* ComplexMissionItem::_jsonIdKey = "id";
const char* ComplexMissionItem::_complexType = "survey";
ComplexMissionItem::ComplexMissionItem(Vehicle* vehicle, QObject* parent)
: VisualMissionItem(vehicle, parent)
, _dirty(false)
{
MissionItem missionItem;
// FIXME: Bogus entries for testing
_missionItems += new MissionItem(this);
_missionItems += new MissionItem(this);
}
ComplexMissionItem::ComplexMissionItem(const ComplexMissionItem& other, QObject* parent)
......@@ -36,20 +49,6 @@ ComplexMissionItem::ComplexMissionItem(const ComplexMissionItem& other, QObject*
}
QVariantList ComplexMissionItem::polygonPath(void)
{
return _polygonPath;
#if 0
QVariantList list;
list << QVariant::fromValue(QGeoCoordinate(-35.362686830000001, 149.16410282999999))
<< QVariant::fromValue(QGeoCoordinate(-35.362660579999996, 149.16606619999999))
<< QVariant::fromValue(QGeoCoordinate(-35.363832989999999, 149.16505769));
return list;
#endif
}
void ComplexMissionItem::clearPolygon(void)
{
_polygonPath.clear();
......@@ -60,6 +59,11 @@ void ComplexMissionItem::addPolygonCoordinate(const QGeoCoordinate coordinate)
{
_polygonPath << QVariant::fromValue(coordinate);
emit polygonPathChanged();
// FIXME: Hack, first polygon point sets entry coordinate
if (_polygonPath.count() == 1) {
setCoordinate(coordinate);
}
}
int ComplexMissionItem::nextSequenceNumber(void) const
......@@ -72,6 +76,10 @@ void ComplexMissionItem::setCoordinate(const QGeoCoordinate& coordinate)
if (_coordinate != coordinate) {
_coordinate = coordinate;
emit coordinateChanged(_coordinate);
_missionItems[0]->setCoordinate(coordinate);
// FIXME: Hack
_setExitCoordinate(coordinate);
}
}
......@@ -83,11 +91,148 @@ void ComplexMissionItem::setDirty(bool dirty)
}
}
bool ComplexMissionItem::save(QJsonObject& missionObject, QJsonArray& missionItems, QString& errorString)
void ComplexMissionItem::save(QJsonObject& saveObject) const
{
saveObject[_jsonVersionKey] = 1;
saveObject[_jsonTypeKey] = _complexType;
saveObject[_jsonIdKey] = sequenceNumber();
// Polygon shape
QJsonArray polygonArray;
for (int i=0; i<_polygonPath.count(); i++) {
const QVariant& polyVar = _polygonPath[i];
QJsonValue jsonValue;
JsonHelper::writeQGeoCoordinate(jsonValue, polyVar.value<QGeoCoordinate>(), false /* writeAltitude */);
polygonArray += jsonValue;
}
saveObject[_jsonPolygonKey] = polygonArray;
// Base mission items
QJsonArray simpleItems;
for (int i=0; i<_missionItems.count(); i++) {
MissionItem* missionItem = _missionItems[i];
QJsonObject jsonObject;
missionItem->save(jsonObject);
simpleItems.append(jsonObject);
}
saveObject[MissionController::jsonSimpleItemsKey] = simpleItems;
}
void ComplexMissionItem::setSequenceNumber(int sequenceNumber)
{
VisualMissionItem::setSequenceNumber(sequenceNumber);
// Update internal mission items to new numbering
for (int i=0; i<_missionItems.count(); i++) {
_missionItems[i]->setSequenceNumber(sequenceNumber++);
}
}
void ComplexMissionItem::_clear(void)
{
Q_UNUSED(missionObject);
Q_UNUSED(missionItems);
// Clear old settings
for (int i=0; i<_missionItems.count(); i++) {
_missionItems[i]->deleteLater();
}
_missionItems.clear();
_polygonPath.clear();
}
bool ComplexMissionItem::load(const QJsonObject& complexObject, QString& errorString)
{
_clear();
// Validate requires keys
QStringList requiredKeys;
requiredKeys << _jsonVersionKey << _jsonTypeKey << _jsonIdKey << _jsonPolygonKey << MissionController::jsonSimpleItemsKey;
if (!JsonHelper::validateRequiredKeys(complexObject, requiredKeys, errorString)) {
_clear();
return false;
}
// Validate types
QStringList keyList;
QList<QJsonValue::Type> typeList;
keyList << _jsonVersionKey << _jsonTypeKey << _jsonIdKey << _jsonPolygonKey << MissionController::jsonSimpleItemsKey;
typeList << QJsonValue::Double << QJsonValue::String << QJsonValue::Double << QJsonValue::Array << QJsonValue::Array;
if (!JsonHelper::validateKeyTypes(complexObject, keyList, typeList, errorString)) {
_clear();
return false;
}
// Version check
if (complexObject[_jsonVersionKey].toInt() != 1) {
errorString = tr("QGroundControl does not support this version of survey items");
_clear();
return false;
}
QString complexType = complexObject[_jsonTypeKey].toString();
if (complexType != _complexType) {
errorString = tr("QGroundControl does not support loading this complex mission item type: %1").arg(complexType);
_clear();
return false;
}
setSequenceNumber(complexObject[_jsonIdKey].toInt());
// Polygon shape
QJsonArray polygonArray(complexObject[_jsonPolygonKey].toArray());
for (int i=0; i<polygonArray.count(); i++) {
const QJsonValue& pointValue = polygonArray[i];
QGeoCoordinate pointCoord;
if (!JsonHelper::toQGeoCoordinate(pointValue, pointCoord, false /* altitudeRequired */, errorString)) {
_clear();
return false;
}
_polygonPath << QVariant::fromValue(pointCoord);
}
// Internal mission items
QJsonArray itemArray(complexObject[MissionController::jsonSimpleItemsKey].toArray());
for (int i=0; i<itemArray.count(); i++) {
const QJsonValue& itemValue = itemArray[i];
if (!itemValue.isObject()) {
errorString = QStringLiteral("Mission item is not an object");
_clear();
return false;
}
MissionItem* item = new MissionItem(_vehicle, this);
if (item->load(itemValue.toObject(), errorString)) {
_missionItems.append(item);
} else {
_clear();
return false;
}
}
errorString = "Complex save NYI";
return false;
int itemCount = _missionItems.count();
if (itemCount > 0) {
setCoordinate(_missionItems[0]->coordinate());
_setExitCoordinate(_missionItems[itemCount - 1]->coordinate());
}
return true;
}
void ComplexMissionItem::_setExitCoordinate(const QGeoCoordinate& coordinate)
{
if (_exitCoordinate != coordinate) {
_exitCoordinate = coordinate;
emit exitCoordinateChanged(coordinate);
int itemCount = _missionItems.count();
if (itemCount > 0) {
_missionItems[itemCount - 1]->setCoordinate(coordinate);
}
}
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
(c) 2009 - 2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#ifndef ComplexMissionItem_H
......@@ -30,7 +30,7 @@
class ComplexMissionItem : public VisualMissionItem
{
Q_OBJECT
public:
ComplexMissionItem(Vehicle* vehicle, QObject* parent = NULL);
ComplexMissionItem(const ComplexMissionItem& other, QObject* parent = NULL);
......@@ -40,13 +40,19 @@ public:
Q_INVOKABLE void clearPolygon(void);
Q_INVOKABLE void addPolygonCoordinate(const QGeoCoordinate coordinate);
QVariantList polygonPath(void);
QVariantList polygonPath(void) { return _polygonPath; }
const QList<MissionItem*>& missionItems(void) { return _missionItems; }
QList<MissionItem*>& missionItems(void) { return _missionItems; }
/// @return The next sequence number to use after this item. Takes into account child items of the complex item
int nextSequenceNumber(void) const;
/// Load the complex mission item from Json
/// @param complexObject Complex mission item json object
/// @param[out] errorString Error if load fails
/// @return true: load success, false: load failed, errorString set
bool load(const QJsonObject& complexObject, QString& errorString);
// Overrides from VisualMissionItem
bool dirty (void) const final { return _dirty; }
......@@ -56,24 +62,36 @@ public:
QString commandDescription (void) const final { return "Survey"; }
QString commandName (void) const final { return "Survey"; }
QGeoCoordinate coordinate (void) const final { return _coordinate; }
QGeoCoordinate exitCoordinate (void) const final { return _coordinate; }
QGeoCoordinate exitCoordinate (void) const final { return _exitCoordinate; }
bool coordinateHasRelativeAltitude (void) const final { return true; }
bool exitCoordinateHasRelativeAltitude (void) const final { return true; }
bool exitCoordinateSameAsEntry (void) const final { return false; }
void setDirty (bool dirty) final;
void setCoordinate (const QGeoCoordinate& coordinate);
bool save (QJsonObject& missionObject, QJsonArray& missionItems, QString& errorString) final;
void setCoordinate (const QGeoCoordinate& coordinate) final;
void setSequenceNumber (int sequenceNumber) final;
void save (QJsonObject& saveObject) const final;
signals:
void polygonPathChanged(void);
private:
void _clear(void);
void _setExitCoordinate(const QGeoCoordinate& coordinate);
bool _dirty;
QVariantList _polygonPath;
QList<MissionItem*> _missionItems;
QGeoCoordinate _coordinate;
QGeoCoordinate _exitCoordinate;
static const char* _jsonVersionKey;
static const char* _jsonTypeKey;
static const char* _jsonPolygonKey;
static const char* _jsonIdKey;
static const char* _complexType;
};
#endif
......@@ -29,6 +29,7 @@ This file is part of the QGROUNDCONTROL project
#include "QGCApplication.h"
#include "SimpleMissionItem.h"
#include "ComplexMissionItem.h"
#include "JsonHelper.h"
#ifndef __mobile__
#include "QGCFileDialog.h"
......@@ -36,11 +37,13 @@ This file is part of the QGROUNDCONTROL project
QGC_LOGGING_CATEGORY(MissionControllerLog, "MissionControllerLog")
const char* MissionController::jsonSimpleItemsKey = "items";
const char* MissionController::_settingsGroup = "MissionController";
const char* MissionController::_jsonVersionKey = "version";
const char* MissionController::_jsonGroundStationKey = "groundStation";
const char* MissionController::_jsonMavAutopilotKey = "MAV_AUTOPILOT";
const char* MissionController::_jsonItemsKey = "items";
const char* MissionController::_jsonComplexItemsKey = "complexItems";
const char* MissionController::_jsonPlannedHomePositionKey = "plannedHomePosition";
MissionController::MissionController(QObject *parent)
......@@ -140,7 +143,9 @@ void MissionController::sendMissionItems(void)
missionItem.setSequenceNumber(sequenceNumber++);
missionItems.append(&missionItem);
} else {
foreach (MissionItem* missionItem, qobject_cast<ComplexMissionItem*>(visualItem)->missionItems()) {
ComplexMissionItem* complexItem = qobject_cast<ComplexMissionItem*>(visualItem);
for (int j=0; j<complexItem->missionItems().count(); j++) {
MissionItem* missionItem = complexItem->missionItems()[i];
missionItem->setSequenceNumber(sequenceNumber++);
missionItems.append(missionItem);
}
......@@ -247,29 +252,56 @@ bool MissionController::_loadJsonMissionFile(const QByteArray& bytes, QmlObjectL
QJsonObject json = jsonDoc.object();
if (!json.contains(_jsonVersionKey)) {
errorString = QStringLiteral("File is missing version key");
// Check for required keys
QStringList requiredKeys;
requiredKeys << _jsonVersionKey << _jsonPlannedHomePositionKey;
if (!JsonHelper::validateRequiredKeys(json, requiredKeys, errorString)) {
return false;
}
// Validate base key types
QStringList keyList;
QList<QJsonValue::Type> typeList;
keyList << jsonSimpleItemsKey << _jsonVersionKey << _jsonGroundStationKey << _jsonMavAutopilotKey << _jsonComplexItemsKey << _jsonPlannedHomePositionKey;
typeList << QJsonValue::Array << QJsonValue::String << QJsonValue::String << QJsonValue::Double << QJsonValue::Array << QJsonValue::Object;
if (!JsonHelper::validateKeyTypes(json, keyList, typeList, errorString)) {
return false;
}
// Version check
if (json[_jsonVersionKey].toString() != "1.0") {
errorString = QStringLiteral("QGroundControl does not support this file version");
return false;
}
if (json.contains(_jsonItemsKey)) {
if (!json[_jsonItemsKey].isArray()) {
errorString = QStringLiteral("items values must be array");
return false;
// Simple items
if (json.contains(jsonSimpleItemsKey)) {
QJsonArray itemArray(json[jsonSimpleItemsKey].toArray());
foreach (const QJsonValue& itemValue, itemArray) {
if (!itemValue.isObject()) {
errorString = QStringLiteral("Mission item is not an object");
return false;
}
SimpleMissionItem* item = new SimpleMissionItem(_activeVehicle, this);
if (item->load(itemValue.toObject(), errorString)) {
missionItems->append(item);
} else {
return false;
}
}
}
QJsonArray itemArray(json[_jsonItemsKey].toArray());
// Complex items
if (json.contains(_jsonComplexItemsKey)) {
QJsonArray itemArray(json[_jsonComplexItemsKey].toArray());
foreach (const QJsonValue& itemValue, itemArray) {
if (!itemValue.isObject()) {
errorString = QStringLiteral("Mission item is not an object");
return false;
}
SimpleMissionItem* item = new SimpleMissionItem(_activeVehicle, this);
ComplexMissionItem* item = new ComplexMissionItem(_activeVehicle, this);
if (item->load(itemValue.toObject(), errorString)) {
missionItems->append(item);
} else {
......@@ -418,12 +450,12 @@ void MissionController::_saveMissionToFile(const QString& filename)
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
qgcApp()->showMessage(file.errorString());
} else {
QJsonObject missionObject; // top level json object
QJsonArray missionItemArray; // array of mission items
QString errorString;
QJsonObject missionFileObject; // top level json object
QJsonArray simpleItemsObject;
QJsonArray complexItemsObject;
missionObject[_jsonVersionKey] = "1.0";