FlightDisplayViewMap.qml 13.6 KB
Newer Older
1 2 3 4 5 6 7 8
/****************************************************************************
 *
 *   (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.
 *
 ****************************************************************************/
9 10


11 12 13 14 15
import QtQuick          2.3
import QtQuick.Controls 1.2
import QtLocation       5.3
import QtPositioning    5.3
import QtQuick.Dialogs  1.2
16 17

import QGroundControl               1.0
18 19 20
import QGroundControl.Airspace      1.0
import QGroundControl.Controllers   1.0
import QGroundControl.Controls      1.0
21 22 23
import QGroundControl.FlightDisplay 1.0
import QGroundControl.FlightMap     1.0
import QGroundControl.Palette       1.0
24
import QGroundControl.ScreenTools   1.0
25 26 27
import QGroundControl.Vehicle       1.0

FlightMap {
28 29 30 31 32
    id:                         flightMap
    anchors.fill:               parent
    mapName:                    _mapName
    allowGCSLocationCenter:     !userPanned
    allowVehicleLocationCenter: !_keepVehicleCentered
33
    planView:                   false
34

35 36
    property alias  scaleState: mapScale.state

37
    // The following properties must be set by the consumer
38
    property var    planMasterController
39
    property var    guidedActionsController
Don Gagne's avatar
Don Gagne committed
40
    property var    flightWidgets
41
    property var    rightPanelWidth
42
    property var    qgcView                             ///< QGCView control which contains this map
43
    property var    multiVehicleView                    ///< true: multi-vehicle view, false: single vehicle view
Don Gagne's avatar
Don Gagne committed
44

45 46
    property rect   centerViewport:             Qt.rect(0, 0, width, height)

47 48 49 50
    property var    _planMasterController:      planMasterController
    property var    _missionController:         _planMasterController.missionController
    property var    _geoFenceController:        _planMasterController.geoFenceController
    property var    _rallyPointController:      _planMasterController.rallyPointController
51 52 53 54
    property var    _activeVehicle:             QGroundControl.multiVehicleManager.activeVehicle
    property var    _activeVehicleCoordinate:   _activeVehicle ? _activeVehicle.coordinate : QtPositioning.coordinate()
    property var    _gotoHereCoordinate:        QtPositioning.coordinate()
    property real   _toolButtonTopMargin:       parent.height - ScreenTools.availableHeight + (ScreenTools.defaultFontPixelHeight / 2)
55
    property bool   _airspaceEnabled:           QGroundControl.airmapSupported ? QGroundControl.settingsManager.airMapSettings.enableAirMap.rawValue : false
56

57 58
    property bool   _disableVehicleTracking:    false
    property bool   _keepVehicleCentered:       _mainIsMap ? false : true
59

60
    function updateAirspace() {
61
        if(_airspaceEnabled) {
62 63 64
            var coordinateNW = flightMap.toCoordinate(Qt.point(0,0), false /* clipToViewPort */)
            var coordinateSE = flightMap.toCoordinate(Qt.point(width,height), false /* clipToViewPort */)
            if(coordinateNW.isValid && coordinateSE.isValid) {
65
                QGroundControl.airspaceManager.setROI(coordinateNW, coordinateSE, false /*planView*/)
66
            }
67
        }
68 69 70 71 72 73 74 75 76
    }

    // Track last known map position and zoom from Fly view in settings

    onZoomLevelChanged: {
        QGroundControl.flightMapZoom = zoomLevel
        updateAirspace()
    }
    onCenterChanged: {
77
        QGroundControl.flightMapPosition = center
78
        updateAirspace()
79
    }
80

81
    // When the user pans the map we stop responding to vehicle coordinate updates until the panRecenterTimer fires
82
    onUserPannedChanged: {
DonLakeFlyer's avatar
DonLakeFlyer committed
83 84 85 86 87 88
        if (userPanned) {
            console.log("user panned")
            userPanned = false
            _disableVehicleTracking = true
            panRecenterTimer.restart()
        }
89 90
    }

91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
    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() {
121
        var vehiclePoint = flightMap.fromCoordinate(_activeVehicleCoordinate, false /* clipToViewport */)
122 123 124 125 126 127 128
        var toolStripRightEdge = mapFromItem(toolStrip, toolStrip.x, 0).x + toolStrip.width
        var instrumentsWidth = 0
        if (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)
129
        return !pointInRect(vehiclePoint, centerViewport)
130 131 132
    }

    function updateMapToVehiclePosition() {
133 134
        // We let FlightMap handle first vehicle position
        if (firstVehiclePositionReceived && _activeVehicleCoordinate.isValid && !_disableVehicleTracking) {
135
            if (_keepVehicleCentered) {
136
                flightMap.center = _activeVehicleCoordinate
137
            } else {
DonLakeFlyer's avatar
DonLakeFlyer committed
138
                if (firstVehiclePositionReceived && recenterNeeded()) {
139
                    animatedMapRecenter(flightMap.center, _activeVehicleCoordinate)
140 141
                }
            }
142 143 144 145
        }
    }

    Timer {
146 147 148
        id:         panRecenterTimer
        interval:   10000
        running:    false
149 150

        onTriggered: {
151
            _disableVehicleTracking = false
152
            updateMapToVehiclePosition()
153 154 155
        }
    }

156 157 158 159 160 161 162
    Timer {
        interval:       500
        running:        true
        repeat:         true
        onTriggered:    updateMapToVehiclePosition()
    }

Don Gagne's avatar
Don Gagne committed
163
    QGCPalette { id: qgcPal; colorGroupEnabled: true }
164
    QGCMapPalette { id: mapPal; lightColors: isSatelliteMap }
Don Gagne's avatar
Don Gagne committed
165

166
    Connections {
167
        target: _missionController
168 169

        onNewItemsFromVehicle: {
170
            var visualItems = _missionController.visualItems
171
            if (visualItems && visualItems.count !== 1) {
172
                mapFitFunctions.fitMapViewportToMissionItems()
173
                firstVehiclePositionReceived = true
174 175
            }
        }
176 177
    }

178
    ExclusiveGroup {
Don Gagne's avatar
Don Gagne committed
179
        id: _mapTypeButtonsExclusiveGroup
180 181
    }

Don Gagne's avatar
Don Gagne committed
182
    MapFitFunctions {
183
        id:                         mapFitFunctions // The name for this id cannot be changed without breaking references outside of this code. Beware!
Don Gagne's avatar
Don Gagne committed
184 185
        map:                        _flightMap
        usePlannedHomePosition:     false
186
        planMasterController:       _planMasterController
187

Don Gagne's avatar
Don Gagne committed
188 189
        property real leftToolWidth:    toolStrip.x + toolStrip.width
    }
190

191 192
    // Add trajectory points to the map
    MapItemView {
193
        model: _mainIsMap ? _activeVehicle ? _activeVehicle.trajectoryPoints : 0 : 0
DonLakeFlyer's avatar
DonLakeFlyer committed
194 195

        delegate: MapPolyline {
Don Gagne's avatar
Don Gagne committed
196 197
            line.width: 3
            line.color: "red"
DonLakeFlyer's avatar
DonLakeFlyer committed
198
            z:          QGroundControl.zOrderTrajectoryLines
Don Gagne's avatar
Don Gagne committed
199
            path: [
200 201
                object.coordinate1,
                object.coordinate2,
Don Gagne's avatar
Don Gagne committed
202 203
            ]
        }
204 205 206 207
    }

    // Add the vehicles to the map
    MapItemView {
208
        model: QGroundControl.multiVehicleManager.vehicles
DonLakeFlyer's avatar
DonLakeFlyer committed
209 210

        delegate: VehicleMapItem {
Don Gagne's avatar
Don Gagne committed
211 212
            vehicle:        object
            coordinate:     object.coordinate
213
            map:            flightMap
Gus Grubba's avatar
Gus Grubba committed
214
            size:           _mainIsMap ? ScreenTools.defaultFontPixelHeight * 3 : ScreenTools.defaultFontPixelHeight
DonLakeFlyer's avatar
DonLakeFlyer committed
215
            z:              QGroundControl.zOrderVehicles
Don Gagne's avatar
Don Gagne committed
216
        }
217 218
    }

219 220
    // Add ADSB vehicles to the map
    MapItemView {
Gus Grubba's avatar
Gus Grubba committed
221
        model: _activeVehicle ? _activeVehicle.adsbVehicles : []
222 223 224 225
        property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
        delegate: VehicleMapItem {
            coordinate:     object.coordinate
            altitude:       object.altitude
226
            callsign:       object.callsign
227
            heading:        object.heading
Gus Grubba's avatar
Gus Grubba committed
228
            alert:          object.alert
229 230 231 232 233
            map:            flightMap
            z:              QGroundControl.zOrderVehicles
        }
    }

234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
    // 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)
            }
        }
