FlightDisplayView.qml 35.6 KB
Newer Older
1 2
/****************************************************************************
 *
Gus Grubba's avatar
Gus Grubba committed
3
 * (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
4 5 6 7 8
 *
 * 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
import QtQuick                  2.11
import QtQuick.Controls         2.4
import QtQuick.Dialogs          1.3
import QtQuick.Layouts          1.11
14

15 16
import QtLocation               5.3
import QtPositioning            5.3
Patrick José Pereira's avatar
Patrick José Pereira committed
17
import QtQuick.Window           2.2
18
import QtQml.Models             2.1
19

20
import QGroundControl               1.0
21 22 23 24
import QGroundControl.Airspace      1.0
import QGroundControl.Controllers   1.0
import QGroundControl.Controls      1.0
import QGroundControl.FactSystem    1.0
Don Gagne's avatar
Don Gagne committed
25
import QGroundControl.FlightDisplay 1.0
26 27
import QGroundControl.FlightMap     1.0
import QGroundControl.Palette       1.0
28
import QGroundControl.ScreenTools   1.0
29
import QGroundControl.Vehicle       1.0
30 31

/// Flight Display View
32
Item {
33

Gus Grubba's avatar
Gus Grubba committed
34
    PlanMasterController {
Gus Grubba's avatar
Gus Grubba committed
35 36 37 38 39
        id: _planController
        Component.onCompleted: {
            start(true /* flyView */)
            mainWindow.planMasterControllerView = _planController
        }
Gus Grubba's avatar
Gus Grubba committed
40 41
    }

42 43 44 45 46 47 48 49 50
    property alias  guidedController:              guidedActionsController
    property bool   activeVehicleJoystickEnabled:  activeVehicle ? activeVehicle.joystickEnabled : false
    property bool   mainIsMap:                     QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_mainIsMapKey,  true) : true
    property bool   isBackgroundDark:              mainIsMap ? (mainWindow.flightDisplayMap ? mainWindow.flightDisplayMap.isSatelliteMap : true) : true

    property var    _missionController:             _planController.missionController
    property var    _geoFenceController:            _planController.geoFenceController
    property var    _rallyPointController:          _planController.rallyPointController
    property bool   _isPipVisible:                  QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_PIPVisibleKey, true) : false
51
    property bool   _useChecklist:                  QGroundControl.settingsManager.appSettings.useChecklist.rawValue && QGroundControl.corePlugin.options.preFlightChecklistUrl.toString().length
52
    property bool   _enforceChecklist:              _useChecklist && QGroundControl.settingsManager.appSettings.enforceChecklist.rawValue
53
    property bool   _checklistComplete:             activeVehicle && (activeVehicle.checkListState === Vehicle.CheckListPassed)
54 55 56 57
    property real   _margins:                       ScreenTools.defaultFontPixelWidth / 2
    property real   _pipSize:                       mainWindow.width * 0.2
    property alias  _guidedController:              guidedActionsController
    property alias  _altitudeSlider:                altitudeSlider
58
    property real   _toolsMargin:                   ScreenTools.defaultFontPixelWidth * 0.75
59

Gus Grubba's avatar
Gus Grubba committed
60
    readonly property var       _dynamicCameras:        activeVehicle ? activeVehicle.dynamicCameras : null
61
    readonly property bool      _isCamera:              _dynamicCameras ? _dynamicCameras.cameras.count > 0 : false
Don Gagne's avatar
Don Gagne committed
62 63 64 65 66 67 68 69 70 71 72
    readonly property real      _defaultRoll:           0
    readonly property real      _defaultPitch:          0
    readonly property real      _defaultHeading:        0
    readonly property real      _defaultAltitudeAMSL:   0
    readonly property real      _defaultGroundSpeed:    0
    readonly property real      _defaultAirSpeed:       0
    readonly property string    _mapName:               "FlightDisplayView"
    readonly property string    _showMapBackgroundKey:  "/showMapBackground"
    readonly property string    _mainIsMapKey:          "MainFlyWindowIsMap"
    readonly property string    _PIPVisibleKey:         "IsPIPVisible"

73 74 75 76 77 78 79 80 81 82 83 84 85 86
    Timer {
        id:             checklistPopupTimer
        interval:       1000
        repeat:         false
        onTriggered: {
            if (visible && !_checklistComplete) {
                checklistDropPanel.open()
            }
            else {
                checklistDropPanel.close()
            }
        }
    }

87
    function setStates() {
88 89
        QGroundControl.saveBoolGlobalSetting(_mainIsMapKey, mainIsMap)
        if(mainIsMap) {
90 91 92
            //-- Adjust Margins
            _flightMapContainer.state   = "fullMode"
            _flightVideo.state          = "pipMode"
93
        } else {
94 95 96
            //-- Adjust Margins
            _flightMapContainer.state   = "pipMode"
            _flightVideo.state          = "fullMode"
97
        }
Don Gagne's avatar
Don Gagne committed
98 99
    }

