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 insertLandItemAfterCurrent() {
198 var nextIndex = _missionController.currentPlanViewVIIndex + 1
199 _missionController.insertLandItem(mapCenter(), nextIndex, true /* makeCurrentItem */)
204 folder: _appSettings ? _appSettings.missionSavePath : ""
206 property bool planFiles: true ///< true: working with plan files, false: working with kml file
208 onAcceptedForSave: (file) => {
210 if (_planMasterController.saveToFile(file)) {
214 _planMasterController.saveToKml(file)
219 onAcceptedForLoad: (file) => {
220 _planMasterController.loadFromFile(file)
221 _planMasterController.fitViewportToItems()
222 _missionController.setCurrentPlanViewSeqNum(0, true)
229 planMasterController: _planMasterController
230 showRallyPointsHelp: _editingLayer === _layerRally
235 anchors.left: parent.left
236 anchors.right: parent.right
237 anchors.top: planToolBar.bottom
238 anchors.bottom: parent.bottom
242 objectName: "planView_map"
244 mapName: "MissionEditor"
245 allowGCSLocationCenter: true
246 allowVehicleLocationCenter: true
249 zoomLevel: QGroundControl.flightMapZoom
250 center: QGroundControl.flightMapPosition
252 // This is the center rectangle of the map which is not obscured by tools
253 property rect centerViewport: Qt.rect(_leftToolWidth + _margin, _margin, editorMap.width - _leftToolWidth - _rightToolWidth - (_margin * 2), (missionStatus.visible ? missionStatus.y : height - _margin) - _margin)
255 property real _leftToolWidth: toolStrip.x + toolStrip.width
256 property real _rightToolWidth: rightPanel.width + rightPanel.anchors.rightMargin
257 property real _nonInteractiveOpacity: 0.5
259 // Initial map position duplicates Fly view position
260 Component.onCompleted: editorMap.center = QGroundControl.flightMapPosition
262 onZoomLevelChanged: {
263 QGroundControl.flightMapZoom = editorMap.zoomLevel
266 QGroundControl.flightMapPosition = editorMap.center
269 onMapClicked: (mouse) => {
270 // Take focus to close any previous editing
271 editorMap.focus = true
273 // Collapse layer switcher on any map click
274 layerSwitcher.expanded = false
277 if (!mainWindow.allowViewSwitch()) {
280 var coordinate = editorMap.toCoordinate(Qt.point(mouse.x, mouse.y), false /* clipToViewPort */)
281 coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces)
282 coordinate.longitude = coordinate.longitude.toFixed(_decimalPlaces)
283 coordinate.altitude = coordinate.altitude.toFixed(_decimalPlaces)
285 switch (_editingLayer) {
287 if (_planMasterController.showCreateFromTemplate) {
288 _missionController.setHomePosition(coordinate)
289 } else if (_addROIOnClick) {
290 _addROIOnClick = false
291 if (_missionController.isROIActive) {
292 var pos = Qt.point(mouse.x, mouse.y)
293 // For some strange reason using mainWindow in mapToItem doesn't work, so we use globals.parent instead which also gets us mainWindow
294 pos = editorMap.mapToItem(globals.parent, pos)
295 var dropPanel = insertOrCancelROIDropPanelComponent.createObject(mainWindow, { mapClickCoord: coordinate, clickRect: Qt.rect(pos.x, pos.y, 0, 0) })
298 insertROIAfterCurrent(coordinate)
300 } else if (_addWaypointOnClick) {
301 insertSimpleItemAfterCurrent(coordinate)
305 if (_rallyPointController.supported) {
306 _rallyPointController.addPoint(coordinate)
312 // Add the mission item visuals to the map
314 model: _missionController.visualItems
315 delegate: MissionItemMapVisual {
317 opacity: _editingLayer == _layerMission ? 1 : editorMap._nonInteractiveOpacity
318 interactive: _editingLayer == _layerMission
319 vehicle: _planMasterController.controllerVehicle
320 onClicked: (sequenceNumber) => { _missionController.setCurrentPlanViewSeqNum(sequenceNumber, false) }
324 // Add lines between waypoints
326 showSpecialVisual: _missionController.isROIBeginCurrentItem
327 model: _missionController.simpleFlightPathSegments
328 opacity: _editingLayer == _layerMission ? 1 : editorMap._nonInteractiveOpacity
331 // Direction arrows in waypoint lines
333 model: _editingLayer == _layerMission ? _missionController.directionArrows : undefined
335 delegate: MapLineArrow {
336 fromCoord: object ? object.coordinate1 : undefined
337 toCoord: object ? object.coordinate2 : undefined
339 z: QGroundControl.zOrderWaypointLines + 1
343 // UI for splitting the current segment
346 anchorPoint.x: sourceItem.width / 2
347 anchorPoint.y: sourceItem.height / 2
348 z: QGroundControl.zOrderWaypointLines + 1
349 visible: _editingLayer == _layerMission
351 sourceItem: SplitIndicator {
352 onClicked: _missionController.insertSimpleMissionItem(splitSegmentItem.coordinate,
353 _missionController.currentPlanViewVIIndex,
354 true /* makeCurrentItem */)
357 function _updateSplitCoord() {
358 if (_missionController.splitSegment) {
359 var distance = _missionController.splitSegment.coordinate1.distanceTo(_missionController.splitSegment.coordinate2)
360 var azimuth = _missionController.splitSegment.coordinate1.azimuthTo(_missionController.splitSegment.coordinate2)
361 splitSegmentItem.coordinate = _missionController.splitSegment.coordinate1.atDistanceAndAzimuth(distance / 2, azimuth)
363 coordinate = QtPositioning.coordinate()
368 target: _missionController
369 function onSplitSegmentChanged() { splitSegmentItem._updateSplitCoord() }
373 target: _missionController.splitSegment
374 function onCoordinate1Changed() { splitSegmentItem._updateSplitCoord() }
375 function onCoordinate2Changed() { splitSegmentItem._updateSplitCoord() }
379 // Add the vehicles to the map
381 model: QGroundControl.multiVehicleManager.vehicles
382 delegate: VehicleMapItem {
384 coordinate: object.coordinate
386 size: ScreenTools.defaultFontPixelHeight * 3
387 z: QGroundControl.zOrderMapItems - 1
392 objectName: "planView_geoFenceMapVisuals"
394 myGeoFenceController: _geoFenceController
395 interactive: _editingLayer == _layerFence
396 homePosition: _missionController.plannedHomePosition
398 opacity: _editingLayer != _layerFence ? editorMap._nonInteractiveOpacity : 1
401 RallyPointMapVisuals {
402 objectName: "planView_rallyPointMapVisuals"
404 myRallyPointController: _rallyPointController
405 interactive: _editingLayer == _layerRally
407 opacity: _editingLayer != _layerRally ? editorMap._nonInteractiveOpacity : 1
412 //-----------------------------------------------------------
416 anchors.margins: _toolsMargin
417 anchors.left: parent.left
418 anchors.top: parent.top
419 z: QGroundControl.zOrderWidgets
420 maxHeight: parent.height - toolStrip.y
421 visible: _editingLayer == _layerMission
423 property bool _isMissionLayer: _editingLayer == _layerMission
426 target: waypointButton
428 value: _addWaypointOnClick
434 value: _addROIOnClick
437 ToolStripActionList {
438 id: toolStripActionList
441 objectName: "planToolStrip_takeoffButton"
442 text: qsTr("Takeoff")
443 iconSource: "/res/takeoff.svg"
444 enabled: _missionController.isInsertTakeoffValid
445 visible: toolStrip._isMissionLayer && !_planMasterController.controllerVehicle.rover
447 insertTakeoffItemAfterCurrent()
451 objectName: "planToolStrip_patternButton"
452 text: _singleComplexItem ? _missionController.complexMissionItems[0].translatedName : qsTr("Pattern")
453 iconSource: "/qmlimages/MapDrawShape.svg"
454 enabled: _missionController.flyThroughCommandsAllowed
455 visible: toolStrip._isMissionLayer
456 dropPanelComponent: _singleComplexItem ? undefined : patternDropPanel
458 if (_singleComplexItem) {
459 insertComplexItemAfterCurrent(_missionController.complexMissionItems[0].canonicalName)
465 objectName: "planToolStrip_waypointButton"
466 text: qsTr("Waypoint")
467 iconSource: "/res/waypoint.svg"
468 enabled: _missionController.flyThroughCommandsAllowed
469 visible: toolStrip._isMissionLayer
472 _addWaypointOnClick = !_addWaypointOnClick
473 if (_addWaypointOnClick) {
474 _addROIOnClick = false
475 // Arming an insert tool leaves template-creation mode, otherwise
476 // map clicks keep moving the home position instead of inserting
477 _planMasterController.userSelectedManualCreation = true
483 objectName: "planToolStrip_roiButton"
484 text: _missionController.isROIActive ? qsTr("Cancel ROI") : qsTr("ROI")
485 iconSource: "/qmlimages/roi.svg"
486 enabled: _missionController.isInsertROIValid
487 visible: toolStrip._isMissionLayer && _planMasterController.controllerVehicle.supports.roiMode
490 _addROIOnClick = !_addROIOnClick
491 if (_addROIOnClick) {
492 _addWaypointOnClick = false
493 _planMasterController.userSelectedManualCreation = true
498 objectName: "planToolStrip_landButton"
499 text: _planMasterController.controllerVehicle.multiRotor
501 : _missionController.isInsertLandValid && _missionController.hasLandItem
504 iconSource: "/res/rtl.svg"
505 enabled: _missionController.isInsertLandValid
506 visible: toolStrip._isMissionLayer
508 insertLandItemAfterCurrent()
513 iconSource: "/res/chevron-double-right.svg"
514 visible: missionStatus.hidden && QGroundControl.corePlugin.options.showMissionStatus
515 onTriggered: missionStatus.showMissionStatus()
520 model: toolStripActionList.model
524 anchors.margins: _toolsMargin
525 anchors.left: toolStrip.right
526 anchors.top: parent.top
527 mapControl: editorMap
533 anchors.top: parent.top
534 anchors.bottom: parent.bottom
535 anchors.right: parent.right
536 width: _rightPanelWidth
537 planMasterController: _planMasterController
539 onEditingLayerChangeRequested: (layer) => _editingLayer = layer
542 // Layer switching icons — only active icon visible; click to expand choices leftward
545 objectName: "planView_layerSwitcher"
546 anchors.right: rightPanel.left
547 anchors.rightMargin: _toolsMargin
548 anchors.top: parent.top
549 anchors.topMargin: _toolsMargin
550 width: layerRow.width
551 height: _layerButtonSize
552 z: QGroundControl.zOrderWidgets
553 visible: !_planMasterController.showCreateFromTemplate
555 property bool expanded: false
556 property real _layerButtonSize: ScreenTools.defaultFontPixelHeight * 2.0
557 property real _spacing: ScreenTools.defaultFontPixelHeight * 0.25
562 onTriggered: layerSwitcher.expanded = false
568 collapseTimer.restart()
574 function choose(nodeType) {
577 rightPanel.selectLayer(nodeType)
580 // Row laid out right-to-left: active icon on the right, choices expand left
583 anchors.right: parent.right
584 spacing: layerSwitcher._spacing
585 layoutDirection: Qt.RightToLeft
587 // Active layer button (always visible)
589 objectName: "layerSwitcher_activeButton"
590 width: layerSwitcher._layerButtonSize
592 radius: ScreenTools.defaultBorderRadius
593 color: QGroundControl.globalPalette.buttonHighlight
596 anchors.centerIn: parent
597 width: parent.width * 0.6
599 source: PlanEditLayers.layerInfos.find(l => l.layer === _editingLayer)?.icon ?? "/res/waypoint.svg"
600 color: QGroundControl.globalPalette.buttonHighlightText
605 onClicked: layerSwitcher.toggle()
609 // Choice buttons (only layers that are NOT the current one)
611 model: PlanEditLayers.layerInfos.filter(l => l.layer !== _editingLayer)
614 required property var modelData
615 objectName: "layerSwitcher_choice_" + modelData.nodeType
616 width: choiceRow.implicitWidth + layerSwitcher._spacing * 2
617 height: layerSwitcher._layerButtonSize
618 radius: ScreenTools.defaultBorderRadius
619 color: QGroundControl.globalPalette.button
621 opacity: layerSwitcher.expanded ? 1 : 0
623 Behavior on opacity { NumberAnimation { duration: 150 } }
627 anchors.centerIn: parent
628 spacing: layerSwitcher._spacing
631 anchors.verticalCenter: parent.verticalCenter
632 width: layerSwitcher._layerButtonSize * 0.6
634 source: modelData.icon
635 color: QGroundControl.globalPalette.buttonText
639 anchors.verticalCenter: parent.verticalCenter
641 color: QGroundControl.globalPalette.buttonText
647 onClicked: layerSwitcher.choose(modelData.nodeType)
656 anchors.margins: _toolsMargin
657 anchors.left: _calcLeftAnchor()
658 anchors.right: rightPanel.left
659 anchors.bottom: parent.bottom
661 visible: !hidden && _editingLayer == _layerMission && QGroundControl.corePlugin.options.showMissionStatus
663 readonly property bool hidden: _planViewSettings.showMissionItemStatus.rawValue ? false : true
665 function showMissionStatus() {
666 _planViewSettings.showMissionItemStatus.rawValue = true
669 function _calcLeftAnchor() {
670 let bottomOfToolStrip = toolStrip.y + toolStrip.height
671 let largestStatsHeight = Math.max(terrainStatus.height, missionStats.height)
672 if (bottomOfToolStrip + largestStatsHeight > parent.height - missionStatus.anchors.margins) {
673 return toolStrip.right
678 function _toggleMissionStatusVisibility() {
679 _planViewSettings.showMissionItemStatus.rawValue = _planViewSettings.showMissionItemStatus.rawValue ? false : true
683 id: missionStatsButtonLayout
684 Layout.alignment: Qt.AlignBottom
687 property real _buttonImplicitWidth: ScreenTools.defaultFontPixelHeight * 1.5
688 property real _buttonImageMargins: _buttonImplicitWidth * 0.15
692 implicitWidth: missionStatsButtonLayout._buttonImplicitWidth
693 implicitHeight: implicitWidth
694 color: checked ? QGroundControl.globalPalette.buttonHighlight : QGroundControl.globalPalette.button
696 property bool checked: true
699 anchors.margins: missionStatsButtonLayout._buttonImageMargins
701 source: "/res/terrain.svg"
702 color: parent.checked ? QGroundControl.globalPalette.buttonHighlightText : QGroundControl.globalPalette.buttonText
708 terrainButton.checked = true
709 missionStatsButton.checked = false
715 id: missionStatsButton
716 implicitWidth: missionStatsButtonLayout._buttonImplicitWidth
717 implicitHeight: implicitWidth
718 color: checked ? QGroundControl.globalPalette.buttonHighlight : QGroundControl.globalPalette.button
720 property bool checked: false
723 anchors.margins: missionStatsButtonLayout._buttonImageMargins
725 source: "/res/sliders.svg"
726 color: parent.checked ? QGroundControl.globalPalette.buttonHighlightText : QGroundControl.globalPalette.buttonText
732 missionStatsButton.checked = true
733 terrainButton.checked = false
739 id: bottomStatusOpenCloseButton
740 implicitWidth: missionStatsButtonLayout._buttonImplicitWidth
741 implicitHeight: implicitWidth
742 color: QGroundControl.globalPalette.button
745 anchors.margins: missionStatsButtonLayout._buttonImageMargins
747 source: "/res/chevron-double-left.svg"
748 color: QGroundControl.globalPalette.buttonText
753 onClicked: missionStatus._toggleMissionStatusVisibility()
760 Layout.alignment: Qt.AlignBottom
761 Layout.fillWidth: true
762 height: ScreenTools.defaultFontPixelHeight * 7
763 missionController: _missionController
764 visible: terrainButton.checked
765 onSetCurrentSeqNum: _missionController.setCurrentPlanViewSeqNum(seqNum, true)
770 Layout.alignment: Qt.AlignBottom
771 Layout.fillWidth: true
772 visible: missionStatsButton.checked
773 planMasterController: _root._planMasterController
778 //- ToolStrip ToolStripDropPanel Components
784 spacing: ScreenTools.defaultFontPixelWidth * 0.5
786 QGCLabel { text: qsTr("Create complex pattern:") }
789 model: _missionController.complexMissionItems
792 text: modelData.translatedName
793 Layout.fillWidth: true
796 insertComplexItemAfterCurrent(modelData.canonicalName)
804 QGCPopupDialogFactory {
805 id: promptForPlanUsageOnVehicleChangePopupFactory
807 dialogComponent: promptForPlanUsageOnVehicleChangePopupComponent
811 id: promptForPlanUsageOnVehicleChangePopupComponent
813 title: _planMasterController.managerVehicle.isOfflineEditingVehicle ? qsTr("Plan View - Vehicle Disconnected") : qsTr("Plan View - Vehicle Changed")
814 buttons: Dialog.NoButton
818 Layout.maximumWidth: parent.width
819 wrapMode: QGCLabel.WordWrap
820 text: _planMasterController.managerVehicle.isOfflineEditingVehicle ?
821 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?")
825 Layout.fillWidth: true
826 text: (_planMasterController.dirtyForSave) ?
827 (_planMasterController.managerVehicle.isOfflineEditingVehicle ?
828 qsTr("Discard Unsaved Changes") : qsTr("Discard Unsaved Changes, Load New Plan From Vehicle")) : qsTr("Load New Plan From Vehicle")
830 _planMasterController.showPlanFromManagerVehicle()
831 _promptForPlanUsageShowing = false
837 Layout.fillWidth: true
838 text: _planMasterController.managerVehicle.isOfflineEditingVehicle ?
839 qsTr("Keep Current Plan") : qsTr("Keep Current Plan, Don't Update From Vehicle")
841 _promptForPlanUsageShowing = false
850 id: insertOrCancelROIDropPanelComponent
853 id: insertOrCancelROIDropPanel
856 property var mapClickCoord
858 sourceComponent: Component {
860 spacing: ScreenTools.defaultFontPixelWidth / 2
863 Layout.fillWidth: true
864 text: qsTr("Insert ROI")
867 insertOrCancelROIDropPanel.close()
868 insertROIAfterCurrent(mapClickCoord)
873 Layout.fillWidth: true
874 text: qsTr("Insert Cancel ROI")
877 insertOrCancelROIDropPanel.close()
878 insertCancelROIAfterCurrent()