Newer
Older
/****************************************************************************
*
* (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.
*
****************************************************************************/
Gus Grubba
committed
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtLocation 5.3
import QtPositioning 5.3
import QtQuick.Dialogs 1.2
import QGroundControl.Airspace 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 {
allowVehicleLocationCenter: !_keepVehicleCentered
zoomLevel: QGroundControl.flightMapZoom
center: QGroundControl.flightMapPosition
property Item pipState: _pipState
QGCPipState {
id: _pipState
pipOverlay: _pipOverlay
isDark: _isFullWindowItemDark
}
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 bool _airspaceEnabled: QGroundControl.airmapSupported ? (QGroundControl.settingsManager.airMapSettings.enableAirMap.rawValue && QGroundControl.airspaceManager.connected): false
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
Gus Grubba
committed
function updateAirspace(reset) {
if(_airspaceEnabled) {
var coordinateNW = _root.toCoordinate(Qt.point(0,0), false /* clipToViewPort */)
var coordinateSE = _root.toCoordinate(Qt.point(width,height), false /* clipToViewPort */)
Gus Grubba
committed
if(coordinateNW.isValid && coordinateSE.isValid) {
Gus Grubba
committed
QGroundControl.airspaceManager.setROI(coordinateNW, coordinateSE, false /*planView*/, reset)
Gus Grubba
committed
}
Gus Grubba
committed
}
function _adjustMapZoomForPipMode() {
_saveZoomLevelSetting = false
if (pipMode) {
if (QGroundControl.flightMapZoom > 3) {
zoomLevel = QGroundControl.flightMapZoom - 3
}
} else {
zoomLevel = QGroundControl.flightMapZoom
Gus Grubba
committed
if (visible) {
// Synchronize center position with Plan View
center = QGroundControl.flightMapPosition
Gus Grubba
committed
onZoomLevelChanged: {
QGroundControl.flightMapZoom = zoomLevel
updateAirspace(false)
}
Gus Grubba
committed
}
onCenterChanged: {
Gus Grubba
committed
updateAirspace(false)
Gus Grubba
committed
updateAirspace(true)
// We track whether the user has panned or not to correctly handle automatic map positioning
Connections {
target: gesture
onPanStarted: _disableVehicleTracking = true
onFlickStarted: _disableVehicleTracking = true
onPanFinished: panRecenterTimer.restart()
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()
}
function _insetRect() {
return Qt.rect(toolInsets.leftEdgeCenterInset,
toolInsets.topEdgeCenterInset,
_root.width - toolInsets.leftEdgeCenterInset - toolInsets.rightEdgeCenterInset,
_root.height - toolInsets.topEdgeCenterInset - toolInsets.bottomEdgeCenterInset)
}
var vehiclePoint = _root.fromCoordinate(_activeVehicleCoordinate, false /* clipToViewport */)
var insetRect = _insetRect()
return !pointInRect(vehiclePoint, insetRect)
}
function updateMapToVehiclePosition() {
// We let FlightMap handle first vehicle position
if (!_keepMapCenteredOnVehicle && firstVehiclePositionReceived && _activeVehicleCoordinate.isValid && !_disableVehicleTracking) {
if (firstVehiclePositionReceived && recenterNeeded()) {
// Move the map such that the vehicle is centered within the inset area
var vehiclePoint = _root.fromCoordinate(_activeVehicleCoordinate, false /* clipToViewport */)
var insetRect = _insetRect()
var centerInsetPoint = Qt.point(insetRect.x + insetRect.width / 2, insetRect.y + insetRect.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) {
id: panRecenterTimer
interval: 10000
running: false
Timer {
interval: 500
running: true
repeat: true
onTriggered: updateMapToVehiclePosition()
}
QGCMapPalette { id: mapPal; lightColors: isSatelliteMap }
onNewItemsFromVehicle: {
if (visualItems && visualItems.count !== 1) {
mapFitFunctions.fitMapViewportToMissionItems()
firstVehiclePositionReceived = true
id: mapFitFunctions // The name for this id cannot be changed without breaking references outside of this code. Beware!
// Add trajectory lines to the map
MapPolyline {
id: trajectoryPolyline
line.width: 3
line.color: "red"
z: QGroundControl.zOrderTrajectoryLines
onActiveVehicleChanged: trajectoryPolyline.path = _activeVehicle ? _activeVehicle.trajectoryPoints.list() : []
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
map: _root
size: pipMode ? ScreenTools.defaultFontPixelHeight : ScreenTools.defaultFontPixelHeight * 3
// 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 {
delegate: VehicleMapItem {
coordinate: object.coordinate
altitude: object.altitude
z: QGroundControl.zOrderVehicles
}
}
// Add the items associated with each vehicles flight plan to the map
Repeater {
model: QGroundControl.multiVehicleManager.vehicles
PlanMapItems {
property var _vehicle: object
PlanMasterController {
id: masterController
Component.onCompleted: startStaticActiveVehicle(object)
}
}
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 {
myGeoFenceController: _geoFenceController
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")
}
}
}
delegate: CameraTriggerIndicator {
coordinate: object.coordinate
z: QGroundControl.zOrderTopMost
}
}
id: gotoLocationItem
visible: false
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
property bool inGotoFlightMode: _activeVehicle ? _activeVehicle.flightMode === _activeVehicle.gotoFlightMode : 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()
}
}
id: orbitMapCircle
mapControl: parent
mapCircle: _mapCircle
visible: false
property alias center: _mapCircle.center
property alias clockwiseRotation: _mapCircle.clockwiseRotation
readonly property real defaultRadius: 30
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
// ROI Location visuals
MapQuickItem {
id: roiLocationItem
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")
}
//-- Visibilty controlled by actual state
function show(coord) {
roiLocationItem.coordinate = coord
}
function hide() {
}
function actionConfirmed() {
}
function actionCancelled() {
}
}
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")
}
}
gotoLocationItem.show(clickMenu.coord)
globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionGoto, clickMenu.coord, gotoLocationItem)
orbitMapCircle.show(clickMenu.coord)
globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionOrbit, clickMenu.coord, orbitMapCircle)
onTriggered: {
roiLocationItem.show(clickMenu.coord)
globals.guidedControllerFlyView.confirmAction(globals.guidedControllerFlyView.actionROI, clickMenu.coord, roiLocationItem)
if (!globals.guidedControllerFlyView.guidedUIVisible && (globals.guidedControllerFlyView.showGotoLocation || globals.guidedControllerFlyView.showOrbit || globals.guidedControllerFlyView.showROI)) {
orbitMapCircle.hide()
gotoLocationItem.hide()
var clickCoord = _root.toCoordinate(Qt.point(mouse.x, mouse.y), false /* clipToViewPort */)
// Airspace overlap support
model: _airspaceEnabled && QGroundControl.settingsManager.airMapSettings.enableAirspace && QGroundControl.airspaceManager.airspaceVisible ? QGroundControl.airspaceManager.airspaces.circles : []
delegate: MapCircle {
center: object.center
radius: object.radius
border.color: object.lineColor
border.width: object.lineWidth
model: _airspaceEnabled && QGroundControl.settingsManager.airMapSettings.enableAirspace && QGroundControl.airspaceManager.airspaceVisible ? QGroundControl.airspaceManager.airspaces.polygons : []
delegate: MapPolygon {
path: object.polygon
border.color: object.lineColor
border.width: object.lineWidth