100 101 102
    function setPipVisibility(state) {
        _isPipVisible = state;
        QGroundControl.saveBoolGlobalSetting(_PIPVisibleKey, state)
103 104
    }

Gus Grubba's avatar
Gus Grubba committed
105 106 107 108 109 110 111 112 113 114 115 116 117 118
    function isInstrumentRight() {
        if(QGroundControl.corePlugin.options.instrumentWidget) {
            if(QGroundControl.corePlugin.options.instrumentWidget.source.toString().length) {
                switch(QGroundControl.corePlugin.options.instrumentWidget.widgetPosition) {
                case CustomInstrumentWidget.POS_TOP_LEFT:
                case CustomInstrumentWidget.POS_BOTTOM_LEFT:
                case CustomInstrumentWidget.POS_CENTER_LEFT:
                    return false;
                }
            }
        }
        return true;
    }

119 120 121 122 123 124
    function showPreflightChecklistIfNeeded () {
        if (activeVehicle && !_checklistComplete && _enforceChecklist) {
            checklistPopupTimer.restart()
        }
    }

125
    Connections {
126 127
        target:                     _missionController
        onResumeMissionUploadFail:  guidedActionsController.confirmAction(guidedActionsController.actionResumeMissionUploadFail)
128 129
    }

130 131 132 133 134 135 136 137 138 139 140 141
    Connections {
        target:                 mainWindow
        onArmVehicle:           guidedController.confirmAction(guidedController.actionArm)
        onDisarmVehicle: {
            if (guidedController.showEmergenyStop) {
                guidedController.confirmAction(guidedController.actionEmergencyStop)
            } else {
                guidedController.confirmAction(guidedController.actionDisarm)
            }
        }
        onVtolTransitionToFwdFlight:    guidedController.confirmAction(guidedController.actionVtolTransitionToFwdFlight)
        onVtolTransitionToMRFlight:     guidedController.confirmAction(guidedController.actionVtolTransitionToMRFlight)
142
        onFlightDisplayMapChanged:      setStates()
143 144
    }

145
    Component.onCompleted: {
146 147 148
        if(QGroundControl.corePlugin.options.flyViewOverlay.toString().length) {
            flyViewOverlay.source = QGroundControl.corePlugin.options.flyViewOverlay
        }
149 150 151
        if(QGroundControl.corePlugin.options.preFlightChecklistUrl.toString().length) {
            checkList.source = QGroundControl.corePlugin.options.preFlightChecklistUrl
        }
152
    }
dogmaphobic's avatar
dogmaphobic committed
153

154 155 156 157 158 159 160 161
    // The following code is used to track vehicle states for showing the mission complete dialog
    property bool vehicleArmed:                     activeVehicle ? activeVehicle.armed : true // true here prevents pop up from showing during shutdown
    property bool vehicleWasArmed:                  false
    property bool vehicleInMissionFlightMode:       activeVehicle ? (activeVehicle.flightMode === activeVehicle.missionFlightMode) : false
    property bool vehicleWasInMissionFlightMode:    false
    property bool showMissionCompleteDialog:        vehicleWasArmed && vehicleWasInMissionFlightMode &&
                                                        (_missionController.containsItems || _geoFenceController.containsItems || _rallyPointController.containsItems ||
                                                        (activeVehicle ? activeVehicle.cameraTriggerPoints.count !== 0 : false))
