MissionEditor.qml 35.1 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
    property int    _currentMissionIndex:   0
52 53
    property bool   _firstVehiclePosition:  true
    property var    activeVehiclePosition:  _activeVehicle ? _activeVehicle.coordinate : QtPositioning.coordinate()
54
    property bool   _lightWidgetBorders:    editorMap.isSatelliteMap
55

56
    onActiveVehiclePositionChanged: updateMapToVehiclePosition()
57

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

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

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

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

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

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

    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
    }

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

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

121
                if (missionItem.specifiesCoordinate && !missionItem.isStandaloneCoordinate) {
122 123 124 125 126 127 128 129
                    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)
                }
130
            }
131
            editorMap.visibleRegion = QtPositioning.rectangle(QtPositioning.coordinate(north - 90.0, west - 180.0), QtPositioning.coordinate(south - 90.0, east - 180.0))
132 133 134
        }
    }

135
    MissionController {
136
        id:         controller
137

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

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

146 147 148
        autoSync:   QGroundControl.flightMapSettings.loadMapSetting(editorMap.mapName, _autoSyncKey, true)

        onAutoSyncChanged:      QGroundControl.flightMapSettings.saveMapSetting(editorMap.mapName, _autoSyncKey, autoSync)
149
*/
150

151
        onVisualItemsChanged: itemDragger.clearItem()
152
        onNewItemsFromVehicle: fitViewportToMissionItems()
153
    }
154

155
    QGCPalette { id: qgcPal; colorGroupEnabled: enabled }
Don Gagne's avatar
Don Gagne committed
156

157 158 159 160 161 162
    ExclusiveGroup {
        id: _mapTypeButtonsExclusiveGroup
    }

    ExclusiveGroup {
        id: _dropButtonsExclusiveGroup
163 164
    }

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

179 180
    property int _moveDialogMissionItemIndex

181 182 183
    Component {
        id: mobileFilePicker

Don Gagne's avatar
Don Gagne committed
184 185 186 187 188 189 190
        QGCMobileFileDialog {
            openDialog:     true
            fileExtension:  QGroundControl.missionFileExtension

            onFilenameReturned: {
                controller.loadMissionFromFile(filename)
                fitViewportToMissionItems()
191
                _currentMissionItem = _visualItems.get(0)
192 193 194 195 196 197 198
            }
        }
    }

    Component {
        id: mobileFileSaver

Don Gagne's avatar
Don Gagne committed
199 200 201
        QGCMobileFileDialog {
            openDialog:     false
            fileExtension:  QGroundControl.missionFileExtension
202

Don Gagne's avatar
Don Gagne committed
203 204
            onFilenameReturned: {
                controller.saveMissionToFile(filename)
205 206 207 208
            }
        }
    }

209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
    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
232
                    text:           qsTr("Move the selected mission item to the be after following mission item:")
233 234 235 236
                }

                QGCComboBox {
                    id:             toCombo
237
                    model:          _visualItems.count
238 239 240 241 242 243
                    currentIndex:   _moveDialogMissionItemIndex
                }
            }
        }
    }

Don Gagne's avatar
Don Gagne committed
244 245
    QGCViewPanel {
        id:             panel
246 247 248 249
        height:         ScreenTools.availableHeight
        anchors.bottom: parent.bottom
        anchors.left:   parent.left
        anchors.right:  parent.right
Don Gagne's avatar
Don Gagne committed
250

Don Gagne's avatar
Don Gagne committed
251
        Item {
Don Gagne's avatar
Don Gagne committed
252 253
            anchors.fill: parent

Don Gagne's avatar
Don Gagne committed
254 255
            FlightMap {
                id:             editorMap
256 257 258 259
                height:         _root.height
                anchors.bottom: parent.bottom
                anchors.left:   parent.left
                anchors.right:  parent.right
Don Gagne's avatar
Don Gagne committed
260
                mapName:        "MissionEditor"
261

262 263
                signal mapClicked(var coordinate)

264 265
                readonly property real animationDuration: 500

266 267 268
                // Initial map position duplicates Fly view position
                Component.onCompleted: editorMap.center = QGroundControl.flightMapPosition

269 270 271 272 273 274 275
                Behavior on zoomLevel {
                    NumberAnimation {
                        duration:       editorMap.animationDuration
                        easing.type:    Easing.InOutQuad
                    }
                }

Don Gagne's avatar
Don Gagne committed
276
                MouseArea {
277 278
                    //-- 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
279 280
                    anchors.fill: parent
                    onClicked: {
281 282 283 284 285 286 287 288 289 290 291 292 293
                        //-- 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)
                            }
294
                        }
Don Gagne's avatar
Don Gagne committed
295
                    }
Don Gagne's avatar
Don Gagne committed
296
                }
Don Gagne's avatar
Don Gagne committed
297

298
                // We use this item to support dragging since dragging a MapQuickItem just doesn't seem to work
Don Gagne's avatar
Don Gagne committed
299 300 301 302
                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
303 304
                    width:          ScreenTools.defaultFontPixelHeight * 2
                    height:         ScreenTools.defaultFontPixelHeight * 2
Don Gagne's avatar
Don Gagne committed
305 306 307
                    color:          "transparent"
                    visible:        false
                    z:              QGroundControl.zOrderMapItems + 1    // Above item icons
308 309 310

                    property var    missionItem
                    property var    missionItemIndicator
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
                    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
326

327
                    function clearItem() {
Don Gagne's avatar
Don Gagne committed
328 329 330 331 332
                        itemDragger.visible = false
                        itemDragger.missionItem = undefined
                        itemDragger.missionItemIndicator = undefined
                    }

333 334 335 336 337 338 339 340
                    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
341 342 343 344
                        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
345
                    }
