MissionEditor.qml 35 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.
 *
 ****************************************************************************/
Don Gagne's avatar
Don Gagne committed
9 10


Don Gagne's avatar
Don Gagne committed
11 12 13 14 15
import QtQuick          2.4
import QtQuick.Controls 1.3
import QtQuick.Dialogs  1.2
import QtLocation       5.3
import QtPositioning    5.3
dogmaphobic's avatar
dogmaphobic committed
16
import QtQuick.Layouts  1.2
Don Gagne's avatar
Don Gagne committed
17

18
import QGroundControl               1.0
Don Gagne's avatar
Don Gagne committed
19 20 21 22
import QGroundControl.FlightMap     1.0
import QGroundControl.ScreenTools   1.0
import QGroundControl.Controls      1.0
import QGroundControl.Palette       1.0
Don Gagne's avatar
Don Gagne committed
23
import QGroundControl.Mavlink       1.0
24
import QGroundControl.Controllers   1.0
Don Gagne's avatar
Don Gagne committed
25 26

/// Mission Editor
Don Gagne's avatar
Don Gagne committed
27

Don Gagne's avatar
Don Gagne committed
28
QGCView {
29 30
    id:         _root

31
    property bool syncNeeded: controller.visualItems.dirty // Unsaved changes, visible to parent container
32

33
    viewPanel:          panel
Don Gagne's avatar
Don Gagne committed
34

35
    // zOrder comes from the Loader in MainWindow.qml
Gus Grubba's avatar
Gus Grubba committed
36
    z: QGroundControl.zOrderTopMost
37

38
    readonly property int       _decimalPlaces:     8
39
    readonly property real      _horizontalMargin:  ScreenTools.defaultFontPixelWidth  / 2
dogmaphobic's avatar
dogmaphobic committed
40
    readonly property real      _margin:            ScreenTools.defaultFontPixelHeight * 0.5
41
    readonly property var       _activeVehicle:     QGroundControl.multiVehicleManager.activeVehicle
Don Gagne's avatar
Don Gagne committed
42
    readonly property real      _rightPanelWidth:   Math.min(parent.width / 3, ScreenTools.defaultFontPixelWidth * 30)
43 44 45 46
    readonly property real      _rightPanelOpacity: 0.8
    readonly property int       _toolButtonCount:   6
    readonly property string    _autoSyncKey:       "AutoSync"
    readonly property int       _addMissionItemsButtonAutoOffTimeout:   10000
47
    readonly property var       _defaultVehicleCoordinate:   QtPositioning.coordinate(37.803784, -122.462276)
48

49
    property var    _visualItems:          controller.visualItems
Don Gagne's avatar
Don Gagne committed
50
    property var    _currentMissionItem
51 52
    property bool   _firstVehiclePosition:  true
    property var    activeVehiclePosition:  _activeVehicle ? _activeVehicle.coordinate : QtPositioning.coordinate()
53
    property bool   _lightWidgetBorders:    editorMap.isSatelliteMap
54

55
    onActiveVehiclePositionChanged: updateMapToVehiclePosition()
56

57
    Connections {
58
        target: QGroundControl.multiVehicleManager
59 60 61 62 63 64

        onActiveVehicleChanged: {
            // When the active vehicle changes we need to allow the first vehicle position to move the map again
            _firstVehiclePosition = true
            updateMapToVehiclePosition()
        }
65
    }
66 67

    function updateMapToVehiclePosition() {
68
        if (_activeVehicle && _activeVehicle.coordinateValid && _activeVehicle.coordinate.isValid && _firstVehiclePosition) {
69 70
            _firstVehiclePosition = false
            editorMap.center = _activeVehicle.coordinate
71 72 73
        }
    }

74 75 76 77 78
    function loadFromVehicle() {
        controller.getMissionItems()
    }

    function loadFromFile() {
79
        if (ScreenTools.isMobile) {
80
            _root.showDialog(mobileFilePicker, qsTr("Select Mission File"), _root.showDialogDefaultWidth, StandardButton.Yes | StandardButton.Cancel)
81
        } else {
Don Gagne's avatar
Don Gagne committed
82
            controller.loadMissionFromFilePicker()
83 84 85 86 87 88
            fitViewportToMissionItems()
        }
    }

    function saveToFile() {
        if (ScreenTools.isMobile) {
89
            _root.showDialog(mobileFileSaver, qsTr("Save Mission File"), _root.showDialogDefaultWidth, StandardButton.Save | StandardButton.Cancel)
90
        } else {
Don Gagne's avatar
Don Gagne committed
91
            controller.saveMissionToFilePicker()
92
        }
93 94 95 96 97 98 99 100 101 102 103 104
    }

    function normalizeLat(lat) {
        // Normalize latitude to range: 0 to 180, S to N
        return lat + 90.0
    }

    function normalizeLon(lon) {
        // Normalize longitude to range: 0 to 360, W to E
        return lon  + 180.0
    }

105
    /// Fix the map viewport to the current mission items.
106
    function fitViewportToMissionItems() {
107 108
        if (_visualItems.count == 1) {
            editorMap.center = _visualItems.get(0).coordinate
109
        } else {
110
            var missionItem = _visualItems.get(0)
111 112 113 114 115
            var north = normalizeLat(missionItem.coordinate.latitude)
            var south = north
            var east = normalizeLon(missionItem.coordinate.longitude)
            var west = east

116 117
            for (var i=1; i<_visualItems.count; i++) {
                missionItem = _visualItems.get(i)
118

119
                if (missionItem.specifiesCoordinate && !missionItem.isStandaloneCoordinate) {
120 121 122 123 124 125 126 127
                    var lat = normalizeLat(missionItem.coordinate.latitude)
                    var lon = normalizeLon(missionItem.coordinate.longitude)

                    north = Math.max(north, lat)
                    south = Math.min(south, lat)
                    east = Math.max(east, lon)
                    west = Math.min(west, lon)
                }
128
            }
129
            editorMap.visibleRegion = QtPositioning.rectangle(QtPositioning.coordinate(north - 90.0, west - 180.0), QtPositioning.coordinate(south - 90.0, east - 180.0))
130 131 132
        }
    }

133
    MissionController {
134
        id:         controller
135

136 137
        Component.onCompleted: {
            start(true /* editMode */)
138
            setCurrentItem(0)
139 140
        }

Don Gagne's avatar
Don Gagne committed
141
        /*
142 143
        FIXME: autoSync is temporarily disconnected since it's still buggy

144 145 146
        autoSync:   QGroundControl.flightMapSettings.loadMapSetting(editorMap.mapName, _autoSyncKey, true)

        onAutoSyncChanged:      QGroundControl.flightMapSettings.saveMapSetting(editorMap.mapName, _autoSyncKey, autoSync)
147
*/
148

149
        onVisualItemsChanged: itemDragger.clearItem()
150
        onNewItemsFromVehicle: fitViewportToMissionItems()
151
    }
152

153
    QGCPalette { id: qgcPal; colorGroupEnabled: enabled }
Don Gagne's avatar
Don Gagne committed
154

155 156 157 158 159 160
    ExclusiveGroup {
        id: _mapTypeButtonsExclusiveGroup
    }

    ExclusiveGroup {
        id: _dropButtonsExclusiveGroup
161 162
    }

163
    function setCurrentItem(sequenceNumber) {
Don Gagne's avatar
Don Gagne committed
164
        _currentMissionItem = undefined
165
        for (var i=0; i<_visualItems.count; i++) {
166 167 168
            var visualItem = _visualItems.get(i)
            if (visualItem.sequenceNumber == sequenceNumber) {
                _currentMissionItem = visualItem
Don Gagne's avatar
Don Gagne committed
169 170
                _currentMissionItem.isCurrentItem = true
            } else {
171
                visualItem.isCurrentItem = false
Don Gagne's avatar
Don Gagne committed
172
            }
173 174 175
        }
    }

176 177
    property int _moveDialogMissionItemIndex

178 179 180
    Component {
        id: mobileFilePicker

Don Gagne's avatar
Don Gagne committed
181 182 183 184 185 186 187
        QGCMobileFileDialog {
            openDialog:     true
            fileExtension:  QGroundControl.missionFileExtension

            onFilenameReturned: {
                controller.loadMissionFromFile(filename)
                fitViewportToMissionItems()
188 189 190 191 192 193 194
            }
        }
    }

    Component {
        id: mobileFileSaver

Don Gagne's avatar
Don Gagne committed
195 196 197
        QGCMobileFileDialog {
            openDialog:     false
            fileExtension:  QGroundControl.missionFileExtension
198

Don Gagne's avatar
Don Gagne committed
199 200
            onFilenameReturned: {
                controller.saveMissionToFile(filename)
201 202 203 204
            }
        }
    }

205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
    Component {
        id: moveDialog

        QGCViewDialog {
            function accept() {
                var toIndex = toCombo.currentIndex

                if (toIndex == 0) {
                    toIndex = 1
                }
                controller.moveMissionItem(_moveDialogMissionItemIndex, toIndex)
                hideDialog()
            }

            Column {
                anchors.left:   parent.left
                anchors.right:  parent.right
                spacing:        ScreenTools.defaultFontPixelHeight

                QGCLabel {
                    anchors.left:   parent.left
                    anchors.right:  parent.right
                    wrapMode:       Text.WordWrap
228
                    text:           qsTr("Move the selected mission item to the be after following mission item:")
229 230 231 232
                }

                QGCComboBox {
                    id:             toCombo
233
                    model:          _visualItems.count
234 235 236 237 238 239
                    currentIndex:   _moveDialogMissionItemIndex
                }
            }
        }
    }

Don Gagne's avatar
Don Gagne committed
240 241
    QGCViewPanel {
        id:             panel
242 243 244 245
        height:         ScreenTools.availableHeight
        anchors.bottom: parent.bottom
        anchors.left:   parent.left
        anchors.right:  parent.right
Don Gagne's avatar
Don Gagne committed
246

Don Gagne's avatar
Don Gagne committed
247
        Item {
Don Gagne's avatar
Don Gagne committed
248 249
            anchors.fill: parent

Don Gagne's avatar
Don Gagne committed
250 251
            FlightMap {
                id:             editorMap
252 253 254 255
                height:         _root.height
                anchors.bottom: parent.bottom
                anchors.left:   parent.left
                anchors.right:  parent.right
Don Gagne's avatar
Don Gagne committed
256
                mapName:        "MissionEditor"
257

258 259
                signal mapClicked(var coordinate)

260 261
                readonly property real animationDuration: 500

262 263 264
                // Initial map position duplicates Fly view position
                Component.onCompleted: editorMap.center = QGroundControl.flightMapPosition

265 266 267 268 269 270 271
                Behavior on zoomLevel {
                    NumberAnimation {
                        duration:       editorMap.animationDuration
                        easing.type:    Easing.InOutQuad
                    }
                }

Don Gagne's avatar
Don Gagne committed
272
                MouseArea {
273 274
                    //-- It's a whole lot faster to just fill parent and deal with top offset below
                    //   than computing the coordinate offset.
Don Gagne's avatar
Don Gagne committed
275 276
                    anchors.fill: parent
                    onClicked: {
277 278 279 280 281 282 283 284 285 286 287 288 289
                        //-- Don't pay attention to items beneath the toolbar.
                        var topLimit = parent.height - ScreenTools.availableHeight
                        if(mouse.y >= topLimit) {
                            var coordinate = editorMap.toCoordinate(Qt.point(mouse.x, mouse.y))
                            coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces)
                            coordinate.longitude = coordinate.longitude.toFixed(_decimalPlaces)
                            coordinate.altitude = coordinate.altitude.toFixed(_decimalPlaces)
                            if (addMissionItemsButton.checked) {
                                var sequenceNumber = controller.insertSimpleMissionItem(coordinate, controller.visualItems.count)
                                setCurrentItem(sequenceNumber)
                            } else {
                                editorMap.mapClicked(coordinate)
                            }
290
                        }
Don Gagne's avatar
Don Gagne committed
291
                    }
Don Gagne's avatar
Don Gagne committed
292
                }
Don Gagne's avatar
Don Gagne committed
293

294
                // We use this item to support dragging since dragging a MapQuickItem just doesn't seem to work
Don Gagne's avatar
Don Gagne committed
295 296 297 298
                Rectangle {
                    id:             itemDragger
                    x:              missionItemIndicator ? (missionItemIndicator.x + missionItemIndicator.anchorPoint.x - (itemDragger.width / 2)) : 100
                    y:              missionItemIndicator ? (missionItemIndicator.y + missionItemIndicator.anchorPoint.y - (itemDragger.height / 2)) : 100
299 300
                    width:          ScreenTools.defaultFontPixelHeight * 2
                    height:         ScreenTools.defaultFontPixelHeight * 2
Don Gagne's avatar
Don Gagne committed
301 302 303
                    color:          "transparent"
                    visible:        false
                    z:              QGroundControl.zOrderMapItems + 1    // Above item icons
304 305 306

                    property var    missionItem
                    property var    missionItemIndicator
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
                    property bool   preventCoordinateBindingLoop: false

                    onXChanged: liveDrag()
                    onYChanged: liveDrag()

                    function liveDrag() {
                        if (!itemDragger.preventCoordinateBindingLoop && Drag.active) {
                            var point = Qt.point(itemDragger.x + (itemDragger.width  / 2), itemDragger.y + (itemDragger.height / 2))
                            var coordinate = editorMap.toCoordinate(point)
                            coordinate.altitude = itemDragger.missionItem.coordinate.altitude
                            itemDragger.preventCoordinateBindingLoop = true
                            itemDragger.missionItem.coordinate = coordinate
                            itemDragger.preventCoordinateBindingLoop = false
                        }
                    }
Don Gagne's avatar
Don Gagne committed
322

323
                    function clearItem() {
Don Gagne's avatar
Don Gagne committed
324 325 326 327 328
                        itemDragger.visible = false
                        itemDragger.missionItem = undefined
                        itemDragger.missionItemIndicator = undefined
                    }

329 330 331 332 333 334 335 336
                    Drag.active:    itemDrag.drag.active
                    Drag.hotSpot.x: width  / 2
                    Drag.hotSpot.y: height / 2

                    MouseArea {
                        id:             itemDrag
                        anchors.fill:   parent
                        drag.target:    parent
Don Gagne's avatar
Don Gagne committed
337 338 339 340
                        drag.minimumX:  0
                        drag.minimumY:  0
                        drag.maximumX:  itemDragger.parent.width - parent.width
                        drag.maximumY:  itemDragger.parent.height - parent.height
Don Gagne's avatar
Don Gagne committed
341
                    }
342
                }
343

344
                // Add the complex mission item polygon to the map
345
                MapItemView {
Don Gagne's avatar
Don Gagne committed
346 347
                    model: controller.complexVisualItems
                    delegate: MapPolygon {
348 349 350 351 352 353
                        color:      'green'
                        path:       object.polygonPath
                        opacity:    0.5
                    }
                }

354 355 356 357 358 359 360 361 362 363
                // Add the complex mission item grid to the map
                MapItemView {
                    model: controller.complexVisualItems

                    delegate: MapPolyline {
                        line.color: "white"
                        path:       object.gridPoints
                    }
                }

364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
                // Add the complex mission item exit coordinates
                MapItemView {
                    model:      controller.complexVisualItems
                    delegate:   exitCoordinateComponent
                }

                Component {
                    id: exitCoordinateComponent

                    MissionItemIndicator {
                        coordinate:     object.exitCoordinate
                        z:              QGroundControl.zOrderMapItems
                        missionItem:    object
                        sequenceNumber: object.lastSequenceNumber
                        visible:        object.specifiesCoordinate
                    }
Don Gagne's avatar
Don Gagne committed
380 381
                }

382 383 384 385 386 387
                // Add the simple mission items to the map
                MapItemView {
                    model:      controller.visualItems
                    delegate:   missionItemComponent
                }

Don Gagne's avatar
Don Gagne committed
388
                Component {
389
                    id: missionItemComponent
Don Gagne's avatar
Don Gagne committed
390 391 392 393

                    MissionItemIndicator {
                        id:             itemIndicator
                        coordinate:     object.coordinate
394
                        visible:        object.specifiesCoordinate
Don Gagne's avatar
Don Gagne committed
395
                        z:              QGroundControl.zOrderMapItems
396
                        missionItem:    object
397
                        sequenceNumber: object.sequenceNumber
Don Gagne's avatar
Don Gagne committed
398

399 400 401
                        //-- If you don't want to allow selecting items beneath the
                        //   toolbar, the code below has to check and see if mouse.y
                        //   is greater than (map.height - ScreenTools.availableHeight)
Don Gagne's avatar
Don Gagne committed
402 403
                        onClicked: setCurrentItem(object.sequenceNumber)

404 405
                        function updateItemIndicator() {
                            if (object.isCurrentItem && itemIndicator.visible && object.specifiesCoordinate && object.isSimpleItem) {
406 407 408 409
                                // Setup our drag item
                                itemDragger.visible = true
                                itemDragger.missionItem = Qt.binding(function() { return object })
                                itemDragger.missionItemIndicator = Qt.binding(function() { return itemIndicator })
Don Gagne's avatar
Don Gagne committed
410 411 412
                            }
                        }

413 414 415
                        Connections {
                            target: object

416 417
                            onIsCurrentItemChanged:         updateItemIndicator()
                            onSpecifiesCoordinateChanged:   updateItemIndicator()
418 419
                        }

Don Gagne's avatar
Don Gagne committed
420 421 422 423 424 425 426 427 428
                        // These are the non-coordinate child mission items attached to this item
                        Row {
                            anchors.top:    parent.top
                            anchors.left:   parent.right

                            Repeater {
                                model: object.childItems

                                delegate: MissionItemIndexLabel {
429
                                    label:          object.abbreviation
Don Gagne's avatar
Don Gagne committed
430 431 432 433 434 435 436 437
                                    isCurrentItem:  object.isCurrentItem
                                    z:              2

                                    onClicked: setCurrentItem(object.sequenceNumber)
                                }
                            }
                        }
                    }
438 439 440
                }

                // Add lines between waypoints
441 442
                MissionLineView {
                    model:          controller.waypointLines
Don Gagne's avatar
Don Gagne committed
443 444
                }

Don Gagne's avatar
Don Gagne committed
445 446
                // Add the vehicles to the map
                MapItemView {
447
                    model: QGroundControl.multiVehicleManager.vehicles
Don Gagne's avatar
Don Gagne committed
448 449 450 451 452 453 454 455 456 457
                    delegate:
                        VehicleMapItem {
                                vehicle:        object
                                coordinate:     object.coordinate
                                isSatellite:    editorMap.isSatelliteMap
                                size:           ScreenTools.defaultFontPixelHeight * 5
                                z:              QGroundControl.zOrderMapItems - 1
                        }
                }

458
                // Mission Item Editor
Don Gagne's avatar
Don Gagne committed
459
                Item {
460
                    id:             missionItemEditor
461
                    height:         ScreenTools.availableHeight
462 463 464 465
                    anchors.bottom: parent.bottom
                    anchors.right:  parent.right
                    width:          _rightPanelWidth
                    opacity:        _rightPanelOpacity
Gus Grubba's avatar
Gus Grubba committed
466
                    z:              QGroundControl.zOrderTopMost
467

Don Gagne's avatar
Don Gagne committed
468 469 470 471 472 473 474
                    MouseArea {
                         // This MouseArea prevents the Map below it from getting Mouse events. Without this
                         // things like mousewheel will scroll the Flickable and then scroll the map as well.
                         anchors.fill:       editorListView
                         onWheel:            wheel.accepted = true
                     }

475
                    ListView {
476 477 478 479
                        id:             editorListView
                        anchors.left:   parent.left
                        anchors.right:  parent.right
                        anchors.top:    parent.top
480
                        height:         parent.height
481 482
                        spacing:        _margin / 2
                        orientation:    ListView.Vertical
483
                        model:          controller.visualItems
484
                        cacheBuffer:    height * 2
485
                        clip:           true
486 487
                        highlightMoveDuration: 250

488
                        delegate: MissionItemEditor {
489 490
                            missionItem:    object
                            width:          parent.width
Don Gagne's avatar
Don Gagne committed
491
                            qgcView:        _root
492
                            readOnly:       false
493 494 495 496

                            onClicked:  setCurrentItem(object.sequenceNumber)

                            onRemove: {
497
                                itemDragger.clearItem()
haigithub's avatar
haigithub committed
498
                                controller.removeMissionItem(index)
499 500
                            }

501
                            onMoveHomeToMapCenter: controller.visualItems.get(0).coordinate = editorMap.center
Don Gagne's avatar
Don Gagne committed
502 503 504 505 506 507

                            Connections {
                                target: object

                                onIsCurrentItemChanged: {
                                    if (object.isCurrentItem) {
508
                                        editorListView.currentIndex = index
Don Gagne's avatar
Don Gagne committed
509 510 511
                                    }
                                }
                            }
512
                        }
513 514 515
                    } // ListView
                } // Item - Mission Item editor

516 517 518 519 520 521 522 523 524 525 526 527 528
                //-- Dismiss Drop Down (if any)
                MouseArea {
                    anchors.fill:   parent
                    enabled:        _dropButtonsExclusiveGroup.current != null
                    onClicked: {
                        if(_dropButtonsExclusiveGroup.current)
                            _dropButtonsExclusiveGroup.current.checked = false
                        _dropButtonsExclusiveGroup.current = null
                    }
                }

                //-- Vertical Tool Buttons
                Column {
529
                    id:                 toolColumn
530
                    anchors.topMargin:  parent.height - ScreenTools.availableHeight + ScreenTools.defaultFontPixelHeight
531 532 533 534
                    anchors.margins:    ScreenTools.defaultFontPixelHeight
                    anchors.left:       parent.left
                    anchors.top:        parent.top
                    spacing:            ScreenTools.defaultFontPixelHeight
Don Gagne's avatar
Don Gagne committed
535
                    z:                  QGroundControl.zOrderWidgets
536 537

                    RoundButton {
538 539 540
                        id:             addMissionItemsButton
                        buttonImage:    "/qmlimages/MapAddMission.svg"
                        lightBorders:   _lightWidgetBorders
541 542
                    }

543
                    RoundButton {
544 545 546 547
                        id:             addShapeButton
                        buttonImage:    "/qmlimages/MapDrawShape.svg"
                        visible:        QGroundControl.experimentalSurvey
                        lightBorders:   _lightWidgetBorders
548 549 550 551 552 553

                        onClicked: {
                            var coordinate = editorMap.center
                            coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces)
                            coordinate.longitude = coordinate.longitude.toFixed(_decimalPlaces)
                            coordinate.altitude = coordinate.altitude.toFixed(_decimalPlaces)
554 555
                            var sequenceNumber = controller.insertComplexMissionItem(coordinate, controller.visualItems.count)
                            setCurrentItem(sequenceNumber)
556
                            checked = false
557
                            addMissionItemsButton.checked = false
558 559 560
                        }
                    }

561 562 563
                    DropButton {
                        id:                 syncButton
                        dropDirection:      dropRight
564
                        buttonImage:        syncNeeded ? "/qmlimages/MapSyncChanged.svg" : "/qmlimages/MapSync.svg"
565 566 567
                        viewportMargins:    ScreenTools.defaultFontPixelWidth / 2
                        exclusiveGroup:     _dropButtonsExclusiveGroup
                        dropDownComponent:  syncDropDownComponent
568 569
                        enabled:            !controller.syncInProgress
                        rotateImage:        controller.syncInProgress
570
                        lightBorders:       _lightWidgetBorders
571 572
                    }

573 574 575 576 577 578
                    DropButton {
                        id:                 centerMapButton
                        dropDirection:      dropRight
                        buttonImage:        "/qmlimages/MapCenter.svg"
                        viewportMargins:    ScreenTools.defaultFontPixelWidth / 2
                        exclusiveGroup:     _dropButtonsExclusiveGroup
579
                        lightBorders:       _lightWidgetBorders
580

581 582
                        dropDownComponent: Component {
                            Column {
dogmaphobic's avatar
dogmaphobic committed
583
                                spacing: ScreenTools.defaultFontPixelWidth * 0.5
584
                                QGCLabel { text: qsTr("Center map:") }
585 586 587
                                Row {
                                    spacing: ScreenTools.defaultFontPixelWidth
                                    QGCButton {
588
                                        text: qsTr("Home")
dogmaphobic's avatar
dogmaphobic committed
589
                                        width:  ScreenTools.defaultFontPixelWidth * 10
590 591
                                        onClicked: {
                                            centerMapButton.hideDropDown()
592
                                            editorMap.center = controller.visualItems.get(0).coordinate
593
                                        }
594
                                    }
595
                                    QGCButton {
596
                                        text: qsTr("Mission")
dogmaphobic's avatar
dogmaphobic committed
597
                                        width:  ScreenTools.defaultFontPixelWidth * 10
598 599 600 601
                                        onClicked: {
                                            centerMapButton.hideDropDown()
                                            fitViewportToMissionItems()
                                        }
602
                                    }
603
                                    QGCButton {
604
                                        text:       qsTr("Vehicle")
dogmaphobic's avatar
dogmaphobic committed
605
                                        width:      ScreenTools.defaultFontPixelWidth * 10
606
                                        enabled:    activeVehicle && activeVehicle.latitude != 0 && activeVehicle.longitude != 0
607
                                        property var activeVehicle: _activeVehicle
608 609
                                        onClicked: {
                                            centerMapButton.hideDropDown()
610
                                            editorMap.center = activeVehicle.coordinate
611
                                        }
612 613 614 615 616 617
                                    }
                                }
                            }
                        }
                    }

618 619 620 621 622 623
                    DropButton {
                        id:                 mapTypeButton
                        dropDirection:      dropRight
                        buttonImage:        "/qmlimages/MapType.svg"
                        viewportMargins:    ScreenTools.defaultFontPixelWidth / 2
                        exclusiveGroup:     _dropButtonsExclusiveGroup
624
                        lightBorders:       _lightWidgetBorders
625 626 627

                        dropDownComponent: Component {
                            Column {
dogmaphobic's avatar
dogmaphobic committed
628
                                spacing: _margin
629
                                QGCLabel { text: qsTr("Map type:") }
630 631 632 633
                                Row {
                                    spacing: ScreenTools.defaultFontPixelWidth
                                    Repeater {
                                        model: QGroundControl.flightMapSettings.mapTypes
634

635 636
                                        QGCButton {
                                            checkable:      true
637
                                            checked:        QGroundControl.flightMapSettings.mapType === text
638 639 640
                                            text:           modelData
                                            exclusiveGroup: _mapTypeButtonsExclusiveGroup
                                            onClicked: {
641
                                                QGroundControl.flightMapSettings.mapType = text
642 643 644
                                                checked = true
                                                mapTypeButton.hideDropDown()
                                            }
645 646 647 648 649 650 651
                                        }
                                    }
                                }
                            }
                        }
                    }

652 653
                    //-- Zoom Map In
                    RoundButton {
654 655 656 657 658
                        id:             mapZoomPlus
                        visible:        !ScreenTools.isTinyScreen && !ScreenTools.isShortScreen
                        buttonImage:    "/qmlimages/ZoomPlus.svg"
                        lightBorders:   _lightWidgetBorders

659 660 661 662 663 664 665 666 667
                        onClicked: {
                            if(editorMap)
                                editorMap.zoomLevel += 0.5
                            checked = false
                        }
                    }

                    //-- Zoom Map Out
                    RoundButton {
668 669 670 671
                        id:             mapZoomMinus
                        visible:        !ScreenTools.isTinyScreen && !ScreenTools.isShortScreen
                        buttonImage:    "/qmlimages/ZoomMinus.svg"
                        lightBorders:   _lightWidgetBorders
672 673 674 675 676 677
                        onClicked: {
                            if(editorMap)
                                editorMap.zoomLevel -= 0.5
                            checked = false
                        }
                    }
678
                }
679

680 681 682 683 684 685 686 687 688
                MapScale {
                    anchors.margins:    ScreenTools.defaultFontPixelHeight * (0.66)
                    anchors.bottom:     waypointValuesDisplay.visible ? waypointValuesDisplay.top : parent.bottom
                    anchors.left:       parent.left
                    z:                  QGroundControl.zOrderWidgets
                    mapControl:         editorMap
                    visible:            !ScreenTools.isTinyScreen
                }

689
                MissionItemStatus {
690
                    id:                 waypointValuesDisplay
691
                    anchors.margins:    ScreenTools.defaultFontPixelWidth
692 693
                    anchors.left:       parent.left
                    anchors.bottom:     parent.bottom
694 695
                    z:                  QGroundControl.zOrderTopMost
                    currentMissionItem: _currentMissionItem
696
                    missionItems:       controller.visualItems
697
                    expandedWidth:      missionItemEditor.x - (ScreenTools.defaultFontPixelWidth * 2)
Don Gagne's avatar
Don Gagne committed
698
                    visible:            !ScreenTools.isShortScreen
699
                }
700
            } // FlightMap
Don Gagne's avatar
Don Gagne committed
701 702
        } // Item - split view container
    } // QGCViewPanel