162 163 164

    onVehicleArmedChanged: {
        if (vehicleArmed) {
165 166
            vehicleWasArmed = true
            vehicleWasInMissionFlightMode = vehicleInMissionFlightMode
167
        } else {
168 169
            if (showMissionCompleteDialog) {
                mainWindow.showComponentDialog(missionCompleteDialogComponent, qsTr("Flight Plan complete"), mainWindow.showDialogDefaultWidth, StandardButton.Close)
170
            }
171 172
            vehicleWasArmed = false
            vehicleWasInMissionFlightMode = false
173 174 175 176
        }
    }

    onVehicleInMissionFlightModeChanged: {
177 178
        if (vehicleInMissionFlightMode && vehicleArmed) {
            vehicleWasInMissionFlightMode = true
179 180 181 182
        }
    }

    Component {
183 184 185
        id: missionCompleteDialogComponent

        QGCViewDialog {
Gus Grubba's avatar
Gus Grubba committed
186
            property var activeVehicleCopy: activeVehicle
187 188 189 190 191
            onActiveVehicleCopyChanged:
                if (!activeVehicleCopy) {
                    hideDialog()
                }

192 193 194 195
            QGCFlickable {
                anchors.fill:   parent
                contentHeight:  column.height

196
                ColumnLayout {
197 198 199 200
                    id:                 column
                    anchors.margins:    _margins
                    anchors.left:       parent.left
                    anchors.right:      parent.right
201
                    spacing:            ScreenTools.defaultFontPixelHeight
202

203 204 205 206 207 208
                    QGCLabel {
                        Layout.fillWidth:       true
                        text:                   qsTr("%1 Images Taken").arg(activeVehicle.cameraTriggerPoints.count)
                        horizontalAlignment:    Text.AlignHCenter
                        visible:                activeVehicle.cameraTriggerPoints.count !== 0
                    }
209

210 211 212 213 214 215 216
                    QGCButton {
                        Layout.fillWidth:   true
                        text:               qsTr("Remove plan from vehicle")
                        visible:            !activeVehicle.connectionLost// && !activeVehicle.apmFirmware  // ArduPilot has a bug somewhere with mission clear
                        onClicked: {
                            _planController.removeAllFromVehicle()
                            hideDialog()
217
                        }
218
                    }
219

220 221 222 223 224 225
                    QGCButton {
                        Layout.fillWidth:   true
                        Layout.alignment:   Qt.AlignHCenter
                        text:               qsTr("Leave plan on vehicle")
                        onClicked:          hideDialog()
                    }
Don Gagne's avatar
Don Gagne committed
226

227 228 229 230 231
                    Rectangle {
                        Layout.fillWidth:   true
                        color:              qgcPal.text
                        height:             1
                    }
Don Gagne's avatar
Don Gagne committed
232

233 234 235 236
                    ColumnLayout {
                        Layout.fillWidth:   true
                        spacing:            ScreenTools.defaultFontPixelHeight
                        visible:            !activeVehicle.connectionLost && _guidedController.showResumeMission
Don Gagne's avatar
Don Gagne committed
237

238 239 240 241 242 243 244 245 246
                        QGCButton {
                            Layout.fillWidth:   true
                            Layout.alignment:   Qt.AlignHCenter
                            text:               qsTr("Resume Mission From Waypoint %1").arg(_guidedController._resumeMissionIndex)

                            onClicked: {
                                guidedController.executeAction(_guidedController.actionResumeMission, null, null)
                                hideDialog()
                            }
Don Gagne's avatar
Don Gagne committed
247 248
                        }

249 250 251 252 253
                        QGCLabel {
                            Layout.fillWidth:   true
                            wrapMode:           Text.WordWrap
                            text:               qsTr("Resume Mission will rebuild the current mission from the last flown waypoint and upload it to the vehicle for the next flight.")
                        }
Don Gagne's avatar
Don Gagne committed
254 255
                    }

256
                    QGCLabel {
Don Gagne's avatar
Don Gagne committed
257
                        Layout.fillWidth:   true
258 259 260 261
                        wrapMode:           Text.WordWrap
                        color:              qgcPal.warningText
                        text:               qsTr("If you are changing batteries for Resume Mission do not disconnect from the vehicle.")
                        visible:            _guidedController.showResumeMission
Don Gagne's avatar
Don Gagne committed
262
                    }
263
                }
264 265 266 267
            }
        }
    }

Patrick José Pereira's avatar
Patrick José Pereira committed
268 269
    Window {
        id:             videoWindow
270 271
        width:          !mainIsMap ? _mapAndVideo.width  : _pipSize
        height:         !mainIsMap ? _mapAndVideo.height : _pipSize * (9/16)
Patrick José Pereira's avatar
Patrick José Pereira committed
272 273 274 275 276 277 278 279 280 281 282
        visible:        false

        Item {
            id:             videoItem
            anchors.fill:   parent
        }

        onClosing: {
            _flightVideo.state = "unpopup"
            videoWindow.visible = false
        }
283
    }
Patrick José Pereira's avatar
Patrick José Pereira committed
284

285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
    /* This timer will startVideo again after the popup window appears and is loaded.
     * Such approach was the only one to avoid a crash for windows users
     */
    Timer {
      id: videoPopUpTimer
      interval: 2000;
      running: false;
      repeat: false
      onTriggered: {
          // If state is popup, the next one will be popup-finished
          if (_flightVideo.state ==  "popup") {
            _flightVideo.state = "popup-finished"
          }
          QGroundControl.videoManager.startVideo()
      }
Patrick José Pereira's avatar
Patrick José Pereira committed
300 301
    }

302
    QGCMapPalette { id: mapPal; lightColors: mainIsMap ? mainWindow.flightDisplayMap.isSatelliteMap : true }
303