251 252
    }

253 254 255 256 257 258
    // Allow custom builds to add map items
    CustomMapItems {
        map:            flightMap
        largeMapView:   _mainIsMap
    }

259 260
    GeoFenceMapVisuals {
        map:                    flightMap
261
        myGeoFenceController:   _geoFenceController
262
        interactive:            false
263
        planView:               false
264
        homePosition:           _activeVehicle && _activeVehicle.homePosition.isValid ? _activeVehicle.homePosition :  QtPositioning.coordinate()
265 266
    }

267 268
    // Rally points on map
    MapItemView {
269
        model: _rallyPointController.points
270 271 272

        delegate: MapQuickItem {
            id:             itemIndicator
273 274
            anchorPoint.x:  sourceItem.anchorPointX
            anchorPoint.y:  sourceItem.anchorPointY
275 276 277 278 279 280 281 282 283 284
            coordinate:     object.coordinate
            z:              QGroundControl.zOrderMapItems

            sourceItem: MissionItemIndexLabel {
                id:         itemIndexLabel
                label:      qsTr("R", "rally point map item label")
            }
        }
    }

Don Gagne's avatar
Don Gagne committed
285 286 287
    // GoTo here waypoint
    MapQuickItem {
        coordinate:     _gotoHereCoordinate
288
        visible:        _activeVehicle && _activeVehicle.guidedModeSupported && _gotoHereCoordinate.isValid
Don Gagne's avatar
Don Gagne committed
289
        z:              QGroundControl.zOrderMapItems
290 291
        anchorPoint.x:  sourceItem.anchorPointX
        anchorPoint.y:  sourceItem.anchorPointY
Don Gagne's avatar
Don Gagne committed
292 293

        sourceItem: MissionItemIndexLabel {
DonLakeFlyer's avatar
DonLakeFlyer committed
294 295 296
            checked:    true
            index:      -1
            label:      qsTr("Goto here", "Goto here waypoint")
Don Gagne's avatar
Don Gagne committed
297
        }
298 299
    }    