346
                }
347

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

358 359 360 361 362 363 364 365 366 367
                // Add the complex mission item grid to the map
                MapItemView {
                    model: controller.complexVisualItems

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

368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
                // 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
384 385
                }

386 387 388 389 390 391
                // Add the simple mission items to the map
                MapItemView {
                    model:      controller.visualItems
                    delegate:   missionItemComponent
                }

Don Gagne's avatar
Don Gagne committed
392
                Component {
393
                    id: missionItemComponent
Don Gagne's avatar
Don Gagne committed
394 395 396 397

                    MissionItemIndicator {
                        id:             itemIndicator
                        coordinate:     object.coordinate
398
                        visible:        object.specifiesCoordinate
Don Gagne's avatar
Don Gagne committed
399
                        z:              QGroundControl.zOrderMapItems
400
                        missionItem:    object
401
                        sequenceNumber: object.sequenceNumber
Don Gagne's avatar
Don Gagne committed
402

403 404 405
                        //-- 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
406 407
                        onClicked: setCurrentItem(object.sequenceNumber)

408 409
                        function updateItemIndicator() {
                            if (object.isCurrentItem && itemIndicator.visible && object.specifiesCoordinate && object.isSimpleItem) {
410 411 412 413
                                // 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
414 415 416
                            }
                        }

417 418 419
                        Connections {
                            target: object

420 421
                            onIsCurrentItemChanged:         updateItemIndicator()
                            onSpecifiesCoordinateChanged:   updateItemIndicator()
422 423
                        }

Don Gagne's avatar
Don Gagne committed
424 425 426 427 428 429 430 431 432
                        // 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 {
433
                                    label:          object.abbreviation
Don Gagne's avatar
Don Gagne committed
434 435 436 437 438 439 440 441
                                    isCurrentItem:  object.isCurrentItem
                                    z:              2

                                    onClicked: setCurrentItem(object.sequenceNumber)
                                }
                            }
                        }
                    }
442 443 444
                }

                // Add lines between waypoints
445 446
                MissionLineView {
                    model:          controller.waypointLines
Don Gagne's avatar
Don Gagne committed
447 448
                }

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

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

Don Gagne's avatar
Don Gagne committed
472 473 474 475 476 477 478
                    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
                     }

479
                    ListView {
480 481 482 483
                        id:             editorListView
                        anchors.left:   parent.left
                        anchors.right:  parent.right
                        anchors.top:    parent.top
484
                        height:         parent.height
485 486
                        spacing:        _margin / 2
                        orientation:    ListView.Vertical
487
                        model:          controller.visualItems
488
                        cacheBuffer:    height * 2
489
                        clip:           true
490
                        currentIndex:   _currentMissionIndex
491 492
                        highlightMoveDuration: 250

493
                        delegate: MissionItemEditor {
494 495
                            missionItem:    object
                            width:          parent.width
Don Gagne's avatar
Don Gagne committed
496
                            qgcView:        _root
497
                            readOnly:       false
498 499 500 501

                            onClicked:  setCurrentItem(object.sequenceNumber)

                            onRemove: {
502
                                itemDragger.clearItem()
haigithub's avatar
haigithub committed
503
                                controller.removeMissionItem(index)
504 505
                            }

506
                            onInsert: {
507
                                var sequenceNumber = controller.insertSimpleMissionItem(editorMap.center, insertAfterIndex)
508 509 510
                                setCurrentItem(sequenceNumber)
                            }

511
                            onMoveHomeToMapCenter: controller.visualItems.get(0).coordinate = editorMap.center
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