diff --git a/qgcresources.qrc b/qgcresources.qrc index f7b69b43b782e20e3e16a0d0fee6a9ec784eddc0..42e9f1527dc4cf3ef610b78998c2680c93b22e1e 100644 --- a/qgcresources.qrc +++ b/qgcresources.qrc @@ -99,6 +99,7 @@ src/FlightMap/Images/MapAddMissionBlack.svg src/FlightMap/Images/MapCenter.svg src/FlightMap/Images/MapCenterBlack.svg + src/FlightMap/Images/MapDrawShape.svg src/FlightMap/Images/MapHome.svg src/FlightMap/Images/MapHomeBlack.svg src/FlightMap/Images/MapSync.svg diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 3e021fcc90cf63c2e280e1081aa0bb28e17b0d69..f2b842280f9940c255afe552f6db967d1b17c59b 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -261,6 +261,8 @@ HEADERS += \ src/MissionManager/MissionController.h \ src/MissionManager/MissionItem.h \ src/MissionManager/MissionManager.h \ + src/MissionManager/ComplexMissionItem.h \ + src/MissionManager/SimpleMissionItem.h \ src/QGC.h \ src/QGCApplication.h \ src/QGCComboBox.h \ @@ -388,6 +390,8 @@ SOURCES += \ src/MissionManager/MissionController.cc \ src/MissionManager/MissionItem.cc \ src/MissionManager/MissionManager.cc \ + src/MissionManager/ComplexMissionItem.cc \ + src/MissionManager/SimpleMissionItem.cc \ src/QGC.cc \ src/QGCApplication.cc \ src/QGCComboBox.cc \ diff --git a/src/FlightMap/Images/MapDrawShape.svg b/src/FlightMap/Images/MapDrawShape.svg new file mode 100644 index 0000000000000000000000000000000000000000..a73a7ad97a5c57c13230cfe6cbe6c3cb5264613e --- /dev/null +++ b/src/FlightMap/Images/MapDrawShape.svg @@ -0,0 +1,9 @@ + + + + + + + + diff --git a/src/MissionEditor/MissionEditor.qml b/src/MissionEditor/MissionEditor.qml index fad97ddc722d1e267fde032476646b9f4671c4d6..9b95774a399c66c1205903e8f5bf8b4fa2a4e52a 100644 --- a/src/MissionEditor/MissionEditor.qml +++ b/src/MissionEditor/MissionEditor.qml @@ -285,6 +285,8 @@ QGCView { anchors.fill: parent mapName: "MissionEditor" + signal mapClicked(var coordinate) + readonly property real animationDuration: 500 // Initial map position duplicates Fly view position @@ -301,15 +303,15 @@ QGCView { anchors.fill: parent onClicked: { + var coordinate = editorMap.toCoordinate(Qt.point(mouse.x, mouse.y)) + coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces) + coordinate.longitude = coordinate.longitude.toFixed(_decimalPlaces) + coordinate.altitude = coordinate.altitude.toFixed(_decimalPlaces) if (addMissionItemsButton.checked) { - var coordinate = editorMap.toCoordinate(Qt.point(mouse.x, mouse.y)) - coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces) - coordinate.longitude = coordinate.longitude.toFixed(_decimalPlaces) - coordinate.altitude = coordinate.altitude.toFixed(_decimalPlaces) - var index = controller.insertMissionItem(coordinate, controller.missionItems.count) + var index = controller.insertSimpleMissionItem(coordinate, controller.missionItems.count) setCurrentItem(index) } else { - editorMap.zoomLevel = editorMap.maxZoomLevel - 2 + editorMap.mapClicked(coordinate) } } } @@ -364,7 +366,7 @@ QGCView { } } - // Add the mission items to the map + // Add the simple mission items to the map MapItemView { model: controller.missionItems delegate: missionItemComponent @@ -421,6 +423,22 @@ QGCView { } } + // Add the complex mission items to the map + MapItemView { + model: controller.complexMissionItems + delegate: polygonItemComponent + } + + Component { + id: polygonItemComponent + + MapPolygon { + color: 'green' + path: object.polygonPath + opacity: 0.5 + } + } + // Add lines between waypoints MissionLineView { model: controller.waypointLines @@ -482,7 +500,7 @@ QGCView { } onInsert: { - controller.insertMissionItem(editorMap.center, i) + controller.insertSimpleMissionItem(editorMap.center, i) setCurrentItem(i) } @@ -522,6 +540,23 @@ QGCView { z: QGroundControl.zOrderWidgets } + RoundButton { + id: addShapeButton + buttonImage: "/qmlimages/MapDrawShape.svg" + z: QGroundControl.zOrderWidgets + visible: QGroundControl.experimentalSurvey + + onClicked: { + var coordinate = editorMap.center + coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces) + coordinate.longitude = coordinate.longitude.toFixed(_decimalPlaces) + coordinate.altitude = coordinate.altitude.toFixed(_decimalPlaces) + var index = controller.insertComplexMissionItem(coordinate, controller.missionItems.count) + setCurrentItem(index) + checked = false + } + } + DropButton { id: syncButton dropDirection: dropRight diff --git a/src/MissionManager/ComplexMissionItem.cc b/src/MissionManager/ComplexMissionItem.cc new file mode 100644 index 0000000000000000000000000000000000000000..f8ae72ca6fd67e597d25094d49aea2f7ee1e30d9 --- /dev/null +++ b/src/MissionManager/ComplexMissionItem.cc @@ -0,0 +1,87 @@ +/*=================================================================== +QGroundControl Open Source Ground Control Station + +(c) 2009, 2010 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 "ComplexMissionItem.h" + +ComplexMissionItem::ComplexMissionItem(Vehicle* vehicle, QObject* parent) + : MissionItem(vehicle, parent) +{ + +} + +ComplexMissionItem::ComplexMissionItem(Vehicle* vehicle, + int sequenceNumber, + MAV_CMD command, + MAV_FRAME frame, + double param1, + double param2, + double param3, + double param4, + double param5, + double param6, + double param7, + bool autoContinue, + bool isCurrentItem, + QObject* parent) + : MissionItem(vehicle, sequenceNumber, command, frame, param1, param2, param3, param4, param5, param6, param7, autoContinue, isCurrentItem, parent) +{ + +} + +ComplexMissionItem::ComplexMissionItem(const ComplexMissionItem& other, QObject* parent) + : MissionItem(other, parent) +{ + +} + +const ComplexMissionItem& ComplexMissionItem::operator=(const ComplexMissionItem& other) +{ + static_cast(*this) = other; + + return *this; +} + +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(); + emit polygonPathChanged(); +} + +void ComplexMissionItem::addPolygonCoordinate(const QGeoCoordinate coordinate) +{ + _polygonPath << QVariant::fromValue(coordinate); + emit polygonPathChanged(); +} diff --git a/src/MissionManager/ComplexMissionItem.h b/src/MissionManager/ComplexMissionItem.h new file mode 100644 index 0000000000000000000000000000000000000000..d0806bd5b654993048bdf9dc8d731b6490f72dfd --- /dev/null +++ b/src/MissionManager/ComplexMissionItem.h @@ -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 . + + ======================================================================*/ + +#ifndef ComplexMissionItem_H +#define ComplexMissionItem_H + +#include "MissionItem.h" + +class ComplexMissionItem : public MissionItem +{ + Q_OBJECT + +public: + ComplexMissionItem(Vehicle* vehicle, QObject* parent = NULL); + + ComplexMissionItem(Vehicle* vehicle, + int sequenceNumber, + MAV_CMD command, + MAV_FRAME frame, + double param1, + double param2, + double param3, + double param4, + double param5, + double param6, + double param7, + bool autoContinue, + bool isCurrentItem, + QObject* parent = NULL); + + ComplexMissionItem(const ComplexMissionItem& other, QObject* parent = NULL); + + const ComplexMissionItem& operator=(const ComplexMissionItem& other); + + Q_PROPERTY(QVariantList polygonPath READ polygonPath NOTIFY polygonPathChanged) + + Q_INVOKABLE void clearPolygon(void); + Q_INVOKABLE void addPolygonCoordinate(const QGeoCoordinate coordinate); + + QVariantList polygonPath(void); + + // Overrides from MissionItem base class + bool simpleItem (void) const final { return false; } + QGeoCoordinate exitCoordinate (void) const final { return coordinate(); } + +signals: + void polygonPathChanged(void); + +private: + QVariantList _polygonPath; +}; + +#endif diff --git a/src/MissionManager/MissionCommands.cc b/src/MissionManager/MissionCommands.cc index 2eef92741f9513cefb3c5284ae26749f4628680c..1ce99e5f6a1c2b2c4d19743fa7cf3ae152912952 100644 --- a/src/MissionManager/MissionCommands.cc +++ b/src/MissionManager/MissionCommands.cc @@ -27,6 +27,8 @@ This file is part of the QGROUNDCONTROL project #include "QGCApplication.h" #include "QGroundControlQmlGlobal.h" +#include + MissionCommands::MissionCommands(QGCApplication* app) : QGCTool(app) , _commonMissionCommands(QStringLiteral(":/json/MavCmdInfoCommon.json")) diff --git a/src/MissionManager/MissionController.cc b/src/MissionManager/MissionController.cc index 69e6b7322d671536a975fd2354bfc72e76a9c947..e7ef1f9f73f22ac34d7405885d6d4c293cd58d61 100644 --- a/src/MissionManager/MissionController.cc +++ b/src/MissionManager/MissionController.cc @@ -27,6 +27,8 @@ This file is part of the QGROUNDCONTROL project #include "CoordinateVector.h" #include "FirmwarePlugin.h" #include "QGCApplication.h" +#include "SimpleMissionItem.h" +#include "ComplexMissionItem.h" #ifndef __mobile__ #include "QGCFileDialog.h" @@ -45,6 +47,7 @@ MissionController::MissionController(QObject *parent) : QObject(parent) , _editMode(false) , _missionItems(NULL) + , _complexMissionItems(NULL) , _activeVehicle(NULL) , _autoSync(false) , _firstItemsFromVehicle(false) @@ -124,9 +127,9 @@ void MissionController::sendMissionItems(void) } } -int MissionController::insertMissionItem(QGeoCoordinate coordinate, int i) +int MissionController::insertSimpleMissionItem(QGeoCoordinate coordinate, int i) { - MissionItem * newItem = new MissionItem(_activeVehicle, this); + MissionItem * newItem = new SimpleMissionItem(_activeVehicle, this); newItem->setSequenceNumber(_missionItems->count()); newItem->setCoordinate(coordinate); newItem->setCommand(MAV_CMD_NAV_WAYPOINT); @@ -152,6 +155,22 @@ int MissionController::insertMissionItem(QGeoCoordinate coordinate, int i) return _missionItems->count() - 1; } +int MissionController::insertComplexMissionItem(QGeoCoordinate coordinate, int i) +{ + ComplexMissionItem * newItem = new ComplexMissionItem(_activeVehicle, this); + newItem->setSequenceNumber(_missionItems->count()); + newItem->setCoordinate(coordinate); + newItem->setCommand(MAV_CMD_NAV_WAYPOINT); + _initMissionItem(newItem); + + _missionItems->insert(i, newItem); + _complexMissionItems->append(newItem); + + _recalcAll(); + + return _missionItems->count() - 1; +} + void MissionController::removeMissionItem(int index) { MissionItem* item = qobject_cast(_missionItems->removeAt(index)); @@ -218,7 +237,7 @@ bool MissionController::_loadJsonMissionFile(const QByteArray& bytes, QmlObjectL return false; } - MissionItem* item = new MissionItem(_activeVehicle, this); + MissionItem* item = new SimpleMissionItem(_activeVehicle, this); if (item->load(itemValue.toObject(), errorString)) { missionItems->append(item); } else { @@ -228,7 +247,7 @@ bool MissionController::_loadJsonMissionFile(const QByteArray& bytes, QmlObjectL } if (json.contains(_jsonPlannedHomePositionKey)) { - MissionItem* item = new MissionItem(_activeVehicle, this); + MissionItem* item = new SimpleMissionItem(_activeVehicle, this); if (item->load(json[_jsonPlannedHomePositionKey].toObject(), errorString)) { missionItems->insert(0, item); @@ -263,7 +282,7 @@ bool MissionController::_loadTextMissionFile(QTextStream& stream, QmlObjectListM if (versionOk) { while (!stream.atEnd()) { - MissionItem* item = new MissionItem(_activeVehicle, this); + MissionItem* item = new SimpleMissionItem(_activeVehicle, this); if (item->load(stream)) { missionItems->append(item); @@ -612,13 +631,24 @@ void MissionController::_initAllMissionItems(void) qDebug() << "home item" << homeItem->coordinate(); + QmlObjectListModel* newComplexItems = new QmlObjectListModel(this); + for (int i=0; i<_missionItems->count(); i++) { - _initMissionItem(qobject_cast(_missionItems->get(i))); + MissionItem* item = qobject_cast(_missionItems->get(i)); + + if (!item->simpleItem()) { + newComplexItems->append(item); + } + _initMissionItem(item); } + delete _complexMissionItems; + _complexMissionItems = newComplexItems; + _recalcAll(); emit missionItemsChanged(); + emit complexMissionItemsChanged(); _missionItems->setDirty(false); @@ -773,6 +803,11 @@ QmlObjectListModel* MissionController::missionItems(void) return _missionItems; } +QmlObjectListModel* MissionController::complexMissionItems(void) +{ + return _complexMissionItems; +} + bool MissionController::_findLastAltitude(double* lastAltitude) { bool found = false; @@ -831,7 +866,7 @@ double MissionController::_normalizeLon(double lon) /// Add the home position item to the front of the list void MissionController::_addPlannedHomePosition(QmlObjectListModel* missionItems, bool addToCenter) { - MissionItem* homeItem = new MissionItem(_activeVehicle, this); + MissionItem* homeItem = new SimpleMissionItem(_activeVehicle, this); missionItems->insert(0, homeItem); if (missionItems->count() > 1 && addToCenter) { diff --git a/src/MissionManager/MissionController.h b/src/MissionManager/MissionController.h index dcee758f76678302852fffd10d7f3b98229d42cf..d6e417035c86521c3118afc0c3c5bdba7829e51a 100644 --- a/src/MissionManager/MissionController.h +++ b/src/MissionManager/MissionController.h @@ -29,6 +29,8 @@ This file is part of the QGROUNDCONTROL project #include "QmlObjectListModel.h" #include "Vehicle.h" #include "QGCLoggingCategory.h" +#include "MavlinkQmlSingleton.h" +#include "MissionItem.h" Q_DECLARE_LOGGING_CATEGORY(MissionControllerLog) @@ -41,6 +43,7 @@ public: ~MissionController(); Q_PROPERTY(QmlObjectListModel* missionItems READ missionItems NOTIFY missionItemsChanged) + Q_PROPERTY(QmlObjectListModel* complexMissionItems READ complexMissionItems NOTIFY complexMissionItemsChanged) Q_PROPERTY(QmlObjectListModel* waypointLines READ waypointLines NOTIFY waypointLinesChanged) Q_PROPERTY(bool autoSync READ autoSync WRITE setAutoSync NOTIFY autoSyncChanged) Q_PROPERTY(bool syncInProgress READ syncInProgress NOTIFY syncInProgressChanged) @@ -57,11 +60,15 @@ public: Q_INVOKABLE QStringList getMobileMissionFiles(void); /// @param i: index to insert at - Q_INVOKABLE int insertMissionItem(QGeoCoordinate coordinate, int i); + Q_INVOKABLE int insertSimpleMissionItem(QGeoCoordinate coordinate, int i); + + /// @param i: index to insert at + Q_INVOKABLE int insertComplexMissionItem(QGeoCoordinate coordinate, int i); // Property accessors QmlObjectListModel* missionItems(void); + QmlObjectListModel* complexMissionItems(void); QmlObjectListModel* waypointLines(void) { return &_waypointLines; } bool autoSync(void) { return _autoSync; } void setAutoSync(bool autoSync); @@ -69,6 +76,7 @@ public: signals: void missionItemsChanged(void); + void complexMissionItemsChanged(void); void waypointLinesChanged(void); void autoSyncChanged(bool autoSync); void newItemsFromVehicle(void); @@ -111,6 +119,7 @@ private: private: bool _editMode; QmlObjectListModel* _missionItems; + QmlObjectListModel* _complexMissionItems; QmlObjectListModel _waypointLines; Vehicle* _activeVehicle; bool _autoSync; diff --git a/src/MissionManager/MissionControllerTest.cc b/src/MissionManager/MissionControllerTest.cc index adf63ffb9a80afa339dc6767f697868a5c1bdc05..8bc2aa198325102e06ab7081af0116e44da01826 100644 --- a/src/MissionManager/MissionControllerTest.cc +++ b/src/MissionManager/MissionControllerTest.cc @@ -137,7 +137,7 @@ void MissionControllerTest::_testAddWaypointWorker(MAV_AUTOPILOT firmwareType) QGeoCoordinate coordinate(37.803784, -122.462276); - _missionController->insertMissionItem(coordinate, _missionController->missionItems()->count()); + _missionController->insertSimpleMissionItem(coordinate, _missionController->missionItems()->count()); QCOMPARE(_multiSpyMissionController->checkOnlySignalsByMask(waypointLinesChangedSignalMask), true); @@ -182,7 +182,7 @@ void MissionControllerTest::_testOfflineToOnlineWorker(MAV_AUTOPILOT firmwareTyp _missionController = new MissionController(); Q_CHECK_PTR(_missionController); _missionController->start(true /* editMode */); - _missionController->insertMissionItem(QGeoCoordinate(37.803784, -122.462276), _missionController->missionItems()->count()); + _missionController->insertSimpleMissionItem(QGeoCoordinate(37.803784, -122.462276), _missionController->missionItems()->count()); // Go online to empty vehicle MissionControllerManagerTest::_initForFirmwareType(firmwareType); diff --git a/src/MissionManager/MissionItem.cc b/src/MissionManager/MissionItem.cc index 76307df1a76278e530771a939869c9879912e60d..22f2bf9457cde4cb7db8919bbd87b41a7a952a04 100644 --- a/src/MissionManager/MissionItem.cc +++ b/src/MissionManager/MissionItem.cc @@ -28,8 +28,6 @@ This file is part of the QGROUNDCONTROL project #include "QGCApplication.h" #include "JsonHelper.h" -QGC_LOGGING_CATEGORY(MissionItemLog, "MissionItemLog") - const double MissionItem::defaultAltitude = 25.0; FactMetaData* MissionItem::_altitudeMetaData = NULL; @@ -71,22 +69,6 @@ static const struct EnumInfo_s _rgMavFrameInfo[] = { { "MAV_FRAME_GLOBAL_TERRAIN_ALT_INT", MAV_FRAME_GLOBAL_TERRAIN_ALT_INT }, }; -QDebug operator<<(QDebug dbg, const MissionItem& missionItem) -{ - QDebugStateSaver saver(dbg); - dbg.nospace() << "MissionItem(" << missionItem.coordinate() << ")"; - - return dbg; -} - -QDebug operator<<(QDebug dbg, const MissionItem* missionItem) -{ - QDebugStateSaver saver(dbg); - dbg.nospace() << "MissionItem(" << missionItem->coordinate() << ")"; - - return dbg; -} - MissionItem::MissionItem(Vehicle* vehicle, QObject* parent) : QObject(parent) , _vehicle(vehicle) diff --git a/src/MissionManager/MissionItem.h b/src/MissionManager/MissionItem.h index bbe999d218019ade6bcc9cc4e0590f88ce741abd..8c87ca5744eb2906d4f74fdd44a00ae51dd8a041 100644 --- a/src/MissionManager/MissionItem.h +++ b/src/MissionManager/MissionItem.h @@ -40,8 +40,7 @@ #include "QmlObjectListModel.h" #include "MissionCommands.h" -Q_DECLARE_LOGGING_CATEGORY(MissionItemLog) - +// Abstract base class for Simple and Complex MissionItem obejcts. class MissionItem : public QObject { Q_OBJECT @@ -77,7 +76,6 @@ public: Q_PROPERTY(MavlinkQmlSingleton::Qml_MAV_CMD command READ command WRITE setCommand NOTIFY commandChanged) Q_PROPERTY(QString commandDescription READ commandDescription NOTIFY commandChanged) Q_PROPERTY(QString commandName READ commandName NOTIFY commandChanged) - Q_PROPERTY(QGeoCoordinate coordinate READ coordinate WRITE setCoordinate NOTIFY coordinateChanged) Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged) Q_PROPERTY(double distance READ distance WRITE setDistance NOTIFY distanceChanged) ///< Distance to previous waypoint Q_PROPERTY(bool friendlyEditAllowed READ friendlyEditAllowed NOTIFY friendlyEditAllowedChanged) @@ -90,6 +88,16 @@ public: Q_PROPERTY(bool specifiesCoordinate READ specifiesCoordinate NOTIFY commandChanged) Q_PROPERTY(bool showHomePosition READ showHomePosition WRITE setShowHomePosition NOTIFY showHomePositionChanged) + // Mission item has two coordinates associated with them: + // coordinate: This is the entry point for a waypoint line into the item. For a simple item it is also the location of the item + // exitCoordinate This is the exit point for a waypoint line coming out of the item. For a SimpleMissionItem this will be the same as + // coordinate. For a ComplexMissionItem it may be different than the entry coordinate. + Q_PROPERTY(QGeoCoordinate coordinate READ coordinate WRITE setCoordinate NOTIFY coordinateChanged) + Q_PROPERTY(QGeoCoordinate exitCoordinate READ exitCoordinate NOTIFY exitCoordinateChanged) + + /// @return true: SimpleMissionItem, false: ComplexMissionItem + Q_PROPERTY(bool simpleItem READ simpleItem NOTIFY simpleItemChanged) + // These properties are used to display the editing ui Q_PROPERTY(QmlObjectListModel* checkboxFacts READ checkboxFacts NOTIFY uiModelChanged) Q_PROPERTY(QmlObjectListModel* comboboxFacts READ comboboxFacts NOTIFY uiModelChanged) @@ -179,6 +187,10 @@ public: static const double defaultAltitude; + // Pure virtuals which must be provides by derived classes + virtual bool simpleItem(void) const = 0; + virtual QGeoCoordinate exitCoordinate(void) const = 0; + public slots: void setDefaultsForCommand(void); @@ -188,6 +200,7 @@ signals: void azimuthChanged (double azimuth); void commandChanged (MavlinkQmlSingleton::Qml_MAV_CMD command); void coordinateChanged (const QGeoCoordinate& coordinate); + void exitCoordinateChanged (const QGeoCoordinate& exitCoordinate); void dirtyChanged (bool dirty); void distanceChanged (double distance); void frameChanged (int frame); @@ -198,6 +211,7 @@ signals: void sequenceNumberChanged (int sequenceNumber); void uiModelChanged (void); void showHomePositionChanged (bool showHomePosition); + void simpleItemChanged (bool simpleItem); private slots: void _setDirtyFromSignal(void); @@ -276,7 +290,4 @@ private: static const char* _jsonCoordinateKey; }; -QDebug operator<<(QDebug dbg, const MissionItem& missionItem); -QDebug operator<<(QDebug dbg, const MissionItem* missionItem); - #endif diff --git a/src/MissionManager/MissionItemTest.cc b/src/MissionManager/MissionItemTest.cc index 74c650d587eb3ca9a99a7a3817aa32fca8cc0269..2c35bbf66226c0ff1752ea2ec5fd399984c65064 100644 --- a/src/MissionManager/MissionItemTest.cc +++ b/src/MissionManager/MissionItemTest.cc @@ -22,7 +22,7 @@ ======================================================================*/ #include "MissionItemTest.h" -#include "MissionItem.h" +#include "SimpleMissionItem.h" const MissionItemTest::ItemInfo_t MissionItemTest::_rgItemInfo[] = { { MAV_CMD_NAV_WAYPOINT, MAV_FRAME_GLOBAL_RELATIVE_ALT }, @@ -184,7 +184,7 @@ void MissionItemTest::_test(void) void MissionItemTest::_testDefaultValues(void) { - MissionItem item(NULL /* Vehicle */); + SimpleMissionItem item(NULL /* Vehicle */); item.setCommand(MAV_CMD_NAV_WAYPOINT); item.setFrame(MAV_FRAME_GLOBAL_RELATIVE_ALT); diff --git a/src/MissionManager/MissionManager.cc b/src/MissionManager/MissionManager.cc index 25616206a6b21fd067cade960c5839e7f8ff0931..14ad0c319493811c1e95906c5cc09ba3b4b70336 100644 --- a/src/MissionManager/MissionManager.cc +++ b/src/MissionManager/MissionManager.cc @@ -29,6 +29,7 @@ #include "FirmwarePlugin.h" #include "MAVLinkProtocol.h" #include "QGCApplication.h" +#include "SimpleMissionItem.h" QGC_LOGGING_CATEGORY(MissionManagerLog, "MissionManagerLog") @@ -64,7 +65,7 @@ void MissionManager::writeMissionItems(const QmlObjectListModel& missionItems) int firstIndex = skipFirstItem ? 1 : 0; for (int i=firstIndex; i(missionItems[i]))); + _missionItems.append(new SimpleMissionItem(*qobject_cast(missionItems[i]))); MissionItem* item = qobject_cast(_missionItems.get(_missionItems.count() - 1)); @@ -252,7 +253,7 @@ void MissionManager::_handleMissionItem(const mavlink_message_t& message) _requestItemRetryCount = 0; _itemIndicesToRead.removeOne(missionItem.seq); - MissionItem* item = new MissionItem(_vehicle, + MissionItem* item = new SimpleMissionItem(_vehicle, missionItem.seq, (MAV_CMD)missionItem.command, (MAV_FRAME)missionItem.frame, @@ -432,7 +433,7 @@ QmlObjectListModel* MissionManager::copyMissionItems(void) QmlObjectListModel* list = new QmlObjectListModel(); for (int i=0; i<_missionItems.count(); i++) { - list->append(new MissionItem(*qobject_cast(_missionItems[i]))); + list->append(new SimpleMissionItem(*qobject_cast(_missionItems[i]))); } return list; diff --git a/src/MissionManager/MissionManagerTest.cc b/src/MissionManager/MissionManagerTest.cc index 0a18fa0ac294c761e475230b1634f0fe01b94f97..c8e32f3c60b091d37b34c57d8bd96b0f14157412 100644 --- a/src/MissionManager/MissionManagerTest.cc +++ b/src/MissionManager/MissionManagerTest.cc @@ -24,6 +24,7 @@ #include "MissionManagerTest.h" #include "LinkManager.h" #include "MultiVehicleManager.h" +#include "SimpleMissionItem.h" const MissionManagerTest::TestCase_t MissionManagerTest::_rgTestCases[] = { { "0\t0\t3\t16\t10\t20\t30\t40\t-10\t-20\t-30\t1\r\n", { 0, QGeoCoordinate(-10.0, -20.0, -30.0), MAV_CMD_NAV_WAYPOINT, 10.0, 20.0, 30.0, 40.0, true, false, MAV_FRAME_GLOBAL_RELATIVE_ALT } }, @@ -48,7 +49,7 @@ void MissionManagerTest::_writeItems(MockLinkMissionItemHandler::FailureMode_t f QmlObjectListModel* list = new QmlObjectListModel(); // Editor has a home position item on the front, so we do the same - MissionItem* homeItem = new MissionItem(NULL /* Vehicle */, this); + SimpleMissionItem* homeItem = new SimpleMissionItem(NULL /* Vehicle */, this); homeItem->setHomePositionSpecialCase(true); homeItem->setCommand(MavlinkQmlSingleton::MAV_CMD_NAV_WAYPOINT); homeItem->setCoordinate(QGeoCoordinate(47.3769, 8.549444, 0)); @@ -58,7 +59,7 @@ void MissionManagerTest::_writeItems(MockLinkMissionItemHandler::FailureMode_t f for (size_t i=0; i<_cTestCases; i++) { const TestCase_t* testCase = &_rgTestCases[i]; - MissionItem* item = new MissionItem(NULL /* Vehicle */, list); + SimpleMissionItem* item = new SimpleMissionItem(NULL /* Vehicle */, list); QTextStream loadStream(testCase->itemStream, QIODevice::ReadOnly); QVERIFY(item->load(loadStream)); diff --git a/src/MissionManager/SimpleMissionItem.cc b/src/MissionManager/SimpleMissionItem.cc new file mode 100644 index 0000000000000000000000000000000000000000..75f389426a773ff8309323b0204d1078ea63868f --- /dev/null +++ b/src/MissionManager/SimpleMissionItem.cc @@ -0,0 +1,61 @@ +/*=================================================================== +QGroundControl Open Source Ground Control Station + +(c) 2009, 2010 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 "SimpleMissionItem.h" + +SimpleMissionItem::SimpleMissionItem(Vehicle* vehicle, QObject* parent) + : MissionItem(vehicle, parent) +{ + +} + +SimpleMissionItem::SimpleMissionItem(Vehicle* vehicle, + int sequenceNumber, + MAV_CMD command, + MAV_FRAME frame, + double param1, + double param2, + double param3, + double param4, + double param5, + double param6, + double param7, + bool autoContinue, + bool isCurrentItem, + QObject* parent) + : MissionItem(vehicle, sequenceNumber, command, frame, param1, param2, param3, param4, param5, param6, param7, autoContinue, isCurrentItem, parent) +{ + +} + +SimpleMissionItem::SimpleMissionItem(const SimpleMissionItem& other, QObject* parent) + : MissionItem(other, parent) +{ + +} + +const SimpleMissionItem& SimpleMissionItem::operator=(const SimpleMissionItem& other) +{ + static_cast(*this) = other; + + return *this; +} diff --git a/src/MissionManager/SimpleMissionItem.h b/src/MissionManager/SimpleMissionItem.h new file mode 100644 index 0000000000000000000000000000000000000000..1a7097e667f3bc194380ca1bb4bcdee8c59e437e --- /dev/null +++ b/src/MissionManager/SimpleMissionItem.h @@ -0,0 +1,62 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009 - 2014 QGROUNDCONTROL PROJECT + + This file is part of the QGROUNDCONTROL project + + QGROUNDCONTROL is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + QGROUNDCONTROL is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QGROUNDCONTROL. If not, see . + + ======================================================================*/ + +#ifndef SimpleMissionItem_H +#define SimpleMissionItem_H + +#include "MissionItem.h" + +class SimpleMissionItem : public MissionItem +{ + Q_OBJECT + +public: + SimpleMissionItem(Vehicle* vehicle, QObject* parent = NULL); + + SimpleMissionItem(Vehicle* vehicle, + int sequenceNumber, + MAV_CMD command, + MAV_FRAME frame, + double param1, + double param2, + double param3, + double param4, + double param5, + double param6, + double param7, + bool autoContinue, + bool isCurrentItem, + QObject* parent = NULL); + + SimpleMissionItem(const SimpleMissionItem& other, QObject* parent = NULL); + + const SimpleMissionItem& operator=(const SimpleMissionItem& other); + + // Overrides from MissionItem base class + bool simpleItem (void) const final { return true; } + QGeoCoordinate exitCoordinate (void) const final { return coordinate(); } + +private: +}; + +#endif diff --git a/src/QGCLoggingCategory.cc b/src/QGCLoggingCategory.cc index e5f94130281090739237f15c97cedb5c2ede86cc..f053d13c776f514019512d73b8e04416fd39e530 100644 --- a/src/QGCLoggingCategory.cc +++ b/src/QGCLoggingCategory.cc @@ -30,7 +30,7 @@ QGC_LOGGING_CATEGORY(FirmwareUpgradeLog, "FirmwareUpgradeLog") QGC_LOGGING_CATEGORY(FirmwareUpgradeVerboseLog, "FirmwareUpgradeVerboseLog") QGC_LOGGING_CATEGORY(MissionCommandsLog, "MissionCommandsLog") - +QGC_LOGGING_CATEGORY(MissionItemLog, "MissionItemLog") QGCLoggingCategoryRegister* _instance = NULL; diff --git a/src/QGCLoggingCategory.h b/src/QGCLoggingCategory.h index 6dc19b4cf18f4da2bad5e94a0320554acf9a2402..4989b2aa2918671d9e32ac9d8621435f50c78662 100644 --- a/src/QGCLoggingCategory.h +++ b/src/QGCLoggingCategory.h @@ -34,6 +34,7 @@ Q_DECLARE_LOGGING_CATEGORY(FirmwareUpgradeLog) Q_DECLARE_LOGGING_CATEGORY(FirmwareUpgradeVerboseLog) Q_DECLARE_LOGGING_CATEGORY(MissionCommandsLog) +Q_DECLARE_LOGGING_CATEGORY(MissionItemLog) /// @def QGC_LOGGING_CATEGORY /// This is a QGC specific replacement for Q_LOGGING_CATEGORY. It will register the category name into a diff --git a/src/QmlControls/MissionItemEditor.qml b/src/QmlControls/MissionItemEditor.qml index 074b52c1451b87ca8eff700eb25a77999d7c7867..9713a13f2716aa34ee13dee240c1ad00f3c6296b 100644 --- a/src/QmlControls/MissionItemEditor.qml +++ b/src/QmlControls/MissionItemEditor.qml @@ -14,6 +14,10 @@ import QGroundControl.Palette 1.0 Rectangle { id: _root + height: editorLoader.y + editorLoader.height + (_margin * 2) + color: missionItem.isCurrentItem ? qgcPal.buttonHighlight : qgcPal.windowShade + radius: _radius + property var missionItem ///< MissionItem associated with this editor property bool readOnly ///< true: read only view, false: full editing view property var qgcView ///< QGCView control used for showing dialogs @@ -23,21 +27,127 @@ Rectangle { signal insert(int i) signal moveHomeToMapCenter - height: innerItem.height + (_margin * 3) - color: missionItem.isCurrentItem ? qgcPal.buttonHighlight : qgcPal.windowShade - radius: _radius - - readonly property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 16 - readonly property real _margin: ScreenTools.defaultFontPixelWidth / 2 - readonly property real _radius: ScreenTools.defaultFontPixelWidth / 2 + readonly property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 16 + readonly property real _margin: ScreenTools.defaultFontPixelWidth / 2 + readonly property real _radius: ScreenTools.defaultFontPixelWidth / 2 + property color _outerTextColor: missionItem.isCurrentItem ? "black" : qgcPal.text - property bool _showValues: missionItem.isCurrentItem QGCPalette { id: qgcPal colorGroupEnabled: enabled } + + MouseArea { + anchors.fill: parent + visible: !missionItem.isCurrentItem + onClicked: _root.clicked() + } + + QGCLabel { + id: label + anchors.verticalCenter: commandPicker.verticalCenter + anchors.leftMargin: _margin + anchors.left: parent.left + text: missionItem.sequenceNumber == 0 ? "H" : missionItem.sequenceNumber + color: _outerTextColor + } + + Image { + id: hamburger + anchors.rightMargin: ScreenTools.defaultFontPixelWidth + anchors.right: parent.right + anchors.verticalCenter: commandPicker.verticalCenter + width: commandPicker.height + height: commandPicker.height + source: "qrc:/qmlimages/Hamburger.svg" + visible: missionItem.isCurrentItem && missionItem.sequenceNumber != 0 + + MouseArea { + anchors.fill: parent + onClicked: hamburgerMenu.popup() + + Menu { + id: hamburgerMenu + + MenuItem { + text: "Insert" + onTriggered: insert(missionItem.sequenceNumber) + } + + MenuItem { + text: "Delete" + onTriggered: remove() + } + + MenuSeparator { + visible: !missionItem.simpleItem + } + + MenuItem { + text: "Show all values" + checkable: true + checked: missionItem.rawEdit + visible: !missionItem.simpleItem + + onTriggered: { + if (missionItem.rawEdit) { + if (missionItem.friendlyEditAllowed) { + missionItem.rawEdit = false + } else { + qgcView.showMessage("Mission Edit", "You have made changes to the mission item which cannot be shown in Simple Mode", StandardButton.Ok) + } + } else { + missionItem.rawEdit = true + } + checked = missionItem.rawEdit + } + } + } + } + } + + QGCButton { + id: commandPicker + anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2 + anchors.rightMargin: ScreenTools.defaultFontPixelWidth + anchors.left: label.right + anchors.right: hamburger.left + visible: missionItem.sequenceNumber != 0 && missionItem.isCurrentItem && !missionItem.rawEdit && missionItem.simpleItem + text: missionItem.commandName + + Component { + id: commandDialog + + MissionCommandDialog { + missionItem: _root.missionItem + } + } + + onClicked: qgcView.showDialog(commandDialog, "Select Mission Command", qgcView.showDialogDefaultWidth, StandardButton.Cancel) + } + + QGCLabel { + anchors.fill: commandPicker + visible: missionItem.sequenceNumber == 0 || !missionItem.isCurrentItem || !missionItem.simpleItem + verticalAlignment: Text.AlignVCenter + text: missionItem.sequenceNumber == 0 ? "Home Position" : (missionItem.simpleItem ? missionItem.commandName : "Survey") + color: _outerTextColor + } + + Loader { + id: editorLoader + anchors.leftMargin: _margin + anchors.topMargin: _margin + anchors.left: parent.left + anchors.top: commandPicker.bottom + sourceComponent: missionItem.simpleItem ? simpleMissionItemEditor : complexMissionItemEditor + + /// How wide the loaded component should be + property real availableWidth: _root.width - (_margin * 2) + } + Component { id: valuesComponent @@ -54,7 +164,7 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top - height: valuesColumn.height + _margin + height: valuesColumn.height + (_margin * 2) Column { id: valuesColumn @@ -69,8 +179,8 @@ Rectangle { text: missionItem.sequenceNumber == 0 ? "Planned home position." : (missionItem.rawEdit ? - "Provides advanced access to all commands/parameters. Be very careful!" : - missionItem.commandDescription) + "Provides advanced access to all commands/parameters. Be very careful!" : + missionItem.commandDescription) } Repeater { @@ -150,114 +260,73 @@ Rectangle { } - Item { - id: innerItem - anchors.margins: _margin - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - height: _showValues ? valuesLoader.y + valuesLoader.height : valuesLoader.y + Component { + id: simpleMissionItemEditor - MouseArea { - anchors.fill: parent - visible: !missionItem.isCurrentItem + Item { + id: innerItem + width: availableWidth + height: _showValues ? valuesLoader.y + valuesLoader.height : valuesLoader.y - onClicked: _root.clicked() - } + property bool _showValues: missionItem.isCurrentItem - QGCLabel { - id: label - anchors.verticalCenter: commandPicker.verticalCenter - color: missionItem.isCurrentItem ? qgcPal.buttonHighlightText : qgcPal.buttonText - text: missionItem.sequenceNumber == 0 ? "H" : missionItem.sequenceNumber - } + Loader { + id: valuesLoader + anchors.left: parent.left + anchors.right: parent.right + sourceComponent: _showValues ? valuesComponent : undefined + } + } // Item + } // Component - simpleMissionItemEditor - Image { - id: hamburger - anchors.rightMargin: ScreenTools.defaultFontPixelWidth - anchors.right: parent.right - anchors.verticalCenter: commandPicker.verticalCenter - width: commandPicker.height - height: commandPicker.height - source: "qrc:/qmlimages/Hamburger.svg" - visible: missionItem.isCurrentItem && missionItem.sequenceNumber != 0 - - MouseArea { - anchors.fill: parent - onClicked: hamburgerMenu.popup() - - Menu { - id: hamburgerMenu - - MenuItem { - text: "Insert" - onTriggered: insert(missionItem.sequenceNumber) - } + Component { + id: complexMissionItemEditor - MenuItem { - text: "Delete" - onTriggered: remove() - } + Rectangle { + id: outerRect + height: editorColumn.height + (_margin * 2) + width: availableWidth + color: qgcPal.windowShadeDark + radius: _radius - MenuSeparator { } + property bool addPointsMode: false - MenuItem { - text: "Show all values" - checkable: true - checked: missionItem.rawEdit + Column { + id: editorColumn + anchors.margins: _margin + anchors.top: parent.top + anchors.left: parent.left + width: availableWidth + spacing: _margin - onTriggered: { - if (missionItem.rawEdit) { - if (missionItem.friendlyEditAllowed) { - missionItem.rawEdit = false - } else { - qgcView.showMessage("Mission Edit", "You have made changes to the mission item which cannot be shown in Simple Mode", StandardButton.Ok) - } - } else { - missionItem.rawEdit = true - } - checked = missionItem.rawEdit + Connections { + target: editorMap + + onMapClicked: { + if (addPointsMode) { + missionItem.addPolygonCoordinate(coordinate) } } } - } - } - - QGCButton { - id: commandPicker - anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2 - anchors.rightMargin: ScreenTools.defaultFontPixelWidth - anchors.left: label.right - anchors.right: hamburger.left - visible: missionItem.sequenceNumber != 0 && missionItem.isCurrentItem && !missionItem.rawEdit - text: missionItem.commandName - Component { - id: commandDialog + QGCLabel { + text: "Fly a grid pattern over a defined area." + wrapMode: Text.WordWrap + } - MissionCommandDialog { - missionItem: _root.missionItem + QGCButton { + text: addPointsMode ? "Finished" : "Draw Polygon" + onClicked: { + if (addPointsMode) { + addPointsMode = false + } else { + missionItem.clearPolygon() + addPointsMode = true + } + } } } - - onClicked: qgcView.showDialog(commandDialog, "Select Mission Command", qgcView.showDialogDefaultWidth, StandardButton.Cancel) - } - - QGCLabel { - anchors.fill: commandPicker - visible: missionItem.sequenceNumber == 0 || !missionItem.isCurrentItem - verticalAlignment: Text.AlignVCenter - text: missionItem.sequenceNumber == 0 ? "Home Position" : missionItem.commandName - color: qgcPal.buttonText } + } // Component - complexMissionItemEditor - Loader { - id: valuesLoader - anchors.topMargin: _margin - anchors.top: commandPicker.bottom - anchors.left: parent.left - anchors.right: parent.right - sourceComponent: _showValues ? valuesComponent : undefined - } - } // Item } // Rectangle diff --git a/src/QmlControls/QGroundControlQmlGlobal.cc b/src/QmlControls/QGroundControlQmlGlobal.cc index 1cc5f77348409456b542e80601d2398302d45eca..37cd834e8d30ef9bc3f7c18321acaadecfa668fa 100644 --- a/src/QmlControls/QGroundControlQmlGlobal.cc +++ b/src/QmlControls/QGroundControlQmlGlobal.cc @@ -206,3 +206,18 @@ void QGroundControlQmlGlobal::setVirtualTabletJoystick(bool enabled) emit virtualTabletJoystickChanged(enabled); } } + +bool QGroundControlQmlGlobal::experimentalSurvey(void) const +{ + QSettings settings; + + return settings.value("ExperimentalSurvey", false).toBool(); +} + +void QGroundControlQmlGlobal::setExperimentalSurvey(bool experimentalSurvey) +{ + QSettings settings; + + settings.setValue("ExperimentalSurvey", experimentalSurvey); + emit experimentalSurveyChanged(experimentalSurvey); +} diff --git a/src/QmlControls/QGroundControlQmlGlobal.h b/src/QmlControls/QGroundControlQmlGlobal.h index 0970cfa4e4e2ea37eeb8eaf94cf5e15926c85101..beae9422e7fcb4271f9350c93c6156086f716f02 100644 --- a/src/QmlControls/QGroundControlQmlGlobal.h +++ b/src/QmlControls/QGroundControlQmlGlobal.h @@ -79,6 +79,9 @@ public: Q_PROPERTY(QGeoCoordinate lastKnownHomePosition READ lastKnownHomePosition CONSTANT) Q_PROPERTY(QGeoCoordinate flightMapPosition MEMBER _flightMapPosition NOTIFY flightMapPositionChanged) + /// @ return: true: experimental survey ip code is turned on + Q_PROPERTY(bool experimentalSurvey READ experimentalSurvey WRITE setExperimentalSurvey NOTIFY experimentalSurveyChanged) + 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); @@ -133,6 +136,9 @@ public: void setIsVersionCheckEnabled (bool enable); void setMavlinkSystemID (int id); + bool experimentalSurvey(void) const; + void setExperimentalSurvey(bool experimentalSurvey); + // Overrides from QGCTool virtual void setToolbox(QGCToolbox* toolbox); @@ -146,6 +152,7 @@ signals: void isVersionCheckEnabledChanged (bool enabled); void mavlinkSystemIDChanged (int id); void flightMapPositionChanged (QGeoCoordinate flightMapPosition); + void experimentalSurveyChanged (bool experimentalSurvey); private: FlightMapSettings* _flightMapSettings; diff --git a/src/main.cc b/src/main.cc index 95bd955d5369521000eed26dfcfbf11578e40c60..7fc13a7fb88dc703580ca51b26cc87f27c394241 100644 --- a/src/main.cc +++ b/src/main.cc @@ -32,6 +32,8 @@ This file is part of the QGROUNDCONTROL project #include #include #include +#include +#include #include "QGCApplication.h" diff --git a/src/ui/preferences/GeneralSettings.qml b/src/ui/preferences/GeneralSettings.qml index 450f4d4f0d088310720cc9bb3ba11dfd32c0eaaf..b51908d115d1142f0e02d24eb61303f60fc9ced4 100644 --- a/src/ui/preferences/GeneralSettings.qml +++ b/src/ui/preferences/GeneralSettings.qml @@ -242,6 +242,8 @@ Rectangle { width: parent.width } + //----------------------------------------------------------------- + //-- Offline mission editing settings Row { spacing: ScreenTools.defaultFontPixelWidth @@ -257,6 +259,19 @@ Rectangle { indexModel: false } } + + Item { + height: ScreenTools.defaultFontPixelHeight / 2 + width: parent.width + } + + //----------------------------------------------------------------- + //-- Experimental Survey settings + QGCCheckBox { + text: "Experimental Survey [WIP - no bugs reports please]" + checked: QGroundControl.experimentalSurvey + onClicked: QGroundControl.experimentalSurvey = checked + } } } }