From e1161ae08155ff07ba2334fdb73c2f76c6469447 Mon Sep 17 00:00:00 2001 From: Gus Grubba Date: Thu, 11 Apr 2019 13:13:03 -0300 Subject: [PATCH] Handling Plan View --- qgroundcontrol.qrc | 2 +- src/FlightDisplay/FlightDisplayView.qml | 18 +-- src/FlightDisplay/FlightDisplayViewMap.qml | 17 ++- src/FlightMap/Widgets/MapFitFunctions.qml | 1 + src/PlanView/PlanToolBar.qml | 84 ++++--------- src/PlanView/PlanView.qml | 116 +++++++----------- .../QGroundControl.Controls.qmldir | 1 - src/api/QGCOptions.cc | 6 + src/api/QGCOptions.h | 3 + src/ui/MainQmlWindow.qml | 102 ++++++++++----- src/ui/toolbar/MainToolBarIndicators.qml | 12 +- 11 files changed, 179 insertions(+), 183 deletions(-) diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index 80fbe5984..9d65b3172 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -19,6 +19,7 @@ src/PlanView/CorridorScanEditor.qml src/QmlControls/QGCViewDialogContainer.qml + src/PlanView/PlanToolBar.qml src/PlanView/CameraCalc.qml src/PlanView/CorridorScanMapVisual.qml src/QmlControls/EditPositionDialog.qml @@ -88,7 +89,6 @@ src/QmlControls/ParameterEditor.qml src/QmlControls/ParameterEditorDialog.qml src/QmlControls/PIDTuning.qml - src/PlanView/PlanToolBar.qml src/QmlControls/PreFlightCheckButton.qml src/QmlControls/PreFlightCheckGroup.qml src/QmlControls/PreFlightCheckList.qml diff --git a/src/FlightDisplay/FlightDisplayView.qml b/src/FlightDisplay/FlightDisplayView.qml index ddfb96bd6..76ac04528 100644 --- a/src/FlightDisplay/FlightDisplayView.qml +++ b/src/FlightDisplay/FlightDisplayView.qml @@ -33,16 +33,19 @@ import QGroundControl.Vehicle 1.0 Item { PlanMasterController { - id: planMasterController - Component.onCompleted: start(true /* flyView */) + id: _planController + Component.onCompleted: { + start(true /* flyView */) + mainWindow.planMasterControllerView = _planController + } } property alias guidedController: guidedActionsController property bool activeVehicleJoystickEnabled: activeVehicle ? activeVehicle.joystickEnabled : false - property var _missionController: planMasterController.missionController - property var _geoFenceController: planMasterController.geoFenceController - property var _rallyPointController: planMasterController.rallyPointController + property var _missionController: _planController.missionController + property var _geoFenceController: _planController.geoFenceController + property var _rallyPointController: _planController.rallyPointController property bool _mainIsMap: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_mainIsMapKey, true) : true property bool _isPipVisible: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_PIPVisibleKey, true) : false property bool _useChecklist: QGroundControl.settingsManager.appSettings.useChecklist.rawValue @@ -195,14 +198,14 @@ Item { Layout.fillWidth: true text: qsTr("%1 Images Taken").arg(activeVehicle.cameraTriggerPoints.count) horizontalAlignment: Text.AlignHCenter - visible: activeVehicle.cameraTriggerPoints.count != 0 + visible: activeVehicle.cameraTriggerPoints.count !== 0 } QGCButton { Layout.fillWidth: true text: qsTr("Remove plan from vehicle") onClicked: { - planMasterController.removeAllFromVehicle() + _planController.removeAllFromVehicle() hideDialog() } } @@ -334,6 +337,7 @@ Item { id: _flightMap anchors.fill: parent guidedActionsController: _guidedController + missionController: _planController flightWidgets: flightDisplayViewWidgets rightPanelWidth: ScreenTools.defaultFontPixelHeight * 9 multiVehicleView: !singleVehicleView.checked diff --git a/src/FlightDisplay/FlightDisplayViewMap.qml b/src/FlightDisplay/FlightDisplayViewMap.qml index faaebb678..0eebe939b 100644 --- a/src/FlightDisplay/FlightDisplayViewMap.qml +++ b/src/FlightDisplay/FlightDisplayViewMap.qml @@ -39,12 +39,12 @@ FlightMap { property var flightWidgets property var rightPanelWidth property var multiVehicleView ///< true: multi-vehicle view, false: single vehicle view + property var missionController property rect centerViewport: Qt.rect(0, 0, width, height) - property var _missionController: planMasterController.missionController - property var _geoFenceController: planMasterController.geoFenceController - property var _rallyPointController: planMasterController.rallyPointController + property var _geoFenceController: missionController.geoFenceController + property var _rallyPointController: missionController.rallyPointController property var _activeVehicleCoordinate: activeVehicle ? activeVehicle.coordinate : QtPositioning.coordinate() property real _toolButtonTopMargin: parent.height - mainWindow.height + (ScreenTools.defaultFontPixelHeight / 2) property bool _airspaceEnabled: QGroundControl.airmapSupported ? (QGroundControl.settingsManager.airMapSettings.enableAirMap.rawValue && QGroundControl.airspaceManager.connected): false @@ -145,7 +145,6 @@ FlightMap { id: panRecenterTimer interval: 10000 running: false - onTriggered: { _disableVehicleTracking = false updateMapToVehiclePosition() @@ -163,10 +162,9 @@ FlightMap { QGCMapPalette { id: mapPal; lightColors: isSatelliteMap } Connections { - target: _missionController - + target: missionController onNewItemsFromVehicle: { - var visualItems = _missionController.visualItems + var visualItems = missionController.visualItems if (visualItems && visualItems.count !== 1) { mapFitFunctions.fitMapViewportToMissionItems() firstVehiclePositionReceived = true @@ -182,13 +180,13 @@ FlightMap { id: mapFitFunctions // The name for this id cannot be changed without breaking references outside of this code. Beware! map: _flightMap usePlannedHomePosition: false - property real leftToolWidth: toolStrip.x + toolStrip.width + planMasterController: missionController + property real leftToolWidth: toolStrip.x + toolStrip.width } // Add trajectory points to the map MapItemView { model: _mainIsMap ? activeVehicle ? activeVehicle.trajectoryPoints : 0 : 0 - delegate: MapPolyline { line.width: 3 line.color: "red" @@ -203,7 +201,6 @@ FlightMap { // Add the vehicles to the map MapItemView { model: QGroundControl.multiVehicleManager.vehicles - delegate: VehicleMapItem { vehicle: object coordinate: object.coordinate diff --git a/src/FlightMap/Widgets/MapFitFunctions.qml b/src/FlightMap/Widgets/MapFitFunctions.qml index 6376b1429..7cc41990c 100644 --- a/src/FlightMap/Widgets/MapFitFunctions.qml +++ b/src/FlightMap/Widgets/MapFitFunctions.qml @@ -17,6 +17,7 @@ import QGroundControl.FlightMap 1.0 Item { property var map property bool usePlannedHomePosition ///< true: planned home position used for calculations, false: vehicle home position use for calculations + property var planMasterController property var _missionController: planMasterController.missionController property var _geoFenceController: planMasterController.geoFenceController diff --git a/src/PlanView/PlanToolBar.qml b/src/PlanView/PlanToolBar.qml index 94e992083..6ffbd53ad 100644 --- a/src/PlanView/PlanToolBar.qml +++ b/src/PlanView/PlanToolBar.qml @@ -12,32 +12,23 @@ import QGroundControl.Palette 1.0 // Toolbar for Plan View Rectangle { id: _root - height: ScreenTools.toolbarHeight - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - z: toolBar.z + 1 color: qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(1,1,1,0.8) : Qt.rgba(0,0,0,0.75) - visible: false - anchors.bottomMargin: 1 - signal showFlyView + property var _planMasterController: mainWindow.planMasterController + property var _currentMissionItem: mainWindow.currentMissionItem ///< Mission item to display status for - property var planMasterController - property var currentMissionItem ///< Mission item to display status for + property var missionItems: _controllerValid ? _planMasterController.missionController.visualItems : undefined + property real missionDistance: _controllerValid ? _planMasterController.missionController.missionDistance : NaN + property real missionTime: _controllerValid ? _planMasterController.missionController.missionTime : NaN + property real missionMaxTelemetry: _controllerValid ? _planMasterController.missionController.missionMaxTelemetry : NaN + property bool missionDirty: _controllerValid ? _planMasterController.missionController.dirty : false - property var missionItems: _controllerValid ? planMasterController.missionController.visualItems : undefined - property real missionDistance: _controllerValid ? planMasterController.missionController.missionDistance : NaN - property real missionTime: _controllerValid ? planMasterController.missionController.missionTime : NaN - property real missionMaxTelemetry: _controllerValid ? planMasterController.missionController.missionMaxTelemetry : NaN - property bool missionDirty: _controllerValid ? planMasterController.missionController.dirty : false + property bool _controllerValid: _planMasterController !== undefined + property bool _controllerOffline: _controllerValid ? _planMasterController.offline : true + property var _controllerDirty: _controllerValid ? _planMasterController.dirty : false + property var _controllerSyncInProgress: _controllerValid ? _planMasterController.syncInProgress : false - property bool _controllerValid: planMasterController !== undefined - property bool _controllerOffline: _controllerValid ? planMasterController.offline : true - property var _controllerDirty: _controllerValid ? planMasterController.dirty : false - property var _controllerSyncInProgress: _controllerValid ? planMasterController.syncInProgress : false - - property bool _statusValid: currentMissionItem !== undefined + property bool _statusValid: _currentMissionItem !== undefined property bool _missionValid: missionItems !== undefined property real _dataFontSize: ScreenTools.defaultFontPointSize @@ -46,20 +37,20 @@ Rectangle { property real _smallValueWidth: ScreenTools.defaultFontPixelWidth * 3 property real _labelToValueSpacing: ScreenTools.defaultFontPixelWidth property real _rowSpacing: ScreenTools.isMobile ? 1 : 0 - property real _distance: _statusValid && currentMissionItem ? currentMissionItem.distance : NaN - property real _altDifference: _statusValid && currentMissionItem ? currentMissionItem.altDifference : NaN - property real _gradient: _statusValid && currentMissionItem && currentMissionItem.distance > 0 ? Math.atan(currentMissionItem.altDifference / currentMissionItem.distance) : NaN + property real _distance: _statusValid && _currentMissionItem ? _currentMissionItem.distance : NaN + property real _altDifference: _statusValid && _currentMissionItem ? _currentMissionItem.altDifference : NaN + property real _gradient: _statusValid && _currentMissionItem && _currentMissionItem.distance > 0 ? Math.atan(_currentMissionItem.altDifference / _currentMissionItem.distance) : NaN property real _gradientPercent: isNaN(_gradient) ? NaN : _gradient * 100 - property real _azimuth: _statusValid && currentMissionItem ? currentMissionItem.azimuth : NaN - property real _heading: _statusValid && currentMissionItem ? currentMissionItem.missionVehicleYaw : NaN + property real _azimuth: _statusValid && _currentMissionItem ? _currentMissionItem.azimuth : NaN + property real _heading: _statusValid && _currentMissionItem ? _currentMissionItem.missionVehicleYaw : NaN property real _missionDistance: _missionValid ? missionDistance : NaN property real _missionMaxTelemetry: _missionValid ? missionMaxTelemetry : NaN property real _missionTime: _missionValid ? missionTime : NaN - property int _batteryChangePoint: _controllerValid ? planMasterController.missionController.batteryChangePoint : -1 - property int _batteriesRequired: _controllerValid ? planMasterController.missionController.batteriesRequired : -1 + property int _batteryChangePoint: _controllerValid ? _planMasterController.missionController.batteryChangePoint : -1 + property int _batteriesRequired: _controllerValid ? _planMasterController.missionController.batteriesRequired : -1 property bool _batteryInfoAvailable: _batteryChangePoint >= 0 || _batteriesRequired >= 0 - property real _controllerProgressPct: _controllerValid ? planMasterController.missionController.progressPct : 0 - property bool _syncInProgress: _controllerValid ? planMasterController.missionController.syncInProgress : false + property real _controllerProgressPct: _controllerValid ? _planMasterController.missionController.progressPct : 0 + property bool _syncInProgress: _controllerValid ? _planMasterController.missionController.syncInProgress : false property string _distanceText: isNaN(_distance) ? "-.-" : QGroundControl.metersToAppSettingsDistanceUnits(_distance).toFixed(1) + " " + QGroundControl.appSettingsDistanceUnitsString property string _altDifferenceText: isNaN(_altDifference) ? "-.-" : QGroundControl.metersToAppSettingsDistanceUnits(_altDifference).toFixed(1) + " " + QGroundControl.appSettingsDistanceUnitsString @@ -73,8 +64,6 @@ Rectangle { readonly property real _margins: ScreenTools.defaultFontPixelWidth - QGCPalette { id: qgcPal } - function getMissionTime() { if(isNaN(_missionTime)) { return "00:00:00" @@ -88,28 +77,6 @@ Rectangle { anchors.fill: parent } - //-- The reason for this Row to be here is so the Logo (Home) button is in the same - // location as the one in the main toolbar. - Row { - id: logoRow - anchors.bottomMargin: 1 - anchors.left: parent.left - anchors.top: parent.top - anchors.bottom: parent.bottom - QGCToolBarButton { - id: settingsButton - anchors.top: parent.top - anchors.bottom: parent.bottom - source: "/qmlimages/PaperPlane.svg" - logo: true - checked: false - onClicked: { - checked = false - showFlyView() - } - } - } - // Progress bar on_ControllerProgressPctChanged: { @@ -134,10 +101,7 @@ Rectangle { QGCLabel { id: uploadCompleteText - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.left: logoRow.right - anchors.right: uploadButton.left + anchors.fill: parent font.pointSize: ScreenTools.largeFontPointSize horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter @@ -151,7 +115,7 @@ Rectangle { anchors.bottom: parent.bottom anchors.leftMargin: _margins anchors.rightMargin: _margins - anchors.left: logoRow.right + anchors.left: parent.left anchors.right: uploadButton.visible ? uploadButton.left : parent.right columnSpacing: 0 columns: 3 @@ -288,7 +252,7 @@ Rectangle { enabled: !_controllerSyncInProgress visible: !_controllerOffline && !_controllerSyncInProgress && !uploadCompleteText.visible primary: _controllerDirty - onClicked: planMasterController.upload() + onClicked: _planMasterController.upload() PropertyAnimation on opacity { easing.type: Easing.OutQuart diff --git a/src/PlanView/PlanView.qml b/src/PlanView/PlanView.qml index 40204cbb7..7249adcc5 100644 --- a/src/PlanView/PlanView.qml +++ b/src/PlanView/PlanView.qml @@ -32,24 +32,22 @@ import QGroundControl.Airmap 1.0 Item { id: _root - z: QGroundControl.zOrderTopMost property bool planControlColapsed: false ///< This property is used to determine dirty state for prompting on QGC shutdown - readonly property bool dirty: _planMasterController.dirty + readonly property bool dirty: _planMasterController.dirty readonly property int _decimalPlaces: 8 readonly property real _horizontalMargin: ScreenTools.defaultFontPixelWidth * 0.5 readonly property real _margin: ScreenTools.defaultFontPixelHeight * 0.5 readonly property real _radius: ScreenTools.defaultFontPixelWidth * 0.5 readonly property real _rightPanelWidth: Math.min(parent.width / 3, ScreenTools.defaultFontPixelWidth * 30) - readonly property real _toolButtonTopMargin: parent.height - mainWindow.height + (ScreenTools.defaultFontPixelHeight / 2) + readonly property real _toolButtonTopMargin: ScreenTools.defaultFontPixelHeight * 0.5 readonly property var _defaultVehicleCoordinate: QtPositioning.coordinate(37.803784, -122.462276) readonly property bool _waypointsOnlyMode: QGroundControl.corePlugin.options.missionWaypointsOnly - property bool _airspaceEnabled: QGroundControl.airmapSupported ? (QGroundControl.settingsManager.airMapSettings.enableAirMap.rawValue && QGroundControl.airspaceManager.connected): false - property var _planMasterController: masterController + property bool _airspaceEnabled: QGroundControl.airmapSupported ? (QGroundControl.settingsManager.airMapSettings.enableAirMap.rawValue && QGroundControl.airspaceManager.connected): false property var _missionController: _planMasterController.missionController property var _geoFenceController: _planMasterController.geoFenceController property var _rallyPointController: _planMasterController.rallyPointController @@ -68,11 +66,6 @@ Item { readonly property int _layerRallyPoints: 3 readonly property string _armedVehicleUploadPrompt: qsTr("Vehicle is currently armed. Do you want to upload the mission to the vehicle?") - Component.onCompleted: { - toolbar.planMasterController = Qt.binding(function () { return _planMasterController }) - toolbar.currentMissionItem = Qt.binding(function () { return _missionController.currentPlanViewItem }) - } - function addComplexItem(complexItemName) { var coordinate = editorMap.center coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces) @@ -127,8 +120,7 @@ Item { } Connections { - target: _appSettings.defaultMissionItemAltitude - + target: _appSettings ? _appSettings.defaultMissionItemAltitude : null onRawValueChanged: { if (_visualItems.count > 1) { mainWindow.showDialog(applyNewAltitude, qsTr("Apply new alititude"), mainWindow.showDialogDefaultWidth, StandardButton.Yes | StandardButton.No) @@ -138,10 +130,8 @@ Item { Component { id: applyNewAltitude - QGCViewMessage { message: qsTr("You have changed the default altitude for mission items. Would you like to apply that altitude to all the items in the current mission?") - function accept() { hideDialog() _missionController.applyDefaultMissionAltitude() @@ -151,25 +141,20 @@ Item { Component { id: activeMissionUploadDialogComponent - QGCViewDialog { - Column { anchors.fill: parent spacing: ScreenTools.defaultFontPixelHeight - QGCLabel { width: parent.width wrapMode: Text.WordWrap text: qsTr("Your vehicle is currently flying a mission. In order to upload a new or modified mission the current mission will be paused.") } - QGCLabel { width: parent.width wrapMode: Text.WordWrap text: qsTr("After the mission is uploaded you can adjust the current waypoint and start the mission.") } - QGCButton { text: qsTr("Pause and Upload") onClicked: { @@ -197,11 +182,13 @@ Item { } PlanMasterController { - id: masterController + id: _planMasterController Component.onCompleted: { start(false /* flyView */) _missionController.setCurrentPlanViewIndex(0, true) + mainWindow.planMasterControllerPlan = _planMasterController + mainWindow.currentPlanMissionItem = _planMasterController.missionController.currentPlanViewItem } function waitingOnDataMessage() { @@ -224,7 +211,7 @@ Item { fileDialog.title = qsTr("Select Plan File") fileDialog.planFiles = true fileDialog.selectExisting = true - fileDialog.nameFilters = masterController.loadNameFilters + fileDialog.nameFilters = _planMasterController.loadNameFilters fileDialog.fileExtension = _appSettings.planFileExtension fileDialog.fileExtension2 = _appSettings.missionFileExtension fileDialog.openForLoad() @@ -238,7 +225,7 @@ Item { fileDialog.title = qsTr("Save Plan") fileDialog.planFiles = true fileDialog.selectExisting = false - fileDialog.nameFilters = masterController.saveNameFilters + fileDialog.nameFilters = _planMasterController.saveNameFilters fileDialog.fileExtension = _appSettings.planFileExtension fileDialog.fileExtension2 = _appSettings.missionFileExtension fileDialog.openForSave() @@ -275,9 +262,8 @@ Item { Connections { target: _missionController - onNewItemsFromVehicle: { - if (_visualItems && _visualItems.count != 1) { + if (_visualItems && _visualItems.count !== 1) { mapFitFunctions.fitMapViewportToMissionItems() } _missionController.setCurrentPlanViewIndex(0, true) @@ -312,23 +298,23 @@ Item { QGCFileDialog { id: fileDialog - folder: _appSettings.missionSavePath + folder: _appSettings ? _appSettings.missionSavePath : "" property bool planFiles: true ///< true: working with plan files, false: working with kml file onAcceptedForSave: { if (planFiles) { - masterController.saveToFile(file) + _planMasterController.saveToFile(file) } else { - masterController.saveToKml(file) + _planMasterController.saveToKml(file) } close() } onAcceptedForLoad: { if (planFiles) { - masterController.loadFromFile(file) - masterController.fitViewportToItems() + _planMasterController.loadFromFile(file) + _planMasterController.fitViewportToItems() _missionController.setCurrentPlanViewIndex(0, true) } else { var retList = ShapeFileHelper.determineShapeType(file) @@ -353,7 +339,6 @@ Item { property string polygonSelectPatternFile Component { id: patternPolygonSelectDialog - QGCViewDialog { function accept() { var complexItemName @@ -365,30 +350,25 @@ Item { insertComplexMissionItemFromKMLOrSHP(complexItemName, polygonSelectPatternFile, -1) hideDialog() } - ExclusiveGroup { id: radioGroup } - Column { anchors.left: parent.left anchors.right: parent.right spacing: ScreenTools.defaultFontPixelHeight - QGCLabel { anchors.left: parent.left anchors.right: parent.right wrapMode: Text.WordWrap text: qsTr("Create which pattern type?") } - QGCRadioButton { id: surveyRadio text: qsTr("Survey") checked: true exclusiveGroup: radioGroup } - QGCRadioButton { text: qsTr("Structure Scan") exclusiveGroup: radioGroup @@ -399,18 +379,15 @@ Item { Component { id: moveDialog - QGCViewDialog { function accept() { var toIndex = toCombo.currentIndex - if (toIndex === 0) { toIndex = 1 } _missionController.moveMissionItem(_moveDialogMissionItemIndex, toIndex) hideDialog() } - Column { anchors.left: parent.left anchors.right: parent.right @@ -578,10 +555,10 @@ Item { color: qgcPal.window title: qsTr("Plan") z: QGroundControl.zOrderWidgets - showAlternateIcon: [ masterController.dirty, false, false, false, false, false, false ] - rotateImage: [ masterController.syncInProgress, false, false, false, false, false, false ] - animateImage: [ masterController.dirty, false, false, false, false, false, false ] - buttonEnabled: [ !masterController.syncInProgress, true, true, true, true, true, true ] + showAlternateIcon: [ _planMasterController.dirty, false, false, false, false, false, false ] + rotateImage: [ _planMasterController.syncInProgress, false, false, false, false, false, false ] + animateImage: [ _planMasterController.dirty, false, false, false, false, false, false ] + buttonEnabled: [ !_planMasterController.syncInProgress, true, true, true, true, true, true ] buttonVisible: [ true, true, _waypointsOnlyMode, true, true, _showZoom, _showZoom ] maxHeight: mapScale.y - toolStrip.y @@ -665,6 +642,7 @@ Item { // Right Panel Controls Item { anchors.fill: rightPanel + anchors.topMargin: _toolButtonTopMargin Column { id: rightControls spacing: ScreenTools.defaultFontPixelHeight * 0.5 @@ -828,7 +806,7 @@ Item { //-- List Elements delegate: MissionItemEditor { map: editorMap - masterController: _planMasterController + masterController: _planMasterController missionItem: object width: parent.width readOnly: false @@ -908,7 +886,7 @@ Item { message: qsTr("You have unsaved/unsent changes. Loading from the Vehicle will lose these changes. Are you sure you want to load from the Vehicle?") function accept() { hideDialog() - masterController.loadFromVehicle() + _planMasterController.loadFromVehicle() } } } @@ -920,7 +898,7 @@ Item { message: qsTr("You have unsaved/unsent changes. Loading from a file will lose these changes. Are you sure you want to load from a file?") function accept() { hideDialog() - masterController.loadFromSelectedFile() + _planMasterController.loadFromSelectedFile() } } } @@ -932,9 +910,9 @@ Item { (_planMasterController.offline ? "" : qsTr("This will also remove all items from the vehicle.")) function accept() { if (_planMasterController.offline) { - masterController.removeAll() + _planMasterController.removeAll() } else { - masterController.removeAllFromVehicle() + _planMasterController.removeAllFromVehicle() } hideDialog() } @@ -946,7 +924,7 @@ Item { QGCViewMessage { message: qsTr("Are you sure you want to remove all mission items and clear the mission from the vehicle?") function accept() { - masterController.removeAllFromVehicle() + _planMasterController.removeAllFromVehicle() hideDialog() } } @@ -997,9 +975,9 @@ Item { QGCButton { text: qsTr("Load KML/SHP...") Layout.fillWidth: true - enabled: !masterController.syncInProgress + enabled: !_planMasterController.syncInProgress onClicked: { - masterController.loadShapeFromSelectedFile() + _planMasterController.loadShapeFromSelectedFile() dropPanel.hide() } } @@ -1018,7 +996,7 @@ Item { QGCLabel { width: sendSaveGrid.width wrapMode: Text.WordWrap - text: masterController.dirty ? + text: _planMasterController.dirty ? (activeVehicle ? qsTr("You have unsaved changes. You should upload to your vehicle, or save to a file:") : qsTr("You have unsaved changes.") @@ -1046,13 +1024,13 @@ Item { QGCButton { text: qsTr("Open...") Layout.fillWidth: true - enabled: !masterController.syncInProgress + enabled: !_planMasterController.syncInProgress onClicked: { dropPanel.hide() - if (masterController.dirty) { + if (_planMasterController.dirty) { mainWindow.showDialog(syncLoadFromFileOverwrite, columnHolder._overwriteText, mainWindow.showDialogDefaultWidth, StandardButton.Yes | StandardButton.Cancel) } else { - masterController.loadFromSelectedFile() + _planMasterController.loadFromSelectedFile() } } } @@ -1060,13 +1038,13 @@ Item { QGCButton { text: qsTr("Save") Layout.fillWidth: true - enabled: !masterController.syncInProgress && masterController.currentPlanFile !== "" + enabled: !_planMasterController.syncInProgress && _planMasterController.currentPlanFile !== "" onClicked: { dropPanel.hide() - if(masterController.currentPlanFile !== "") { - masterController.saveToCurrent() + if(_planMasterController.currentPlanFile !== "") { + _planMasterController.saveToCurrent() } else { - masterController.saveToSelectedFile() + _planMasterController.saveToSelectedFile() } } } @@ -1074,17 +1052,17 @@ Item { QGCButton { text: qsTr("Save As...") Layout.fillWidth: true - enabled: !masterController.syncInProgress && _visualItems.count > 1 + enabled: !_planMasterController.syncInProgress && _visualItems.count > 1 onClicked: { dropPanel.hide() - masterController.saveToSelectedFile() + _planMasterController.saveToSelectedFile() } } QGCButton { text: qsTr("Save Mission Waypoints As KML...") Layout.columnSpan: 2 - enabled: !masterController.syncInProgress && _visualItems.count > 1 + enabled: !_planMasterController.syncInProgress && _visualItems.count > 1 onClicked: { // First point does not count if (_visualItems.count < 2) { @@ -1092,7 +1070,7 @@ Item { return } dropPanel.hide() - masterController.saveKmlToSelectedFile() + _planMasterController.saveKmlToSelectedFile() } } @@ -1109,25 +1087,25 @@ Item { QGCButton { text: qsTr("Upload") Layout.fillWidth: true - enabled: !masterController.offline && !masterController.syncInProgress && _visualItems.count > 1 + enabled: !_planMasterController.offline && !_planMasterController.syncInProgress && _visualItems.count > 1 visible: !QGroundControl.corePlugin.options.disableVehicleConnection onClicked: { dropPanel.hide() - masterController.upload() + _planMasterController.upload() } } QGCButton { text: qsTr("Download") Layout.fillWidth: true - enabled: !masterController.offline && !masterController.syncInProgress + enabled: !_planMasterController.offline && !_planMasterController.syncInProgress visible: !QGroundControl.corePlugin.options.disableVehicleConnection onClicked: { dropPanel.hide() - if (masterController.dirty) { + if (_planMasterController.dirty) { mainWindow.showDialog(syncLoadFromVehicleOverwrite, columnHolder._overwriteText, mainWindow.showDialogDefaultWidth, StandardButton.Yes | StandardButton.Cancel) } else { - masterController.loadFromVehicle() + _planMasterController.loadFromVehicle() } } } @@ -1136,7 +1114,7 @@ Item { text: qsTr("Clear Vehicle Mission") Layout.fillWidth: true Layout.columnSpan: 2 - enabled: !masterController.offline && !masterController.syncInProgress + enabled: !_planMasterController.offline && !_planMasterController.syncInProgress visible: !QGroundControl.corePlugin.options.disableVehicleConnection onClicked: { dropPanel.hide() @@ -1147,4 +1125,4 @@ Item { } } } -} // QGCVIew +} diff --git a/src/QmlControls/QGroundControl.Controls.qmldir b/src/QmlControls/QGroundControl.Controls.qmldir index 0bdca1500..ef1bcdf9d 100644 --- a/src/QmlControls/QGroundControl.Controls.qmldir +++ b/src/QmlControls/QGroundControl.Controls.qmldir @@ -33,7 +33,6 @@ PageView 1.0 PageView.qml ParameterEditor 1.0 ParameterEditor.qml ParameterEditorDialog 1.0 ParameterEditorDialog.qml PIDTuning 1.0 PIDTuning.qml -PlanToolBar 1.0 PlanToolBar.qml PreFlightCheckButton 1.0 PreFlightCheckButton.qml PreFlightCheckGroup 1.0 PreFlightCheckGroup.qml PreFlightCheckList 1.0 PreFlightCheckList.qml diff --git a/src/api/QGCOptions.cc b/src/api/QGCOptions.cc index 4d0a90e2a..e79d9bc61 100644 --- a/src/api/QGCOptions.cc +++ b/src/api/QGCOptions.cc @@ -36,6 +36,12 @@ QGCOptions::mainToolbarIndicatorsUrl() const return QUrl(QStringLiteral("qrc:/toolbar/MainToolBarIndicators.qml")); } +QUrl +QGCOptions::planToolbarIndicatorsUrl() const +{ + return QUrl(QStringLiteral("PlanToolBar.qml")); +} + CustomInstrumentWidget::CustomInstrumentWidget(QObject* parent) : QObject(parent) diff --git a/src/api/QGCOptions.h b/src/api/QGCOptions.h index 695630efe..057233cf8 100644 --- a/src/api/QGCOptions.h +++ b/src/api/QGCOptions.h @@ -30,6 +30,7 @@ public: Q_PROPERTY(CustomInstrumentWidget* instrumentWidget READ instrumentWidget CONSTANT) Q_PROPERTY(QUrl flyViewOverlay READ flyViewOverlay CONSTANT) Q_PROPERTY(QUrl mainToolbarIndicatorsUrl READ mainToolbarIndicatorsUrl CONSTANT) + Q_PROPERTY(QUrl planToolbarIndicatorsUrl READ planToolbarIndicatorsUrl CONSTANT) Q_PROPERTY(bool showSensorCalibrationCompass READ showSensorCalibrationCompass NOTIFY showSensorCalibrationCompassChanged) Q_PROPERTY(bool showSensorCalibrationGyro READ showSensorCalibrationGyro NOTIFY showSensorCalibrationGyroChanged) Q_PROPERTY(bool showSensorCalibrationAccel READ showSensorCalibrationAccel NOTIFY showSensorCalibrationAccelChanged) @@ -80,6 +81,8 @@ public: virtual QUrl flyViewOverlay () const { return QUrl(); } /// Allows replacing the toolbar container virtual QUrl mainToolbarIndicatorsUrl () const; + /// Allows replacing the Plan View toolbar container + virtual QUrl planToolbarIndicatorsUrl () const; /// By returning false you can hide the following sensor calibration pages virtual bool showSensorCalibrationCompass () const { return true; } virtual bool showSensorCalibrationGyro () const { return true; } diff --git a/src/ui/MainQmlWindow.qml b/src/ui/MainQmlWindow.qml index d331db0d4..95b81553d 100644 --- a/src/ui/MainQmlWindow.qml +++ b/src/ui/MainQmlWindow.qml @@ -27,27 +27,29 @@ ApplicationWindow { height: 768 visible: true - Component.onCompleted: { - toolbarIndicators.source = _mainToolbarIndicators - } - - readonly property real _topBottomMargins: ScreenTools.defaultFontPixelHeight * 0.5 - readonly property string _mainToolbarIndicators: QGroundControl.corePlugin.options.mainToolbarIndicatorsUrl - readonly property string _settingsViewSource: "AppSettings.qml" - readonly property string _setupViewSource: "SetupView.qml" - readonly property string _planViewSource: "PlanView.qml" - readonly property string _analyzeViewSource: !ScreenTools.isMobile ? "AnalyzeView.qml" : "MavlinkConsolePage.qml" + readonly property real _topBottomMargins: ScreenTools.defaultFontPixelHeight * 0.5 + readonly property string _mainToolbarIndicators: QGroundControl.corePlugin.options.mainToolbarIndicatorsUrl + readonly property string _planToolbarIndicators: QGroundControl.corePlugin.options.planToolbarIndicatorsUrl + readonly property string _settingsViewSource: "AppSettings.qml" + readonly property string _setupViewSource: "SetupView.qml" + readonly property string _planViewSource: "PlanView.qml" + readonly property string _analyzeViewSource: !ScreenTools.isMobile ? "AnalyzeView.qml" : "MavlinkConsolePage.qml" //------------------------------------------------------------------------- //-- Global Scope Variables - property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle - property bool communicationLost: activeVehicle ? activeVehicle.connectionLost : false - property string formatedMessage: activeVehicle ? activeVehicle.formatedMessage : "" - property real availableHeight: mainWindow.height - mainWindow.header.height - readonly property string navButtonWidth: ScreenTools.defaultFontPixelWidth * 24 - readonly property real defaultTextHeight: ScreenTools.defaultFontPixelHeight - readonly property real defaultTextWidth: ScreenTools.defaultFontPixelWidth + property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + property bool communicationLost: activeVehicle ? activeVehicle.connectionLost : false + property string formatedMessage: activeVehicle ? activeVehicle.formatedMessage : "" + property real availableHeight: mainWindow.height - mainWindow.header.height + + property var currentPlanMissionItem: null + property var planMasterControllerPlan: null + property var planMasterControllerView: null + + readonly property string navButtonWidth: ScreenTools.defaultFontPixelWidth * 24 + readonly property real defaultTextHeight: ScreenTools.defaultFontPixelHeight + readonly property real defaultTextWidth: ScreenTools.defaultFontPixelWidth QGCPalette { id: qgcPal; colorGroupEnabled: true } @@ -74,8 +76,14 @@ ApplicationWindow { enableToolbar() drawer.close() if(isPlanView) { - + rootBackground.visible = false + planViewLoader.visible = true + if(toolbarIndicators.source !== _planToolbarIndicators) { + toolbarIndicators.source = _planToolbarIndicators + } } else { + rootBackground.visible = true + planViewLoader.visible = false if(toolbarIndicators.source !== _mainToolbarIndicators) { toolbarIndicators.source = _mainToolbarIndicators } @@ -190,13 +198,6 @@ ApplicationWindow { property bool _forceClose: false - onClosing: { - if (!_forceClose) { - activeConnectionsCloseDialog.check() - close.accepted = false - } - } - function reallyClose() { _forceClose = true mainWindow.close() @@ -242,16 +243,59 @@ ApplicationWindow { } //------------------------------------------------------------------------- - //-- Main, full window background + //-- Check for unsaved missions + + onClosing: { + if (!_forceClose) { + unsavedMissionCloseDialog.check() + close.accepted = false + } + } + + MessageDialog { + id: unsavedMissionCloseDialog + title: qsTr("%1 close").arg(QGroundControl.appName) + text: qsTr("You have a mission edit in progress which has not been saved/sent. If you close you will lose changes. Are you sure you want to close?") + standardButtons: StandardButton.Yes | StandardButton.No + modality: Qt.ApplicationModal + visible: false + onYes: activeConnectionsCloseDialog.check() + function check() { + if (planViewLoader.item && planViewLoader.item.dirty) { + unsavedMissionCloseDialog.open() + } else { + activeConnectionsCloseDialog.check() + } + } + } + + //------------------------------------------------------------------------- + //-- Main, full window background (Fly View) background: Item { id: rootBackground anchors.fill: parent FlightDisplayView { id: flightView anchors.fill: parent + //----------------------------------------------------------------- + //-- Loader helper for any child, no matter how deep can display an + // element on top of the video window. + Loader { + id: rootVideoLoader + anchors.centerIn: parent + } } } + //------------------------------------------------------------------------- + //-- Plan View + Loader { + id: planViewLoader + anchors.fill: parent + visible: false + source: "PlanView.qml" + } + //------------------------------------------------------------------------- //-- Global Indicator Bar header: ToolBar { @@ -262,6 +306,7 @@ ApplicationWindow { } RowLayout { anchors.fill: parent + spacing: 0 Rectangle { height: parent.height width: height @@ -286,13 +331,10 @@ ApplicationWindow { } } } - Item { - height: 1 - width: ScreenTools.defaultFontPixelWidth * 2 - } Loader { id: toolbarIndicators height: parent.height + source: _mainToolbarIndicators Layout.fillWidth: true } } diff --git a/src/ui/toolbar/MainToolBarIndicators.qml b/src/ui/toolbar/MainToolBarIndicators.qml index c8981ac35..7964f95d4 100644 --- a/src/ui/toolbar/MainToolBarIndicators.qml +++ b/src/ui/toolbar/MainToolBarIndicators.qml @@ -74,11 +74,13 @@ Item { //------------------------------------------------------------------------- //-- Toolbar Indicators Row { - id: indicatorRow - anchors.top: parent.top - anchors.bottom: parent.bottom - spacing: ScreenTools.defaultFontPixelWidth * 1.5 - visible: activeVehicle && !communicationLost + id: indicatorRow + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2 + spacing: ScreenTools.defaultFontPixelWidth * 1.5 + visible: activeVehicle && !communicationLost //--------------------------------------------------------------------- //-- Vehicle Selector -- 2.22.0