You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
409 lines
14 KiB
409 lines
14 KiB
/**************************************************************************** |
|
* |
|
* (c) 2009-2016 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.3 |
|
import QtQuick.Controls 1.2 |
|
import QtLocation 5.3 |
|
import QtPositioning 5.3 |
|
import QtQuick.Dialogs 1.2 |
|
|
|
import QGroundControl 1.0 |
|
import QGroundControl.FlightDisplay 1.0 |
|
import QGroundControl.FlightMap 1.0 |
|
import QGroundControl.ScreenTools 1.0 |
|
import QGroundControl.Controls 1.0 |
|
import QGroundControl.Palette 1.0 |
|
import QGroundControl.Vehicle 1.0 |
|
import QGroundControl.Controllers 1.0 |
|
|
|
FlightMap { |
|
id: flightMap |
|
anchors.fill: parent |
|
mapName: _mapName |
|
allowGCSLocationCenter: !userPanned |
|
allowVehicleLocationCenter: !_keepVehicleCentered |
|
planView: false |
|
|
|
property alias scaleState: mapScale.state |
|
|
|
// The following properties must be set by the consumer |
|
property var planMasterController |
|
property var guidedActionsController |
|
property var flightWidgets |
|
property var rightPanelWidth |
|
property var qgcView ///< QGCView control which contains this map |
|
property var multiVehicleView ///< true: multi-vehicle view, false: single vehicle view |
|
|
|
property rect centerViewport: Qt.rect(0, 0, width, height) |
|
|
|
property var _planMasterController: planMasterController |
|
property var _missionController: _planMasterController.missionController |
|
property var _geoFenceController: _planMasterController.geoFenceController |
|
property var _rallyPointController: _planMasterController.rallyPointController |
|
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle |
|
property var _activeVehicleCoordinate: _activeVehicle ? _activeVehicle.coordinate : QtPositioning.coordinate() |
|
property real _toolButtonTopMargin: parent.height - ScreenTools.availableHeight + (ScreenTools.defaultFontPixelHeight / 2) |
|
|
|
property bool _disableVehicleTracking: false |
|
property bool _keepVehicleCentered: _mainIsMap ? false : true |
|
|
|
// Track last known map position and zoom from Fly view in settings |
|
onZoomLevelChanged: QGroundControl.flightMapZoom = zoomLevel |
|
onCenterChanged: QGroundControl.flightMapPosition = center |
|
|
|
// When the user pans the map we stop responding to vehicle coordinate updates until the panRecenterTimer fires |
|
onUserPannedChanged: { |
|
if (userPanned) { |
|
console.log("user panned") |
|
userPanned = false |
|
_disableVehicleTracking = true |
|
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: flightMap.center = QtPositioning.coordinate(animatedLatitude, animatedLongitude) |
|
onAnimatedLongitudeChanged: flightMap.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 recenterNeeded() { |
|
var vehiclePoint = flightMap.fromCoordinate(_activeVehicleCoordinate, false /* clipToViewport */) |
|
var toolStripRightEdge = mapFromItem(toolStrip, toolStrip.x, 0).x + toolStrip.width |
|
var instrumentsWidth = 0 |
|
if (QGroundControl.corePlugin.options.instrumentWidget && QGroundControl.corePlugin.options.instrumentWidget.widgetPosition === CustomInstrumentWidget.POS_TOP_RIGHT) { |
|
// Assume standard instruments |
|
instrumentsWidth = flightDisplayViewWidgets.getPreferredInstrumentWidth() |
|
} |
|
var centerViewport = Qt.rect(toolStripRightEdge, 0, width - toolStripRightEdge - instrumentsWidth, height) |
|
return !pointInRect(vehiclePoint, centerViewport) |
|
} |
|
|
|
function updateMapToVehiclePosition() { |
|
// We let FlightMap handle first vehicle position |
|
if (firstVehiclePositionReceived && _activeVehicleCoordinate.isValid && !_disableVehicleTracking) { |
|
if (_keepVehicleCentered) { |
|
flightMap.center = _activeVehicleCoordinate |
|
} else { |
|
if (firstVehiclePositionReceived && recenterNeeded()) { |
|
animatedMapRecenter(flightMap.center, _activeVehicleCoordinate) |
|
} |
|
} |
|
} |
|
} |
|
|
|
Timer { |
|
id: panRecenterTimer |
|
interval: 10000 |
|
running: false |
|
|
|
onTriggered: { |
|
_disableVehicleTracking = false |
|
updateMapToVehiclePosition() |
|
} |
|
} |
|
|
|
Timer { |
|
interval: 500 |
|
running: true |
|
repeat: true |
|
onTriggered: updateMapToVehiclePosition() |
|
} |
|
|
|
QGCPalette { id: qgcPal; colorGroupEnabled: true } |
|
QGCMapPalette { id: mapPal; lightColors: isSatelliteMap } |
|
|
|
Connections { |
|
target: _missionController |
|
|
|
onNewItemsFromVehicle: { |
|
var visualItems = _missionController.visualItems |
|
if (visualItems && visualItems.count !== 1) { |
|
mapFitFunctions.fitMapViewportToMissionItems() |
|
firstVehiclePositionReceived = true |
|
} |
|
} |
|
} |
|
|
|
ExclusiveGroup { |
|
id: _mapTypeButtonsExclusiveGroup |
|
} |
|
|
|
MapFitFunctions { |
|
id: mapFitFunctions // The name for this id cannot be changed without breaking references outside of this code. Beware! |
|
map: _flightMap |
|
usePlannedHomePosition: false |
|
planMasterController: _planMasterController |
|
|
|
property real leftToolWidth: toolStrip.x + toolStrip.width |
|
} |
|
|
|
// Add trajectory points to the map |
|
MapItemView { |
|
model: _mainIsMap ? _activeVehicle ? _activeVehicle.trajectoryPoints : 0 : 0 |
|
|
|
delegate: MapPolyline { |
|
line.width: 3 |
|
line.color: "red" |
|
z: QGroundControl.zOrderTrajectoryLines |
|
path: [ |
|
object.coordinate1, |
|
object.coordinate2, |
|
] |
|
} |
|
} |
|
|
|
// Add the vehicles to the map |
|
MapItemView { |
|
model: QGroundControl.multiVehicleManager.vehicles |
|
|
|
delegate: VehicleMapItem { |
|
vehicle: object |
|
coordinate: object.coordinate |
|
map: flightMap |
|
size: _mainIsMap ? ScreenTools.defaultFontPixelHeight * 3 : ScreenTools.defaultFontPixelHeight |
|
z: QGroundControl.zOrderVehicles |
|
} |
|
} |
|
|
|
// Add ADSB vehicles to the map |
|
MapItemView { |
|
model: _activeVehicle ? _activeVehicle.adsbVehicles : 0 |
|
|
|
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle |
|
|
|
delegate: VehicleMapItem { |
|
coordinate: object.coordinate |
|
altitude: object.altitude |
|
callsign: object.callsign |
|
heading: object.heading |
|
map: flightMap |
|
z: QGroundControl.zOrderVehicles |
|
} |
|
} |
|
|
|
// Add the items associated with each vehicles flight plan to the map |
|
Repeater { |
|
model: QGroundControl.multiVehicleManager.vehicles |
|
|
|
PlanMapItems { |
|
map: flightMap |
|
largeMapView: _mainIsMap |
|
masterController: masterController |
|
isActiveVehicle: _vehicle.active |
|
|
|
property var _vehicle: object |
|
|
|
PlanMasterController { |
|
id: masterController |
|
Component.onCompleted: startStaticActiveVehicle(object) |
|
} |
|
} |
|
} |
|
|
|
// Allow custom builds to add map items |
|
CustomMapItems { |
|
map: flightMap |
|
largeMapView: _mainIsMap |
|
} |
|
|
|
GeoFenceMapVisuals { |
|
map: flightMap |
|
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 |
|
} |
|
} |
|
|
|
MapQuickItem { |
|
id: gotoLocationItem |
|
visible: false |
|
z: QGroundControl.zOrderMapItems |
|
anchorPoint.x: sourceItem.anchorPointX |
|
anchorPoint.y: sourceItem.anchorPointY |
|
|
|
sourceItem: MissionItemIndexLabel { |
|
checked: true |
|
index: -1 |
|
label: qsTr("Goto here", "Goto here waypoint") |
|
} |
|
|
|
function show(coord) { |
|
gotoLocationItem.coordinate = coord |
|
gotoLocationItem.visible = true |
|
} |
|
|
|
function hide() { |
|
gotoLocationItem.visible = false |
|
} |
|
} |
|
|
|
QGCMapCircleVisuals { |
|
id: orbitMapCircle |
|
mapControl: parent |
|
mapCircle: _mapCircle |
|
visible: false |
|
|
|
property alias center: _mapCircle.center |
|
property real radius: defaultRadius |
|
|
|
readonly property real defaultRadius: 30 |
|
|
|
function show(coord) { |
|
orbitMapCircle.radius = defaultRadius |
|
orbitMapCircle.center = coord |
|
orbitMapCircle.visible = true |
|
} |
|
|
|
function hide() { |
|
orbitMapCircle.visible = false |
|
} |
|
|
|
Component.onCompleted: guidedActionsController.orbitMapCircle = orbitMapCircle |
|
|
|
QGCMapCircle { |
|
id: _mapCircle |
|
interactive: true |
|
radius.rawValue: orbitMapCircle.radius |
|
} |
|
} |
|
|
|
// Handle guided mode clicks |
|
MouseArea { |
|
anchors.fill: parent |
|
|
|
Menu { |
|
id: clickMenu |
|
|
|
property var coord |
|
|
|
MenuItem { |
|
text: qsTr("Go to location") |
|
visible: guidedActionsController.showGotoLocation |
|
|
|
onTriggered: { |
|
gotoLocationItem.show(clickMenu.coord) |
|
orbitMapCircle.hide() |
|
guidedActionsController.confirmAction(guidedActionsController.actionGoto, clickMenu.coord) |
|
} |
|
} |
|
|
|
MenuItem { |
|
text: qsTr("Orbit at location") |
|
visible: guidedActionsController.showOrbit |
|
|
|
onTriggered: { |
|
orbitMapCircle.show(clickMenu.coord) |
|
gotoLocationItem.hide() |
|
guidedActionsController.confirmAction(guidedActionsController.actionOrbit, clickMenu.coord) |
|
} |
|
} |
|
} |
|
|
|
onClicked: { |
|
if (guidedActionsController.guidedUIVisible || (!guidedActionsController.showGotoLocation && !guidedActionsController.showOrbit)) { |
|
return |
|
} |
|
orbitMapCircle.hide() |
|
gotoLocationItem.hide() |
|
var clickCoord = flightMap.toCoordinate(Qt.point(mouse.x, mouse.y), false /* clipToViewPort */) |
|
if (guidedActionsController.showGotoLocation && guidedActionsController.showOrbit) { |
|
clickMenu.coord = clickCoord |
|
clickMenu.popup() |
|
} else if (guidedActionsController.showGotoLocation) { |
|
gotoLocationItem.show(clickCoord) |
|
guidedActionsController.confirmAction(guidedActionsController.actionGoto, clickCoord) |
|
} else if (guidedActionsController.showOrbit) { |
|
orbitMapCircle.show(clickCoord) |
|
guidedActionsController.confirmAction(guidedActionsController.actionOrbit, clickCoord) |
|
} |
|
} |
|
} |
|
|
|
MapScale { |
|
id: mapScale |
|
anchors.right: parent.right |
|
anchors.margins: ScreenTools.defaultFontPixelHeight * (0.33) |
|
anchors.topMargin: ScreenTools.defaultFontPixelHeight * (0.33) + state === "bottomMode" ? 0 : ScreenTools.toolbarHeight |
|
anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * (0.33) |
|
mapControl: flightMap |
|
visible: !ScreenTools.isTinyScreen |
|
state: "bottomMode" |
|
states: [ |
|
State { |
|
name: "topMode" |
|
AnchorChanges { |
|
target: mapScale |
|
anchors.top: parent.top |
|
anchors.bottom: undefined |
|
} |
|
}, |
|
State { |
|
name: "bottomMode" |
|
AnchorChanges { |
|
target: mapScale |
|
anchors.top: undefined |
|
anchors.bottom: parent.bottom |
|
} |
|
} |
|
] |
|
} |
|
}
|
|
|