300
    // Camera trigger points
301
    MapItemView {
302
        model: _activeVehicle ? _activeVehicle.cameraTriggerPoints : 0
303 304 305 306 307 308 309

        delegate: CameraTriggerIndicator {
            coordinate:     object.coordinate
            z:              QGroundControl.zOrderTopMost
        }
    }

Don Gagne's avatar
Don Gagne committed
310
    // Handle guided mode clicks
311 312
    MouseArea {
        anchors.fill: parent
Don Gagne's avatar
Don Gagne committed
313 314

        onClicked: {
DonLakeFlyer's avatar
DonLakeFlyer committed
315
            if (guidedActionsController.showGotoLocation && !guidedActionsController.guidedUIVisible) {
316 317
                _gotoHereCoordinate = flightMap.toCoordinate(Qt.point(mouse.x, mouse.y), false /* clipToViewPort */)
                guidedActionsController.confirmAction(guidedActionsController.actionGoto, _gotoHereCoordinate)
Don Gagne's avatar
Don Gagne committed
318 319
            }
        }
320
    }
321 322

    MapScale {
323
        id:                     mapScale
324
        anchors.right:          parent.right
325 326 327
        anchors.margins:        ScreenTools.defaultFontPixelHeight * (0.33)
        anchors.topMargin:      ScreenTools.defaultFontPixelHeight * (0.33) + state === "bottomMode" ? 0 : ScreenTools.toolbarHeight
        anchors.bottomMargin:   ScreenTools.defaultFontPixelHeight * (0.33)
328 329
        mapControl:             flightMap
        visible:                !ScreenTools.isTinyScreen
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
        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
                }
            }
        ]
349
    }
350

351
    // Airspace overlap support
352
    MapItemView {
353
        model:              _airspaceEnabled && QGroundControl.airspaceManager.airspaceVisible ? QGroundControl.airspaceManager.airspaces.circles : []
354 355 356
        delegate: MapCircle {
            center:         object.center
            radius:         object.radius
357
            color:          Qt.rgba(0.94, 0.87, 0, 0.15)
Gus Grubba's avatar
Gus Grubba committed
358
            border.color:   Qt.rgba(1,1,1,0.85)
359 360 361 362
        }
    }

    MapItemView {
363
        model:              _airspaceEnabled && QGroundControl.airspaceManager.airspaceVisible ? QGroundControl.airspaceManager.airspaces.polygons : []
364 365
        delegate: MapPolygon {
            path:           object.polygon
366 367
            color:          Qt.rgba(0.94, 0.87, 0, 0.15)
            border.color:   Qt.rgba(1,1,1,0.85)
368 369
        }
    }
370
}