diff --git a/src/MissionManager/PlanMasterController.cc b/src/MissionManager/PlanMasterController.cc index fcab01ea5c956fc811c316df6968c0bed7087ed6..9375928a5988a952aea1fb5046d1fdd3e12a3021 100644 --- a/src/MissionManager/PlanMasterController.cc +++ b/src/MissionManager/PlanMasterController.cc @@ -155,37 +155,59 @@ void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle) connect(_managerVehicle->rallyPointManager(), &RallyPointManager::sendComplete, this, &PlanMasterController::_sendRallyPointsComplete); } - emit managerVehicleChanged(_managerVehicle); - - // Vehicle changed so we need to signal everything _offline = newOffline; - emit containsItemsChanged(containsItems()); - emit syncInProgressChanged(); - emit dirtyChanged(dirty()); emit offlineChanged(offline()); + emit managerVehicleChanged(_managerVehicle); - if (!_flyView) { - if (!offline()) { - // We are in Plan view and we have a newly connected vehicle: - // - If there is no plan available in Plan view show the one from the vehicle - // - Otherwise leave the current plan alone - if (!containsItems()) { - qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Plan view is empty so loading from manager"; - _showPlanFromManagerVehicle(); - } - } - } else { - if (offline()) { - // No more active vehicle, clear mission - qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Fly view is offline clearing plan"; + if (_flyView) { + // We are in the Fly View + if (newOffline) { + // No active vehicle, clear mission + qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Fly View - No active vehicle, clearing stale plan"; removeAll(); } else { // Fly view has changed to a new active vehicle, update to show correct mission - qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Fly view is online so loading from manager"; + qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Fly View - New active vehicle, loading new plan from manager vehicle"; _showPlanFromManagerVehicle(); } + } else { + // We are in the Plan view. + if (containsItems()) { + // The plan view has a stale plan in it + if (dirty()) { + // Plan is dirty, the user must decide what to do in all cases + qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Plan View - Previous dirty plan exists, no new active vehicle, sending promptForPlanUsageOnVehicleChange signal"; + emit promptForPlanUsageOnVehicleChange(); + } else { + // Plan is not dirty + if (newOffline) { + // The active vehicle went away with no new active vehicle + qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Plan View - Previous clean plan exists, no new active vehicle, clear stale plan"; + removeAll(); + } else { + // We are transitioning from one active vehicle to another. Show the plan from the new vehicle. + qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Plan View - Previous clean plan exists, new active vehicle, loading from new manager vehicle"; + _showPlanFromManagerVehicle(); + } + } + } else { + // There is no previous Plan in the view + if (newOffline) { + // Nothing special to do in this case + qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Plan View - No previous plan, no longer connected to vehicle, nothing to do"; + } else { + // Just show the plan from the new vehicle + qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Plan View - No previous plan, new active vehicle, loading from new manager vehicle"; + _showPlanFromManagerVehicle(); + } + } } + // Vehicle changed so we need to signal everything + emit containsItemsChanged(containsItems()); + emit syncInProgressChanged(); + emit dirtyChanged(dirty()); + _updatePlanCreatorsList(); } @@ -621,3 +643,16 @@ void PlanMasterController::_updatePlanCreatorsList(void) } } } + +void PlanMasterController::showPlanFromManagerVehicle(void) +{ + if (offline()) { + // There is no new vehicle so clear any previous plan + qCDebug(PlanMasterControllerLog) << "showPlanFromManagerVehicle: Plan View - No new vehicle, clear any previous plan"; + removeAll(); + } else { + // We have a new active vehicle, show the plan from that + qCDebug(PlanMasterControllerLog) << "showPlanFromManagerVehicle: Plan View - New vehicle available, show plan from new manager vehicle"; + _showPlanFromManagerVehicle(); + } +} diff --git a/src/MissionManager/PlanMasterController.h b/src/MissionManager/PlanMasterController.h index cd25156e564d4892829e389afdf60d3a58620eb2..4dbb889dcdb976094d2d9ebd4de1be58db6f4608 100644 --- a/src/MissionManager/PlanMasterController.h +++ b/src/MissionManager/PlanMasterController.h @@ -64,6 +64,9 @@ public: /// a nightmare of circular header dependency problems. Q_INVOKABLE int readyForSaveState(void) const { return _missionController.readyForSaveState(); } + /// Replaces any current plan with the plan from the manager vehicle even if offline. + Q_INVOKABLE void showPlanFromManagerVehicle(void); + /// Sends a plan to the specified file /// @param[in] vehicle Vehicle we are sending a plan to /// @param[in] filename Plan file to load @@ -108,13 +111,14 @@ public: static const char* kJsonRallyPointsObjectKey; signals: - void containsItemsChanged (bool containsItems); - void syncInProgressChanged (void); - void dirtyChanged (bool dirty); - void offlineChanged (bool offlineEditing); - void currentPlanFileChanged (); - void planCreatorsChanged (QmlObjectListModel* planCreators); - void managerVehicleChanged (Vehicle* managerVehicle); + void containsItemsChanged (bool containsItems); + void syncInProgressChanged (void); + void dirtyChanged (bool dirty); + void offlineChanged (bool offlineEditing); + void currentPlanFileChanged (void); + void planCreatorsChanged (QmlObjectListModel* planCreators); + void managerVehicleChanged (Vehicle* managerVehicle); + void promptForPlanUsageOnVehicleChange (void); private slots: void _activeVehicleChanged (Vehicle* activeVehicle); diff --git a/src/PlanView/PlanView.qml b/src/PlanView/PlanView.qml index ef1151ee84962e1679e51336568cdb92891cf309..407efb451e32bd5d89364e8345bdd03ec0f21831 100644 --- a/src/PlanView/PlanView.qml +++ b/src/PlanView/PlanView.qml @@ -53,6 +53,7 @@ Item { property int _toolStripBottom: toolStrip.height + toolStrip.y property var _appSettings: QGroundControl.settingsManager.appSettings property var _planViewSettings: QGroundControl.settingsManager.planViewSettings + property bool _promptForPlanUsageShowing: false readonly property var _layers: [_layerMission, _layerGeoFence, _layerRallyPoints] @@ -134,6 +135,53 @@ Item { } } + Component { + id: promptForPlanUsageOnVehicleChangePopupComponent + QGCPopupDialog { + title: _planMasterController.managerVehicle.isOfflineEditingVehicle ? qsTr("Plan View - Vehicle Disconnected") : qsTr("Plan View - Vehicle Changed") + buttons: StandardButton.NoButton + + ColumnLayout { + QGCLabel { + Layout.maximumWidth: parent.width + wrapMode: QGCLabel.WordWrap + text: _planMasterController.managerVehicle.isOfflineEditingVehicle ? + qsTr("The vehicle associated with the plan in the Plan View is no longer available. What would you like to do with that plan?") : + qsTr("The plan being worked on in the Plan View is not from the current vehicle. What would you like to do with that plan?") + } + + QGCButton { + Layout.fillWidth: true + text: _planMasterController.dirty ? + (_planMasterController.managerVehicle.isOfflineEditingVehicle ? + qsTr("Discard Unsaved Changes") : + qsTr("Discard Unsaved Changes, Load New Plan From Vehicle")) : + qsTr("Load New Plan From Vehicle") + onClicked: { + _planMasterController.showPlanFromManagerVehicle() + _promptForPlanUsageShowing = false + hideDialog(); + } + } + + QGCButton { + Layout.fillWidth: true + text: _planMasterController.managerVehicle.isOfflineEditingVehicle ? + qsTr("Keep Current Plan") : + qsTr("Keep Current Plan, Don't Update From Vehicle") + onClicked: { + if (!_planMasterController.managerVehicle.isOfflineEditingVehicle) { + _planMasterController.dirty = true + } + _promptForPlanUsageShowing = false + hideDialog() + } + } + } + } + } + + Component { id: firmwareOrVehicleMismatchUploadDialogComponent QGCViewMessage { @@ -173,6 +221,13 @@ Item { mainWindow.planMasterControllerPlanView = _planMasterController } + onPromptForPlanUsageOnVehicleChange: { + if (!_promptForPlanUsageShowing) { + _promptForPlanUsageShowing = true + mainWindow.showPopupDialogFromComponent(promptForPlanUsageOnVehicleChangePopupComponent) + } + } + function waitingOnIncompleteDataMessage(save) { var saveOrUpload = save ? qsTr("Save") : qsTr("Upload") mainWindow.showMessageDialog(qsTr("Unable to %1").arg(saveOrUpload), qsTr("Plan has incomplete items. Complete all items and %1 again.").arg(saveOrUpload))