From ab9e64b885fa9b76c8e50cfc91e5269b264bbe08 Mon Sep 17 00:00:00 2001 From: DonLakeFlyer Date: Thu, 14 Nov 2019 13:26:38 -0800 Subject: [PATCH] More work on contextual Plan tools --- src/MissionManager/MissionCommandTree.cc | 5 +- src/MissionManager/MissionCommandTree.h | 3 +- src/MissionManager/MissionController.cc | 41 ++++++++++----- src/MissionManager/MissionController.h | 63 +++++++++++++----------- src/MissionManager/SimpleMissionItem.cc | 1 + src/PlanView/MissionItemEditor.qml | 5 +- src/PlanView/PlanView.qml | 46 ++++++++++------- src/QmlControls/MissionCommandDialog.qml | 9 ++-- src/QmlControls/ToolStrip.qml | 2 + 9 files changed, 104 insertions(+), 71 deletions(-) diff --git a/src/MissionManager/MissionCommandTree.cc b/src/MissionManager/MissionCommandTree.cc index 8f486ead1..d3109f396 100644 --- a/src/MissionManager/MissionCommandTree.cc +++ b/src/MissionManager/MissionCommandTree.cc @@ -219,7 +219,7 @@ const MissionCommandUIInfo* MissionCommandTree::getUIInfo(Vehicle* vehicle, MAV_ } } -QVariantList MissionCommandTree::getCommandsForCategory(Vehicle* vehicle, const QString& category) +QVariantList MissionCommandTree::getCommandsForCategory(Vehicle* vehicle, const QString& category, bool showFlyThroughCommands) { MAV_AUTOPILOT baseFirmwareType; MAV_TYPE baseVehicleType; @@ -237,7 +237,8 @@ QVariantList MissionCommandTree::getCommandsForCategory(Vehicle* vehicle, const for (MAV_CMD command: commandMap.keys()) { if (supportedCommands.contains(command)) { MissionCommandUIInfo* uiInfo = commandMap[command]; - if (uiInfo->category() == category || category == _allCommandsCategory) { + if ((uiInfo->category() == category || category == _allCommandsCategory) && + (showFlyThroughCommands || !uiInfo->specifiesCoordinate() || uiInfo->isStandaloneCoordinate())) { list.append(QVariant::fromValue(uiInfo)); } } diff --git a/src/MissionManager/MissionCommandTree.h b/src/MissionManager/MissionCommandTree.h index 138843586..e55dc0812 100644 --- a/src/MissionManager/MissionCommandTree.h +++ b/src/MissionManager/MissionCommandTree.h @@ -62,7 +62,8 @@ public: const MissionCommandUIInfo* getUIInfo(Vehicle* vehicle, MAV_CMD command); - Q_INVOKABLE QVariantList getCommandsForCategory(Vehicle* vehicle, const QString& category); + /// @param showFlyThroughCommands - true: al commands shows, false: filter out commands which the vehicle flies through (specifiedCoordinate=true, standaloneCoordinate=false) + Q_INVOKABLE QVariantList getCommandsForCategory(Vehicle* vehicle, const QString& category, bool showFlyThroughCommands); // Overrides from QGCTool virtual void setToolbox(QGCToolbox* toolbox); diff --git a/src/MissionManager/MissionController.cc b/src/MissionManager/MissionController.cc index 74c6a109d..82a60931f 100644 --- a/src/MissionManager/MissionController.cc +++ b/src/MissionManager/MissionController.cc @@ -2181,14 +2181,16 @@ VisualMissionItem* MissionController::currentPlanViewItem(void) const void MissionController::setCurrentPlanViewIndex(int sequenceNumber, bool force) { if (_visualItems && (force || sequenceNumber != _currentPlanViewIndex)) { - bool foundLand = false; - int takeoffIndex = -1; + bool foundLand = false; + int takeoffIndex = -1; + int landIndex = -1; - _splitSegment = nullptr; - _currentPlanViewItem = nullptr; - _currentPlanViewIndex = -1; - _isInsertTakeoffValid = true; - _isInsertLandValid = true; + _splitSegment = nullptr; + _currentPlanViewItem = nullptr; + _currentPlanViewIndex = -1; + _isInsertTakeoffValid = true; + _isInsertLandValid = true; + _flyThroughCommandsAllowed = true; for (int i = 0; i < _visualItems->count(); i++) { VisualMissionItem* pVI = qobject_cast(_visualItems->get(i)); @@ -2214,6 +2216,7 @@ void MissionController::setCurrentPlanViewIndex(int sequenceNumber, bool force) case MAV_CMD_DO_LAND_START: case MAV_CMD_NAV_RETURN_TO_LAUNCH: foundLand = true; + landIndex = i; break; default: break; @@ -2222,6 +2225,7 @@ void MissionController::setCurrentPlanViewIndex(int sequenceNumber, bool force) FixedWingLandingComplexItem* fwLanding = qobject_cast(pVI); if (fwLanding) { foundLand = true; + landIndex = i; } } } @@ -2248,13 +2252,23 @@ void MissionController::setCurrentPlanViewIndex(int sequenceNumber, bool force) } } - if (takeoffIndex != -1 && sequenceNumber <= takeoffIndex) { - // Takeoff item was found which means mission starts from ground. - // Land is only valid after the takeoff item. - _isInsertLandValid = false; - } else if (foundLand) { - // Can't have to land sequences + if (takeoffIndex != -1) { + // Takeoff item was found which means mission starts from ground + if (sequenceNumber < takeoffIndex) { + // Land is only valid after the takeoff item. + _isInsertLandValid = false; + // Fly through commands are not allowed prior to the takeoff command + _flyThroughCommandsAllowed = false; + } + } + + if (foundLand) { + // Can't have more than one land sequence _isInsertLandValid = false; + if (sequenceNumber >= landIndex) { + // Can't have fly through commands after a land item + _flyThroughCommandsAllowed = false; + } } emit currentPlanViewIndexChanged(); @@ -2262,6 +2276,7 @@ void MissionController::setCurrentPlanViewIndex(int sequenceNumber, bool force) emit splitSegmentChanged(); emit isInsertTakeoffValidChanged(); emit isInsertLandValidChanged(); + emit flyThroughCommandsAllowedChanged(); } } diff --git a/src/MissionManager/MissionController.h b/src/MissionManager/MissionController.h index 1c5e22644..bcea44bb5 100644 --- a/src/MissionManager/MissionController.h +++ b/src/MissionManager/MissionController.h @@ -92,8 +92,9 @@ public: Q_PROPERTY(QString surveyComplexItemName READ surveyComplexItemName CONSTANT) Q_PROPERTY(QString corridorScanComplexItemName READ corridorScanComplexItemName CONSTANT) Q_PROPERTY(QString structureScanComplexItemName READ structureScanComplexItemName CONSTANT) - Q_PROPERTY(bool isInsertTakeoffValid MEMBER _isInsertTakeoffValid NOTIFY isInsertTakeoffValidChanged) ///< true: Takeoff tool should be enabled - Q_PROPERTY(bool isInsertLandValid MEMBER _isInsertLandValid NOTIFY isInsertLandValidChanged) ///< true: Land tool should be enabled + Q_PROPERTY(bool isInsertTakeoffValid MEMBER _isInsertTakeoffValid NOTIFY isInsertTakeoffValidChanged) + Q_PROPERTY(bool isInsertLandValid MEMBER _isInsertLandValid NOTIFY isInsertLandValidChanged) + Q_PROPERTY(bool flyThroughCommandsAllowed MEMBER _flyThroughCommandsAllowed NOTIFY flyThroughCommandsAllowedChanged) Q_INVOKABLE void removeMissionItem(int index); @@ -228,32 +229,33 @@ public: static const QString patternSurveyName; signals: - void visualItemsChanged (void); - void waypointPathChanged (void); - void splitSegmentChanged (void); - void newItemsFromVehicle (void); - void missionDistanceChanged (double missionDistance); - void missionTimeChanged (void); - void missionHoverDistanceChanged (double missionHoverDistance); - void missionHoverTimeChanged (void); - void missionCruiseDistanceChanged (double missionCruiseDistance); - void missionCruiseTimeChanged (void); - void missionMaxTelemetryChanged (double missionMaxTelemetry); - void complexMissionItemNamesChanged (void); - void resumeMissionIndexChanged (void); - void resumeMissionReady (void); - void resumeMissionUploadFail (void); - void batteryChangePointChanged (int batteryChangePoint); - void batteriesRequiredChanged (int batteriesRequired); - void plannedHomePositionChanged (QGeoCoordinate plannedHomePosition); - void progressPctChanged (double progressPct); - void currentMissionIndexChanged (int currentMissionIndex); - void currentPlanViewIndexChanged (void); - void currentPlanViewItemChanged (void); - void missionBoundingCubeChanged (void); - void missionItemCountChanged (int missionItemCount); - void isInsertTakeoffValidChanged (void); - void isInsertLandValidChanged (void); + void visualItemsChanged (void); + void waypointPathChanged (void); + void splitSegmentChanged (void); + void newItemsFromVehicle (void); + void missionDistanceChanged (double missionDistance); + void missionTimeChanged (void); + void missionHoverDistanceChanged (double missionHoverDistance); + void missionHoverTimeChanged (void); + void missionCruiseDistanceChanged (double missionCruiseDistance); + void missionCruiseTimeChanged (void); + void missionMaxTelemetryChanged (double missionMaxTelemetry); + void complexMissionItemNamesChanged (void); + void resumeMissionIndexChanged (void); + void resumeMissionReady (void); + void resumeMissionUploadFail (void); + void batteryChangePointChanged (int batteryChangePoint); + void batteriesRequiredChanged (int batteriesRequired); + void plannedHomePositionChanged (QGeoCoordinate plannedHomePosition); + void progressPctChanged (double progressPct); + void currentMissionIndexChanged (int currentMissionIndex); + void currentPlanViewIndexChanged (void); + void currentPlanViewItemChanged (void); + void missionBoundingCubeChanged (void); + void missionItemCountChanged (int missionItemCount); + void isInsertTakeoffValidChanged (void); + void isInsertLandValidChanged (void); + void flyThroughCommandsAllowedChanged (void); private slots: void _newMissionItemsAvailableFromVehicle(bool removeAllRequested); @@ -330,8 +332,9 @@ private: QGCGeoBoundingCube _travelBoundingCube; QGeoCoordinate _takeoffCoordinate; CoordinateVector* _splitSegment; - bool _isInsertTakeoffValid = true; - bool _isInsertLandValid = true; + bool _isInsertTakeoffValid = true; + bool _isInsertLandValid = true; + bool _flyThroughCommandsAllowed = true; static const char* _settingsGroup; diff --git a/src/MissionManager/SimpleMissionItem.cc b/src/MissionManager/SimpleMissionItem.cc index a276bc7f6..f8253dc5f 100644 --- a/src/MissionManager/SimpleMissionItem.cc +++ b/src/MissionManager/SimpleMissionItem.cc @@ -399,6 +399,7 @@ QString SimpleMissionItem::abbreviation() const case MAV_CMD_NAV_VTOL_LAND: return tr("VTOL Land"); case MAV_CMD_DO_SET_ROI: + case MAV_CMD_DO_SET_ROI_LOCATION: return tr("ROI"); default: return QString(); diff --git a/src/PlanView/MissionItemEditor.qml b/src/PlanView/MissionItemEditor.qml index ac8f8345b..870edd678 100644 --- a/src/PlanView/MissionItemEditor.qml +++ b/src/PlanView/MissionItemEditor.qml @@ -240,8 +240,9 @@ Rectangle { id: commandDialog MissionCommandDialog { - missionItem: _root.missionItem - map: _root.map + missionItem: _root.missionItem + map: _root.map + flyThroughCommandsAllowed: _missionController.flyThroughCommandsAllowed } } diff --git a/src/PlanView/PlanView.qml b/src/PlanView/PlanView.qml index 9c1a71e7c..76bfd9fa6 100644 --- a/src/PlanView/PlanView.qml +++ b/src/PlanView/PlanView.qml @@ -304,10 +304,8 @@ Item { /// @param coordinate Location to insert item /// @param index Insert item at this index function insertROIMissionItem(coordinate, index) { - var sequenceNumber = _missionController.insertROIMissionItem(coordinate, index) - _missionController.setCurrentPlanViewIndex(sequenceNumber, true) + _missionController.insertROIMissionItem(coordinate, index, true /* makeCurrentItem */) _addROIOnClick = false - toolStrip.lastClickedButton.checked = false } function selectNextNotReady() { @@ -491,6 +489,7 @@ Item { _addROIOnClick = false insertROIMissionItem(coordinate, _missionController.visualItems.count) } + break case _layerRallyPoints: if (_rallyPointController.supported && _addWaypointOnClick) { @@ -632,7 +631,8 @@ Item { readonly property int landButtonIndex: 6 readonly property int centerButtonIndex: 7 - property bool _isRally: _editingLayer == _layerRallyPoints + property bool _isRallyLayer: _editingLayer == _layerRallyPoints + property bool _isMissionLayer: _editingLayer == _layerMission model: [ { @@ -654,13 +654,13 @@ Item { name: qsTr("Takeoff"), iconSource: "/res/takeoff.svg", buttonEnabled: _missionController.isInsertTakeoffValid, - buttonVisible: _editingLayer == _layerMission + buttonVisible: _isMissionLayer }, { name: _editingLayer == _layerRallyPoints ? qsTr("Rally Point") : qsTr("Waypoint"), iconSource: "/qmlimages/MapAddMission.svg", - buttonEnabled: true, - buttonVisible: true, + buttonEnabled: _isRallyLayer ? true : _missionController.flyThroughCommandsAllowed, + buttonVisible: _isRallyLayer || _isMissionLayer, toggle: true, checked: _addWaypointOnClick }, @@ -668,21 +668,21 @@ Item { name: qsTr("ROI"), iconSource: "/qmlimages/MapAddMission.svg", buttonEnabled: true, - buttonVisible: !_isRally && _waypointsOnlyMode, + buttonVisible: _isMissionLayer, toggle: true }, { name: _singleComplexItem ? _missionController.complexMissionItemNames[0] : qsTr("Pattern"), iconSource: "/qmlimages/MapDrawShape.svg", - buttonEnabled: true, - buttonVisible: !_isRally, + buttonEnabled: _missionController.flyThroughCommandsAllowed, + buttonVisible: _isMissionLayer, dropPanelComponent: _singleComplexItem ? undefined : patternDropPanel }, { name: _planMasterController.controllerVehicle.fixedWing ? qsTr("Land") : qsTr("Return"), iconSource: "/res/rtl.svg", buttonEnabled: _missionController.isInsertLandValid, - buttonVisible: _editingLayer == _layerMission + buttonVisible: _isMissionLayer }, { name: qsTr("Center"), @@ -693,39 +693,49 @@ Item { } ] + function allAddClickBoolsOff() { + _addROIOnClick = false + _addWaypointOnClick = false + } + onClicked: { switch (index) { case flyButtonIndex: mainWindow.showFlyView() break case takeoffButtonIndex: + allAddClickBoolsOff() _missionController.insertTakeoffItem(mapCenter(), _missionController.currentMissionIndex, true /* makeCurrentItem */) break case waypointButtonIndex: - if(_addWaypointOnClick) { - //-- Toggle it off - _addWaypointOnClick = false - _addROIOnClick = false + if (_addWaypointOnClick) { + allAddClickBoolsOff() setChecked(index, false) } else { + allAddClickBoolsOff() _addWaypointOnClick = checked - _addROIOnClick = false } break case roiButtonIndex: + allAddClickBoolsOff() _addROIOnClick = checked - _addWaypointOnClick = false break case patternButtonIndex: + allAddClickBoolsOff() if (_singleComplexItem) { addComplexItem(_missionController.complexMissionItemNames[0]) } break case landButtonIndex: + allAddClickBoolsOff() _missionController.insertLandItem(mapCenter(), _missionController.currentMissionIndex, true /* makeCurrentItem */) break } } + + onDropped: { + allAddClickBoolsOff() + } } //----------------------------------------------------------- @@ -1257,8 +1267,6 @@ Item { } } } - - } } } diff --git a/src/QmlControls/MissionCommandDialog.qml b/src/QmlControls/MissionCommandDialog.qml index 9bc925a65..c36c3ad5c 100644 --- a/src/QmlControls/MissionCommandDialog.qml +++ b/src/QmlControls/MissionCommandDialog.qml @@ -19,8 +19,9 @@ import QGroundControl.Palette 1.0 QGCViewDialog { id: root - property var missionItem - property var map + property var missionItem + property var map + property bool flyThroughCommandsAllowed property var _vehicle: QGroundControl.multiVehicleManager.activeVehicle @@ -40,7 +41,7 @@ QGCViewDialog { model: QGroundControl.missionCommandTree.categoriesForVehicle(_vehicle) function categorySelected(category) { - commandList.model = QGroundControl.missionCommandTree.getCommandsForCategory(_vehicle, category) + commandList.model = QGroundControl.missionCommandTree.getCommandsForCategory(_vehicle, category, flyThroughCommandsAllowed) } Component.onCompleted: { @@ -97,7 +98,7 @@ QGCViewDialog { MouseArea { anchors.fill: parent onClicked: { - missionItem.setMapCenterHintForCommandChange(map.center) + missionItem.setMapCenterHintForCommandChange(map.center) missionItem.command = mavCmdInfo.command root.reject() } diff --git a/src/QmlControls/ToolStrip.qml b/src/QmlControls/ToolStrip.qml index be668af7f..6948e0dde 100644 --- a/src/QmlControls/ToolStrip.qml +++ b/src/QmlControls/ToolStrip.qml @@ -36,6 +36,7 @@ Rectangle { property real _idealWidth: (ScreenTools.isMobile ? ScreenTools.minTouchPixels : ScreenTools.defaultFontPixelWidth * 8) + toolStripColumn.anchors.margins * 2 signal clicked(int index, bool checked) + signal dropped(int index) function setChecked(idx, check) { repeater.itemAt(idx).checked = check @@ -88,6 +89,7 @@ Rectangle { } else if (checked) { var panelEdgeTopPoint = mapToItem(_root, width, 0) dropPanel.show(panelEdgeTopPoint, height, modelData.dropPanelComponent) + _root.dropped(index) } if(_root && buttonTemplate) _root.lastClickedButton = buttonTemplate -- 2.22.0