QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
FlyViewMap.qml
Go to the documentation of this file.
1import QtQuick
2import QtQuick.Controls
3import QtLocation
4import QtPositioning
5import QtQuick.Dialogs
6import QtQuick.Layouts
7
8import QGroundControl
9import QGroundControl.Controls
10import QGroundControl.FlyView
11import QGroundControl.FlightMap
12
13FlightMap {
14 id: _root
15 allowGCSLocationCenter: true
16 allowVehicleLocationCenter: !_keepVehicleCentered
17 planView: false
18 zoomLevel: QGroundControl.flightMapZoom
19 center: QGroundControl.flightMapPosition
20
21 property Item pipView
22 property Item pipState: _pipState
23 property var rightPanelWidth
24 property var planMasterController
25 property bool pipMode: false // true: map is shown in a small pip mode
26 property var toolInsets // Insets for the center viewport area
27
28 property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
29 property var _planMasterController: planMasterController
30 property var _geoFenceController: planMasterController.geoFenceController
31 property var _rallyPointController: planMasterController.rallyPointController
32 property var _activeVehicleCoordinate: _activeVehicle ? _activeVehicle.coordinate : QtPositioning.coordinate()
33 property real _toolButtonTopMargin: parent.height - mainWindow.height + (ScreenTools.defaultFontPixelHeight / 2)
34 property real _toolsMargin: ScreenTools.defaultFontPixelWidth * 0.75
35 property var _flyViewSettings: QGroundControl.settingsManager.flyViewSettings
36 property bool _keepMapCenteredOnVehicle: _flyViewSettings.keepMapCenteredOnVehicle.rawValue
37
38 property bool _disableVehicleTracking: false
39 property bool _keepVehicleCentered: pipMode ? true : false
40 property bool _saveZoomLevelSetting: true
41
42 function _adjustMapZoomForPipMode() {
43 _saveZoomLevelSetting = false
44 if (pipMode) {
45 if (QGroundControl.flightMapZoom > 3) {
46 zoomLevel = QGroundControl.flightMapZoom - 3
47 }
48 } else {
49 zoomLevel = QGroundControl.flightMapZoom
50 }
51 _saveZoomLevelSetting = true
52 }
53
54 onPipModeChanged: _adjustMapZoomForPipMode()
55
56 onVisibleChanged: {
57 if (visible) {
58 // Synchronize center position with Plan View
59 center = QGroundControl.flightMapPosition
60 }
61 }
62
63 onZoomLevelChanged: {
64 if (_saveZoomLevelSetting) {
65 QGroundControl.flightMapZoom = _root.zoomLevel
66 }
67 }
68 onCenterChanged: {
69 QGroundControl.flightMapPosition = _root.center
70 }
71
72 // We track whether the user has panned or not to correctly handle automatic map positioning
73 onMapPanStart: _disableVehicleTracking = true
74 onMapPanStop: panRecenterTimer.restart()
75
76 function pointInRect(point, rect) {
77 return point.x > rect.x &&
78 point.x < rect.x + rect.width &&
79 point.y > rect.y &&
80 point.y < rect.y + rect.height;
81 }
82
83 property real _animatedLatitudeStart
84 property real _animatedLatitudeStop
85 property real _animatedLongitudeStart
86 property real _animatedLongitudeStop
87 property real animatedLatitude
88 property real animatedLongitude
89
90 onAnimatedLatitudeChanged: _root.center = QtPositioning.coordinate(animatedLatitude, animatedLongitude)
91 onAnimatedLongitudeChanged: _root.center = QtPositioning.coordinate(animatedLatitude, animatedLongitude)
92
93 NumberAnimation on animatedLatitude { id: animateLat; from: _animatedLatitudeStart; to: _animatedLatitudeStop; duration: 1000 }
94 NumberAnimation on animatedLongitude { id: animateLong; from: _animatedLongitudeStart; to: _animatedLongitudeStop; duration: 1000 }
95
96 function animatedMapRecenter(fromCoord, toCoord) {
97 _animatedLatitudeStart = fromCoord.latitude
98 _animatedLongitudeStart = fromCoord.longitude
99 _animatedLatitudeStop = toCoord.latitude
100 _animatedLongitudeStop = toCoord.longitude
101 animateLat.start()
102 animateLong.start()
103 }
104
105 // returns the rectangle formed by the four center insets
106 // used for checking if vehicle is under ui, and as a target for recentering the view
107 function _insetCenterRect() {
108 return Qt.rect(toolInsets.leftEdgeCenterInset,
109 toolInsets.topEdgeCenterInset,
110 _root.width - toolInsets.leftEdgeCenterInset - toolInsets.rightEdgeCenterInset,
111 _root.height - toolInsets.topEdgeCenterInset - toolInsets.bottomEdgeCenterInset)
112 }
113
114 // returns the four rectangles formed by the 8 corner insets
115 // used for detecting if the vehicle has flown under the instrument panel, virtual joystick etc
116 function _insetCornerRects() {
117 var rects = {
118 "topleft": Qt.rect(0,0,
119 toolInsets.leftEdgeTopInset,
120 toolInsets.topEdgeLeftInset),
121 "topright": Qt.rect(_root.width-toolInsets.rightEdgeTopInset,0,
122 toolInsets.rightEdgeTopInset,
123 toolInsets.topEdgeRightInset),
124 "bottomleft": Qt.rect(0,_root.height-toolInsets.bottomEdgeLeftInset,
125 toolInsets.leftEdgeBottomInset,
126 toolInsets.bottomEdgeLeftInset),
127 "bottomright": Qt.rect(_root.width-toolInsets.rightEdgeBottomInset,_root.height-toolInsets.bottomEdgeRightInset,
128 toolInsets.rightEdgeBottomInset,
129 toolInsets.bottomEdgeRightInset)}
130 return rects
131 }
132
133 function recenterNeeded() {
134 var vehiclePoint = _root.fromCoordinate(_activeVehicleCoordinate, false /* clipToViewport */)
135 var centerRect = _insetCenterRect()
136 //return !pointInRect(vehiclePoint,insetRect)
137
138 // If we are outside the center inset rectangle, recenter
139 if(!pointInRect(vehiclePoint, centerRect)){
140 return true
141 }
142
143 // if we are inside the center inset rectangle
144 // then additionally check if we are underneath one of the corner inset rectangles
145 var cornerRects = _insetCornerRects()
146 if(pointInRect(vehiclePoint, cornerRects["topleft"])){
147 return true
148 } else if(pointInRect(vehiclePoint, cornerRects["topright"])){
149 return true
150 } else if(pointInRect(vehiclePoint, cornerRects["bottomleft"])){
151 return true
152 } else if(pointInRect(vehiclePoint, cornerRects["bottomright"])){
153 return true
154 }
155
156 // if we are inside the center inset rectangle, and not under any corner elements
157 return false
158 }
159
160 function updateMapToVehiclePosition() {
161 if (animateLat.running || animateLong.running) {
162 return
163 }
164 // We let FlightMap handle first vehicle position
165 if (!_keepMapCenteredOnVehicle && firstVehiclePositionReceived && _activeVehicleCoordinate.isValid && !_disableVehicleTracking) {
166 if (_keepVehicleCentered) {
167 _root.center = _activeVehicleCoordinate
168 } else {
169 if (firstVehiclePositionReceived && recenterNeeded()) {
170 // Move the map such that the vehicle is centered within the inset area
171 var vehiclePoint = _root.fromCoordinate(_activeVehicleCoordinate, false /* clipToViewport */)
172 var centerInsetRect = _insetCenterRect()
173 var centerInsetPoint = Qt.point(centerInsetRect.x + centerInsetRect.width / 2, centerInsetRect.y + centerInsetRect.height / 2)
174 var centerOffset = Qt.point((_root.width / 2) - centerInsetPoint.x, (_root.height / 2) - centerInsetPoint.y)
175 var vehicleOffsetPoint = Qt.point(vehiclePoint.x + centerOffset.x, vehiclePoint.y + centerOffset.y)
176 var vehicleOffsetCoord = _root.toCoordinate(vehicleOffsetPoint, false /* clipToViewport */)
177 animatedMapRecenter(_root.center, vehicleOffsetCoord)
178 }
179 }
180 }
181 }
182
183 on_ActiveVehicleCoordinateChanged: {
184 if (_keepMapCenteredOnVehicle && _activeVehicleCoordinate.isValid && !_disableVehicleTracking) {
185 _root.center = _activeVehicleCoordinate
186 }
187 }
188
189 PipState {
190 id: _pipState
191 pipView: _root.pipView
192 isDark: _isFullWindowItemDark
193 }
194
195 Timer {
196 id: panRecenterTimer
197 interval: 10000
198 running: false
199 onTriggered: {
200 _disableVehicleTracking = false
201 updateMapToVehiclePosition()
202 }
203 }
204
205 Timer {
206 interval: 500
207 running: true
208 repeat: true
209 onTriggered: updateMapToVehiclePosition()
210 }
211
212 QGCMapPalette { id: mapPal; lightColors: isSatelliteMap }
213
214 Connections {
215 target: _missionController
216 ignoreUnknownSignals: true
217 function onNewItemsFromVehicle() {
218 var visualItems = _missionController.visualItems
219 if (visualItems && visualItems.count !== 1) {
220 mapFitFunctions.fitMapViewportToMissionItems()
221 firstVehiclePositionReceived = true
222 }
223 }
224 }
225
226 MapFitFunctions {
227 id: mapFitFunctions // The name for this id cannot be changed without breaking references outside of this code. Beware!
228 map: _root
229 usePlannedHomePosition: false
230 planMasterController: _planMasterController
231 }
232
233 ObstacleDistanceOverlayMap {
234 id: obstacleDistance
235 showText: !pipMode
236 }
237
238 // Add trajectory lines to the map
239 MapPolyline {
240 id: trajectoryPolyline
241 line.width: 3
242 line.color: "red"
243 z: QGroundControl.zOrderTrajectoryLines
244 visible: !pipMode
245
246 Connections {
247 target: QGroundControl.multiVehicleManager
248 function onActiveVehicleChanged(activeVehicle) {
249 trajectoryPolyline.path = _activeVehicle ? _activeVehicle.trajectoryPoints.list() : []
250 }
251 }
252
253 Connections {
254 target: _activeVehicle ? _activeVehicle.trajectoryPoints : null
255 function onPointAdded(coordinate) { trajectoryPolyline.addCoordinate(coordinate) }
256 function onUpdateLastPoint(coordinate) { trajectoryPolyline.replaceCoordinate(trajectoryPolyline.pathLength() - 1, coordinate) }
257 function onPointsCleared() { trajectoryPolyline.path = [] }
258 }
259 }
260
261 // Add the vehicles to the map
262 MapItemView {
263 model: QGroundControl.multiVehicleManager.vehicles
264 delegate: VehicleMapItem {
265 vehicle: object
266 coordinate: object.coordinate
267 map: _root
268 size: pipMode ? ScreenTools.defaultFontPixelHeight : ScreenTools.defaultFontPixelHeight * 3
269 z: QGroundControl.zOrderVehicles
270 }
271 }
272 // Add distance sensor view
273 MapItemView{
274 model: QGroundControl.multiVehicleManager.vehicles
275 delegate: ProximityRadarMapView {
276 vehicle: object
277 coordinate: object.coordinate
278 map: _root
279 z: QGroundControl.zOrderVehicles
280 }
281 }
282 // Add ADSB vehicles to the map
283 MapItemView {
284 model: QGroundControl.adsbVehicleManager.adsbVehicles
285 delegate: VehicleMapItem {
286 coordinate: object.coordinate
287 altitude: object.altitude
288 callsign: object.callsign
289 heading: object.heading
290 alert: object.alert
291 map: _root
292 size: pipMode ? ScreenTools.defaultFontPixelHeight : ScreenTools.defaultFontPixelHeight * 2.5
293 z: QGroundControl.zOrderVehicles
294 }
295 }
296
297 // Add the items associated with each vehicles flight plan to the map
298 Repeater {
299 model: QGroundControl.multiVehicleManager.vehicles
300
301 PlanMapItems {
302 map: _root
303 largeMapView: !pipMode
304 planMasterController: masterController
305 vehicle: _vehicle
306
307 property var _vehicle: object
308
309 PlanMasterController {
310 id: masterController
311 Component.onCompleted: startStaticActiveVehicle(object)
312 }
313 }
314 }
315
316 // Allow custom builds to add map items
317 CustomMapItems {
318 map: _root
319 largeMapView: !pipMode
320 }
321
322 GeoFenceMapVisuals {
323 map: _root
324 myGeoFenceController: _geoFenceController
325 interactive: false
326 planView: false
327 homePosition: _activeVehicle && _activeVehicle.homePosition.isValid ? _activeVehicle.homePosition : QtPositioning.coordinate()
328 }
329
330 // Rally points on map
331 MapItemView {
332 model: _rallyPointController.points
333
334 delegate: MapQuickItem {
335 id: itemIndicator
336 anchorPoint.x: sourceItem.anchorPointX
337 anchorPoint.y: sourceItem.anchorPointY
338 coordinate: object.coordinate
339 z: QGroundControl.zOrderMapItems
340
341 sourceItem: MissionItemIndexLabel {
342 id: itemIndexLabel
343 label: qsTr("R", "rally point map item label")
344 }
345 }
346 }
347
348 // Camera trigger points
349 MapItemView {
350 model: _activeVehicle ? _activeVehicle.cameraTriggerPoints : 0
351
352 delegate: CameraTriggerIndicator {
353 coordinate: object.coordinate
354 z: QGroundControl.zOrderTopMost
355 }
356 }
357
358 // GoTo Location forward flight circle visuals
359 QGCMapCircleVisuals {
360 id: fwdFlightGotoMapCircle
361 mapControl: parent
362 mapCircle: _fwdFlightGotoMapCircle
363 radiusLabelVisible: true
364 visible: gotoLocationItem.visible && _activeVehicle &&
365 _activeVehicle.inFwdFlight &&
366 !_activeVehicle.orbitActive
367
368 property alias coordinate: _fwdFlightGotoMapCircle.center
369 property alias radius: _fwdFlightGotoMapCircle.radius
370 property alias clockwiseRotation: _fwdFlightGotoMapCircle.clockwiseRotation
371
372 Component.onCompleted: {
373 // Only allow editing the radius, not the position
374 centerDragHandleVisible = false
375
376 globals.guidedControllerFlyView.fwdFlightGotoMapCircle = this
377 }
378
379 Binding {
380 target: _fwdFlightGotoMapCircle
381 property: "center"
382 value: gotoLocationItem.coordinate
383 }
384
385 function startLoiterRadiusEdit() {
386 _fwdFlightGotoMapCircle.interactive = true
387 }
388
389 // Called when loiter edit is confirmed
390 function actionConfirmed() {
391 _fwdFlightGotoMapCircle.interactive = false
392 _fwdFlightGotoMapCircle._commitRadius()
393 }
394
395 // Called when loiter edit is cancelled
396 function actionCancelled() {
397 _fwdFlightGotoMapCircle.interactive = false
398 _fwdFlightGotoMapCircle._restoreRadius()
399 }
400
401 QGCMapCircle {
402 id: _fwdFlightGotoMapCircle
403 interactive: false
404 showRotation: true
405 clockwiseRotation: true
406
407 property real _defaultLoiterRadius: _flyViewSettings.forwardFlightGoToLocationLoiterRad.value
408 property real _committedRadius;
409
410 onCenterChanged: {
411 radius.rawValue = _defaultLoiterRadius
412 // Don't commit the radius in case this operation is undone
413 }
414
415 Component.onCompleted: {
416 radius.rawValue = _defaultLoiterRadius
417 _commitRadius()
418 }
419
420 function _commitRadius() {
421 _committedRadius = radius.rawValue
422 }
423
424 function _restoreRadius() {
425 radius.rawValue = _committedRadius
426 }
427 }
428 }
429
430 // GoTo Location visuals
431 MapQuickItem {
432 id: gotoLocationItem
433 visible: false
434 z: QGroundControl.zOrderMapItems
435 anchorPoint.x: sourceItem.anchorPointX
436 anchorPoint.y: sourceItem.anchorPointY
437 sourceItem: MissionItemIndexLabel {
438 checked: true
439 index: -1
440 label: qsTr("Go here", "Go to location waypoint")
441 }
442
443 property bool inGotoFlightMode: _activeVehicle ? _activeVehicle.flightMode === _activeVehicle.gotoFlightMode : false
444
445 property var _committedCoordinate: null
446
447 onInGotoFlightModeChanged: {
448 if (!inGotoFlightMode && gotoLocationItem.visible) {
449 // Hide goto indicator when vehicle falls out of guided mode
450 hide()
451 }
452 }
453
454 function show(coord) {
455 gotoLocationItem.coordinate = coord
456 gotoLocationItem.visible = true
457 }
458
459 function hide() {
460 gotoLocationItem.visible = false
461 }
462
463 function actionConfirmed() {
464 _commitCoordinate()
465
466 // Commit the new radius which possibly changed
467 fwdFlightGotoMapCircle.actionConfirmed()
468
469 // We leave the indicator visible. The handling for onInGuidedModeChanged will hide it.
470 }
471
472 function actionCancelled() {
473 _restoreCoordinate()
474
475 // Also restore the loiter radius
476 fwdFlightGotoMapCircle.actionCancelled()
477 }
478
479 function _commitCoordinate() {
480 // Must deep copy
481 _committedCoordinate = QtPositioning.coordinate(
482 coordinate.latitude,
483 coordinate.longitude
484 );
485 }
486
487 function _restoreCoordinate() {
488 if (_committedCoordinate) {
489 coordinate = _committedCoordinate
490 } else {
491 hide()
492 }
493 }
494 }
495
496 // Orbit editing visuals
497 QGCMapCircleVisuals {
498 id: orbitMapCircle
499 mapControl: parent
500 mapCircle: _mapCircle
501 visible: false
502
503 property alias center: _mapCircle.center
504 property alias clockwiseRotation: _mapCircle.clockwiseRotation
505 readonly property real defaultRadius: 30
506
507 Connections {
508 target: QGroundControl.multiVehicleManager
509 function onActiveVehicleChanged(activeVehicle) {
510 if (!activeVehicle) {
511 orbitMapCircle.visible = false
512 }
513 }
514 }
515
516 function show(coord) {
517 _mapCircle.radius.rawValue = defaultRadius
518 orbitMapCircle.center = coord
519 orbitMapCircle.visible = true
520 }
521
522 function hide() {
523 orbitMapCircle.visible = false
524 }
525
526 function actionConfirmed() {
527 // Live orbit status is handled by telemetry so we hide here and telemetry will show again.
528 hide()
529 }
530
531 function actionCancelled() {
532 hide()
533 }
534
535 function radius() {
536 return _mapCircle.radius.rawValue
537 }
538
539 Component.onCompleted: globals.guidedControllerFlyView.orbitMapCircle = orbitMapCircle
540
541 QGCMapCircle {
542 id: _mapCircle
543 interactive: true
544 radius.rawValue: 30
545 showRotation: true
546 clockwiseRotation: true
547 }
548 }
549
550 // ROI Location visuals
551 MapQuickItem {
552 id: roiLocationItem
553 visible: _activeVehicle && _activeVehicle.isROIEnabled
554 z: QGroundControl.zOrderMapItems
555 anchorPoint.x: sourceItem.anchorPointX
556 anchorPoint.y: sourceItem.anchorPointY
557
558 Connections {
559 target: _activeVehicle
560 function onRoiCoordChanged(centerCoord) {
561 roiLocationItem.show(centerCoord)
562 }
563 }
564
565 MouseArea {
566 anchors.fill: parent
567 onClicked: (position) => {
568 position = Qt.point(position.x, position.y)
569 var clickCoord = _root.toCoordinate(position, false /* clipToViewPort */)
570 // For some strange reason using mainWindow in mapToItem doesn't work, so we use globals.parent instead which also gets us mainWindow
571 position = mapToItem(globals.parent, position)
572 var dropPanel = roiEditDropPanelComponent.createObject(mainWindow, { clickRect: Qt.rect(position.x, position.y, 0, 0) })
573 dropPanel.open()
574 }
575 }
576
577 sourceItem: MissionItemIndexLabel {
578 checked: true
579 index: -1
580 label: qsTr("ROI here", "Make this a Region Of Interest")
581 }
582
583 //-- Visibilty controlled by actual state
584 function show(coord) {
585 roiLocationItem.coordinate = coord
586 }
587 }
588
589 // Orbit telemetry visuals
590 QGCMapCircleVisuals {
591 id: orbitTelemetryCircle
592 mapControl: parent
593 mapCircle: _activeVehicle ? _activeVehicle.orbitMapCircle : null
594 visible: _activeVehicle ? _activeVehicle.orbitActive : false
595 }
596
597 MapQuickItem {
598 id: orbitCenterIndicator
599 anchorPoint.x: sourceItem.anchorPointX
600 anchorPoint.y: sourceItem.anchorPointY
601 coordinate: _activeVehicle ? _activeVehicle.orbitMapCircle.center : QtPositioning.coordinate()
602 visible: orbitTelemetryCircle.visible && !gotoLocationItem.visible
603
604 sourceItem: MissionItemIndexLabel {
605 checked: true
606 index: -1
607 label: qsTr("Orbit", "Orbit waypoint")
608 }
609 }
610
611 QGCPopupDialogFactory {
612 id: roiEditPositionDialogFactory
613
614 dialogComponent: roiEditPositionDialogComponent
615 }
616
617 Component {
618 id: roiEditPositionDialogComponent
619
620 EditPositionDialog {
621 title: qsTr("Edit ROI Position")
622 coordinate: roiLocationItem.coordinate
623 onCoordinateChanged: {
624 roiLocationItem.coordinate = coordinate
625 _activeVehicle.guidedModeROI(coordinate)
626 }
627 }
628 }
629
630 Component {
631 id: roiEditDropPanelComponent
632
633 DropPanel {
634 id: roiEditDropPanel
635
636 sourceComponent: Component {
637 ColumnLayout {
638 spacing: ScreenTools.defaultFontPixelWidth / 2
639
640 QGCButton {
641 Layout.fillWidth: true
642 text: qsTr("Cancel ROI")
643 onClicked: {
644 _activeVehicle.stopGuidedModeROI()
645 roiEditDropPanel.close()
646 }
647 }
648
649 QGCButton {
650 Layout.fillWidth: true
651 text: qsTr("Edit Position")
652 onClicked: {
653 roiEditPositionDialogFactory.open({ showSetPositionFromVehicle: false })
654 roiEditDropPanel.close()
655 }
656 }
657 }
658 }
659 }
660 }
661
662 Component {
663 id: mapClickDropPanelComponent
664
665 DropPanel {
666 id: mapClickDropPanel
667
668 property var mapClickCoord
669
670 sourceComponent: Component {
671 ColumnLayout {
672 spacing: ScreenTools.defaultFontPixelWidth / 2
673
674 QGCButton {
675 Layout.fillWidth: true
676 text: qsTr("Go to location")
677 visible: globals.guidedControllerFlyView.showGotoLocation
678 onClicked: {
679 mapClickDropPanel.close()
680 gotoLocationItem.show(mapClickCoord)
681
682 if ((_activeVehicle.flightMode == _activeVehicle.gotoFlightMode) && !_flyViewSettings.goToLocationRequiresConfirmInGuided.value) {
683 globals.guidedControllerFlyView.executeAction(globals.guidedControllerFlyView.actionGoto, mapClickCoord, gotoLocationItem)
684 gotoLocationItem.actionConfirmed() // Still need to call this to commit the new coordinate and radius
685 } else {
686 globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionGoto, mapClickCoord, gotoLocationItem)
687 }
688 }
689 }
690
691 QGCButton {
692 Layout.fillWidth: true
693 text: qsTr("Orbit at location")
694 visible: globals.guidedControllerFlyView.showOrbit
695 onClicked: {
696 mapClickDropPanel.close()
697 orbitMapCircle.show(mapClickCoord)
698 globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionOrbit, mapClickCoord, orbitMapCircle)
699 }
700 }
701
702 QGCButton {
703 Layout.fillWidth: true
704 text: qsTr("ROI at location")
705 visible: globals.guidedControllerFlyView.showROI
706 onClicked: {
707 mapClickDropPanel.close()
708 globals.guidedControllerFlyView.executeAction(globals.guidedControllerFlyView.actionROI, mapClickCoord, 0, false)
709 }
710 }
711
712 QGCButton {
713 Layout.fillWidth: true
714 text: qsTr("Set home here")
715 visible: globals.guidedControllerFlyView.showSetHome
716 onClicked: {
717 mapClickDropPanel.close()
718 globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionSetHome, mapClickCoord)
719 }
720 }
721
722 QGCButton {
723 Layout.fillWidth: true
724 text: qsTr("Set Estimator Origin")
725 visible: globals.guidedControllerFlyView.showSetEstimatorOrigin
726 onClicked: {
727 mapClickDropPanel.close()
728 globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionSetEstimatorOrigin, mapClickCoord)
729 }
730 }
731
732 QGCButton {
733 Layout.fillWidth: true
734 text: qsTr("Set Heading")
735 visible: globals.guidedControllerFlyView.showChangeHeading
736 onClicked: {
737 mapClickDropPanel.close()
738 globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionChangeHeading, mapClickCoord)
739 }
740 }
741
742 ColumnLayout {
743 spacing: 0
744 QGCLabel { text: qsTr("Lat: %1").arg(mapClickCoord.latitude.toFixed(6)) }
745 QGCLabel { text: qsTr("Lon: %1").arg(mapClickCoord.longitude.toFixed(6)) }
746 }
747 }
748 }
749 }
750 }
751
752 onMapClicked: (position) => {
753 if (!globals.guidedControllerFlyView.guidedUIVisible &&
754 (globals.guidedControllerFlyView.showGotoLocation || globals.guidedControllerFlyView.showOrbit ||
755 globals.guidedControllerFlyView.showROI || globals.guidedControllerFlyView.showSetHome ||
756 globals.guidedControllerFlyView.showSetEstimatorOrigin)) {
757
758 position = Qt.point(position.x, position.y)
759 var clickCoord = _root.toCoordinate(position, false /* clipToViewPort */)
760 // For some strange reason using mainWindow in mapToItem doesn't work, so we use globals.parent instead which also gets us mainWindow
761 position = _root.mapToItem(globals.parent, position)
762 var dropPanel = mapClickDropPanelComponent.createObject(mainWindow, { mapClickCoord: clickCoord, clickRect: Qt.rect(position.x, position.y, 0, 0) })
763 dropPanel.open()
764 }
765 }
766
767 MapScale {
768 id: mapScale
769 anchors.margins: _toolsMargin
770 anchors.left: parent.left
771 anchors.top: parent.top
772 mapControl: _root
773 visible: !ScreenTools.isTinyScreen && QGroundControl.corePlugin.options.flyView.showMapScale && mapControl.pipState.state === mapControl.pipState.windowState
774
775 property real centerInset: visible ? parent.height - y : 0
776 }
777
778}