From e6f439f47dcaabfbced52354be8a57ab80fbbf36 Mon Sep 17 00:00:00 2001 From: DonLakeFlyer Date: Tue, 8 Oct 2019 10:50:17 -0700 Subject: [PATCH] Wizard Mode for Create Plan --- src/MissionManager/CorridorScanPlanCreator.cc | 18 +- src/MissionManager/CustomPlanCreator.cc | 17 +- .../FixedWingLandingComplexItem.cc | 13 +- .../FixedWingLandingComplexItem.h | 36 +- src/MissionManager/MissionController.cc | 54 ++- src/MissionManager/MissionController.h | 33 +- src/MissionManager/SimpleMissionItem.cc | 7 + src/MissionManager/SimpleMissionItem.h | 3 +- .../StructureScanComplexItem.cc | 4 +- .../StructureScanPlanCreator.cc | 17 +- src/MissionManager/SurveyPlanCreator.cc | 18 +- .../TransectStyleComplexItem.cc | 6 +- src/MissionManager/VisualMissionItem.cc | 9 + src/MissionManager/VisualMissionItem.h | 30 +- src/PlanView/CorridorScanEditor.qml | 15 +- src/PlanView/FWLandingPatternEditor.qml | 81 ++-- src/PlanView/FWLandingPatternMapVisual.qml | 18 +- src/PlanView/MissionItemEditor.qml | 1 + src/PlanView/PlanView.qml | 25 +- src/PlanView/SimpleItemEditor.qml | 360 ++++++++++-------- src/PlanView/StructureScanEditor.qml | 15 +- src/PlanView/SurveyItemEditor.qml | 15 +- 22 files changed, 493 insertions(+), 302 deletions(-) diff --git a/src/MissionManager/CorridorScanPlanCreator.cc b/src/MissionManager/CorridorScanPlanCreator.cc index 5f361861a..c52ba0793 100644 --- a/src/MissionManager/CorridorScanPlanCreator.cc +++ b/src/MissionManager/CorridorScanPlanCreator.cc @@ -10,6 +10,7 @@ #include "CorridorScanPlanCreator.h" #include "PlanMasterController.h" #include "MissionSettingsItem.h" +#include "FixedWingLandingComplexItem.h" CorridorScanPlanCreator::CorridorScanPlanCreator(PlanMasterController* planMasterController, QObject* parent) : PlanCreator(planMasterController, MissionController::patternCorridorScanName, QStringLiteral("/qmlimages/PlanCreator/CorridorScanPlanCreator.png"), parent) @@ -20,19 +21,16 @@ CorridorScanPlanCreator::CorridorScanPlanCreator(PlanMasterController* planMaste void CorridorScanPlanCreator::createPlan(const QGeoCoordinate& mapCenterCoord) { _planMasterController->removeAll(); - int seqNum = _missionController->insertComplexMissionItem( - MissionController::patternCorridorScanName, - mapCenterCoord, - _missionController->visualItems()->count()); + VisualMissionItem* takeoffItem = _missionController->insertSimpleMissionItem(mapCenterCoord, -1); + takeoffItem->setWizardMode(true); + _missionController->insertComplexMissionItem(MissionController::patternCorridorScanName, mapCenterCoord, -1)->setWizardMode(true); if (_planMasterController->managerVehicle()->fixedWing()) { - _missionController->insertComplexMissionItem( - MissionController::patternFWLandingName, - mapCenterCoord, - _missionController->visualItems()->count()); + FixedWingLandingComplexItem* landingItem = qobject_cast(_missionController->insertComplexMissionItem(MissionController::patternFWLandingName, mapCenterCoord, -1)); + landingItem->setWizardMode(true); + landingItem->setLoiterDragAngleOnly(true); } else { MissionSettingsItem* settingsItem = _missionController->visualItems()->value(0); settingsItem->setMissionEndRTL(true); } - _missionController->setCurrentPlanViewIndex(seqNum, false); - + _missionController->setCurrentPlanViewIndex(takeoffItem->sequenceNumber(), true); } diff --git a/src/MissionManager/CustomPlanCreator.cc b/src/MissionManager/CustomPlanCreator.cc index 08626ffb6..9d9051720 100644 --- a/src/MissionManager/CustomPlanCreator.cc +++ b/src/MissionManager/CustomPlanCreator.cc @@ -10,6 +10,7 @@ #include "CustomPlanCreator.h" #include "PlanMasterController.h" #include "MissionSettingsItem.h" +#include "FixedWingLandingComplexItem.h" CustomPlanCreator::CustomPlanCreator(PlanMasterController* planMasterController, QObject* parent) : PlanCreator(planMasterController, tr("Custom"), QStringLiteral("/qmlimages/PlanCreator/CustomPlanCreator.png"), parent) @@ -20,18 +21,18 @@ CustomPlanCreator::CustomPlanCreator(PlanMasterController* planMasterController, void CustomPlanCreator::createPlan(const QGeoCoordinate& mapCenterCoord) { _planMasterController->removeAll(); - int seqNum = _missionController->insertSimpleMissionItem(mapCenterCoord, _missionController->visualItems()->count()); - _missionController->insertSimpleMissionItem(mapCenterCoord.atDistanceAndAzimuth(50, 135), _missionController->visualItems()->count()); - _missionController->insertSimpleMissionItem(mapCenterCoord.atDistanceAndAzimuth(50, -135), _missionController->visualItems()->count()); + VisualMissionItem* takeoffItem = _missionController->insertSimpleMissionItem(mapCenterCoord, -1); + takeoffItem->setWizardMode(true); + _missionController->insertSimpleMissionItem(mapCenterCoord.atDistanceAndAzimuth(50, 135), -1)->setWizardMode(true); + _missionController->insertSimpleMissionItem(mapCenterCoord.atDistanceAndAzimuth(50, -135),-1)->setWizardMode(true); if (_planMasterController->managerVehicle()->fixedWing()) { - _missionController->insertComplexMissionItem( - MissionController::patternFWLandingName, - mapCenterCoord, - _missionController->visualItems()->count()); + FixedWingLandingComplexItem* landingItem = qobject_cast(_missionController->insertComplexMissionItem(MissionController::patternFWLandingName, mapCenterCoord, -1)); + landingItem->setWizardMode(true); + landingItem->setLoiterDragAngleOnly(true); } else { MissionSettingsItem* settingsItem = _missionController->visualItems()->value(0); settingsItem->setMissionEndRTL(true); } - _missionController->setCurrentPlanViewIndex(seqNum, false); + _missionController->setCurrentPlanViewIndex(takeoffItem->sequenceNumber(), true); } diff --git a/src/MissionManager/FixedWingLandingComplexItem.cc b/src/MissionManager/FixedWingLandingComplexItem.cc index 9e7a8390e..e9f9f1704 100644 --- a/src/MissionManager/FixedWingLandingComplexItem.cc +++ b/src/MissionManager/FixedWingLandingComplexItem.cc @@ -51,6 +51,7 @@ FixedWingLandingComplexItem::FixedWingLandingComplexItem(Vehicle* vehicle, bool , _dirty (false) , _landingCoordSet (false) , _ignoreRecalcSignals (false) + , _loiterDragAngleOnly (false) , _metaDataMap (FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/FWLandingPattern.FactMetaData.json"), this)) , _landingDistanceFact (settingsGroup, _metaDataMap[loiterToLandDistanceName]) , _loiterAltitudeFact (settingsGroup, _metaDataMap[loiterAltitudeName]) @@ -101,6 +102,8 @@ FixedWingLandingComplexItem::FixedWingLandingComplexItem(Vehicle* vehicle, bool connect(this, &FixedWingLandingComplexItem::altitudesAreRelativeChanged, this, &FixedWingLandingComplexItem::exitCoordinateHasRelativeAltitudeChanged); connect(this, &FixedWingLandingComplexItem::landingCoordSetChanged, this, &FixedWingLandingComplexItem::readyForSaveStateChanged); + connect(this, &FixedWingLandingComplexItem::wizardModeChanged, this, &FixedWingLandingComplexItem::readyForSaveStateChanged); + if (vehicle->apmFirmware()) { // ArduPilot does not support camera commands _stopTakingVideoFact.setRawValue(false); @@ -712,5 +715,13 @@ void FixedWingLandingComplexItem::_signalLastSequenceNumberChanged(void) FixedWingLandingComplexItem::ReadyForSaveState FixedWingLandingComplexItem::readyForSaveState(void) const { - return _landingCoordSet ? ReadyForSave : NotReadyForSaveData; + return _landingCoordSet && !_wizardMode ? ReadyForSave : NotReadyForSaveData; +} + +void FixedWingLandingComplexItem::setLoiterDragAngleOnly(bool loiterDragAngleOnly) +{ + if (loiterDragAngleOnly != _loiterDragAngleOnly) { + _loiterDragAngleOnly = loiterDragAngleOnly; + emit loiterDragAngleOnlyChanged(_loiterDragAngleOnly); + } } diff --git a/src/MissionManager/FixedWingLandingComplexItem.h b/src/MissionManager/FixedWingLandingComplexItem.h index f79b92d3f..0f9354d34 100644 --- a/src/MissionManager/FixedWingLandingComplexItem.h +++ b/src/MissionManager/FixedWingLandingComplexItem.h @@ -26,21 +26,22 @@ class FixedWingLandingComplexItem : public ComplexMissionItem public: FixedWingLandingComplexItem(Vehicle* vehicle, bool flyView, QObject* parent); - Q_PROPERTY(Fact* loiterAltitude READ loiterAltitude CONSTANT) - Q_PROPERTY(Fact* loiterRadius READ loiterRadius CONSTANT) - Q_PROPERTY(Fact* landingAltitude READ landingAltitude CONSTANT) - Q_PROPERTY(Fact* landingHeading READ landingHeading CONSTANT) - Q_PROPERTY(Fact* valueSetIsDistance READ valueSetIsDistance CONSTANT) - Q_PROPERTY(Fact* landingDistance READ landingDistance CONSTANT) - Q_PROPERTY(Fact* glideSlope READ glideSlope CONSTANT) - Q_PROPERTY(bool loiterClockwise MEMBER _loiterClockwise NOTIFY loiterClockwiseChanged) - Q_PROPERTY(bool altitudesAreRelative MEMBER _altitudesAreRelative NOTIFY altitudesAreRelativeChanged) - Q_PROPERTY(Fact* stopTakingPhotos READ stopTakingPhotos CONSTANT) - Q_PROPERTY(Fact* stopTakingVideo READ stopTakingVideo CONSTANT) - Q_PROPERTY(QGeoCoordinate loiterCoordinate READ loiterCoordinate WRITE setLoiterCoordinate NOTIFY loiterCoordinateChanged) - Q_PROPERTY(QGeoCoordinate loiterTangentCoordinate READ loiterTangentCoordinate NOTIFY loiterTangentCoordinateChanged) - Q_PROPERTY(QGeoCoordinate landingCoordinate READ landingCoordinate WRITE setLandingCoordinate NOTIFY landingCoordinateChanged) - Q_PROPERTY(bool landingCoordSet MEMBER _landingCoordSet NOTIFY landingCoordSetChanged) + Q_PROPERTY(Fact* loiterAltitude READ loiterAltitude CONSTANT) + Q_PROPERTY(Fact* loiterRadius READ loiterRadius CONSTANT) + Q_PROPERTY(Fact* landingAltitude READ landingAltitude CONSTANT) + Q_PROPERTY(Fact* landingHeading READ landingHeading CONSTANT) + Q_PROPERTY(Fact* valueSetIsDistance READ valueSetIsDistance CONSTANT) + Q_PROPERTY(Fact* landingDistance READ landingDistance CONSTANT) + Q_PROPERTY(Fact* glideSlope READ glideSlope CONSTANT) + Q_PROPERTY(bool loiterClockwise MEMBER _loiterClockwise NOTIFY loiterClockwiseChanged) + Q_PROPERTY(bool altitudesAreRelative MEMBER _altitudesAreRelative NOTIFY altitudesAreRelativeChanged) + Q_PROPERTY(Fact* stopTakingPhotos READ stopTakingPhotos CONSTANT) + Q_PROPERTY(Fact* stopTakingVideo READ stopTakingVideo CONSTANT) + Q_PROPERTY(QGeoCoordinate loiterCoordinate READ loiterCoordinate WRITE setLoiterCoordinate NOTIFY loiterCoordinateChanged) + Q_PROPERTY(QGeoCoordinate loiterTangentCoordinate READ loiterTangentCoordinate NOTIFY loiterTangentCoordinateChanged) + Q_PROPERTY(QGeoCoordinate landingCoordinate READ landingCoordinate WRITE setLandingCoordinate NOTIFY landingCoordinateChanged) + Q_PROPERTY(bool landingCoordSet MEMBER _landingCoordSet NOTIFY landingCoordSetChanged) + Q_PROPERTY(bool loiterDragAngleOnly READ loiterDragAngleOnly WRITE setLoiterDragAngleOnly NOTIFY loiterDragAngleOnlyChanged) Fact* loiterAltitude (void) { return &_loiterAltitudeFact; } Fact* loiterRadius (void) { return &_loiterRadiusFact; } @@ -54,9 +55,11 @@ public: QGeoCoordinate landingCoordinate (void) const { return _landingCoordinate; } QGeoCoordinate loiterCoordinate (void) const { return _loiterCoordinate; } QGeoCoordinate loiterTangentCoordinate (void) const { return _loiterTangentCoordinate; } + bool loiterDragAngleOnly (void) const { return _loiterDragAngleOnly; } void setLandingCoordinate (const QGeoCoordinate& coordinate); void setLoiterCoordinate (const QGeoCoordinate& coordinate); + void setLoiterDragAngleOnly (bool loiterDragAngleOnly); /// Scans the loaded items for a landing pattern complex item static bool scanForItem(QmlObjectListModel* visualItems, bool flyView, Vehicle* vehicle); @@ -66,7 +69,6 @@ public: static MissionItem* createLandItem (int seqNum, bool altRel, double lat, double lon, double alt, QObject* parent); // Overrides from ComplexMissionItem - double complexDistance (void) const final; int lastSequenceNumber (void) const final; bool load (const QJsonObject& complexObject, int sequenceNumber, QString& errorString) final; @@ -123,6 +125,7 @@ signals: void loiterClockwiseChanged (bool loiterClockwise); void altitudesAreRelativeChanged (bool altitudesAreRelative); void valueSetIsDistanceChanged (bool valueSetIsDistance); + void loiterDragAngleOnlyChanged (bool loiterDragAngleOnly); private slots: void _recalcFromHeadingAndDistanceChange (void); @@ -147,6 +150,7 @@ private: QGeoCoordinate _landingCoordinate; bool _landingCoordSet; bool _ignoreRecalcSignals; + bool _loiterDragAngleOnly; QMap _metaDataMap; diff --git a/src/MissionManager/MissionController.cc b/src/MissionManager/MissionController.cc index e21df318b..f22eda98c 100644 --- a/src/MissionManager/MissionController.cc +++ b/src/MissionManager/MissionController.cc @@ -349,7 +349,7 @@ int MissionController::_nextSequenceNumber(void) } } -int MissionController::insertSimpleMissionItem(QGeoCoordinate coordinate, int visualItemIndex) +VisualMissionItem* MissionController::insertSimpleMissionItem(QGeoCoordinate coordinate, int visualItemIndex, bool makeCurrentItem) { int sequenceNumber = _nextSequenceNumber(); SimpleMissionItem * newItem = new SimpleMissionItem(_controllerVehicle, _flyView, this); @@ -373,15 +373,23 @@ int MissionController::insertSimpleMissionItem(QGeoCoordinate coordinate, int vi } } newItem->setMissionFlightStatus(_missionFlightStatus); - _visualItems->insert(visualItemIndex, newItem); + if (visualItemIndex == -1) { + _visualItems->append(newItem); + } else { + _visualItems->insert(visualItemIndex, newItem); + } // We send the click coordinate through here to be able to set the planned home position from the user click location if needed _recalcAllWithClickCoordinate(coordinate); - return newItem->sequenceNumber(); + if (makeCurrentItem) { + setCurrentPlanViewIndex(newItem->sequenceNumber(), true); + } + + return newItem; } -int MissionController::insertROIMissionItem(QGeoCoordinate coordinate, int visualItemIndex) +VisualMissionItem* MissionController::insertROIMissionItem(QGeoCoordinate coordinate, int visualItemIndex, bool makeCurrentItem) { int sequenceNumber = _nextSequenceNumber(); SimpleMissionItem * newItem = new SimpleMissionItem(_controllerVehicle, _flyView, this); @@ -399,16 +407,24 @@ int MissionController::insertROIMissionItem(QGeoCoordinate coordinate, int visua newItem->altitude()->setRawValue(prevAltitude); newItem->setAltitudeMode(static_cast(prevAltitudeMode)); } - _visualItems->insert(visualItemIndex, newItem); + if (visualItemIndex == -1) { + _visualItems->append(newItem); + } else { + _visualItems->insert(visualItemIndex, newItem); + } _recalcAll(); - return newItem->sequenceNumber(); + if (makeCurrentItem) { + setCurrentPlanViewIndex(newItem->sequenceNumber(), true); + } + + return newItem; } -int MissionController::insertComplexMissionItem(QString itemName, QGeoCoordinate mapCenterCoordinate, int visualItemIndex) +VisualMissionItem* MissionController::insertComplexMissionItem(QString itemName, QGeoCoordinate mapCenterCoordinate, int visualItemIndex, bool makeCurrentItem) { - ComplexMissionItem* newItem; + ComplexMissionItem* newItem = nullptr; // If the ComplexMissionItem is inserted first, add a TakeOff SimpleMissionItem if (_visualItems->count() == 1 && (_controllerVehicle->fixedWing() || _controllerVehicle->vtol() || _controllerVehicle->multiRotor())) { @@ -428,15 +444,17 @@ int MissionController::insertComplexMissionItem(QString itemName, QGeoCoordinate newItem = new CorridorScanComplexItem(_controllerVehicle, _flyView, QString() /* kmlFile */, _visualItems /* parent */); } else { qWarning() << "Internal error: Unknown complex item:" << itemName; - return sequenceNumber; + return nullptr; } - return _insertComplexMissionItemWorker(newItem, visualItemIndex); + _insertComplexMissionItemWorker(newItem, visualItemIndex, makeCurrentItem); + + return newItem; } -int MissionController::insertComplexMissionItemFromKMLOrSHP(QString itemName, QString file, int visualItemIndex) +VisualMissionItem* MissionController::insertComplexMissionItemFromKMLOrSHP(QString itemName, QString file, int visualItemIndex, bool makeCurrentItem) { - ComplexMissionItem* newItem; + ComplexMissionItem* newItem = nullptr; if (itemName == patternSurveyName) { newItem = new SurveyComplexItem(_controllerVehicle, _flyView, file, _visualItems); @@ -446,13 +464,15 @@ int MissionController::insertComplexMissionItemFromKMLOrSHP(QString itemName, QS newItem = new CorridorScanComplexItem(_controllerVehicle, _flyView, file, _visualItems); } else { qWarning() << "Internal error: Unknown complex item:" << itemName; - return _nextSequenceNumber(); + return nullptr; } - return _insertComplexMissionItemWorker(newItem, visualItemIndex); + _insertComplexMissionItemWorker(newItem, visualItemIndex, makeCurrentItem); + + return newItem; } -int MissionController::_insertComplexMissionItemWorker(ComplexMissionItem* complexItem, int visualItemIndex) +void MissionController::_insertComplexMissionItemWorker(ComplexMissionItem* complexItem, int visualItemIndex, bool makeCurrentItem) { int sequenceNumber = _nextSequenceNumber(); bool surveyStyleItem = qobject_cast(complexItem) || @@ -500,7 +520,9 @@ int MissionController::_insertComplexMissionItemWorker(ComplexMissionItem* compl } _recalcAll(); - return complexItem->sequenceNumber(); + if (makeCurrentItem) { + setCurrentPlanViewIndex(complexItem->sequenceNumber(), true); + } } void MissionController::removeMissionItem(int index) diff --git a/src/MissionManager/MissionController.h b/src/MissionManager/MissionController.h index 7848bcc45..9a092c9c9 100644 --- a/src/MissionManager/MissionController.h +++ b/src/MissionManager/MissionController.h @@ -103,28 +103,35 @@ public: Q_INVOKABLE void removeMissionItem(int index); /// Add a new simple mission item to the list - /// @param visualItemIndex: index to insert at - /// @return Sequence number for new item - Q_INVOKABLE int insertSimpleMissionItem(QGeoCoordinate coordinate, int visualItemIndex); + /// @param coordinate: Coordinate for item + /// @param visualItemIndex: index to insert at, -1 for end of list + /// @param makeCurrentItem: true: Make this item the current item + /// @return Newly created item + Q_INVOKABLE VisualMissionItem* insertSimpleMissionItem(QGeoCoordinate coordinate, int visualItemIndex, bool makeCurrentItem = false); /// Add a new ROI mission item to the list - /// @param visualItemIndex: index to insert at - /// @return Sequence number for new item - Q_INVOKABLE int insertROIMissionItem(QGeoCoordinate coordinate, int visualItemIndex); + /// @param coordinate: Coordinate for item + /// @param visualItemIndex: index to insert at, -1 for end of list + /// @param makeCurrentItem: true: Make this item the current item + /// @return Newly created item + Q_INVOKABLE VisualMissionItem* insertROIMissionItem(QGeoCoordinate coordinate, int visualItemIndex, bool makeCurrentItem = false); /// Add a new complex mission item to the list /// @param itemName: Name of complex item to create (from complexMissionItemNames) /// @param mapCenterCoordinate: coordinate for current center of map - /// @param visualItemIndex: index to insert at - /// @return Sequence number for new item - Q_INVOKABLE int insertComplexMissionItem(QString itemName, QGeoCoordinate mapCenterCoordinate, int visualItemIndex); + /// @param visualItemIndex: index to insert at, -1 for end of list + /// @param makeCurrentItem: true: Make this item the current item + /// @return Newly created item + Q_INVOKABLE VisualMissionItem* insertComplexMissionItem(QString itemName, QGeoCoordinate mapCenterCoordinate, int visualItemIndex, bool makeCurrentItem = false); /// Add a new complex mission item to the list /// @param itemName: Name of complex item to create (from complexMissionItemNames) /// @param file: kml or shp file to load from shape from - /// @param visualItemIndex: index to insert at, -1 for end - /// @return Sequence number for new item - Q_INVOKABLE int insertComplexMissionItemFromKMLOrSHP(QString itemName, QString file, int visualItemIndex); + /// @param coordinate: Coordinate for item + /// @param visualItemIndex: index to insert at, -1 for end of list + /// @param makeCurrentItem: true: Make this item the current item + /// @return Newly created item + Q_INVOKABLE VisualMissionItem* insertComplexMissionItemFromKMLOrSHP(QString itemName, QString file, int visualItemIndex, bool makeCurrentItem = false); Q_INVOKABLE void resumeMission(int resumeIndex); @@ -284,7 +291,7 @@ private: void _initLoadedVisualItems(QmlObjectListModel* loadedVisualItems); CoordinateVector* _addWaypointLineSegment(CoordVectHashTable& prevItemPairHashTable, VisualItemPair& pair); void _addTimeDistance(bool vtolInHover, double hoverTime, double cruiseTime, double extraTime, double distance, int seqNum); - int _insertComplexMissionItemWorker(ComplexMissionItem* complexItem, int visualItemIndex); + void _insertComplexMissionItemWorker(ComplexMissionItem* complexItem, int visualItemIndex, bool makeCurrentItem); void _warnIfTerrainFrameUsed(void); private: diff --git a/src/MissionManager/SimpleMissionItem.cc b/src/MissionManager/SimpleMissionItem.cc index 486b49885..d66a3ce62 100644 --- a/src/MissionManager/SimpleMissionItem.cc +++ b/src/MissionManager/SimpleMissionItem.cc @@ -200,6 +200,8 @@ void SimpleMissionItem::_connectSignals(void) connect(this, &SimpleMissionItem::cameraSectionChanged, this, &SimpleMissionItem::_setDirty); connect(this, &SimpleMissionItem::cameraSectionChanged, this, &SimpleMissionItem::_updateLastSequenceNumber); + connect(this, &SimpleMissionItem::wizardModeChanged, this, &SimpleMissionItem::readyForSaveStateChanged); + // These are coordinate parameters, they must emit coordinateChanged signal connect(&_missionItem._param5Fact, &Fact::valueChanged, this, &SimpleMissionItem::_sendCoordinateChanged); connect(&_missionItem._param6Fact, &Fact::valueChanged, this, &SimpleMissionItem::_sendCoordinateChanged); @@ -325,6 +327,7 @@ bool SimpleMissionItem::load(QTextStream &loadStream) } _updateOptionalSections(); } + return success; } @@ -726,6 +729,10 @@ void SimpleMissionItem::_terrainAltChanged(void) SimpleMissionItem::ReadyForSaveState SimpleMissionItem::readyForSaveState(void) const { + if (_wizardMode) { + return NotReadyForSaveData; + } + bool terrainReady = !specifiesAltitude() || !qIsNaN(_missionItem._param7Fact.rawValue().toDouble()); return terrainReady ? ReadyForSave : NotReadyForSaveTerrain; } diff --git a/src/MissionManager/SimpleMissionItem.h b/src/MissionManager/SimpleMissionItem.h index ff89b3b5d..c839e4c50 100644 --- a/src/MissionManager/SimpleMissionItem.h +++ b/src/MissionManager/SimpleMissionItem.h @@ -99,7 +99,6 @@ public: const MissionItem& missionItem(void) const { return _missionItem; } // Overrides from VisualMissionItem - bool dirty (void) const final { return _dirty; } bool isSimpleItem (void) const final { return true; } bool isStandaloneCoordinate (void) const final; @@ -154,7 +153,7 @@ private slots: void _rebuildFacts (void); void _rebuildTextFieldFacts (void); void _possibleAdditionalTimeDelayChanged(void); - void _setDefaultsForCommand (void); + void _setDefaultsForCommand (void); private: void _connectSignals (void); diff --git a/src/MissionManager/StructureScanComplexItem.cc b/src/MissionManager/StructureScanComplexItem.cc index 0a74efe46..51d6a261a 100644 --- a/src/MissionManager/StructureScanComplexItem.cc +++ b/src/MissionManager/StructureScanComplexItem.cc @@ -87,6 +87,8 @@ StructureScanComplexItem::StructureScanComplexItem(Vehicle* vehicle, bool flyVie connect(&_layersFact, &Fact::valueChanged, this, &StructureScanComplexItem::_recalcScanDistance); connect(&_flightPolygon, &QGCMapPolygon::pathChanged, this, &StructureScanComplexItem::_recalcScanDistance); + connect(this, &StructureScanComplexItem::wizardModeChanged, this, &StructureScanComplexItem::readyForSaveStateChanged); + _recalcLayerInfo(); if (!kmlOrShpFile.isEmpty()) { @@ -621,5 +623,5 @@ void StructureScanComplexItem::_recalcScanDistance() StructureScanComplexItem::ReadyForSaveState StructureScanComplexItem::readyForSaveState(void) const { - return _structurePolygon.isValid() ? ReadyForSave : NotReadyForSaveData; + return _structurePolygon.isValid() && !_wizardMode ? ReadyForSave : NotReadyForSaveData; } diff --git a/src/MissionManager/StructureScanPlanCreator.cc b/src/MissionManager/StructureScanPlanCreator.cc index 902ba1179..5f1b09eac 100644 --- a/src/MissionManager/StructureScanPlanCreator.cc +++ b/src/MissionManager/StructureScanPlanCreator.cc @@ -10,6 +10,7 @@ #include "StructureScanPlanCreator.h" #include "PlanMasterController.h" #include "MissionSettingsItem.h" +#include "FixedWingLandingComplexItem.h" StructureScanPlanCreator::StructureScanPlanCreator(PlanMasterController* planMasterController, QObject* parent) : PlanCreator(planMasterController, MissionController::patternStructureScanName, QStringLiteral("/qmlimages/PlanCreator/StructureScanPlanCreator.png"), parent) @@ -20,18 +21,16 @@ StructureScanPlanCreator::StructureScanPlanCreator(PlanMasterController* planMas void StructureScanPlanCreator::createPlan(const QGeoCoordinate& mapCenterCoord) { _planMasterController->removeAll(); - int seqNum = _missionController->insertComplexMissionItem( - MissionController::patternStructureScanName, - mapCenterCoord, - _missionController->visualItems()->count()); + VisualMissionItem* takeoffItem = _missionController->insertSimpleMissionItem(mapCenterCoord, -1); + takeoffItem->setWizardMode(true); + _missionController->insertComplexMissionItem(MissionController::patternStructureScanName, mapCenterCoord, -1)->setWizardMode(true); if (_planMasterController->managerVehicle()->fixedWing()) { - _missionController->insertComplexMissionItem( - MissionController::patternFWLandingName, - mapCenterCoord, - _missionController->visualItems()->count()); + FixedWingLandingComplexItem* landingItem = qobject_cast(_missionController->insertComplexMissionItem(MissionController::patternFWLandingName, mapCenterCoord, -1)); + landingItem->setWizardMode(true); + landingItem->setLoiterDragAngleOnly(true); } else { MissionSettingsItem* settingsItem = _missionController->visualItems()->value(0); settingsItem->setMissionEndRTL(true); } - _missionController->setCurrentPlanViewIndex(seqNum, false); + _missionController->setCurrentPlanViewIndex(takeoffItem->sequenceNumber(), true); } diff --git a/src/MissionManager/SurveyPlanCreator.cc b/src/MissionManager/SurveyPlanCreator.cc index 83146592e..e2715aeea 100644 --- a/src/MissionManager/SurveyPlanCreator.cc +++ b/src/MissionManager/SurveyPlanCreator.cc @@ -10,6 +10,8 @@ #include "SurveyPlanCreator.h" #include "PlanMasterController.h" #include "MissionSettingsItem.h" +#include "FixedWingLandingComplexItem.h" +#include "FixedWingLandingComplexItem.h" SurveyPlanCreator::SurveyPlanCreator(PlanMasterController* planMasterController, QObject* parent) : PlanCreator(planMasterController, MissionController::patternSurveyName, QStringLiteral("/qmlimages/PlanCreator/SurveyPlanCreator.png"), parent) @@ -20,18 +22,16 @@ SurveyPlanCreator::SurveyPlanCreator(PlanMasterController* planMasterController, void SurveyPlanCreator::createPlan(const QGeoCoordinate& mapCenterCoord) { _planMasterController->removeAll(); - int seqNum = _missionController->insertComplexMissionItem( - MissionController::patternSurveyName, - mapCenterCoord, - _missionController->visualItems()->count()); + VisualMissionItem* takeoffItem = _missionController->insertSimpleMissionItem(mapCenterCoord, -1); + takeoffItem->setWizardMode(true); + _missionController->insertComplexMissionItem(MissionController::patternSurveyName, mapCenterCoord, -1)->setWizardMode(true); if (_planMasterController->managerVehicle()->fixedWing()) { - _missionController->insertComplexMissionItem( - MissionController::patternFWLandingName, - mapCenterCoord, - _missionController->visualItems()->count()); + FixedWingLandingComplexItem* landingItem = qobject_cast(_missionController->insertComplexMissionItem(MissionController::patternFWLandingName, mapCenterCoord, -1)); + landingItem->setWizardMode(true); + landingItem->setLoiterDragAngleOnly(true); } else { MissionSettingsItem* settingsItem = _missionController->visualItems()->value(0); settingsItem->setMissionEndRTL(true); } - _missionController->setCurrentPlanViewIndex(seqNum, false); + _missionController->setCurrentPlanViewIndex(takeoffItem->sequenceNumber(), true); } diff --git a/src/MissionManager/TransectStyleComplexItem.cc b/src/MissionManager/TransectStyleComplexItem.cc index e75621ea0..308d5c835 100644 --- a/src/MissionManager/TransectStyleComplexItem.cc +++ b/src/MissionManager/TransectStyleComplexItem.cc @@ -106,8 +106,8 @@ TransectStyleComplexItem::TransectStyleComplexItem(Vehicle* vehicle, bool flyVie connect(this, &TransectStyleComplexItem::visualTransectPointsChanged, this, &TransectStyleComplexItem::complexDistanceChanged); connect(this, &TransectStyleComplexItem::visualTransectPointsChanged, this, &TransectStyleComplexItem::greatestDistanceToChanged); - - connect(this, &TransectStyleComplexItem::followTerrainChanged, this, &TransectStyleComplexItem::_followTerrainChanged); + connect(this, &TransectStyleComplexItem::followTerrainChanged, this, &TransectStyleComplexItem::_followTerrainChanged); + connect(this, &TransectStyleComplexItem::wizardModeChanged, this, &TransectStyleComplexItem::readyForSaveStateChanged); connect(&_surveyAreaPolygon, &QGCMapPolygon::isValidChanged, this, &TransectStyleComplexItem::readyForSaveStateChanged); @@ -494,7 +494,7 @@ TransectStyleComplexItem::ReadyForSaveState TransectStyleComplexItem::readyForSa { bool terrainReady = _followTerrain ? _transectsPathHeightInfo.count() : true; bool polygonNotReady = !_surveyAreaPolygon.isValid(); - return polygonNotReady ? + return (polygonNotReady || _wizardMode) ? NotReadyForSaveData : (terrainReady ? ReadyForSave : NotReadyForSaveTerrain); } diff --git a/src/MissionManager/VisualMissionItem.cc b/src/MissionManager/VisualMissionItem.cc index 2982f565e..75aafb233 100644 --- a/src/MissionManager/VisualMissionItem.cc +++ b/src/MissionManager/VisualMissionItem.cc @@ -37,6 +37,7 @@ VisualMissionItem::VisualMissionItem(Vehicle* vehicle, bool flyView, QObject* pa , _distance (0.0) , _missionGimbalYaw (qQNaN()) , _missionVehicleYaw (qQNaN()) + , _wizardMode (false) , _lastLatTerrainQuery (0) , _lastLonTerrainQuery (0) { @@ -56,6 +57,7 @@ VisualMissionItem::VisualMissionItem(const VisualMissionItem& other, bool flyVie , _terrainCollision (false) , _azimuth (0.0) , _distance (0.0) + , _wizardMode (false) { *this = other; @@ -218,3 +220,10 @@ void VisualMissionItem::_setBoundingCube(QGCGeoBoundingCube bc) } } +void VisualMissionItem::setWizardMode(bool wizardMode) +{ + if (wizardMode != _wizardMode) { + _wizardMode = wizardMode; + emit wizardModeChanged(_wizardMode); + } +} diff --git a/src/MissionManager/VisualMissionItem.h b/src/MissionManager/VisualMissionItem.h index dc35d8a69..5d9459f95 100644 --- a/src/MissionManager/VisualMissionItem.h +++ b/src/MissionManager/VisualMissionItem.h @@ -74,6 +74,7 @@ public: Q_PROPERTY(double missionGimbalYaw READ missionGimbalYaw NOTIFY missionGimbalYawChanged) ///< Current gimbal yaw state at this point in mission Q_PROPERTY(double missionVehicleYaw READ missionVehicleYaw NOTIFY missionVehicleYawChanged) ///< Expected vehicle yaw at this point in mission Q_PROPERTY(bool flyView READ flyView CONSTANT) + Q_PROPERTY(bool wizardMode READ wizardMode WRITE setWizardMode NOTIFY wizardModeChanged) Q_PROPERTY(ReadyForSaveState readyForSaveState READ readyForSaveState NOTIFY readyForSaveStateChanged) Q_PROPERTY(QGCGeoBoundingCube* boundingCube READ boundingCube NOTIFY boundingCubeChanged) @@ -88,19 +89,17 @@ public: Q_PROPERTY(double distance READ distance WRITE setDistance NOTIFY distanceChanged) ///< Distance to previous waypoint // Property accesors - - bool homePosition (void) const { return _homePositionSpecialCase; } - void setHomePositionSpecialCase (bool homePositionSpecialCase) { _homePositionSpecialCase = homePositionSpecialCase; } - - double altDifference (void) const { return _altDifference; } - double altPercent (void) const { return _altPercent; } - double terrainPercent (void) const { return _terrainPercent; } - bool terrainCollision (void) const { return _terrainCollision; } - double azimuth (void) const { return _azimuth; } - double distance (void) const { return _distance; } - bool isCurrentItem (void) const { return _isCurrentItem; } - double terrainAltitude (void) const { return _terrainAltitude; } - bool flyView (void) const { return _flyView; } + bool homePosition (void) const { return _homePositionSpecialCase; } + double altDifference (void) const { return _altDifference; } + double altPercent (void) const { return _altPercent; } + double terrainPercent (void) const { return _terrainPercent; } + bool terrainCollision(void) const { return _terrainCollision; } + double azimuth (void) const { return _azimuth; } + double distance (void) const { return _distance; } + bool isCurrentItem (void) const { return _isCurrentItem; } + double terrainAltitude (void) const { return _terrainAltitude; } + bool flyView (void) const { return _flyView; } + bool wizardMode (void) const { return _wizardMode; } QmlObjectListModel* childItems(void) { return &_childItems; } @@ -111,6 +110,9 @@ public: void setTerrainCollision(bool terrainCollision); void setAzimuth (double azimuth); void setDistance (double distance); + void setWizardMode (bool wizardMode); + + void setHomePositionSpecialCase (bool homePositionSpecialCase) { _homePositionSpecialCase = homePositionSpecialCase; } Vehicle* vehicle(void) { return _vehicle; } @@ -205,6 +207,7 @@ signals: void additionalTimeDelayChanged (void); void boundingCubeChanged (void); void readyForSaveStateChanged (void); + void wizardModeChanged (bool wizardMode); void coordinateHasRelativeAltitudeChanged (bool coordinateHasRelativeAltitude); void exitCoordinateHasRelativeAltitudeChanged (bool exitCoordinateHasRelativeAltitude); @@ -226,6 +229,7 @@ protected: QString _editorQml; ///< Qml resource for editing item double _missionGimbalYaw; double _missionVehicleYaw; + bool _wizardMode; ///< true: Item editor is showing wizard completion panel QGCGeoBoundingCube _boundingCube; ///< The bounding "cube" of this element. diff --git a/src/PlanView/CorridorScanEditor.qml b/src/PlanView/CorridorScanEditor.qml index f7fb0299f..86058e936 100644 --- a/src/PlanView/CorridorScanEditor.qml +++ b/src/PlanView/CorridorScanEditor.qml @@ -56,23 +56,34 @@ Rectangle { anchors.right: parent.right ColumnLayout { + id: wizardModeColumn anchors.left: parent.left anchors.right: parent.right spacing: _margin - visible: !missionItem.corridorPolyline.isValid + visible: !missionItem.corridorPolyline.isValid || missionItem.wizardMode QGCLabel { Layout.fillWidth: true wrapMode: Text.WordWrap text: qsTr("Use the Corridor Tools to create the polyline which defines the corridor.") } + + QGCButton { + text: qsTr("Done With Polyline") + Layout.fillWidth: true + enabled: missionItem.corridorPolyline.isValid + onClicked: { + missionItem.wizardMode = false + editorRoot.selectNextNotReadyItem() + } + } } Column { anchors.left: parent.left anchors.right: parent.right spacing: _margin - visible: missionItem.corridorPolyline.isValid + visible: !wizardModeColumn.visible QGCTabBar { id: tabBar diff --git a/src/PlanView/FWLandingPatternEditor.qml b/src/PlanView/FWLandingPatternEditor.qml index da04fd851..44a1493d7 100644 --- a/src/PlanView/FWLandingPatternEditor.qml +++ b/src/PlanView/FWLandingPatternEditor.qml @@ -49,7 +49,7 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right spacing: _margin - visible: missionItem.landingCoordSet + visible: !editorColumnNeedLandingPoint.visible SectionHeader { id: loiterPointSection @@ -216,33 +216,70 @@ Rectangle { anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right - visible: !missionItem.landingCoordSet + visible: !missionItem.landingCoordSet || missionItem.wizardMode spacing: ScreenTools.defaultFontPixelHeight - QGCLabel { - anchors.left: parent.left - anchors.right: parent.right - wrapMode: Text.WordWrap - horizontalAlignment: Text.AlignHCenter - text: qsTr("Click in map to set landing point.") - } + Column { + id: landingCoordColumn + anchors.left: parent.left + anchors.right: parent.right + spacing: ScreenTools.defaultFontPixelHeight + visible: !missionItem.landingCoordSet + + QGCLabel { + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignHCenter + text: qsTr("Click in map to set landing point.") + } - QGCLabel { - anchors.left: parent.left - anchors.right: parent.right - horizontalAlignment: Text.AlignHCenter - text: qsTr("- or -") - visible: activeVehicle + QGCLabel { + anchors.left: parent.left + anchors.right: parent.right + horizontalAlignment: Text.AlignHCenter + text: qsTr("- or -") + visible: activeVehicle + } + + QGCButton { + anchors.horizontalCenter: parent.horizontalCenter + text: _setToVehicleLocationStr + visible: activeVehicle + + onClicked: { + missionItem.landingCoordinate = activeVehicle.coordinate + missionItem.landingHeading.rawValue = activeVehicle.heading.rawValue + } + } } - QGCButton { - anchors.horizontalCenter: parent.horizontalCenter - text: _setToVehicleLocationStr - visible: activeVehicle + ColumnLayout { + anchors.left: parent.left + anchors.right: parent.right + spacing: ScreenTools.defaultFontPixelHeight + visible: !landingCoordColumn.visible + + onVisibleChanged: { + if (visible) { + console.log(missionItem.landingDistance.rawValue) + } + } - onClicked: { - missionItem.landingCoordinate = activeVehicle.coordinate - missionItem.landingHeading.rawValue = activeVehicle.heading.rawValue + QGCLabel { + Layout.fillWidth: true + wrapMode: Text.WordWrap + text: qsTr("Drag the loiter point to adjust landing direction for wind and obstacles.") + } + + QGCButton { + text: qsTr("Done Adjusting") + Layout.fillWidth: true + onClicked: { + missionItem.wizardMode = false + missionItem.landingDragAngleOnly = false + editorRoot.selectNextNotReadyItem() + } } } } diff --git a/src/PlanView/FWLandingPatternMapVisual.qml b/src/PlanView/FWLandingPatternMapVisual.qml index fbb1a41e6..d46634551 100644 --- a/src/PlanView/FWLandingPatternMapVisual.qml +++ b/src/PlanView/FWLandingPatternMapVisual.qml @@ -198,11 +198,25 @@ Item { itemIndicator: _loiterPointObject itemCoordinate: _missionItem.loiterCoordinate - onItemCoordinateChanged: _missionItem.loiterCoordinate = itemCoordinate + property bool _preventReentrancy: false + + onItemCoordinateChanged: { + if (!_preventReentrancy) { + if (Drag.active && _missionItem.loiterDragAngleOnly) { + _preventReentrancy = true + var angle = _missionItem.landingCoordinate.azimuthTo(itemCoordinate) + var distance = _missionItem.landingCoordinate.distanceTo(_missionItem.loiterCoordinate) + _missionItem.loiterCoordinate = _missionItem.landingCoordinate.atDistanceAndAzimuth(distance, angle) + _preventReentrancy = false + } else { + _missionItem.loiterCoordinate = itemCoordinate + } + } + } } } - // Control which is used to drag the loiter point + // Control which is used to drag the landing point Component { id: landDragAreaComponent diff --git a/src/PlanView/MissionItemEditor.qml b/src/PlanView/MissionItemEditor.qml index c81b53d5a..8b8a577c6 100644 --- a/src/PlanView/MissionItemEditor.qml +++ b/src/PlanView/MissionItemEditor.qml @@ -29,6 +29,7 @@ Rectangle { signal remove signal insertWaypoint signal insertComplexItem(string complexItemName) + signal selectNextNotReadyItem property var _masterController: masterController property var _missionController: _masterController.missionController diff --git a/src/PlanView/PlanView.qml b/src/PlanView/PlanView.qml index 42f6be7ca..42aeb4234 100644 --- a/src/PlanView/PlanView.qml +++ b/src/PlanView/PlanView.qml @@ -68,13 +68,11 @@ Item { } function insertComplexMissionItem(complexItemName, coordinate, index) { - var sequenceNumber = _missionController.insertComplexMissionItem(complexItemName, coordinate, index) - _missionController.setCurrentPlanViewIndex(sequenceNumber, true) + _missionController.insertComplexMissionItem(complexItemName, coordinate, index, true /* makeCurrentItem */) } function insertComplexMissionItemFromKMLOrSHP(complexItemName, file, index) { - var sequenceNumber = _missionController.insertComplexMissionItemFromKMLOrSHP(complexItemName, file, index) - _missionController.setCurrentPlanViewIndex(sequenceNumber, true) + _missionController.insertComplexMissionItemFromKMLOrSHP(complexItemName, file, index, true /* makeCurrentItem */) } function updateAirspace(reset) { @@ -267,8 +265,7 @@ Item { /// @param coordinate Location to insert item /// @param index Insert item at this index function insertSimpleMissionItem(coordinate, index) { - var sequenceNumber = _missionController.insertSimpleMissionItem(coordinate, index) - _missionController.setCurrentPlanViewIndex(sequenceNumber, true) + _missionController.insertSimpleMissionItem(coordinate, index, true /* makeCurrentItem */) } /// Inserts a new ROI mission item @@ -281,6 +278,17 @@ Item { toolStrip.lastClickedButton.checked = false } + function selectNextNotReady() { + var foundCurrent = false + for (var i=0; i<_missionController.visualItems.count; i++) { + var vmi = _missionController.visualItems.get(i) + if (vmi.readyForSaveState === VisualMissionItem.NotReadyForSaveData) { + _missionController.setCurrentPlanViewIndex(vmi.sequenceNumber, true) + break + } + } + } + property int _moveDialogMissionItemIndex QGCFileDialog { @@ -822,8 +830,9 @@ Item { } _missionController.setCurrentPlanViewIndex(removeIndex, true) } - onInsertWaypoint: insertSimpleMissionItem(editorMap.center, index) - onInsertComplexItem: insertComplexMissionItem(complexItemName, editorMap.center, index) + onInsertWaypoint: insertSimpleMissionItem(editorMap.center, index) + onInsertComplexItem: insertComplexMissionItem(complexItemName, editorMap.center, index) + onSelectNextNotReadyItem: selectNextNotReady() } } } diff --git a/src/PlanView/SimpleItemEditor.qml b/src/PlanView/SimpleItemEditor.qml index e289462cc..0406f621c 100644 --- a/src/PlanView/SimpleItemEditor.qml +++ b/src/PlanView/SimpleItemEditor.qml @@ -13,7 +13,7 @@ import QGroundControl.Palette 1.0 // Editor for Simple mission items Rectangle { width: availableWidth - height: valuesColumn.height + (_margin * 2) + height: editorColumn.height + (_margin * 2) color: qgcPal.windowShadeDark radius: _radius @@ -53,212 +53,246 @@ Rectangle { } Column { - id: valuesColumn + id: editorColumn anchors.margins: _margin anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top - spacing: _margin - - QGCLabel { - width: parent.width - wrapMode: Text.WordWrap - font.pointSize: ScreenTools.smallFontPointSize - text: missionItem.rawEdit ? - qsTr("Provides advanced access to all commands/parameters. Be very careful!") : - missionItem.commandDescription - } - - GridLayout { - anchors.left: parent.left - anchors.right: parent.right - columns: 2 - Repeater { - model: missionItem.comboboxFacts + ColumnLayout { + anchors.left: parent.left + anchors.right: parent.right + spacing: _margin + visible: missionItem.wizardMode - QGCLabel { - text: object.name - visible: object.name !== "" - Layout.column: 0 - Layout.row: index - } + QGCLabel { + text: qsTr("Adjust the initial launch location by selecting 'P' and dragging it to the correct location.") + Layout.fillWidth: true + wrapMode: Text.WordWrap } - Repeater { - model: missionItem.comboboxFacts + QGCLabel { + text: qsTr("Adjust the takeoff completion location by dragging it to the correct location.") + Layout.fillWidth: true + wrapMode: Text.WordWrap + } - FactComboBox { - indexModel: false - model: object.enumStrings - fact: object - font.pointSize: ScreenTools.smallFontPointSize - Layout.column: 1 - Layout.row: index - Layout.fillWidth: true + QGCButton { + text: qsTr("Done Adjusting") + Layout.fillWidth: true + onClicked: { + missionItem.wizardMode = false + editorRoot.selectNextNotReadyItem() } } } - Rectangle { - anchors.left: parent.left - anchors.right: parent.right - height: altColumn.y + altColumn.height + _margin - color: qgcPal.windowShade - visible: _specifiesAltitude - - Column { - id: altColumn - anchors.margins: _margin - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - spacing: _margin - - Item { - width: altHamburger.x + altHamburger.width - height: altModeLabel.height - - QGCLabel { id: altModeLabel } - - QGCColoredImage { - id: altHamburger - anchors.leftMargin: ScreenTools.defaultFontPixelWidth / 4 - anchors.left: altModeLabel.right - anchors.verticalCenter: altModeLabel.verticalCenter - width: ScreenTools.defaultFontPixelHeight / 2 - height: width - sourceSize.height: height - source: "/res/DropArrow.svg" - color: qgcPal.text - } + Column { + anchors.left: parent.left + anchors.right: parent.right + spacing: _margin + visible: !missionItem.wizardMode + + QGCLabel { + width: parent.width + wrapMode: Text.WordWrap + font.pointSize: ScreenTools.smallFontPointSize + text: missionItem.rawEdit ? + qsTr("Provides advanced access to all commands/parameters. Be very careful!") : + missionItem.commandDescription + } - QGCMouseArea { - anchors.fill: parent - onClicked: altHamburgerMenu.popup() - } + GridLayout { + anchors.left: parent.left + anchors.right: parent.right + columns: 2 - QGCMenu { - id: altHamburgerMenu + Repeater { + model: missionItem.comboboxFacts - QGCMenuItem { - text: qsTr("Altitude Relative To Home") - checkable: true - checked: missionItem.altitudeMode === QGroundControl.AltitudeModeRelative - onTriggered: missionItem.altitudeMode = QGroundControl.AltitudeModeRelative - } + QGCLabel { + text: object.name + visible: object.name !== "" + Layout.column: 0 + Layout.row: index + } + } + + Repeater { + model: missionItem.comboboxFacts + + FactComboBox { + indexModel: false + model: object.enumStrings + fact: object + font.pointSize: ScreenTools.smallFontPointSize + Layout.column: 1 + Layout.row: index + Layout.fillWidth: true + } + } + } - QGCMenuItem { - text: qsTr("Altitude Above Mean Sea Level") - checkable: true - checked: missionItem.altitudeMode === QGroundControl.AltitudeModeAbsolute - visible: QGroundControl.corePlugin.options.showMissionAbsoluteAltitude - onTriggered: missionItem.altitudeMode = QGroundControl.AltitudeModeAbsolute + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + height: altColumn.y + altColumn.height + _margin + color: qgcPal.windowShade + visible: _specifiesAltitude + + Column { + id: altColumn + anchors.margins: _margin + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + spacing: _margin + + Item { + width: altHamburger.x + altHamburger.width + height: altModeLabel.height + + QGCLabel { id: altModeLabel } + + QGCColoredImage { + id: altHamburger + anchors.leftMargin: ScreenTools.defaultFontPixelWidth / 4 + anchors.left: altModeLabel.right + anchors.verticalCenter: altModeLabel.verticalCenter + width: ScreenTools.defaultFontPixelHeight / 2 + height: width + sourceSize.height: height + source: "/res/DropArrow.svg" + color: qgcPal.text } - QGCMenuItem { - text: qsTr("Altitude Above Terrain") - checkable: true - checked: missionItem.altitudeMode === QGroundControl.AltitudeModeAboveTerrain - onTriggered: missionItem.altitudeMode = QGroundControl.AltitudeModeAboveTerrain - visible: missionItem.specifiesCoordinate + QGCMouseArea { + anchors.fill: parent + onClicked: altHamburgerMenu.popup() } - QGCMenuItem { - text: qsTr("Terrain Frame") - checkable: true - checked: missionItem.altitudeMode === QGroundControl.AltitudeModeTerrainFrame - visible: missionItem.altitudeMode === QGroundControl.AltitudeModeTerrainFrame - onTriggered: missionItem.altitudeMode = QGroundControl.AltitudeModeTerrainFrame + QGCMenu { + id: altHamburgerMenu + + QGCMenuItem { + text: qsTr("Altitude Relative To Home") + checkable: true + checked: missionItem.altitudeMode === QGroundControl.AltitudeModeRelative + onTriggered: missionItem.altitudeMode = QGroundControl.AltitudeModeRelative + } + + QGCMenuItem { + text: qsTr("Altitude Above Mean Sea Level") + checkable: true + checked: missionItem.altitudeMode === QGroundControl.AltitudeModeAbsolute + visible: QGroundControl.corePlugin.options.showMissionAbsoluteAltitude + onTriggered: missionItem.altitudeMode = QGroundControl.AltitudeModeAbsolute + } + + QGCMenuItem { + text: qsTr("Altitude Above Terrain") + checkable: true + checked: missionItem.altitudeMode === QGroundControl.AltitudeModeAboveTerrain + onTriggered: missionItem.altitudeMode = QGroundControl.AltitudeModeAboveTerrain + visible: missionItem.specifiesCoordinate + } + + QGCMenuItem { + text: qsTr("Terrain Frame") + checkable: true + checked: missionItem.altitudeMode === QGroundControl.AltitudeModeTerrainFrame + visible: missionItem.altitudeMode === QGroundControl.AltitudeModeTerrainFrame + onTriggered: missionItem.altitudeMode = QGroundControl.AltitudeModeTerrainFrame + } } } - } - AltitudeFactTextField { - id: altField - fact: missionItem.altitude - altitudeMode: missionItem.altitudeMode - anchors.left: parent.left - anchors.right: parent.right - } + AltitudeFactTextField { + id: altField + fact: missionItem.altitude + altitudeMode: missionItem.altitudeMode + anchors.left: parent.left + anchors.right: parent.right + } - QGCLabel { - id: altModeHelp - wrapMode: Text.WordWrap - font.pointSize: ScreenTools.smallFontPointSize - anchors.left: parent.left - anchors.right: parent.right + QGCLabel { + id: altModeHelp + wrapMode: Text.WordWrap + font.pointSize: ScreenTools.smallFontPointSize + anchors.left: parent.left + anchors.right: parent.right + } } } - } - GridLayout { - anchors.left: parent.left - anchors.right: parent.right - flow: GridLayout.TopToBottom - rows: missionItem.textFieldFacts.count + - missionItem.nanFacts.count + - (missionItem.speedSection.available ? 1 : 0) - columns: 2 + GridLayout { + anchors.left: parent.left + anchors.right: parent.right + flow: GridLayout.TopToBottom + rows: missionItem.textFieldFacts.count + + missionItem.nanFacts.count + + (missionItem.speedSection.available ? 1 : 0) + columns: 2 - Repeater { - model: missionItem.textFieldFacts + Repeater { + model: missionItem.textFieldFacts - QGCLabel { text: object.name } - } + QGCLabel { text: object.name } + } - Repeater { - model: missionItem.nanFacts + Repeater { + model: missionItem.nanFacts - QGCCheckBox { - text: object.name - checked: !isNaN(object.rawValue) - onClicked: object.rawValue = checked ? 0 : NaN + QGCCheckBox { + text: object.name + checked: !isNaN(object.rawValue) + onClicked: object.rawValue = checked ? 0 : NaN + } } - } - QGCCheckBox { - id: flightSpeedCheckbox - text: qsTr("Flight Speed") - checked: missionItem.speedSection.specifyFlightSpeed - onClicked: missionItem.speedSection.specifyFlightSpeed = checked - visible: missionItem.speedSection.available - } + QGCCheckBox { + id: flightSpeedCheckbox + text: qsTr("Flight Speed") + checked: missionItem.speedSection.specifyFlightSpeed + onClicked: missionItem.speedSection.specifyFlightSpeed = checked + visible: missionItem.speedSection.available + } - Repeater { - model: missionItem.textFieldFacts + Repeater { + model: missionItem.textFieldFacts - FactTextField { - showUnits: true - fact: object - Layout.fillWidth: true - enabled: !object.readOnly + FactTextField { + showUnits: true + fact: object + Layout.fillWidth: true + enabled: !object.readOnly + } } - } - Repeater { - model: missionItem.nanFacts + Repeater { + model: missionItem.nanFacts + + FactTextField { + showUnits: true + fact: object + Layout.fillWidth: true + enabled: !isNaN(object.rawValue) + } + } FactTextField { - showUnits: true - fact: object + fact: missionItem.speedSection.flightSpeed Layout.fillWidth: true - enabled: !isNaN(object.rawValue) + enabled: flightSpeedCheckbox.checked + visible: missionItem.speedSection.available } } - FactTextField { - fact: missionItem.speedSection.flightSpeed - Layout.fillWidth: true - enabled: flightSpeedCheckbox.checked - visible: missionItem.speedSection.available + CameraSection { + checked: missionItem.cameraSection.settingsSpecified + visible: missionItem.cameraSection.available } } - - CameraSection { - checked: missionItem.cameraSection.settingsSpecified - visible: missionItem.cameraSection.available - } - } // Column -} // Rectangle + } +} diff --git a/src/PlanView/StructureScanEditor.qml b/src/PlanView/StructureScanEditor.qml index fdf61f6e5..31e307ef6 100644 --- a/src/PlanView/StructureScanEditor.qml +++ b/src/PlanView/StructureScanEditor.qml @@ -57,23 +57,34 @@ Rectangle { anchors.right: parent.right ColumnLayout { + id: wizardColumn anchors.left: parent.left anchors.right: parent.right spacing: _margin - visible: !missionItem.structurePolygon.isValid + visible: !missionItem.structurePolygon.isValid || missionItem.wizardMode QGCLabel { Layout.fillWidth: true wrapMode: Text.WordWrap text: qsTr("Use the Polygon Tools to create the polygon which outlines the structure.") } + + QGCButton { + text: qsTr("Done With Polygon") + Layout.fillWidth: true + enabled: missionItem.structurePolygon.isValid + onClicked: { + missionItem.wizardMode = false + editorRoot.selectNextNotReadyItem() + } + } } Column { anchors.left: parent.left anchors.right: parent.right spacing: _margin - visible: missionItem.structurePolygon.isValid + visible: !wizardColumn.visible QGCTabBar { id: tabBar diff --git a/src/PlanView/SurveyItemEditor.qml b/src/PlanView/SurveyItemEditor.qml index 92f41a0b2..291dd8680 100644 --- a/src/PlanView/SurveyItemEditor.qml +++ b/src/PlanView/SurveyItemEditor.qml @@ -56,23 +56,34 @@ Rectangle { anchors.right: parent.right ColumnLayout { + id: wizardColumn anchors.left: parent.left anchors.right: parent.right spacing: _margin - visible: !missionItem.surveyAreaPolygon.isValid + visible: !missionItem.surveyAreaPolygon.isValid || missionItem.wizardMode QGCLabel { Layout.fillWidth: true wrapMode: Text.WordWrap text: qsTr("Use the Polygon Tools to create the polygon which outlines your survey area.") } + + QGCButton { + text: qsTr("Done With Polygon") + Layout.fillWidth: true + enabled: missionItem.surveyAreaPolygon.isValid + onClicked: { + missionItem.wizardMode = false + editorRoot.selectNextNotReadyItem() + } + } } Column { anchors.left: parent.left anchors.right: parent.right spacing: _margin - visible: missionItem.surveyAreaPolygon.isValid + visible: !wizardColumn.visible QGCTabBar { id: tabBar -- 2.22.0