703

704 705 706 707
    Component {
        id: syncLoadFromVehicleOverwrite
        QGCViewMessage {
            id:         syncLoadFromVehicleCheck
708
            message:   qsTr("You have unsaved/unsent mission changes. Loading the mission from the Vehicle will lose these changes. Are you sure you want to load the mission from the Vehicle?")
709 710
            function accept() {
                hideDialog()
711
                loadFromVehicle()
712 713 714 715 716 717 718 719
            }
        }
    }

    Component {
        id: syncLoadFromFileOverwrite
        QGCViewMessage {
            id:         syncLoadFromVehicleCheck
720
            message:   qsTr("You have unsaved/unsent mission changes. Loading a mission from a file will lose these changes. Are you sure you want to load a mission from a file?")
721 722
            function accept() {
                hideDialog()
723
                loadFromFile()
724 725 726 727
            }
        }
    }

728 729 730
    Component {
        id: removeAllPromptDialog
        QGCViewMessage {
731
            message: qsTr("Are you sure you want to delete all mission items?")
732 733 734 735 736 737 738 739
            function accept() {
                itemDragger.clearItem()
                controller.removeAllMissionItems()
                hideDialog()
            }
        }
    }

740 741 742 743 744 745
    Component {
        id: syncDropDownComponent
        Column {
            id:         columnHolder
            spacing:    _margin
            QGCLabel {
dogmaphobic's avatar
dogmaphobic committed
746
                width:      sendSaveGrid.width
747
                wrapMode:   Text.WordWrap
748
                text:       syncNeeded && !controller.autoSync ?
749 750
                                qsTr("You have unsaved changed to you mission. You should send to your vehicle, or save to a file:") :
                                qsTr("Sync:")
751
            }
dogmaphobic's avatar
dogmaphobic committed
752 753 754 755 756 757 758
            GridLayout {
                id:                 sendSaveGrid
                columns:            2
                anchors.margins:    _margin
                rowSpacing:         _margin
                columnSpacing:      ScreenTools.defaultFontPixelWidth
                visible:            true //autoSyncCheckBox.enabled && autoSyncCheckBox.checked
759
                QGCButton {
dogmaphobic's avatar
dogmaphobic committed
760 761 762
                    text:               qsTr("Send To Vehicle")
                    Layout.fillWidth:   true
                    enabled:            _activeVehicle && !controller.syncInProgress
763 764 765 766 767 768
                    onClicked: {
                        syncButton.hideDropDown()
                        controller.sendMissionItems()
                    }
                }
                QGCButton {
dogmaphobic's avatar
dogmaphobic committed
769 770 771
                    text:               qsTr("Load From Vehicle")
                    Layout.fillWidth:   true
                    enabled:            _activeVehicle && !controller.syncInProgress
772 773
                    onClicked: {
                        syncButton.hideDropDown()
774
                        if (syncNeeded) {
775
                            _root.showDialog(syncLoadFromVehicleOverwrite, qsTr("Mission overwrite"), _root.showDialogDefaultWidth, StandardButton.Yes | StandardButton.Cancel)
776
                        } else {
777
                            loadFromVehicle()
778
                        }
779 780 781
                    }
                }
                QGCButton {
dogmaphobic's avatar
dogmaphobic committed
782 783 784
                    text:               qsTr("Save To File...")
                    Layout.fillWidth:   true
                    enabled:            !controller.syncInProgress
785 786
                    onClicked: {
                        syncButton.hideDropDown()
787
                        saveToFile()
788 789 790
                    }
                }
                QGCButton {
dogmaphobic's avatar
dogmaphobic committed
791 792 793
                    text:               qsTr("Load From File...")
                    Layout.fillWidth:   true
                    enabled:            !controller.syncInProgress
794 795
                    onClicked: {
                        syncButton.hideDropDown()
796
                        if (syncNeeded) {
797
                            _root.showDialog(syncLoadFromFileOverwrite, qsTr("Mission overwrite"), _root.showDialogDefaultWidth, StandardButton.Yes | StandardButton.Cancel)
798
                        } else {
799
                            loadFromFile()
800
                        }
801 802
                    }
                }
dogmaphobic's avatar
dogmaphobic committed
803 804 805 806 807 808 809
                QGCButton {
                    text:               qsTr("Remove All")
                    Layout.fillWidth:   true
                    onClicked:  {
                        syncButton.hideDropDown()
                        _root.showDialog(removeAllPromptDialog, qsTr("Delete all"), _root.showDialogDefaultWidth, StandardButton.Yes | StandardButton.No)
                    }
810 811 812
                }
            }

dogmaphobic's avatar
dogmaphobic committed
813

814 815
/*
        FIXME: autoSync is temporarily disconnected since it's still buggy
816 817 818 819 820 821 822 823 824 825 826 827 828 829 830

            QGCLabel {
                id:         autoSyncDisallowedLabel
                visible:    _activeVehicle && _activeVehicle.armed
                text:       "AutoSync is not allowed whie vehicle is armed"
            }

            QGCCheckBox {
                id:         autoSyncCheckBox
                checked:    controller.autoSync
                text:       "Automatically sync changes with vehicle"
                enabled:    _activeVehicle ? !_activeVehicle.armed : false

                onClicked: controller.autoSync = checked
            }
831
*/
832 833
        }
    }
Don Gagne's avatar
Don Gagne committed
834
} // QGCVIew