|
|
|
/****************************************************************************
|
|
|
|
*
|
|
|
|
* (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
|
|
|
|
*
|
|
|
|
* QGroundControl is licensed according to the terms in the file
|
|
|
|
* COPYING.md in the root of the source code directory.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
import QtQuick 2.11
|
|
|
|
import QtQuick.Controls 2.4
|
|
|
|
import QtLocation 5.3
|
|
|
|
import QtPositioning 5.3
|
|
|
|
import QtQuick.Dialogs 1.2
|
|
|
|
import QtQuick.Layouts 1.11
|
|
|
|
|
|
|
|
import QGroundControl 1.0
|
|
|
|
import QGroundControl.Controllers 1.0
|
|
|
|
import QGroundControl.Controls 1.0
|
|
|
|
import QGroundControl.FlightDisplay 1.0
|
|
|
|
import QGroundControl.FlightMap 1.0
|
|
|
|
import QGroundControl.Palette 1.0
|
|
|
|
import QGroundControl.ScreenTools 1.0
|
|
|
|
import QGroundControl.Vehicle 1.0
|
|
|
|
|
|
|
|
FlightMap {
|
|
|
|
id: _root
|
|
|
|
allowGCSLocationCenter: true
|
|
|
|
allowVehicleLocationCenter: !_keepVehicleCentered
|
|
|
|
planView: false
|
|
|
|
zoomLevel: QGroundControl.flightMapZoom
|
|
|
|
center: QGroundControl.flightMapPosition
|
|
|
|
|
|
|
|
property Item pipState: _pipState
|
|
|
|
QGCPipState {
|
|
|
|
id: _pipState
|
|
|
|
pipOverlay: _pipOverlay
|
|
|
|
isDark: _isFullWindowItemDark
|
|
|
|
}
|
|
|
|
|
|
|
|
property var rightPanelWidth
|
|
|
|
property var planMasterController
|
|
|
|
property bool pipMode: false // true: map is shown in a small pip mode
|
|
|
|
property var toolInsets // Insets for the center viewport area
|
|
|
|
|
|
|
|
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
|
|
|
|
property var _planMasterController: planMasterController
|
|
|
|
property var _geoFenceController: planMasterController.geoFenceController
|
|
|
|
property var _rallyPointController: planMasterController.rallyPointController
|
|
|
|
property var _activeVehicleCoordinate: _activeVehicle ? _activeVehicle.coordinate : QtPositioning.coordinate()
|
|
|
|
property real _toolButtonTopMargin: parent.height - mainWindow.height + (ScreenTools.defaultFontPixelHeight / 2)
|
|
|
|
property real _toolsMargin: ScreenTools.defaultFontPixelWidth * 0.75
|
|
|
|
property var _flyViewSettings: QGroundControl.settingsManager.flyViewSettings
|
|
|
|
property bool _keepMapCenteredOnVehicle: _flyViewSettings.keepMapCenteredOnVehicle.rawValue
|
|
|
|
|
|
|
|
property bool _disableVehicleTracking: false
|
|
|
|
property bool _keepVehicleCentered: pipMode ? true : false
|
|
|
|
property bool _saveZoomLevelSetting: true
|
|
|
|
|
|
|
|
function _adjustMapZoomForPipMode() {
|
|
|
|
_saveZoomLevelSetting = false
|
|
|
|
if (pipMode) {
|
|
|
|
if (QGroundControl.flightMapZoom > 3) {
|
|
|
|
zoomLevel = QGroundControl.flightMapZoom - 3
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
zoomLevel = QGroundControl.flightMapZoom
|
|
|
|
}
|
|
|
|
_saveZoomLevelSetting = true
|
|
|
|
}
|
|
|
|
|
|
|
|
onPipModeChanged: _adjustMapZoomForPipMode()
|
|
|
|
|
|
|
|
onVisibleChanged: {
|
|
|
|
if (visible) {
|
|
|
|
// Synchronize center position with Plan View
|
|
|
|
center = QGroundControl.flightMapPosition
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
onZoomLevelChanged: {
|
|
|
|
if (_saveZoomLevelSetting) {
|
|
|
|
QGroundControl.flightMapZoom = zoomLevel
|
|
|
|
}
|
|
|
|
}
|
|
|
|
onCenterChanged: {
|
|
|
|
QGroundControl.flightMapPosition = center
|
|
|
|
}
|
|
|
|
|
|
|
|
// We track whether the user has panned or not to correctly handle automatic map positioning
|
|
|
|
Connections {
|
|
|
|
target: gesture
|
|
|
|
|
|
|
|
function onPanStarted() { _disableVehicleTracking = true }
|
|
|
|
function onFlickStarted() { _disableVehicleTracking = true }
|
|
|
|
function onPanFinished() { panRecenterTimer.restart() }
|
|
|
|
function onFlickFinished() { panRecenterTimer.restart() }
|
|
|
|
}
|
|
|
|
|
|
|
|
function pointInRect(point, rect) {
|
|
|
|
return point.x > rect.x &&
|
|
|
|
point.x < rect.x + rect.width &&
|
|
|
|
point.y > rect.y &&
|
|
|
|
point.y < rect.y + rect.height;
|
|
|
|
}
|
|
|
|
|
|
|
|
property real _animatedLatitudeStart
|
|
|
|
property real _animatedLatitudeStop
|
|
|
|
property real _animatedLongitudeStart
|
|
|
|
property real _animatedLongitudeStop
|
|
|
|
property real animatedLatitude
|
|
|
|
property real animatedLongitude
|
|
|
|
|
|
|
|
onAnimatedLatitudeChanged: _root.center = QtPositioning.coordinate(animatedLatitude, animatedLongitude)
|
|
|
|
onAnimatedLongitudeChanged: _root.center = QtPositioning.coordinate(animatedLatitude, animatedLongitude)
|
|
|
|
|
|
|
|
NumberAnimation on animatedLatitude { id: animateLat; from: _animatedLatitudeStart; to: _animatedLatitudeStop; duration: 1000 }
|
|
|
|
NumberAnimation on animatedLongitude { id: animateLong; from: _animatedLongitudeStart; to: _animatedLongitudeStop; duration: 1000 }
|
|
|
|
|
|
|
|
function animatedMapRecenter(fromCoord, toCoord) {
|
|
|
|
_animatedLatitudeStart = fromCoord.latitude
|
|
|
|
_animatedLongitudeStart = fromCoord.longitude
|
|
|
|
_animatedLatitudeStop = toCoord.latitude
|
|
|
|
_animatedLongitudeStop = toCoord.longitude
|
|
|
|
animateLat.start()
|
|
|
|
animateLong.start()
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns the rectangle formed by the four center insets
|
|
|
|
// used for checking if vehicle is under ui, and as a target for recentering the view
|
|
|
|
function _insetCenterRect() {
|
|
|
|
return Qt.rect(toolInsets.leftEdgeCenterInset,
|
|
|
|
toolInsets.topEdgeCenterInset,
|
|
|
|
_root.width - toolInsets.leftEdgeCenterInset - toolInsets.rightEdgeCenterInset,
|
|
|
|
_root.height - toolInsets.topEdgeCenterInset - toolInsets.bottomEdgeCenterInset)
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns the four rectangles formed by the 8 corner insets
|
|
|
|
// used for detecting if the vehicle has flown under the instrument panel, virtual joystick etc
|
|
|
|
function _insetCornerRects() {
|
|
|
|
var rects = {
|
|
|
|
"topleft": Qt.rect(0,0,
|
|
|
|
toolInsets.leftEdgeTopInset,
|
|
|
|
toolInsets.topEdgeLeftInset),
|
|
|
|
"topright": Qt.rect(_root.width-toolInsets.rightEdgeTopInset,0,
|
|
|
|
toolInsets.rightEdgeTopInset,
|
|
|
|
toolInsets.topEdgeRightInset),
|
|
|
|
"bottomleft": Qt.rect(0,_root.height-toolInsets.bottomEdgeLeftInset,
|
|
|
|
toolInsets.leftEdgeBottomInset,
|
|
|
|
toolInsets.bottomEdgeLeftInset),
|
|
|
|
"bottomright": Qt.rect(_root.width-toolInsets.rightEdgeBottomInset,_root.height-toolInsets.bottomEdgeRightInset,
|
|
|
|
toolInsets.rightEdgeBottomInset,
|
|
|
|
toolInsets.bottomEdgeRightInset)}
|
|
|
|
return rects
|
|
|
|
}
|
|
|
|
|
|
|
|
function recenterNeeded() {
|
|
|
|
var vehiclePoint = _root.fromCoordinate(_activeVehicleCoordinate, false /* clipToViewport */)
|
|
|
|
var centerRect = _insetCenterRect()
|
|
|
|
//return !pointInRect(vehiclePoint,insetRect)
|
|
|
|
|
|
|
|
// If we are outside the center inset rectangle, recenter
|
|
|
|
if(!pointInRect(vehiclePoint, centerRect)){
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// if we are inside the center inset rectangle
|
|
|
|
// then additionally check if we are underneath one of the corner inset rectangles
|
|
|
|
var cornerRects = _insetCornerRects()
|
|
|
|
if(pointInRect(vehiclePoint, cornerRects["topleft"])){
|
|
|
|
return true
|
|
|
|
} else if(pointInRect(vehiclePoint, cornerRects["topright"])){
|
|
|
|
return true
|
|
|
|
} else if(pointInRect(vehiclePoint, cornerRects["bottomleft"])){
|
|
|
|
return true
|
|
|
|
} else if(pointInRect(vehiclePoint, cornerRects["bottomright"])){
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// if we are inside the center inset rectangle, and not under any corner elements
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
function updateMapToVehiclePosition() {
|
|
|
|
if (animateLat.running || animateLong.running) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
// We let FlightMap handle first vehicle position
|
|
|
|
if (!_keepMapCenteredOnVehicle && firstVehiclePositionReceived && _activeVehicleCoordinate.isValid && !_disableVehicleTracking) {
|
|
|
|
if (_keepVehicleCentered) {
|
|
|
|
_root.center = _activeVehicleCoordinate
|
|
|
|
} else {
|
|
|
|
if (firstVehiclePositionReceived && recenterNeeded()) {
|
|
|
|
// Move the map such that the vehicle is centered within the inset area
|
|
|
|
var vehiclePoint = _root.fromCoordinate(_activeVehicleCoordinate, false /* clipToViewport */)
|
|
|
|
var centerInsetRect = _insetCenterRect()
|
|
|
|
var centerInsetPoint = Qt.point(centerInsetRect.x + centerInsetRect.width / 2, centerInsetRect.y + centerInsetRect.height / 2)
|
|
|
|
var centerOffset = Qt.point((_root.width / 2) - centerInsetPoint.x, (_root.height / 2) - centerInsetPoint.y)
|
|
|
|
var vehicleOffsetPoint = Qt.point(vehiclePoint.x + centerOffset.x, vehiclePoint.y + centerOffset.y)
|
|
|
|
var vehicleOffsetCoord = _root.toCoordinate(vehicleOffsetPoint, false /* clipToViewport */)
|
|
|
|
animatedMapRecenter(_root.center, vehicleOffsetCoord)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
on_ActiveVehicleCoordinateChanged: {
|
|
|
|
if (_keepMapCenteredOnVehicle && _activeVehicleCoordinate.isValid && !_disableVehicleTracking) {
|
|
|
|
_root.center = _activeVehicleCoordinate
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Timer {
|
|
|
|
id: panRecenterTimer
|
|
|
|
interval: 10000
|
|
|
|
running: false
|
|
|
|
onTriggered: {
|
|
|
|
_disableVehicleTracking = false
|
|
|
|
updateMapToVehiclePosition()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Timer {
|
|
|
|
interval: 500
|
|
|
|
running: true
|
|
|
|
repeat: true
|
|
|
|
onTriggered: updateMapToVehiclePosition()
|
|
|
|
}
|
|
|
|
|
|
|
|
QGCMapPalette { id: mapPal; lightColors: isSatelliteMap }
|
|
|
|
|
|
|
|
Connections {
|
|
|
|
target: _missionController
|
|
|
|
ignoreUnknownSignals: true
|
|
|
|
function onNewItemsFromVehicle() {
|
|
|
|
var visualItems = _missionController.visualItems
|
|
|
|
if (visualItems && visualItems.count !== 1) {
|
|
|
|
mapFitFunctions.fitMapViewportToMissionItems()
|
|
|
|
firstVehiclePositionReceived = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MapFitFunctions {
|
|
|
|
id: mapFitFunctions // The name for this id cannot be changed without breaking references outside of this code. Beware!
|
|
|
|
map: _root
|
|
|
|
usePlannedHomePosition: false
|
|
|
|
planMasterController: _planMasterController
|
|
|
|
}
|
|
|
|
|
|
|
|
ObstacleDistanceOverlayMap {
|
|
|
|
id: obstacleDistance
|
|
|
|
showText: !pipMode
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add trajectory lines to the map
|
|
|
|
MapPolyline {
|
|
|
|
id: trajectoryPolyline
|
|
|
|
line.width: 3
|
|
|
|
line.color: "red"
|
|
|
|
z: QGroundControl.zOrderTrajectoryLines
|
|
|
|
visible: !pipMode
|
|
|
|
|
|
|
|
Connections {
|
|
|
|
target: QGroundControl.multiVehicleManager
|
|
|
|
function onActiveVehicleChanged(activeVehicle) {
|
|
|
|
trajectoryPolyline.path = _activeVehicle ? _activeVehicle.trajectoryPoints.list() : []
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Connections {
|
|
|
|
target: _activeVehicle ? _activeVehicle.trajectoryPoints : null
|
|
|
|
onPointAdded: trajectoryPolyline.addCoordinate(coordinate)
|
|
|
|
onUpdateLastPoint: trajectoryPolyline.replaceCoordinate(trajectoryPolyline.pathLength() - 1, coordinate)
|
|
|
|
onPointsCleared: trajectoryPolyline.path = []
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the vehicles to the map
|
|
|
|
MapItemView {
|
|
|
|
model: QGroundControl.multiVehicleManager.vehicles
|
|
|
|
delegate: VehicleMapItem {
|
|
|
|
vehicle: object
|
|
|
|
coordinate: object.coordinate
|
|
|
|
map: _root
|
|
|
|
size: pipMode ? ScreenTools.defaultFontPixelHeight : ScreenTools.defaultFontPixelHeight * 3
|
|
|
|
z: QGroundControl.zOrderVehicles
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Add distance sensor view
|
|
|
|
MapItemView{
|
|
|
|
model: QGroundControl.multiVehicleManager.vehicles
|
|
|
|
delegate: ProximityRadarMapView {
|
|
|
|
vehicle: object
|
|
|
|
coordinate: object.coordinate
|
|
|
|
map: _root
|
|
|
|
z: QGroundControl.zOrderVehicles
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Add ADSB vehicles to the map
|
|
|
|
MapItemView {
|
|
|
|
model: QGroundControl.adsbVehicleManager.adsbVehicles
|
|
|
|
delegate: VehicleMapItem {
|
|
|
|
coordinate: object.coordinate
|
|
|
|
altitude: object.altitude
|
|
|
|
callsign: object.callsign
|
|
|
|
heading: object.heading
|
|
|
|
alert: object.alert
|
|
|
|
map: _root
|
|
|
|
size: pipMode ? ScreenTools.defaultFontPixelHeight : ScreenTools.defaultFontPixelHeight * 2.5
|
|
|
|
z: QGroundControl.zOrderVehicles
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the items associated with each vehicles flight plan to the map
|
|
|
|
Repeater {
|
|
|
|
model: QGroundControl.multiVehicleManager.vehicles
|
|
|
|
|
|
|
|
PlanMapItems {
|
|
|
|
map: _root
|
|
|
|
largeMapView: !pipMode
|
|
|
|
planMasterController: masterController
|
|
|
|
vehicle: _vehicle
|
|
|
|
|
|
|
|
property var _vehicle: object
|
|
|
|
|
|
|
|
PlanMasterController {
|
|
|
|
id: masterController
|
|
|
|
Component.onCompleted: startStaticActiveVehicle(object)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MapItemView {
|
|
|
|
model: pipMode ? undefined : _missionController.directionArrows
|
|
|
|
|
|
|
|
delegate: MapLineArrow {
|
|
|
|
fromCoord: object ? object.coordinate1 : undefined
|
|
|
|
toCoord: object ? object.coordinate2 : undefined
|
|
|
|
arrowPosition: 2
|
|
|
|
z: QGroundControl.zOrderWaypointLines
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allow custom builds to add map items
|
|
|
|
CustomMapItems {
|
|
|
|
map: _root
|
|
|
|
largeMapView: !pipMode
|
|
|
|
}
|
|
|
|
|
|
|
|
GeoFenceMapVisuals {
|
|
|
|
map: _root
|
|
|
|
myGeoFenceController: _geoFenceController
|
|
|
|
interactive: false
|
|
|
|
planView: false
|
|
|
|
homePosition: _activeVehicle && _activeVehicle.homePosition.isValid ? _activeVehicle.homePosition : QtPositioning.coordinate()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Rally points on map
|
|
|
|
MapItemView {
|
|
|
|
model: _rallyPointController.points
|
|
|
|
|
|
|
|
delegate: MapQuickItem {
|
|
|
|
id: itemIndicator
|
|
|
|
anchorPoint.x: sourceItem.anchorPointX
|
|
|
|
anchorPoint.y: sourceItem.anchorPointY
|
|
|
|
coordinate: object.coordinate
|
|
|
|
z: QGroundControl.zOrderMapItems
|
|
|
|
|
|
|
|
sourceItem: MissionItemIndexLabel {
|
|
|
|
id: itemIndexLabel
|
|
|
|
label: qsTr("R", "rally point map item label")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Camera trigger points
|
|
|
|
MapItemView {
|
|
|
|
model: _activeVehicle ? _activeVehicle.cameraTriggerPoints : 0
|
|
|
|
|
|
|
|
delegate: CameraTriggerIndicator {
|
|
|
|
coordinate: object.coordinate
|
|
|
|
z: QGroundControl.zOrderTopMost
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// GoTo Location visuals
|
|
|
|
MapQuickItem {
|
|
|
|
id: gotoLocationItem
|
|
|
|
visible: false
|
|
|
|
z: QGroundControl.zOrderMapItems
|
|
|
|
anchorPoint.x: sourceItem.anchorPointX
|
|
|
|
anchorPoint.y: sourceItem.anchorPointY
|
|
|
|
sourceItem: MissionItemIndexLabel {
|
|
|
|
checked: true
|
|
|
|
index: -1
|
|
|
|
label: qsTr("Go here", "Go to location waypoint")
|
|
|
|
}
|
|
|
|
|
|
|
|
property bool inGotoFlightMode: _activeVehicle ? _activeVehicle.flightMode === _activeVehicle.gotoFlightMode : false
|
|
|
|
|
|
|
|
onInGotoFlightModeChanged: {
|
|
|
|
if (!inGotoFlightMode && gotoLocationItem.visible) {
|
|
|
|
// Hide goto indicator when vehicle falls out of guided mode
|
|
|
|
gotoLocationItem.visible = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Connections {
|
|
|
|
target: QGroundControl.multiVehicleManager
|
|
|
|
function onActiveVehicleChanged(activeVehicle) {
|
|
|
|
if (!activeVehicle) {
|
|
|
|
gotoLocationItem.visible = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function show(coord) {
|
|
|
|
gotoLocationItem.coordinate = coord
|
|
|
|
gotoLocationItem.visible = true
|
|
|
|
}
|
|
|
|
|
|
|
|
function hide() {
|
|
|
|
gotoLocationItem.visible = false
|
|
|
|
}
|
|
|
|
|
|
|
|
function actionConfirmed() {
|
|
|
|
// We leave the indicator visible. The handling for onInGuidedModeChanged will hide it.
|
|
|
|
}
|
|
|
|
|
|
|
|
function actionCancelled() {
|
|
|
|
hide()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Orbit editing visuals
|
|
|
|
QGCMapCircleVisuals {
|
|
|
|
id: orbitMapCircle
|
|
|
|
mapControl: parent
|
|
|
|
mapCircle: _mapCircle
|
|
|
|
visible: false
|
|
|
|
|
|
|
|
property alias center: _mapCircle.center
|
|
|
|
property alias clockwiseRotation: _mapCircle.clockwiseRotation
|
|
|
|
readonly property real defaultRadius: 30
|
|
|
|
|
|
|
|
Connections {
|
|
|
|
target: QGroundControl.multiVehicleManager
|
|
|
|
function onActiveVehicleChanged(activeVehicle) {
|
|
|
|
if (!activeVehicle) {
|
|
|
|
orbitMapCircle.visible = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function show(coord) {
|
|
|
|
_mapCircle.radius.rawValue = defaultRadius
|
|
|
|
orbitMapCircle.center = coord
|
|
|
|
orbitMapCircle.visible = true
|
|
|
|
}
|
|
|
|
|
|
|
|
function hide() {
|
|
|
|
orbitMapCircle.visible = false
|
|
|
|
}
|
|
|
|
|
|
|
|
function actionConfirmed() {
|
|
|
|
// Live orbit status is handled by telemetry so we hide here and telemetry will show again.
|
|
|
|
hide()
|
|
|
|
}
|
|
|
|
|
|
|
|
function actionCancelled() {
|
|
|
|
hide()
|
|
|
|
}
|
|
|
|
|
|
|
|
function radius() {
|
|
|
|
return _mapCircle.radius.rawValue
|
|
|
|
}
|
|
|
|
|
|
|
|
Component.onCompleted: globals.guidedControllerFlyView.orbitMapCircle = orbitMapCircle
|
|
|
|
|
|
|
|
QGCMapCircle {
|
|
|
|
id: _mapCircle
|
|
|
|
interactive: true
|
|
|
|
radius.rawValue: 30
|
|
|
|
showRotation: true
|
|
|
|
clockwiseRotation: true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ROI Location visuals
|
|
|
|
MapQuickItem {
|
|
|
|
id: roiLocationItem
|
|
|
|
visible: _activeVehicle && _activeVehicle.isROIEnabled
|
|
|
|
z: QGroundControl.zOrderMapItems
|
|
|
|
anchorPoint.x: sourceItem.anchorPointX
|
|
|
|
anchorPoint.y: sourceItem.anchorPointY
|
|
|
|
|
|
|
|
sourceItem: MissionItemIndexLabel {
|
|
|
|
checked: true
|
|
|
|
index: -1
|
|
|
|
label: qsTr("ROI here", "Make this a Region Of Interest")
|
|
|
|
|
|
|
|
onClicked: (position) => {
|
|
|
|
var roiEditMenu = popupMenuComponent.createObject(_root, { coord: roiLocationItem.coordinate, contentItemComponent: roiEditMenuComponent })
|
|
|
|
var clickPoint = mapToItem(_root, position.x, position.y)
|
|
|
|
roiEditMenu.setPosition(clickPoint.x, clickPoint.y)
|
|
|
|
roiEditMenu.open()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-- Visibilty controlled by actual state
|
|
|
|
function show(coord) {
|
|
|
|
roiLocationItem.coordinate = coord
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Orbit telemetry visuals
|
|
|
|
QGCMapCircleVisuals {
|
|
|
|
id: orbitTelemetryCircle
|
|
|
|
mapControl: parent
|
|
|
|
mapCircle: _activeVehicle ? _activeVehicle.orbitMapCircle : null
|
|
|
|
visible: _activeVehicle ? _activeVehicle.orbitActive : false
|
|
|
|
}
|
|
|
|
|
|
|
|
MapQuickItem {
|
|
|
|
id: orbitCenterIndicator
|
|
|
|
anchorPoint.x: sourceItem.anchorPointX
|
|
|
|
anchorPoint.y: sourceItem.anchorPointY
|
|
|
|
coordinate: _activeVehicle ? _activeVehicle.orbitMapCircle.center : QtPositioning.coordinate()
|
|
|
|
visible: orbitTelemetryCircle.visible
|
|
|
|
|
|
|
|
sourceItem: MissionItemIndexLabel {
|
|
|
|
checked: true
|
|
|
|
index: -1
|
|
|
|
label: qsTr("Orbit", "Orbit waypoint")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MouseArea {
|
|
|
|
anchors.fill: parent
|
|
|
|
|
|
|
|
onClicked: {
|
|
|
|
if (!globals.guidedControllerFlyView.guidedUIVisible &&
|
|
|
|
(globals.guidedControllerFlyView.showGotoLocation || globals.guidedControllerFlyView.showOrbit || globals.guidedControllerFlyView.showROI || globals.guidedControllerFlyView.showSetHome || globals.guidedControllerFlyView.showSetEstimatorOrigin)) {
|
|
|
|
orbitMapCircle.hide()
|
|
|
|
gotoLocationItem.hide()
|
|
|
|
var clickCoord = _root.toCoordinate(Qt.point(mouse.x, mouse.y), false /* clipToViewPort */)
|
|
|
|
var mapClickMenu = popupMenuComponent.createObject(_root, { coord: clickCoord, contentItemComponent: mapClickMenuComponent })
|
|
|
|
mapClickMenu.setPosition(mouse.x, mouse.y)
|
|
|
|
mapClickMenu.open()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Component {
|
|
|
|
id: popupMenuComponent
|
|
|
|
|
|
|
|
Popup {
|
|
|
|
id: mapClickMenu
|
|
|
|
modal: true
|
|
|
|
|
|
|
|
property var coord
|
|
|
|
property var contentItemComponent
|
|
|
|
|
|
|
|
function setPosition(mouseX, mouseY) {
|
|
|
|
var newX = mouseX
|
|
|
|
var newY = mouseY
|
|
|
|
|
|
|
|
// Filtering coordinates
|
|
|
|
if (newX + mapClickMenu.width > _root.width) {
|
|
|
|
newX = _root.width - mapClickMenu.width
|
|
|
|
}
|
|
|
|
if (newY + mapClickMenu.height > _root.height) {
|
|
|
|
newY = _root.height - mapClickMenu.height
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set coordiantes
|
|
|
|
x = newX
|
|
|
|
y = newY
|
|
|
|
}
|
|
|
|
|
|
|
|
background: Rectangle {
|
|
|
|
radius: ScreenTools.defaultFontPixelHeight * 0.5
|
|
|
|
color: qgcPal.window
|
|
|
|
border.color: qgcPal.text
|
|
|
|
}
|
|
|
|
|
|
|
|
contentItem: Loader {
|
|
|
|
sourceComponent: contentItemComponent
|
|
|
|
|
|
|
|
property var mapClickCoord: mapClickMenu.coord
|
|
|
|
property var popup: mapClickMenu
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Component {
|
|
|
|
id: mapClickMenuComponent
|
|
|
|
|
|
|
|
ColumnLayout {
|
|
|
|
id: mainLayout
|
|
|
|
spacing: ScreenTools.defaultFontPixelWidth / 2
|
|
|
|
|
|
|
|
QGCButton {
|
|
|
|
Layout.fillWidth: true
|
|
|
|
text: qsTr("Go to location")
|
|
|
|
visible: globals.guidedControllerFlyView.showGotoLocation
|
|
|
|
onClicked: {
|
|
|
|
if (popup.opened) {
|
|
|
|
popup.close()
|
|
|
|
}
|
|
|
|
gotoLocationItem.show(mapClickCoord)
|
|
|
|
globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionGoto, mapClickCoord, gotoLocationItem)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QGCButton {
|
|
|
|
Layout.fillWidth: true
|
|
|
|
text: qsTr("Orbit at location")
|
|
|
|
visible: globals.guidedControllerFlyView.showOrbit
|
|
|
|
onClicked: {
|
|
|
|
if (popup.opened) {
|
|
|
|
popup.close()
|
|
|
|
}
|
|
|
|
orbitMapCircle.show(mapClickCoord)
|
|
|
|
globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionOrbit, mapClickCoord, orbitMapCircle)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QGCButton {
|
|
|
|
Layout.fillWidth: true
|
|
|
|
text: qsTr("ROI at location")
|
|
|
|
visible: globals.guidedControllerFlyView.showROI
|
|
|
|
onClicked: {
|
|
|
|
if (popup.opened) {
|
|
|
|
popup.close()
|
|
|
|
}
|
|
|
|
roiLocationItem.show(mapClickCoord)
|
|
|
|
globals.guidedControllerFlyView.executeAction(globals.guidedControllerFlyView.actionROI, mapClickCoord, 0, false)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QGCButton {
|
|
|
|
Layout.fillWidth: true
|
|
|
|
text: qsTr("Set home here")
|
|
|
|
visible: globals.guidedControllerFlyView.showSetHome
|
|
|
|
onClicked: {
|
|
|
|
if (popup.opened) {
|
|
|
|
popup.close()
|
|
|
|
}
|
|
|
|
globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionSetHome, mapClickCoord)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Component {
|
|
|
|
id: roiEditPositionDialogComponent
|
|
|
|
|
|
|
|
EditPositionDialog {
|
|
|
|
title: qsTr("Edit ROI Position")
|
|
|
|
coordinate: roiLocationItem.coordinate
|
|
|
|
onCoordinateChanged: {
|
|
|
|
roiLocationItem.coordinate = coordinate
|
|
|
|
_activeVehicle.guidedModeROI(coordinate)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Component {
|
|
|
|
id: roiEditMenuComponent
|
|
|
|
|
|
|
|
ColumnLayout {
|
|
|
|
id: mainLayout
|
|
|
|
spacing: ScreenTools.defaultFontPixelWidth / 2
|
|
|
|
|
|
|
|
QGCButton {
|
|
|
|
Layout.fillWidth: true
|
|
|
|
text: qsTr("Cancel ROI")
|
|
|
|
onClicked: {
|
|
|
|
_activeVehicle.stopGuidedModeROI()
|
|
|
|
popup.close()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QGCButton {
|
|
|
|
Layout.fillWidth: true
|
|
|
|
text: qsTr("Edit Position")
|
|
|
|
onClicked: {
|
|
|
|
roiEditPositionDialogComponent.createObject(mainWindow, { showSetPositionFromVehicle: false }).open()
|
|
|
|
popup.close()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MapScale {
|
|
|
|
id: mapScale
|
|
|
|
anchors.margins: _toolsMargin
|
|
|
|
anchors.left: parent.left
|
|
|
|
anchors.top: parent.top
|
|
|
|
mapControl: _root
|
|
|
|
buttonsOnLeft: true
|
|
|
|
visible: !ScreenTools.isTinyScreen && QGroundControl.corePlugin.options.flyView.showMapScale && mapControl.pipState.state === mapControl.pipState.windowState
|
|
|
|
|
|
|
|
property real centerInset: visible ? parent.height - y : 0
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|