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