304
    Item {
305
        id:             _mapAndVideo
306
        anchors.fill:   parent
307 308 309 310

        //-- Map View
        Item {
            id: _flightMapContainer
311
            z:  mainIsMap ? _mapAndVideo.z + 1 : _mapAndVideo.z + 2
312 313
            anchors.left:   _mapAndVideo.left
            anchors.bottom: _mapAndVideo.bottom
314 315 316
            visible:        mainIsMap || _isPipVisible && !QGroundControl.videoManager.fullScreen
            width:          mainIsMap ? _mapAndVideo.width  : _pipSize
            height:         mainIsMap ? _mapAndVideo.height : _pipSize * (9/16)
317 318 319 320 321 322 323 324 325 326 327 328 329 330
            states: [
                State {
                    name:   "pipMode"
                    PropertyChanges {
                        target:             _flightMapContainer
                        anchors.margins:    ScreenTools.defaultFontPixelHeight
                    }
                },
                State {
                    name:   "fullMode"
                    PropertyChanges {
                        target:             _flightMapContainer
                        anchors.margins:    0
                    }
331
                }
332 333
            ]
            FlightDisplayViewMap {
334
                id:                         _fMap
335 336
                anchors.fill:               parent
                guidedActionsController:    _guidedController
Gus Grubba's avatar
Gus Grubba committed
337
                missionController:          _planController
338 339
                flightWidgets:              flightDisplayViewWidgets
                rightPanelWidth:            ScreenTools.defaultFontPixelHeight * 9
340
                multiVehicleView:           !singleVehicleView.checked
341
                scaleState:                 (mainIsMap && flyViewOverlay.item) ? (flyViewOverlay.item.scaleState ? flyViewOverlay.item.scaleState : "bottomMode") : "bottomMode"
342 343
                Component.onCompleted: {
                    mainWindow.flightDisplayMap = _fMap
344
                    _fMap.adjustMapSize()
345
                }
346
            }
347
        }
348

349
        //-- Video View
350
        Item {
351
            id:             _flightVideo
352 353 354
            z:              mainIsMap ? _mapAndVideo.z + 2 : _mapAndVideo.z + 1
            width:          !mainIsMap ? _mapAndVideo.width  : _pipSize
            height:         !mainIsMap ? _mapAndVideo.height : _pipSize * (9/16)
355 356
            anchors.left:   _mapAndVideo.left
            anchors.bottom: _mapAndVideo.bottom
357
            visible:        QGroundControl.videoManager.hasVideo && (!mainIsMap || _isPipVisible)
358 359 360 361 362 363

            onParentChanged: {
                /* If video comes back from popup
                 * correct anchors.
                 * Such thing is not possible with ParentChange.
                 */
364
                if(parent == _mapAndVideo) {
365
                    // Do anchors again after popup
366 367
                    anchors.left =       _mapAndVideo.left
                    anchors.bottom =     _mapAndVideo.bottom
368
                    anchors.margins =    _toolsMargin
369 370 371
                }
            }

372 373 374 375
            states: [
                State {
                    name:   "pipMode"
                    PropertyChanges {
376
                        target:             _flightVideo
377
                        anchors.margins:    ScreenTools.defaultFontPixelHeight
Patrick José Pereira's avatar
Patrick José Pereira committed
378 379
                    }
                    PropertyChanges {
380 381
                        target:             _flightVideoPipControl
                        inPopup:            false
382 383 384 385 386
                    }
                },
                State {
                    name:   "fullMode"
                    PropertyChanges {
387
                        target:             _flightVideo
388 389
                        anchors.margins:    0
                    }
Patrick José Pereira's avatar
Patrick José Pereira committed
390
                    PropertyChanges {
391 392
                        target:             _flightVideoPipControl
                        inPopup:            false
Patrick José Pereira's avatar
Patrick José Pereira committed
393 394 395 396 397
                    }
                },
                State {
                    name: "popup"
                    StateChangeScript {
398 399
                        script: {
                            // Stop video, restart it again with Timer
Gus Grubba's avatar
Gus Grubba committed
400
                            // Avoiding crashes if ParentChange is not yet done
401 402 403
                            QGroundControl.videoManager.stopVideo()
                            videoPopUpTimer.running = true
                        }
Patrick José Pereira's avatar
Patrick José Pereira committed
404
                    }
405
                    PropertyChanges {
406 407
                        target:             _flightVideoPipControl
                        inPopup:            true
408 409 410 411
                    }
                },
                State {
                    name: "popup-finished"
Patrick José Pereira's avatar
Patrick José Pereira committed
412
                    ParentChange {
413 414 415 416 417 418
                        target:             _flightVideo
                        parent:             videoItem
                        x:                  0
                        y:                  0
                        width:              videoItem.width
                        height:             videoItem.height
Patrick José Pereira's avatar
Patrick José Pereira committed
419 420 421 422 423
                    }
                },
                State {
                    name: "unpopup"
                    StateChangeScript {
424 425 426 427
                        script: {
                            QGroundControl.videoManager.stopVideo()
                            videoPopUpTimer.running = true
                        }
Patrick José Pereira's avatar
Patrick José Pereira committed
428 429
                    }
                    ParentChange {
430 431
                        target:             _flightVideo
                        parent:             _mapAndVideo
Patrick José Pereira's avatar
Patrick José Pereira committed
432 433
                    }
                    PropertyChanges {
434 435
                        target:             _flightVideoPipControl
                        inPopup:             false
Patrick José Pereira's avatar
Patrick José Pereira committed
436
                    }
437
                }
438
            ]
439
            //-- Video Streaming
440
            FlightDisplayViewVideo {
Patrick José Pereira's avatar
Patrick José Pereira committed
441
                id:             videoStreaming
442 443 444 445
                anchors.fill:   parent
                visible:        QGroundControl.videoManager.isGStreamer
            }
            //-- UVC Video (USB Camera or Video Device)
446 447
            Loader {
                id:             cameraLoader
448 449
                anchors.fill:   parent
                visible:        !QGroundControl.videoManager.isGStreamer
450
                source:         visible ? (QGroundControl.videoManager.uvcEnabled ? "qrc:/qml/FlightDisplayViewUVC.qml" : "qrc:/qml/FlightDisplayViewDummy.qml") : ""
451
            }
dogmaphobic's avatar
dogmaphobic committed
452
        }
453 454 455 456

        QGCPipable {
            id:                 _flightVideoPipControl
            z:                  _flightVideo.z + 3
457 458
            width:              _pipSize
            height:             _pipSize * (9/16)
459 460
            anchors.left:       _mapAndVideo.left
            anchors.bottom:     _mapAndVideo.bottom
461
            anchors.margins:    ScreenTools.defaultFontPixelHeight
462
            visible:            QGroundControl.videoManager.hasVideo && !QGroundControl.videoManager.fullScreen && _flightVideo.state != "popup"
463 464
            isHidden:           !_isPipVisible
            isDark:             isBackgroundDark
465
            enablePopup:        mainIsMap
466
            onActivated: {
467
                mainIsMap = !mainIsMap
468
                setStates()
469
                _fMap.adjustMapSize()
470 471 472 473
            }
            onHideIt: {
                setPipVisibility(!state)
            }
Patrick José Pereira's avatar
Patrick José Pereira committed
474 475 476 477
            onPopup: {
                videoWindow.visible = true
                _flightVideo.state = "popup"
            }
478 479
            onNewWidth: {
                _pipSize = newWidth
Jacob Walser's avatar
Jacob Walser committed
480
            }
dogmaphobic's avatar
dogmaphobic committed
481
        }
Don Gagne's avatar
Don Gagne committed
482

483 484
        Row {
            id:                     singleMultiSelector
485 486
            anchors.topMargin:      ScreenTools.toolbarHeight + _toolsMargin
            anchors.rightMargin:    _toolsMargin
487 488
            anchors.right:          parent.right
            spacing:                ScreenTools.defaultFontPixelWidth
489
            z:                      _mapAndVideo.z + 4
490
            visible:                QGroundControl.multiVehicleManager.vehicles.count > 1 && QGroundControl.corePlugin.options.enableMultiVehicleList
491 492 493 494 495

            QGCRadioButton {
                id:             singleVehicleView
                text:           qsTr("Single")
                checked:        true
496
                textColor:      mapPal.text
497 498 499
            }

            QGCRadioButton {
500
                text:           qsTr("Multi-Vehicle")
501
                textColor:      mapPal.text
502 503 504
            }
        }

505
        FlightDisplayViewWidgets {
506
            id:                 flightDisplayViewWidgets
507
            z:                  _mapAndVideo.z + 4
508
            height:             availableHeight - (singleMultiSelector.visible ? singleMultiSelector.height + _toolsMargin : 0) - _toolsMargin
509
            anchors.left:       parent.left
510
            anchors.right:      altitudeSlider.visible ? altitudeSlider.left : parent.right
511
            anchors.bottom:     parent.bottom
512
            anchors.top:        singleMultiSelector.visible? singleMultiSelector.bottom : undefined
513
            useLightColors:     isBackgroundDark
514
            missionController:  _missionController
515
            visible:            singleVehicleView.checked && !QGroundControl.videoManager.fullScreen
516 517
        }

518 519 520 521 522
        //-------------------------------------------------------------------------
        //-- Loader helper for plugins to overlay elements over the fly view
        Loader {
            id:                 flyViewOverlay
            z:                  flightDisplayViewWidgets.z + 1
523
            visible:            !QGroundControl.videoManager.fullScreen
524
            height:             mainWindow.height - mainWindow.header.height
525 526 527 528 529
            anchors.left:       parent.left
            anchors.right:      altitudeSlider.visible ? altitudeSlider.left : parent.right
            anchors.bottom:     parent.bottom
        }

530
        MultiVehicleList {
531
            anchors.margins:            _toolsMargin
532 533 534 535
            anchors.top:                singleMultiSelector.bottom
            anchors.right:              parent.right
            anchors.bottom:             parent.bottom
            width:                      ScreenTools.defaultFontPixelWidth * 30
536
            visible:                    !singleVehicleView.checked && !QGroundControl.videoManager.fullScreen && QGroundControl.corePlugin.options.enableMultiVehicleList
537
            z:                          _mapAndVideo.z + 4
538
            guidedActionsController:    _guidedController
539
        }
dogmaphobic's avatar
dogmaphobic committed
540

541
        //-- Virtual Joystick
542
        Loader {
543
            id:                         virtualJoystickMultiTouch
544
            z:                          _mapAndVideo.z + 5
545
            width:                      parent.width  - (_flightVideoPipControl.width / 2)
546
            height:                     Math.min(mainWindow.height * 0.25, ScreenTools.defaultFontPixelWidth * 16)
Gus Grubba's avatar
Gus Grubba committed
547
            visible:                    (_virtualJoystick ? _virtualJoystick.value : false) && !QGroundControl.videoManager.fullScreen && !(activeVehicle ? activeVehicle.highLatencyLink : false)
548 549
            anchors.bottom:             _flightVideoPipControl.top
            anchors.bottomMargin:       ScreenTools.defaultFontPixelHeight * 2
550
            anchors.horizontalCenter:   flightDisplayViewWidgets.horizontalCenter
551
            source:                     "qrc:/qml/VirtualJoystick.qml"
Gus Grubba's avatar
Gus Grubba committed
552
            active:                     (_virtualJoystick ? _virtualJoystick.value : false) && !(activeVehicle ? activeVehicle.highLatencyLink : false)
Don Gagne's avatar
Don Gagne committed
553

554
            property bool useLightColors: isBackgroundDark
555 556
            // The default behaviour is not centralized throttle
            property bool centralizeThrottle: _virtualJoystickCentralized ? _virtualJoystickCentralized.value : false
557 558

            property Fact _virtualJoystick: QGroundControl.settingsManager.appSettings.virtualJoystick
559
            property Fact _virtualJoystickCentralized: QGroundControl.settingsManager.appSettings.virtualJoystickCentralized
Don Gagne's avatar
Don Gagne committed
560
        }
561 562

        ToolStrip {
Gus Grubba's avatar
Gus Grubba committed
563
            visible:            (activeVehicle ? activeVehicle.guidedModeSupported : true) && !QGroundControl.videoManager.fullScreen
564
            id:                 toolStrip
565

566
            anchors.leftMargin: isInstrumentRight() ? _toolsMargin : undefined
567
            anchors.left:       isInstrumentRight() ? _mapAndVideo.left : undefined
Gus Grubba's avatar
Gus Grubba committed
568
            anchors.rightMargin:isInstrumentRight() ? undefined : ScreenTools.defaultFontPixelWidth
569
            anchors.right:      isInstrumentRight() ? undefined : _mapAndVideo.right
570
            anchors.topMargin:  _toolsMargin
571
            anchors.top:        parent.top
572
            z:                  _mapAndVideo.z + 4
573
            maxHeight:          parent.height - toolStrip.y + (_flightVideo.visible ? (_flightVideo.y - parent.height) : 0)
574
            title:              qsTr("Fly")
575

576
            property bool _anyActionAvailable: _guidedController.showStartMission || _guidedController.showResumeMission || _guidedController.showChangeAlt || _guidedController.showLandAbort
577 578
            property var _actionModel: [
                {
579 580 581 582
                    title:      _guidedController.startMissionTitle,
                    text:       _guidedController.startMissionMessage,
                    action:     _guidedController.actionStartMission,
                    visible:    _guidedController.showStartMission
583
                },
Don Gagne's avatar
Don Gagne committed
584 585 586 587 588 589
                {
                    title:      _guidedController.continueMissionTitle,
                    text:       _guidedController.continueMissionMessage,
                    action:     _guidedController.actionContinueMission,
                    visible:    _guidedController.showContinueMission
                },
590
                {
591 592 593 594
                    title:      _guidedController.changeAltTitle,
                    text:       _guidedController.changeAltMessage,
                    action:     _guidedController.actionChangeAlt,
                    visible:    _guidedController.showChangeAlt
595 596
                },
                {
597 598 599 600
                    title:      _guidedController.landAbortTitle,
                    text:       _guidedController.landAbortMessage,
                    action:     _guidedController.actionLandAbort,
                    visible:    _guidedController.showLandAbort
601 602 603 604
                }
            ]

            model: [
605 606 607
                {
                    name:               "Checklist",
                    iconSource:         "/qmlimages/check.svg",
Gus Grubba's avatar
Gus Grubba committed
608 609
                    buttonVisible:      _useChecklist,
                    buttonEnabled:      _useChecklist && activeVehicle && !activeVehicle.armed,
610
                },
611
                {
Gus Grubba's avatar
Gus Grubba committed
612 613 614
                    name:               _guidedController.takeoffTitle,
                    iconSource:         "/res/takeoff.svg",
                    buttonVisible:      _guidedController.showTakeoff || !_guidedController.showLand,
615
                    buttonEnabled:      _guidedController.showTakeoff,
Gus Grubba's avatar
Gus Grubba committed
616
                    action:             _guidedController.actionTakeoff
617 618
                },
                {
Gus Grubba's avatar
Gus Grubba committed
619 620 621 622 623
                    name:               _guidedController.landTitle,
                    iconSource:         "/res/land.svg",
                    buttonVisible:      _guidedController.showLand && !_guidedController.showTakeoff,
                    buttonEnabled:      _guidedController.showLand,
                    action:             _guidedController.actionLand
624 625
                },
                {
Gus Grubba's avatar
Gus Grubba committed
626 627 628 629 630
                    name:               _guidedController.rtlTitle,
                    iconSource:         "/res/rtl.svg",
                    buttonVisible:      true,
                    buttonEnabled:      _guidedController.showRTL,
                    action:             _guidedController.actionRTL
631 632
                },
                {
Gus Grubba's avatar
Gus Grubba committed
633 634 635 636 637
                    name:               _guidedController.pauseTitle,
                    iconSource:         "/res/pause-mission.svg",
                    buttonVisible:      _guidedController.showPause,
                    buttonEnabled:      _guidedController.showPause,
                    action:             _guidedController.actionPause
638 639
                },
                {
Gus Grubba's avatar
Gus Grubba committed
640 641
                    name:               qsTr("Action"),
                    iconSource:         "/res/action.svg",
642
                    buttonVisible:      _anyActionAvailable,
Gus Grubba's avatar
Gus Grubba committed
643
                    action:             -1
DonLakeFlyer's avatar
DonLakeFlyer committed
644
                }
645 646 647
            ]

            onClicked: {
648
                if(index === 0) {
649
                    checklistDropPanel.open()
650
                } else {
651
                    guidedActionsController.closeAll()
652 653 654 655 656 657 658
                    var action = model[index].action
                    if (action === -1) {
                        guidedActionList.model   = _actionModel
                        guidedActionList.visible = true
                    } else {
                        _guidedController.confirmAction(action)
                    }
659
                }
660

661 662 663 664
            }
        }

        GuidedActionsController {
665
            id:                 guidedActionsController
666
            missionController:  _missionController
667
            confirmDialog:      guidedActionConfirm
DonLakeFlyer's avatar
DonLakeFlyer committed
668
            actionList:         guidedActionList
Don Gagne's avatar
Don Gagne committed
669
            altitudeSlider:     _altitudeSlider
670 671
            z:                  _flightVideoPipControl.z + 1

672
            onShowStartMissionChanged: {
673
                if (showStartMission) {
674 675 676 677
                    confirmAction(actionStartMission)
                }
            }

678 679 680 681 682 683
            onShowContinueMissionChanged: {
                if (showContinueMission) {
                    confirmAction(actionContinueMission)
                }
            }

684 685 686 687 688
            onShowLandAbortChanged: {
                if (showLandAbort) {
                    confirmAction(actionLandAbort)
                }
            }
689 690 691 692 693 694 695

            /// Close all dialogs
            function closeAll() {
                guidedActionConfirm.visible = false
                guidedActionList.visible    = false
                altitudeSlider.visible      = false
            }
696 697
        }

698
        GuidedActionConfirm {
699 700 701 702
            id:                         guidedActionConfirm
            anchors.margins:            _margins
            anchors.bottom:             parent.bottom
            anchors.horizontalCenter:   parent.horizontalCenter
703 704
            guidedController:           _guidedController
            altitudeSlider:             _altitudeSlider
705 706
        }

707
        GuidedActionList {
708 709 710 711
            id:                         guidedActionList
            anchors.margins:            _margins
            anchors.bottom:             parent.bottom
            anchors.horizontalCenter:   parent.horizontalCenter
712
            guidedController:           _guidedController
713 714 715
        }

        //-- Altitude slider
DonLakeFlyer's avatar
DonLakeFlyer committed
716
        GuidedAltitudeSlider {
717 718 719 720 721 722
            id:                 altitudeSlider
            anchors.margins:    _margins
            anchors.right:      parent.right
            anchors.topMargin:  ScreenTools.toolbarHeight + _margins
            anchors.top:        parent.top
            anchors.bottom:     parent.bottom
723
            z:                  _guidedController.z
724 725 726 727 728
            radius:             ScreenTools.defaultFontPixelWidth / 2
            width:              ScreenTools.defaultFontPixelWidth * 10
            color:              qgcPal.window
            visible:            false
        }
Don Gagne's avatar
Don Gagne committed
729
    }
