diff --git a/src/FlightDisplay/GuidedActionsController.qml b/src/FlightDisplay/GuidedActionsController.qml index 533907b4e0f..95e026ae61f 100644 --- a/src/FlightDisplay/GuidedActionsController.qml +++ b/src/FlightDisplay/GuidedActionsController.qml @@ -105,9 +105,12 @@ Item { readonly property int actionStepAlt: 25 property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + property var _planMasterController: globals.planMasterControllerPlanView + property bool _syncInProgress: _planMasterController.syncInProgress + property bool _dirty: _planMasterController.dirty property bool _useChecklist: QGroundControl.settingsManager.appSettings.useChecklist.rawValue && QGroundControl.corePlugin.options.preFlightChecklistUrl.toString().length property bool _enforceChecklist: _useChecklist && QGroundControl.settingsManager.appSettings.enforceChecklist.rawValue - property bool _canArm: _activeVehicle ? (_useChecklist ? (_enforceChecklist ? _activeVehicle.checkListState === Vehicle.CheckListPassed : true) : true) : false + property bool _canArm: canArm() property bool showEmergenyStop: _guidedActionsEnabled && !_hideEmergenyStop && _vehicleArmed && _vehicleFlying property bool showArm: _guidedActionsEnabled && !_vehicleArmed && _canArm @@ -283,6 +286,41 @@ Item { function onVtolTransitionToMRFlightRequest() { vtolTransitionToMRFlightRequest() } } + Connections { + target: _activeVehicle + function onRallyPointManagerErrorChanged() { + _canArm = canArm() + } + function onGeoFenceManagerErrorChanged() { + _canArm = canArm() + } + function onMissionManagerErrorChanged() { + _canArm = canArm() + } + } + + Connections { + target: _planMasterController + function onSyncInProgressChanged() { + _syncInProgress = _planMasterController.syncInProgress + _canArm = canArm() + } + function onDirtyChanged() { + _dirty = _planMasterController.dirty + _canArm = canArm() + } + } + + + + function planError() { + return _activeVehicle && (_activeVehicle.missionManagerError != "" || _activeVehicle.geoFenceManagerError != "" || _activeVehicle.rallyPointManagerError != "") + } + + function canArm() { + return _activeVehicle ? !planError() && !_dirty && (_useChecklist ? (_enforceChecklist ? _activeVehicle.checkListState === Vehicle.CheckListPassed : true) : true) && !_syncInProgress : false + } + function armVehicleRequest() { confirmAction(actionArm) } diff --git a/src/MissionManager/AviantMissionTools.cc b/src/MissionManager/AviantMissionTools.cc index 968bf67963c..bee7705a8d3 100644 --- a/src/MissionManager/AviantMissionTools.cc +++ b/src/MissionManager/AviantMissionTools.cc @@ -368,7 +368,11 @@ void AviantMissionTools::_parseAndLoadMissionResponse(const QByteArray &bytes) tr("Mission Tools - ") + _getOperationName(_currentOperation)); return; } - + + if (_currentOperation == FetchKyteOrderMissionFile) { + _masterController->clearCurrentPlanFile(); + } + qgcApp()->showAppMessage(tr("Operation successful"), tr("Mission Tools - ") + _getOperationName(_currentOperation)); } diff --git a/src/MissionManager/GeoFenceController.cc b/src/MissionManager/GeoFenceController.cc index b084c3b4759..2077b7fc739 100644 --- a/src/MissionManager/GeoFenceController.cc +++ b/src/MissionManager/GeoFenceController.cc @@ -114,6 +114,7 @@ void GeoFenceController::_managerVehicleChanged(Vehicle* managerVehicle) connect(_geoFenceManager, &GeoFenceManager::sendComplete, this, &GeoFenceController::_managerSendComplete); connect(_geoFenceManager, &GeoFenceManager::removeAllComplete, this, &GeoFenceController::_managerRemoveAllComplete); connect(_geoFenceManager, &GeoFenceManager::inProgressChanged, this, &GeoFenceController::syncInProgressChanged); + connect(_geoFenceManager, &GeoFenceManager::progressPct, this, &GeoFenceController::_progressPctChanged); //-- GeoFenceController::supported() tests both the capability bit AND the protocol version. connect(_managerVehicle, &Vehicle::capabilityBitsChanged, this, &GeoFenceController::supportedChanged); @@ -352,6 +353,7 @@ void GeoFenceController::_managerLoadComplete(void) emit loadComplete(); } _itemsRequested = false; + _managerVehicle->clearGeoFenceManagerError(); } void GeoFenceController::_managerSendComplete(bool error) @@ -522,6 +524,14 @@ void GeoFenceController::_parametersReady(void) emit paramCircularFenceChanged(); } +void GeoFenceController::_progressPctChanged(double progressPct) +{ + if (!QGC::fuzzyCompare(progressPct, _progressPct)) { + _progressPct = progressPct; + emit progressPctChanged(progressPct); + } +} + bool GeoFenceController::isEmpty(void) const { return _polygons.count() == 0 && _circles.count() == 0 && !_breachReturnPoint.isValid(); diff --git a/src/MissionManager/GeoFenceController.h b/src/MissionManager/GeoFenceController.h index 3a0d750c2d4..e16c2454a61 100644 --- a/src/MissionManager/GeoFenceController.h +++ b/src/MissionManager/GeoFenceController.h @@ -35,6 +35,7 @@ class GeoFenceController : public PlanElementController Q_PROPERTY(QGeoCoordinate breachReturnPoint READ breachReturnPoint WRITE setBreachReturnPoint NOTIFY breachReturnPointChanged) Q_PROPERTY(Fact* breachReturnAltitude READ breachReturnAltitude CONSTANT) Q_PROPERTY(QStringList fenceActions READ fenceActions CONSTANT) + Q_PROPERTY(double progressPct READ progressPct NOTIFY progressPctChanged) // Hack to expose PX4 circular fence controlled by GF_MAX_HOR_DIST Q_PROPERTY(double paramCircularFence READ paramCircularFence NOTIFY paramCircularFenceChanged) @@ -83,14 +84,16 @@ class GeoFenceController : public PlanElementController QmlObjectListModel* circles (void) { return &_circles; } QGeoCoordinate breachReturnPoint (void) const { return _breachReturnPoint; } - void setBreachReturnPoint (const QGeoCoordinate& breachReturnPoint); - bool isEmpty (void) const; + void setBreachReturnPoint (const QGeoCoordinate& breachReturnPoint); + bool isEmpty (void) const; + double progressPct (void) const { return _progressPct; } signals: void breachReturnPointChanged (QGeoCoordinate breachReturnPoint); void editorQmlChanged (QString editorQml); void loadComplete (void); void paramCircularFenceChanged (void); + void progressPctChanged (double progressPct); private slots: void _polygonDirtyChanged (bool dirty); @@ -102,7 +105,8 @@ private slots: void _managerSendComplete (bool error); void _managerRemoveAllComplete (bool error); void _parametersReady (void); - void _managerVehicleChanged (Vehicle* managerVehicle); + void _managerVehicleChanged (Vehicle* managerVehicle); + void _progressPctChanged (double progressPct); private: void _init(void); @@ -117,6 +121,7 @@ private slots: double _breachReturnDefaultAltitude = qQNaN(); bool _itemsRequested = false; Fact* _px4ParamCircularFenceFact = nullptr; + double _progressPct = 0; static QMap _metaDataMap; diff --git a/src/MissionManager/MissionController.cc b/src/MissionManager/MissionController.cc index cac624d0fc0..5f512cfe24a 100644 --- a/src/MissionManager/MissionController.cc +++ b/src/MissionManager/MissionController.cc @@ -203,7 +203,7 @@ void MissionController::_newMissionItemsAvailableFromVehicle(bool removeAllReque _visualItems = newControllerMissionItems; _settingsItem = settingsItem; - + _managerVehicle->clearMissionManagerError(); MissionController::_scanForAdditionalSettings(_visualItems, _masterController); _initAllVisualItems(); diff --git a/src/MissionManager/PlanMasterController.cc b/src/MissionManager/PlanMasterController.cc index 2f90ed7dd19..8ae08444ad5 100644 --- a/src/MissionManager/PlanMasterController.cc +++ b/src/MissionManager/PlanMasterController.cc @@ -437,6 +437,12 @@ void PlanMasterController::loadFromFile(const QString& filename) } } +void PlanMasterController::clearCurrentPlanFile() +{ + _currentPlanFile.clear(); + emit currentPlanFileChanged(); +} + QJsonDocument PlanMasterController::saveToJson() { QJsonObject planJson; @@ -588,6 +594,7 @@ void PlanMasterController::removeAllFromVehicle(void) if (_rallyPointController.supported()) { _rallyPointController.removeAllFromVehicle(); } + _currentPlanFile.clear(); setDirty(false); } else { qWarning() << "PlanMasterController::removeAllFromVehicle called while offline"; diff --git a/src/MissionManager/PlanMasterController.h b/src/MissionManager/PlanMasterController.h index 93a4640bd60..8228612109b 100644 --- a/src/MissionManager/PlanMasterController.h +++ b/src/MissionManager/PlanMasterController.h @@ -105,6 +105,8 @@ class PlanMasterController : public QObject QJsonDocument saveToJson (); bool loadFromJson (QJsonDocument jsonDoc, QString &errorString); + void clearCurrentPlanFile (); + Vehicle* controllerVehicle(void) { return _controllerVehicle; } Vehicle* managerVehicle(void) { return _managerVehicle; } diff --git a/src/MissionManager/RallyPointController.cc b/src/MissionManager/RallyPointController.cc index 07354956f81..390b2415471 100644 --- a/src/MissionManager/RallyPointController.cc +++ b/src/MissionManager/RallyPointController.cc @@ -71,6 +71,7 @@ void RallyPointController::_managerVehicleChanged(Vehicle* managerVehicle) connect(_rallyPointManager, &RallyPointManager::sendComplete, this, &RallyPointController::_managerSendComplete); connect(_rallyPointManager, &RallyPointManager::removeAllComplete, this, &RallyPointController::_managerRemoveAllComplete); connect(_rallyPointManager, &RallyPointManager::inProgressChanged, this, &RallyPointController::syncInProgressChanged); + connect(_rallyPointManager, &RallyPointManager::progressPct, this, &RallyPointController::_progressPctChanged); //-- RallyPointController::supported() tests both the capability bit AND the protocol version. connect(_managerVehicle, &Vehicle::capabilityBitsChanged, this, &RallyPointController::supportedChanged); @@ -246,6 +247,7 @@ void RallyPointController::_managerLoadComplete(void) setDirty(false); _setFirstPointCurrent(); emit loadComplete(); + _managerVehicle->clearRallyPointManagerError(); } _itemsRequested = false; } @@ -357,6 +359,14 @@ bool RallyPointController::showPlanFromManagerVehicle (void) } } +void RallyPointController::_progressPctChanged(double progressPct) +{ + if (!QGC::fuzzyCompare(progressPct, _progressPct)) { + _progressPct = progressPct; + emit progressPctChanged(progressPct); + } +} + bool RallyPointController::isEmpty(void) const { return _points.count() == 0; diff --git a/src/MissionManager/RallyPointController.h b/src/MissionManager/RallyPointController.h index 04651977512..ea97d200db8 100644 --- a/src/MissionManager/RallyPointController.h +++ b/src/MissionManager/RallyPointController.h @@ -32,6 +32,7 @@ class RallyPointController : public PlanElementController Q_PROPERTY(QmlObjectListModel* points READ points CONSTANT) Q_PROPERTY(QString editorQml READ editorQml CONSTANT) Q_PROPERTY(QObject* currentRallyPoint READ currentRallyPoint WRITE setCurrentRallyPoint NOTIFY currentRallyPointChanged) + Q_PROPERTY(double progressPct READ progressPct NOTIFY progressPctChanged) Q_INVOKABLE void addPoint (QGeoCoordinate point); Q_INVOKABLE void removePoint (QObject* rallyPoint); @@ -54,12 +55,14 @@ class RallyPointController : public PlanElementController QString editorQml (void) const; QObject* currentRallyPoint (void) const { return _currentRallyPoint; } - void setCurrentRallyPoint (QObject* rallyPoint); - bool isEmpty (void) const; + void setCurrentRallyPoint (QObject* rallyPoint); + bool isEmpty (void) const; + double progressPct (void) const { return _progressPct; } signals: void currentRallyPointChanged(QObject* rallyPoint); void loadComplete(void); + void progressPctChanged (double progressPct); private slots: void _managerLoadComplete (void); @@ -68,6 +71,7 @@ private slots: void _setFirstPointCurrent (void); void _updateContainsItems (void); void _managerVehicleChanged (Vehicle* managerVehicle); + void _progressPctChanged (double progressPct); private: Vehicle* _managerVehicle = nullptr; @@ -76,6 +80,7 @@ private slots: QmlObjectListModel _points; QObject* _currentRallyPoint = nullptr; bool _itemsRequested = false; + double _progressPct = 0; static const int _jsonCurrentVersion = 2; static const int _jsonCurrentVersionWithRPType = 102; diff --git a/src/PlanView/PlanToolBarIndicators.qml b/src/PlanView/PlanToolBarIndicators.qml index fb852c1f6c0..75ae9953335 100644 --- a/src/PlanView/PlanToolBarIndicators.qml +++ b/src/PlanView/PlanToolBarIndicators.qml @@ -85,47 +85,13 @@ Item { return complete } - // Progress bar - Connections { - target: _controllerValid ? _planMasterController.missionController : null - onProgressPctChanged: { - if (_controllerProgressPct === 1) { - missionStats.visible = false - uploadCompleteText.visible = true - progressBar.visible = false - resetProgressTimer.start() - } else if (_controllerProgressPct > 0) { - progressBar.visible = true - } - } - } - - Timer { - id: resetProgressTimer - interval: 5000 - onTriggered: { - missionStats.visible = true - uploadCompleteText.visible = false - } - } - - QGCLabel { - id: uploadCompleteText - anchors.fill: parent - font.pointSize: ScreenTools.largeFontPointSize - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - text: qsTr("Done") - visible: false - } - GridLayout { id: missionStats anchors.top: parent.top anchors.bottom: parent.bottom anchors.leftMargin: _margins anchors.left: parent.left - columnSpacing: 0 + columnSpacing: _smallValueWidth columns: 5 GridLayout { @@ -162,7 +128,6 @@ Item { QGCLabel { text: _distanceText font.pointSize: _dataFontSize - Layout.minimumWidth: _largeValueWidth } QGCLabel { text: qsTr("Gradient:"); font.pointSize: _dataFontSize; } @@ -207,7 +172,6 @@ Item { QGCLabel { text: _missionMaxTelemetryText font.pointSize: _dataFontSize - Layout.minimumWidth: _largeValueWidth } QGCLabel { text: qsTr("Time:"); font.pointSize: _dataFontSize; } @@ -245,7 +209,7 @@ Item { id: uploadButton text: _controllerDirty ? qsTr("Upload Required") : qsTr("Upload") enabled: !_controllerSyncInProgress - visible: !_controllerOffline && !_controllerSyncInProgress && !uploadCompleteText.visible + visible: !_controllerOffline && !_controllerSyncInProgress primary: _controllerDirty onClicked: _planMasterController.upload() @@ -282,70 +246,6 @@ Item { return parts.pop(); } } - Item { width: 1; height: 1 } - } - } - - // Small mission download progress bar - Rectangle { - id: progressBar - anchors.left: parent.left - anchors.bottom: parent.bottom - height: 4 - width: _controllerProgressPct * parent.width - color: qgcPal.colorGreen - visible: false - - onVisibleChanged: { - if (visible) { - largeProgressBar._userHide = false - } - } - } - - // Large mission download progress bar - Rectangle { - id: largeProgressBar - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - height: parent.height - color: qgcPal.window - visible: _showLargeProgress - - property bool _userHide: false - property bool _showLargeProgress: progressBar.visible && !_userHide && qgcPal.globalTheme === QGCPalette.Light - - Connections { - target: QGroundControl.multiVehicleManager - onActiveVehicleChanged: largeProgressBar._userHide = false - } - - Rectangle { - anchors.top: parent.top - anchors.bottom: parent.bottom - width: _controllerProgressPct * parent.width - color: qgcPal.colorGreen - } - - QGCLabel { - anchors.centerIn: parent - text: qsTr("Syncing Mission") - font.pointSize: ScreenTools.largeFontPointSize - } - - QGCLabel { - anchors.margins: _margin - anchors.right: parent.right - anchors.bottom: parent.bottom - text: qsTr("Click anywhere to hide") - - property real _margin: ScreenTools.defaultFontPixelWidth / 2 - } - - MouseArea { - anchors.fill: parent - onClicked: largeProgressBar._userHide = true } } } diff --git a/src/PlanView/PlanView.qml b/src/PlanView/PlanView.qml index 1ff22b44844..022173a30f4 100644 --- a/src/PlanView/PlanView.qml +++ b/src/PlanView/PlanView.qml @@ -400,12 +400,15 @@ Item { globals.planMasterControllerPlanView = _planMasterController } + /* + We never want to discard the mission in plan view, so we remove the popup alltogehter onPromptForPlanUsageOnVehicleChange: { if (!_promptForPlanUsageShowing) { _promptForPlanUsageShowing = true mainWindow.showPopupDialogFromComponent(promptForPlanUsageOnVehicleChangePopupComponent) } } + */ function waitingOnIncompleteDataMessage(save) { var saveOrUpload = save ? qsTr("Save") : qsTr("Upload") @@ -478,10 +481,6 @@ Item { fileDialog.nameFilters = ShapeFileHelper.fileDialogKMLFilters fileDialog.openForSave() } - - function browseKyteOrders() { - mainWindow.showPopupDialogFromComponent(promptForBrowsingKyteOrders) - } } Connections { @@ -1053,7 +1052,7 @@ Item { map: editorMap masterController: _planMasterController missionItem: object - width: parent.width + width: parent ? parent.width : 0 readOnly: false onClicked: _missionController.setCurrentPlanViewSeqNum(object.sequenceNumber, false) onRemove: { @@ -1404,7 +1403,7 @@ Item { enabled: !_planMasterController.syncInProgress && _aviantSettings.kyteBackendUrl.rawValue != "" onClicked: { dropPanel.hide() - _planMasterController.browseKyteOrders() + mainWindow.showPopupDialogFromComponent(promptForBrowsingKyteOrders) } } } diff --git a/src/PlanView/RallyPointMapVisuals.qml b/src/PlanView/RallyPointMapVisuals.qml index 0276bb02a6c..a163eebcc24 100644 --- a/src/PlanView/RallyPointMapVisuals.qml +++ b/src/PlanView/RallyPointMapVisuals.qml @@ -46,12 +46,16 @@ Item { MissionItemIndicatorDrag { mapControl: _root.map - itemCoordinate: rallyPointObject.coordinate + itemCoordinate: rallyPointObject ? rallyPointObject.coordinate : null visible: rallyPointObject === myRallyPointController.currentRallyPoint && _root.interactive property var rallyPointObject - onItemCoordinateChanged: rallyPointObject.coordinate = itemCoordinate + onItemCoordinateChanged: { + if (rallyPointObject) { + rallyPointObject.coordinate = itemCoordinate + } + } } } @@ -70,11 +74,15 @@ Item { sourceItem: MissionItemIndexLabel { id: itemIndexLabel // Rally point types: 0=Always, 1=MR only, 2=FW only - label: rallyPointObject.type == 2 ? "F" : rallyPointObject.type == 1 ? "M" : "R" - important: rallyPointObject.type == 2 - checked: _editingLayer == _layerRallyPoints ? rallyPointObject === myRallyPointController.currentRallyPoint : false + label: rallyPointObject && rallyPointObject.type !== undefined + ? (rallyPointObject.type == 2 ? "F" : rallyPointObject.type == 1 ? "M" : "R") + : "R" + important: rallyPointObject ? (rallyPointObject.type == 2) : false + checked: rallyPointObject + ? (_editingLayer == _layerRallyPoints ? rallyPointObject === myRallyPointController.currentRallyPoint : false) + : false highlightSelected: true - onClicked: myRallyPointController.currentRallyPoint = rallyPointObject + onClicked: if (rallyPointObject) { myRallyPointController.currentRallyPoint = rallyPointObject } } } } diff --git a/src/Vehicle/Vehicle.cc b/src/Vehicle/Vehicle.cc index 8dbcdab1c93..6531cc35951 100644 --- a/src/Vehicle/Vehicle.cc +++ b/src/Vehicle/Vehicle.cc @@ -2266,18 +2266,49 @@ void Vehicle::_missionManagerError(int errorCode, const QString& errorMsg) { Q_UNUSED(errorCode); qgcApp()->showAppMessage(tr("Mission transfer failed. Error: %1").arg(errorMsg)); + if (_missionManagerErrorMsg != errorMsg) { + _missionManagerErrorMsg = errorMsg; + emit missionManagerErrorChanged(); + } +} + +void Vehicle::clearMissionManagerError() +{ + _missionManagerErrorMsg = ""; + emit missionManagerErrorChanged(); } void Vehicle::_geoFenceManagerError(int errorCode, const QString& errorMsg) { Q_UNUSED(errorCode); qgcApp()->showAppMessage(tr("GeoFence transfer failed. Error: %1").arg(errorMsg)); + if (_geoFenceManagerErrorMsg != errorMsg) { + _geoFenceManagerErrorMsg = errorMsg; + emit geoFenceManagerErrorChanged(); + } +} + +void Vehicle::clearGeoFenceManagerError() +{ + _geoFenceManagerErrorMsg = ""; + emit geoFenceManagerErrorChanged(); } void Vehicle::_rallyPointManagerError(int errorCode, const QString& errorMsg) { Q_UNUSED(errorCode); qgcApp()->showAppMessage(tr("Rally Point transfer failed. Error: %1").arg(errorMsg)); + if (_rallyPointManagerErrorMsg != errorMsg) { + qDebug() << "Rally Point transfer failed. Error: " << errorMsg; + _rallyPointManagerErrorMsg = errorMsg; + emit rallyPointManagerErrorChanged(); + } +} + +void Vehicle::clearRallyPointManagerError() +{ + _rallyPointManagerErrorMsg = ""; + emit rallyPointManagerErrorChanged(); } void Vehicle::_clearCameraTriggerPoints() diff --git a/src/Vehicle/Vehicle.h b/src/Vehicle/Vehicle.h index 02161ccdf07..7585ea1ae17 100644 --- a/src/Vehicle/Vehicle.h +++ b/src/Vehicle/Vehicle.h @@ -259,6 +259,9 @@ class Vehicle : public FactGroup Q_PROPERTY(bool requiresGpsFix READ requiresGpsFix NOTIFY requiresGpsFixChanged) Q_PROPERTY(double loadProgress READ loadProgress NOTIFY loadProgressChanged) Q_PROPERTY(bool initialConnectComplete READ isInitialConnectComplete NOTIFY initialConnectComplete) + Q_PROPERTY(QString missionManagerError READ missionManagerError NOTIFY missionManagerErrorChanged) + Q_PROPERTY(QString geoFenceManagerError READ geoFenceManagerError NOTIFY geoFenceManagerErrorChanged) + Q_PROPERTY(QString rallyPointManagerError READ rallyPointManagerError NOTIFY rallyPointManagerErrorChanged) // The following properties relate to Orbit status Q_PROPERTY(bool orbitActive READ orbitActive NOTIFY orbitActiveChanged) @@ -526,6 +529,10 @@ class Vehicle : public FactGroup QString prearmError() const { return _prearmError; } void setPrearmError(const QString& prearmError); + void clearRallyPointManagerError(); + void clearGeoFenceManagerError(); + void clearMissionManagerError(); + QmlObjectListModel* cameraTriggerPoints () { return &_cameraTriggerPoints; } int flowImageIndex() const{ return _flowImageIndex; } @@ -559,6 +566,9 @@ class Vehicle : public FactGroup int messageCount () const{ return _messageCount; } QString formattedMessages (); QString latestError () { return _latestError; } + QString missionManagerError () const { return _missionManagerErrorMsg; } + QString rallyPointManagerError () const { return _rallyPointManagerErrorMsg; } + QString geoFenceManagerError () const { return _geoFenceManagerErrorMsg; } float latitude () { return static_cast(_coordinate.latitude()); } float longitude () { return static_cast(_coordinate.longitude()); } bool mavPresent () { return _mav != nullptr; } @@ -853,6 +863,9 @@ public slots: void handleNewCriticalVehicleMessage (UASMessage* message); signals: + void missionManagerErrorChanged(); + void geoFenceManagerErrorChanged(); + void rallyPointManagerErrorChanged(); void coordinateChanged (QGeoCoordinate coordinate); void positionSetpointChanged (QGeoCoordinate positionSetpoint); void joystickEnabledChanged (bool enabled); @@ -1119,7 +1132,9 @@ private slots: bool _readyToFlyAvailable = false; bool _readyToFly = false; bool _allSensorsHealthy = true; - + QString _missionManagerErrorMsg; + QString _geoFenceManagerErrorMsg; + QString _rallyPointManagerErrorMsg; SysStatusSensorInfo _sysStatusSensorInfo; QGCCameraManager* _cameraManager = nullptr; diff --git a/src/ui/toolbar/MainStatusIndicator.qml b/src/ui/toolbar/MainStatusIndicator.qml index 67fbd81594d..120db24219c 100644 --- a/src/ui/toolbar/MainStatusIndicator.qml +++ b/src/ui/toolbar/MainStatusIndicator.qml @@ -27,6 +27,11 @@ RowLayout { property real _margins: ScreenTools.defaultFontPixelWidth property real _spacing: ScreenTools.defaultFontPixelWidth / 2 + property var _planMasterController: globals.planMasterControllerPlanView + property bool _syncInProgress: _planMasterController.syncInProgress + property bool _dirty: _planMasterController.dirty + + QGCLabel { id: mainStatusLabel text: mainStatusText() @@ -58,7 +63,27 @@ RowLayout { } } else { if (_activeVehicle.readyToFlyAvailable) { - if (_activeVehicle.readyToFly) { + if (_syncInProgress) { + _mainStatusBGColor = "yellow" + return "Syncing mission..." + } + else if (_activeVehicle.missionManagerError) { + _mainStatusBGColor = "red" + return "Error syncing mission: " + _activeVehicle.missionManagerError + } + else if (_activeVehicle.geoFenceManagerError) { + _mainStatusBGColor = "red" + return "Error syncing geofence: " + _activeVehicle.geoFenceManagerError + } + else if (_activeVehicle.rallyPointManagerError) { + _mainStatusBGColor = "red" + return "Error syncing rally points: " + _activeVehicle.rallyPointManagerError + } + else if (_dirty) { + _mainStatusBGColor = "yellow" + return qsTr("Mission not uploaded to vehicle") + } + else if (_activeVehicle.readyToFly) { _mainStatusBGColor = "green" return mainStatusLabel._readyToFlyText } else { diff --git a/src/ui/toolbar/MainToolBar.qml b/src/ui/toolbar/MainToolBar.qml index d1069c2a2e9..f57e5489288 100644 --- a/src/ui/toolbar/MainToolBar.qml +++ b/src/ui/toolbar/MainToolBar.qml @@ -29,9 +29,14 @@ Rectangle { readonly property int planViewToolbar: 1 readonly property int simpleToolbar: 2 - property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle - property bool _communicationLost: _activeVehicle ? _activeVehicle.vehicleLinkManager.communicationLost : false - property color _mainStatusBGColor: qgcPal.brandingPurple + property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + property bool _communicationLost: _activeVehicle ? _activeVehicle.vehicleLinkManager.communicationLost : false + property color _mainStatusBGColor: qgcPal.brandingPurple + property var _planMasterController: globals.planMasterControllerPlanView + property bool _controllerValid: _planMasterController !== undefined && _planMasterController !== null + property real _missionControllerProgressPct: (_controllerValid && _planMasterController) ? _planMasterController.missionController.progressPct : 0 + property real _rallyPointControllerProgressPct: (_controllerValid && _planMasterController) ? _planMasterController.rallyPointController.progressPct : 0 + property real _geoFenceControllerProgressPct: (_controllerValid && _planMasterController) ? _planMasterController.geoFenceController.progressPct : 0 QGCPalette { id: qgcPal } @@ -161,12 +166,39 @@ Rectangle { } } + // Geofence download progress bar + Rectangle { + anchors.bottom: parent.bottom + height: _root.height * 0.075 + width: _geoFenceControllerProgressPct * parent.width + color: qgcPal.colorBlue + visible: _geoFenceControllerProgressPct > 0 && _geoFenceControllerProgressPct < 1 && !largeProgressBar.visible + } + + // Rally point download progress bar + Rectangle { + anchors.bottom: parent.bottom + height: _root.height * 0.075 + width: _rallyPointControllerProgressPct * parent.width + color: qgcPal.colorBlue + visible: _rallyPointControllerProgressPct > 0 && _rallyPointControllerProgressPct < 1 && !largeProgressBar.visible + } + + // Mission download progress bar + Rectangle { + anchors.bottom: parent.bottom + height: _root.height * 0.075 + width: _missionControllerProgressPct * parent.width + color: qgcPal.colorBlue + visible: _missionControllerProgressPct > 0 && _missionControllerProgressPct < 1 && !largeProgressBar.visible + } + // Small parameter download progress bar Rectangle { anchors.bottom: parent.bottom - height: _root.height * 0.05 + height: _root.height * 0.075 width: _activeVehicle ? _activeVehicle.loadProgress * parent.width : 0 - color: qgcPal.colorGreen + color: qgcPal.colorBlue visible: !largeProgressBar.visible } @@ -189,17 +221,63 @@ Rectangle { function onActiveVehicleChanged(activeVehicle) { largeProgressBar._userHide = false } } + // Geofence download progress Rectangle { - anchors.top: parent.top - anchors.bottom: parent.bottom - width: _activeVehicle ? _activeVehicle.loadProgress * parent.width : 0 - color: qgcPal.colorGreen + id: geoFenceProgressBar + height: parent.height / 2 + color: qgcPal.colorBlue + width: _geoFenceControllerProgressPct * parent.width + visible: _geoFenceControllerProgressPct > 0 && _geoFenceControllerProgressPct < 1 + } + + // Rally point download progress + Rectangle { + height: parent.height / 2 + color: qgcPal.colorBlue + width: _rallyPointControllerProgressPct * parent.width + visible: _rallyPointControllerProgressPct > 0 && _rallyPointControllerProgressPct < 1 + } + + // Mission download progress + Rectangle { + height: parent.height / 2 + color: qgcPal.colorBlue + width: _missionControllerProgressPct * parent.width + visible: _missionControllerProgressPct > 0 && _missionControllerProgressPct < 1 + } + + // Parameter download progress + Rectangle { + id: parameterProgressBar + height: parent.height / 2 + y: parent.height / 2 + color: qgcPal.colorBlue + width: _activeVehicle ? _activeVehicle.loadProgress * parent.width : 0 + } + + QGCLabel { + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: geoFenceProgressBar.verticalCenter + text: { + if (_geoFenceControllerProgressPct > 0 && _geoFenceControllerProgressPct < 1) { + return qsTr("Geofence Downloading: %1%").arg(Math.round(_geoFenceControllerProgressPct * 100)) + } else if (_rallyPointControllerProgressPct > 0 && _rallyPointControllerProgressPct < 1) { + return qsTr("Rally point Downloading: %1%").arg(Math.round(_rallyPointControllerProgressPct * 100)) + } else if (_missionControllerProgressPct > 0 && _missionControllerProgressPct < 1) { + return qsTr("Mission Downloading: %1%").arg(Math.round(_missionControllerProgressPct * 100)) + } else { + return "" + } + } + font.pointSize: ScreenTools.defaultFontPointSize } + // Label for parameter downloading QGCLabel { - anchors.centerIn: parent - text: qsTr("Downloading") - font.pointSize: ScreenTools.largeFontPointSize + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parameterProgressBar.verticalCenter + text: qsTr("Parameter Downloading: %1%").arg(Math.round((_activeVehicle ? _activeVehicle.loadProgress : 0) * 100)) + font.pointSize: ScreenTools.defaultFontPointSize } QGCLabel {