10import QGroundControl.FlightMap
11import QGroundControl.Controls
12import QGroundControl.FactControls
13import QGroundControl.FlyView
14import QGroundControl.Geo
15import QGroundControl.Toolbar
20 readonly property int _decimalPlaces: 8
21 readonly property real _margin: ScreenTools.defaultFontPixelHeight * 0.5
22 readonly property real _toolsMargin: ScreenTools.defaultFontPixelWidth * 0.75
23 readonly property real _rightPanelWidth: Math.min(width / 3, ScreenTools.defaultFontPixelWidth * 30)
25 property var _planMasterController: planMasterController
26 property var _missionController: _planMasterController.missionController
27 property var _geoFenceController: _planMasterController.geoFenceController
28 property var _rallyPointController: _planMasterController.rallyPointController
29 property var _visualItems: _missionController.visualItems
30 property bool _singleComplexItem: _missionController.complexMissionItems.length === 1
31 property int _editingLayer: _layerMission
32 property var _appSettings: QGroundControl.settingsManager.appSettings
33 property var _planViewSettings: QGroundControl.settingsManager.planViewSettings
34 property bool _promptForPlanUsageShowing: false
35 property bool _addROIOnClick: false
36 property bool _addWaypointOnClick: false
38 readonly property int _layerMission: PlanEditLayers.layerMission
39 readonly property int _layerFence: PlanEditLayers.layerFence
40 readonly property int _layerRally: PlanEditLayers.layerRally
44 editorMap.zoomLevel = QGroundControl.flightMapZoom
45 editorMap.center = QGroundControl.flightMapPosition
51 function onToolbarButtonClicked() {
52 _addWaypointOnClick = false
53 _addROIOnClick = false
57 function mapCenter() {
58 var coordinate = editorMap.center
59 coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces)
60 coordinate.longitude = coordinate.longitude.toFixed(_decimalPlaces)
61 coordinate.altitude = coordinate.altitude.toFixed(_decimalPlaces)
66 id: mapFitFunctions // The name for this id cannot be changed without breaking references outside of this code. Beware!
68 usePlannedHomePosition: true
69 planMasterController: _planMasterController
72 PlanMasterController {
73 id: planMasterController
76 Component.onCompleted: {
77 _planMasterController.start()
78 _missionController.setCurrentPlanViewSeqNum(0, true)
81 onPromptForPlanUsageOnVehicleChange: {
82 if (!_promptForPlanUsageShowing) {
83 _promptForPlanUsageShowing = true
84 promptForPlanUsageOnVehicleChangePopupFactory.open()
88 function waitingOnIncompleteDataMessage(save) {
89 var saveOrUpload = save ? qsTr("Save") : qsTr("Upload")
90 QGroundControl.showMessageDialog(_root, qsTr("Unable to %1").arg(saveOrUpload), qsTr("Plan has incomplete items. Complete all items and %1 again.").arg(saveOrUpload))
93 function waitingOnTerrainDataMessage(save) {
94 var saveOrUpload = save ? qsTr("Save") : qsTr("Upload")
95 QGroundControl.showMessageDialog(_root, qsTr("Unable to %1").arg(saveOrUpload), qsTr("Plan is waiting on terrain data from server for correct altitude values."))
98 function checkReadyForSaveUpload(save) {
99 if (readyForSaveState() == VisualMissionItem.NotReadyForSaveData) {
100 waitingOnIncompleteDataMessage(save)
102 } else if (readyForSaveState() == VisualMissionItem.NotReadyForSaveTerrain) {
103 waitingOnTerrainDataMessage(save)
110 if (!checkReadyForSaveUpload(false /* save */)) {
113 switch (_missionController.sendToVehiclePreCheck()) {
114 case MissionController.SendToVehiclePreCheckStateOk: sendToVehicle()
116 case MissionController.SendToVehiclePreCheckStateActiveMission: QGroundControl.showMessageDialog(_root, qsTr("Send To Vehicle"), qsTr("Current mission must be paused prior to uploading a new Plan"))
118 case MissionController.SendToVehiclePreCheckStateFirwmareVehicleMismatch: QGroundControl.showMessageDialog(_root, qsTr("Plan Upload"),
119 qsTr("This Plan was created for a different firmware or vehicle type than the firmware/vehicle type of vehicle you are uploading to. " +
120 "This can lead to errors or incorrect behavior. " +
121 "It is recommended to recreate the Plan for the correct firmware/vehicle type.\n\n" +
122 "Click 'Ok' to upload the Plan anyway."),
123 Dialog.Ok | Dialog.Cancel,
124 function() { _planMasterController.sendToVehicle() })
129 function loadFromSelectedFile() {
130 fileDialog.title = qsTr("Select Plan File")
131 fileDialog.planFiles = true
132 fileDialog.nameFilters = _planMasterController.loadNameFilters
133 fileDialog.openForLoad()
136 function saveToSelectedFile() {
137 if (!checkReadyForSaveUpload(true /* save */)) {
140 fileDialog.title = qsTr("Save Plan")
141 fileDialog.planFiles = true
142 fileDialog.nameFilters = _planMasterController.saveNameFilters
143 fileDialog.openForSave()
146 function fitViewportToItems() {
147 mapFitFunctions.fitMapViewportToMissionItems()
150 function saveKmlToSelectedFile() {
151 if (!checkReadyForSaveUpload(true /* save */)) {
154 fileDialog.title = qsTr("Save KML")
155 fileDialog.planFiles = false
156 fileDialog.nameFilters = ShapeFileHelper.fileDialogKMLFilters
157 fileDialog.openForSave()
162 target: _missionController
164 function onNewItemsFromVehicle() {
165 if (_visualItems && _visualItems.count !== 1) {
166 mapFitFunctions.fitMapViewportToMissionItems()
168 _missionController.setCurrentPlanViewSeqNum(0, true)
172 function insertSimpleItemAfterCurrent(coordinate) {
173 var nextIndex = _missionController.currentPlanViewVIIndex + 1
174 _missionController.insertSimpleMissionItem(coordinate, nextIndex, true /* makeCurrentItem */)
177 function insertROIAfterCurrent(coordinate) {
178 var nextIndex = _missionController.currentPlanViewVIIndex + 1
179 _missionController.insertROIMissionItem(coordinate, nextIndex, true /* makeCurrentItem */)
182 function insertCancelROIAfterCurrent() {
183 var nextIndex = _missionController.currentPlanViewVIIndex + 1
184 _missionController.insertCancelROIMissionItem(nextIndex, true /* makeCurrentItem */)
187 function insertComplexItemAfterCurrent(complexItemName) {
188 var nextIndex = _missionController.currentPlanViewVIIndex + 1
189 _missionController.insertComplexMissionItem(complexItemName, mapCenter(), nextIndex, true /* makeCurrentItem */)
192 function insertTakeoffItemAfterCurrent() {
193 var nextIndex = _missionController.currentPlanViewVIIndex + 1
194 _missionController.insertTakeoffItem(mapCenter(), nextIndex, true /* makeCurrentItem */)
197 function insertVTOLMulticopterTakeoffItemAfterCurrent() {
198 var nextIndex = _missionController.currentPlanViewVIIndex + 1
199 _missionController.insertVTOLMulticopterTakeoffItem(mapCenter(), nextIndex, true /* makeCurrentItem */)
202 function insertLandItemAfterCurrent() {
203 var nextIndex = _missionController.currentPlanViewVIIndex + 1
204 _missionController.insertLandItem(mapCenter(), nextIndex, true /* makeCurrentItem */)
207 function _landButtonText() {
208 // Must mirror MissionController::insertLandItem: only fixed-wing/VTOL get landing patterns
209 if (!_planMasterController.controllerVehicle.fixedWing && !_planMasterController.controllerVehicle.vtol) {
210 return qsTr("Return")
212 if (_missionController.isInsertLandValid && _missionController.hasLandItem) {
213 return qsTr("Alt Land")
220 folder: _appSettings ? _appSettings.missionSavePath : ""
222 property bool planFiles: true ///< true: working with plan files, false: working with kml file
224 onAcceptedForSave: (file) => {
226 if (_planMasterController.saveToFile(file)) {
230 _planMasterController.saveToKml(file)
235 onAcceptedForLoad: (file) => {
236 _planMasterController.loadFromFile(file)
237 _planMasterController.fitViewportToItems()
238 _missionController.setCurrentPlanViewSeqNum(0, true)
245 planMasterController: _planMasterController
246 showRallyPointsHelp: _editingLayer === _layerRally
251 anchors.left: parent.left
252 anchors.right: parent.right
253 anchors.top: planToolBar.bottom
254 anchors.bottom: parent.bottom
258 objectName: "planView_map"
260 mapName: "MissionEditor"
261 allowGCSLocationCenter: true
262 allowVehicleLocationCenter: true
265 zoomLevel: QGroundControl.flightMapZoom
266 center: QGroundControl.flightMapPosition
268 // This is the center rectangle of the map which is not obscured by tools
269 property rect centerViewport: Qt.rect(_leftToolWidth + _margin, _margin, editorMap.width - _leftToolWidth - _rightToolWidth - (_margin * 2), (missionStatus.visible ? missionStatus.y : height - _margin) - _margin)
271 property real _leftToolWidth: toolStrip.x + toolStrip.width
272 property real _rightToolWidth: rightPanel.width + rightPanel.anchors.rightMargin
273 property real _nonInteractiveOpacity: 0.5
275 // Initial map position duplicates Fly view position
276 Component.onCompleted: editorMap.center = QGroundControl.flightMapPosition
278 onZoomLevelChanged: {
279 QGroundControl.flightMapZoom = editorMap.zoomLevel
282 QGroundControl.flightMapPosition = editorMap.center
285 onMapClicked: (mouse) => {
286 // Take focus to close any previous editing
287 editorMap.focus = true
289 // Collapse layer switcher on any map click
290 layerSwitcher.expanded = false
293 if (!mainWindow.allowViewSwitch()) {
296 var coordinate = editorMap.toCoordinate(Qt.point(mouse.x, mouse.y), false /* clipToViewPort */)
297 coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces)
298 coordinate.longitude = coordinate.longitude.toFixed(_decimalPlaces)
299 coordinate.altitude = coordinate.altitude.toFixed(_decimalPlaces)
301 switch (_editingLayer) {
303 if (_planMasterController.showCreateFromTemplate) {
304 _missionController.setHomePosition(coordinate)
305 } else if (_addROIOnClick) {
306 _addROIOnClick = false
307 if (_missionController.isROIActive) {
308 var pos = Qt.point(mouse.x, mouse.y)
309 // For some strange reason using mainWindow in mapToItem doesn't work, so we use globals.parent instead which also gets us mainWindow
310 pos = editorMap.mapToItem(globals.parent, pos)
311 var dropPanel = insertOrCancelROIDropPanelComponent.createObject(mainWindow, { mapClickCoord: coordinate, clickRect: Qt.rect(pos.x, pos.y, 0, 0) })
314 insertROIAfterCurrent(coordinate)
316 } else if (_addWaypointOnClick) {
317 insertSimpleItemAfterCurrent(coordinate)
321 if (_rallyPointController.supported) {
322 _rallyPointController.addPoint(coordinate)
328 MissionItemIndicatorGroup {
329 id: _missionItemIndicatorGroup
332 missionItems: _root._missionController.visualItems
333 onItemSelected: (sequenceNumber) => {
334 _root._missionController.setCurrentPlanViewSeqNum(sequenceNumber, false)
338 // Add the mission item visuals to the map
340 model: _missionController.visualItems
341 delegate: MissionItemMapVisual {
343 opacity: _editingLayer == _layerMission ? 1 : editorMap._nonInteractiveOpacity
344 interactive: _editingLayer == _layerMission
345 vehicle: _planMasterController.controllerVehicle
346 indicatorGroup: _missionItemIndicatorGroup
347 onClicked: (sequenceNumber) => {
348 _root._missionController.setCurrentPlanViewSeqNum(sequenceNumber, false)
353 // Add lines between waypoints
355 showSpecialVisual: _missionController.isROIBeginCurrentItem
356 model: _missionController.simpleFlightPathSegments
357 opacity: _editingLayer == _layerMission ? 1 : editorMap._nonInteractiveOpacity
360 // Direction arrows in waypoint lines
362 model: _editingLayer == _layerMission ? _missionController.directionArrows : undefined
364 delegate: MapLineArrow {
365 fromCoord: object ? object.coordinate1 : undefined
366 toCoord: object ? object.coordinate2 : undefined
368 mapControl: editorMap
369 z: QGroundControl.zOrderWaypointLines + 1
373 // UI for splitting the current segment
377 property real _screenLegLength: 0
379 anchorPoint.x: sourceItem.width / 2
380 anchorPoint.y: sourceItem.height / 2
381 z: QGroundControl.zOrderWaypointLines + 1
382 visible: _editingLayer == _layerMission
383 && _screenLegLength > _missionItemIndicatorGroup.groupingDistance * 2
385 sourceItem: SplitIndicator {
386 onClicked: _missionController.insertSimpleMissionItem(splitSegmentItem.coordinate,
387 _missionController.currentPlanViewVIIndex,
388 true /* makeCurrentItem */)
391 function _updateScreenLegLength() {
392 const segment = _root._missionController.splitSegment
393 if (segment && segment.coordinate1.isValid && segment.coordinate2.isValid) {
394 const fromPoint = editorMap.fromCoordinate(segment.coordinate1, false /* clipToViewPort */)
395 const toPoint = editorMap.fromCoordinate(segment.coordinate2, false /* clipToViewPort */)
396 _screenLegLength = Math.hypot(toPoint.x - fromPoint.x, toPoint.y - fromPoint.y)
402 function _updateSplitCoord() {
403 if (_missionController.splitSegment) {
404 var distance = _missionController.splitSegment.coordinate1.distanceTo(_missionController.splitSegment.coordinate2)
405 var azimuth = _missionController.splitSegment.coordinate1.azimuthTo(_missionController.splitSegment.coordinate2)
406 splitSegmentItem.coordinate = _missionController.splitSegment.coordinate1.atDistanceAndAzimuth(distance / 2, azimuth)
408 coordinate = QtPositioning.coordinate()
410 _updateScreenLegLength()
414 target: _missionController
415 function onSplitSegmentChanged() { splitSegmentItem._updateSplitCoord() }
419 target: _missionController.splitSegment
420 function onCoordinate1Changed() { splitSegmentItem._updateSplitCoord() }
421 function onCoordinate2Changed() { splitSegmentItem._updateSplitCoord() }
426 function onCenterChanged() { splitSegmentItem._updateScreenLegLength() }
427 function onZoomLevelChanged() { splitSegmentItem._updateScreenLegLength() }
431 // Add the vehicles to the map
433 model: QGroundControl.multiVehicleManager.vehicles
434 delegate: VehicleMapItem {
436 coordinate: object.coordinate
438 size: ScreenTools.defaultFontPixelHeight * 3
439 z: QGroundControl.zOrderMapItems - 1
444 objectName: "planView_geoFenceMapVisuals"
446 myGeoFenceController: _geoFenceController
447 interactive: _editingLayer == _layerFence
448 homePosition: _missionController.plannedHomePosition
450 opacity: _editingLayer != _layerFence ? editorMap._nonInteractiveOpacity : 1
453 RallyPointMapVisuals {
454 objectName: "planView_rallyPointMapVisuals"
456 myRallyPointController: _rallyPointController
457 interactive: _editingLayer == _layerRally
459 opacity: _editingLayer != _layerRally ? editorMap._nonInteractiveOpacity : 1
464 //-----------------------------------------------------------
468 anchors.margins: _toolsMargin
469 anchors.left: parent.left
470 anchors.top: parent.top
471 z: QGroundControl.zOrderWidgets
472 maxHeight: parent.height - toolStrip.y
473 visible: _editingLayer == _layerMission
475 property bool _isMissionLayer: _editingLayer == _layerMission
478 target: waypointButton
480 value: _addWaypointOnClick
486 value: _addROIOnClick
489 ToolStripActionList {
490 id: toolStripActionList
493 objectName: "planToolStrip_takeoffButton"
494 text: qsTr("Takeoff")
495 iconSource: "/res/takeoff.svg"
496 enabled: _missionController.isInsertTakeoffValid
497 visible: toolStrip._isMissionLayer && !_planMasterController.controllerVehicle.rover
498 dropPanelComponent: _planMasterController.controllerVehicle.supports.vtolMulticopterTakeoff
499 ? vtolTakeoffDropPanel
502 insertTakeoffItemAfterCurrent()
506 objectName: "planToolStrip_patternButton"
507 text: _singleComplexItem ? _missionController.complexMissionItems[0].translatedName : qsTr("Pattern")
508 iconSource: "/qmlimages/MapDrawShape.svg"
509 enabled: _missionController.flyThroughCommandsAllowed
510 visible: toolStrip._isMissionLayer
511 dropPanelComponent: _singleComplexItem ? undefined : patternDropPanel
513 if (_singleComplexItem) {
514 insertComplexItemAfterCurrent(_missionController.complexMissionItems[0].canonicalName)
520 objectName: "planToolStrip_waypointButton"
521 text: qsTr("Waypoint")
522 iconSource: "/res/waypoint.svg"
523 enabled: _missionController.flyThroughCommandsAllowed
524 visible: toolStrip._isMissionLayer
527 _addWaypointOnClick = !_addWaypointOnClick
528 if (_addWaypointOnClick) {
529 _addROIOnClick = false
530 // Arming an insert tool leaves template-creation mode, otherwise
531 // map clicks keep moving the home position instead of inserting
532 _planMasterController.userSelectedManualCreation = true
538 objectName: "planToolStrip_roiButton"
539 text: _missionController.isROIActive ? qsTr("Cancel ROI") : qsTr("ROI")
540 iconSource: "/qmlimages/roi.svg"
541 enabled: _missionController.isInsertROIValid
542 visible: toolStrip._isMissionLayer && _planMasterController.controllerVehicle.supports.roiMode
545 _addROIOnClick = !_addROIOnClick
546 if (_addROIOnClick) {
547 _addWaypointOnClick = false
548 _planMasterController.userSelectedManualCreation = true
553 objectName: "planToolStrip_landButton"
554 text: _landButtonText()
555 iconSource: "/res/rtl.svg"
556 enabled: _missionController.isInsertLandValid
557 visible: toolStrip._isMissionLayer
559 insertLandItemAfterCurrent()
564 iconSource: "/res/chevron-double-right.svg"
565 visible: missionStatus.hidden && QGroundControl.corePlugin.options.showMissionStatus
566 onTriggered: missionStatus.showMissionStatus()
571 model: toolStripActionList.model
575 anchors.margins: _toolsMargin
576 anchors.left: toolStrip.right
577 anchors.top: parent.top
578 mapControl: editorMap
584 anchors.top: parent.top
585 anchors.bottom: parent.bottom
586 anchors.right: parent.right
587 width: _rightPanelWidth
588 planMasterController: _planMasterController
590 onEditingLayerChangeRequested: (layer) => _editingLayer = layer
593 // Layer switching icons — only active icon visible; click to expand choices leftward
596 objectName: "planView_layerSwitcher"
597 anchors.right: rightPanel.left
598 anchors.rightMargin: _toolsMargin
599 anchors.top: parent.top
600 anchors.topMargin: _toolsMargin
601 width: layerRow.width
602 height: _layerButtonSize
603 z: QGroundControl.zOrderWidgets
604 visible: !_planMasterController.showCreateFromTemplate
606 property bool expanded: false
607 property real _layerButtonSize: ScreenTools.defaultFontPixelHeight * 2.0
608 property real _spacing: ScreenTools.defaultFontPixelHeight * 0.25
613 onTriggered: layerSwitcher.expanded = false
619 collapseTimer.restart()
625 function choose(nodeType) {
628 rightPanel.selectLayer(nodeType)
631 // Row laid out right-to-left: active icon on the right, choices expand left
634 anchors.right: parent.right
635 spacing: layerSwitcher._spacing
636 layoutDirection: Qt.RightToLeft
638 // Active layer button (always visible)
640 objectName: "layerSwitcher_activeButton"
641 width: layerSwitcher._layerButtonSize
643 radius: ScreenTools.defaultBorderRadius
644 color: QGroundControl.globalPalette.buttonHighlight
647 anchors.centerIn: parent
648 width: parent.width * 0.6
650 source: PlanEditLayers.layerInfos.find(l => l.layer === _editingLayer)?.icon ?? "/res/waypoint.svg"
651 color: QGroundControl.globalPalette.buttonHighlightText
656 onClicked: layerSwitcher.toggle()
660 // Choice buttons (only layers that are NOT the current one)
662 model: PlanEditLayers.layerInfos.filter(l => l.layer !== _editingLayer)
665 required property var modelData
666 objectName: "layerSwitcher_choice_" + modelData.nodeType
667 width: choiceRow.implicitWidth + layerSwitcher._spacing * 2
668 height: layerSwitcher._layerButtonSize
669 radius: ScreenTools.defaultBorderRadius
670 color: QGroundControl.globalPalette.button
672 opacity: layerSwitcher.expanded ? 1 : 0
674 Behavior on opacity { NumberAnimation { duration: 150 } }
678 anchors.centerIn: parent
679 spacing: layerSwitcher._spacing
682 anchors.verticalCenter: parent.verticalCenter
683 width: layerSwitcher._layerButtonSize * 0.6
685 source: modelData.icon
686 color: QGroundControl.globalPalette.buttonText
690 anchors.verticalCenter: parent.verticalCenter
692 color: QGroundControl.globalPalette.buttonText
698 onClicked: layerSwitcher.choose(modelData.nodeType)
707 anchors.margins: _toolsMargin
708 anchors.left: _calcLeftAnchor()
709 anchors.right: rightPanel.left
710 anchors.bottom: parent.bottom
712 visible: !hidden && _editingLayer == _layerMission && QGroundControl.corePlugin.options.showMissionStatus
714 readonly property bool hidden: _planViewSettings.showMissionItemStatus.rawValue ? false : true
716 function showMissionStatus() {
717 _planViewSettings.showMissionItemStatus.rawValue = true
720 function _calcLeftAnchor() {
721 let bottomOfToolStrip = toolStrip.y + toolStrip.height
722 let largestStatsHeight = Math.max(terrainStatus.height, missionStats.height)
723 if (bottomOfToolStrip + largestStatsHeight > parent.height - missionStatus.anchors.margins) {
724 return toolStrip.right
729 function _toggleMissionStatusVisibility() {
730 _planViewSettings.showMissionItemStatus.rawValue = _planViewSettings.showMissionItemStatus.rawValue ? false : true
734 id: missionStatsButtonLayout
735 Layout.alignment: Qt.AlignBottom
738 property real _buttonImplicitWidth: ScreenTools.defaultFontPixelHeight * 1.5
739 property real _buttonImageMargins: _buttonImplicitWidth * 0.15
743 implicitWidth: missionStatsButtonLayout._buttonImplicitWidth
744 implicitHeight: implicitWidth
745 color: checked ? QGroundControl.globalPalette.buttonHighlight : QGroundControl.globalPalette.button
747 property bool checked: true
750 anchors.margins: missionStatsButtonLayout._buttonImageMargins
752 source: "/res/terrain.svg"
753 color: parent.checked ? QGroundControl.globalPalette.buttonHighlightText : QGroundControl.globalPalette.buttonText
759 terrainButton.checked = true
760 missionStatsButton.checked = false
766 id: missionStatsButton
767 implicitWidth: missionStatsButtonLayout._buttonImplicitWidth
768 implicitHeight: implicitWidth
769 color: checked ? QGroundControl.globalPalette.buttonHighlight : QGroundControl.globalPalette.button
771 property bool checked: false
774 anchors.margins: missionStatsButtonLayout._buttonImageMargins
776 source: "/res/sliders.svg"
777 color: parent.checked ? QGroundControl.globalPalette.buttonHighlightText : QGroundControl.globalPalette.buttonText
783 missionStatsButton.checked = true
784 terrainButton.checked = false
790 id: bottomStatusOpenCloseButton
791 implicitWidth: missionStatsButtonLayout._buttonImplicitWidth
792 implicitHeight: implicitWidth
793 color: QGroundControl.globalPalette.button
796 anchors.margins: missionStatsButtonLayout._buttonImageMargins
798 source: "/res/chevron-double-left.svg"
799 color: QGroundControl.globalPalette.buttonText
804 onClicked: missionStatus._toggleMissionStatusVisibility()
811 Layout.alignment: Qt.AlignBottom
812 Layout.fillWidth: true
813 height: ScreenTools.defaultFontPixelHeight * 7
814 missionController: _missionController
815 visible: terrainButton.checked
816 onSetCurrentSeqNum: _missionController.setCurrentPlanViewSeqNum(seqNum, true)
821 Layout.alignment: Qt.AlignBottom
822 Layout.fillWidth: true
823 visible: missionStatsButton.checked
824 planMasterController: _root._planMasterController
829 //- ToolStrip ToolStripDropPanel Components
835 spacing: ScreenTools.defaultFontPixelWidth * 0.5
837 QGCLabel { text: qsTr("Create complex pattern:") }
840 model: _missionController.complexMissionItems
843 text: modelData.translatedName
844 Layout.fillWidth: true
847 insertComplexItemAfterCurrent(modelData.canonicalName)
856 id: vtolTakeoffDropPanel
859 spacing: ScreenTools.defaultFontPixelWidth * 0.5
861 QGCLabel { text: qsTr("Choose takeoff mode:") }
864 objectName: "planTakeoff_vtolButton"
865 text: qsTr("VTOL takeoff")
866 Layout.fillWidth: true
870 insertTakeoffItemAfterCurrent()
876 objectName: "planTakeoff_mcButton"
877 text: qsTr("Multicopter takeoff")
878 Layout.fillWidth: true
881 insertVTOLMulticopterTakeoffItemAfterCurrent()
888 QGCPopupDialogFactory {
889 id: promptForPlanUsageOnVehicleChangePopupFactory
891 dialogComponent: promptForPlanUsageOnVehicleChangePopupComponent
895 id: promptForPlanUsageOnVehicleChangePopupComponent
897 title: _planMasterController.managerVehicle.isOfflineEditingVehicle ? qsTr("Plan View - Vehicle Disconnected") : qsTr("Plan View - Vehicle Changed")
898 buttons: Dialog.NoButton
902 Layout.maximumWidth: parent.width
903 wrapMode: QGCLabel.WordWrap
904 text: _planMasterController.managerVehicle.isOfflineEditingVehicle ?
905 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?")
909 Layout.fillWidth: true
910 text: (_planMasterController.dirtyForSave) ?
911 (_planMasterController.managerVehicle.isOfflineEditingVehicle ?
912 qsTr("Discard Unsaved Changes") : qsTr("Discard Unsaved Changes, Load New Plan From Vehicle")) : qsTr("Load New Plan From Vehicle")
914 _planMasterController.showPlanFromManagerVehicle()
915 _promptForPlanUsageShowing = false
921 Layout.fillWidth: true
922 text: _planMasterController.managerVehicle.isOfflineEditingVehicle ?
923 qsTr("Keep Current Plan") : qsTr("Keep Current Plan, Don't Update From Vehicle")
925 _promptForPlanUsageShowing = false
934 id: insertOrCancelROIDropPanelComponent
937 id: insertOrCancelROIDropPanel
940 property var mapClickCoord
942 sourceComponent: Component {
944 spacing: ScreenTools.defaultFontPixelWidth / 2
947 Layout.fillWidth: true
948 text: qsTr("Insert ROI")
951 insertOrCancelROIDropPanel.close()
952 insertROIAfterCurrent(mapClickCoord)
957 Layout.fillWidth: true
958 text: qsTr("Insert Cancel ROI")
961 insertOrCancelROIDropPanel.close()
962 insertCancelROIAfterCurrent()