730

731
    //-- Airspace Indicator
732
    Rectangle {
733 734 735
        id:             airspaceIndicator
        width:          airspaceRow.width + (ScreenTools.defaultFontPixelWidth * 3)
        height:         airspaceRow.height * 1.25
736
        color:          qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(1,1,1,0.95) : Qt.rgba(0,0,0,0.75)
737
        visible:        QGroundControl.airmapSupported && mainIsMap && flightPermit && flightPermit !== AirspaceFlightPlanProvider.PermitNone
738 739 740 741 742 743 744
        radius:         3
        border.width:   1
        border.color:   qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(0,0,0,0.35) : Qt.rgba(1,1,1,0.35)
        anchors.top:    parent.top
        anchors.topMargin: ScreenTools.toolbarHeight + (ScreenTools.defaultFontPixelHeight * 0.25)
        anchors.horizontalCenter: parent.horizontalCenter
        Row {
745
            id: airspaceRow
746 747
            spacing: ScreenTools.defaultFontPixelWidth
            anchors.centerIn: parent
748
            QGCLabel { text: airspaceIndicator.providerName+":"; anchors.verticalCenter: parent.verticalCenter; }
749 750
            QGCLabel {
                text: {
751
                    if(airspaceIndicator.flightPermit) {
Gus Grubba's avatar
Gus Grubba committed
752
                        if(airspaceIndicator.flightPermit === AirspaceFlightPlanProvider.PermitPending)
753
                            return qsTr("Approval Pending")
754
                        if(airspaceIndicator.flightPermit === AirspaceFlightPlanProvider.PermitAccepted || airspaceIndicator.flightPermit === AirspaceFlightPlanProvider.PermitNotRequired)
755
                            return qsTr("Flight Approved")
Gus Grubba's avatar
Gus Grubba committed
756
                        if(airspaceIndicator.flightPermit === AirspaceFlightPlanProvider.PermitRejected)
757
                            return qsTr("Flight Rejected")
758 759 760 761
                    }
                    return ""
                }
                color: {
762
                    if(airspaceIndicator.flightPermit) {
Gus Grubba's avatar
Gus Grubba committed
763
                        if(airspaceIndicator.flightPermit === AirspaceFlightPlanProvider.PermitPending)
764
                            return qgcPal.colorOrange
765
                        if(airspaceIndicator.flightPermit === AirspaceFlightPlanProvider.PermitAccepted || airspaceIndicator.flightPermit === AirspaceFlightPlanProvider.PermitNotRequired)
766 767 768 769 770 771 772
                            return qgcPal.colorGreen
                    }
                    return qgcPal.colorRed
                }
                anchors.verticalCenter: parent.verticalCenter;
            }
        }
Gus Grubba's avatar
Gus Grubba committed
773
        property var  flightPermit: QGroundControl.airmapSupported ? QGroundControl.airspaceManager.flightPlan.flightPermitStatus : null
774
        property string  providerName: QGroundControl.airspaceManager.providerName
775 776
    }

777
    //-- Checklist GUI
778 779 780 781
    Popup {
        id:             checklistDropPanel
        x:              Math.round((mainWindow.width  - width)  * 0.5)
        y:              Math.round((mainWindow.height - height) * 0.5)
Gus Grubba's avatar
Gus Grubba committed
782 783
        height:         checkList.height
        width:          checkList.width
784 785 786 787
        modal:          true
        focus:          true
        closePolicy:    Popup.CloseOnEscape | Popup.CloseOnPressOutside
        background: Rectangle {
788 789 790
            anchors.fill:  parent
            color:      Qt.rgba(0,0,0,0)
            clip:       true
791
        }
792

793 794 795
        Loader {
            id:         checkList
            anchors.centerIn: parent
796
        }
797 798 799 800 801 802 803 804 805 806 807 808

        property alias checkListItem: checkList.item

        Connections {
            target: checkList.item
            onAllChecksPassedChanged: {
                if (target.allChecksPassed)
                {
                    checklistPopupTimer.restart()
                }
            }
        }
809
    }
810

811
}