MissionEditor.qml 35.2 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
    viewPanel:          panel
Don Gagne's avatar
Don Gagne committed
32

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

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

Don Gagne's avatar
Don Gagne committed
47
    property bool   _syncNeeded:            controller.visualItems.dirty // Unsaved changes, visible to parent container
48
    property var    _visualItems:           controller.visualItems
Don Gagne's avatar
Don Gagne committed
49
    property var    _currentMissionItem
50
    property int    _currentMissionIndex:   0
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
            fitViewportToMissionItems()
84
            _currentMissionItem = _visualItems.get(0)
85 86 87 88 89
        }
    }

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

    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
    }

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

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

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

134
    MissionController {
135
        id:         controller
136

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

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

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

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

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

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

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

    ExclusiveGroup {
        id: _dropButtonsExclusiveGroup
162 163
    }

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

178 179
    property int _moveDialogMissionItemIndex

180 181 182
    Component {
        id: mobileFilePicker

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

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

    Component {
        id: mobileFileSaver

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

Don Gagne's avatar
Don Gagne committed
202 203
            onFilenameReturned: {
                controller.saveMissionToFile(filename)
204 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
    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
231
                    text:           qsTr("Move the selected mission item to the be after following mission item:")
232 233 234 235
                }

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

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

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

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

261 262
                signal mapClicked(var coordinate)

263 264
                readonly property real animationDuration: 500

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

416 417 418
                        Connections {
                            target: object

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

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

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

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

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

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

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

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

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

                            onClicked:  setCurrentItem(object.sequenceNumber)

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

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

510
                            onMoveHomeToMapCenter: controller.visualItems.get(0).coordinate = editorMap.center
511
                        }
512 513 514
                    } // ListView
                } // Item - Mission Item editor

515 516 517 518 519 520 521 522 523 524 525 526 527
                //-- 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 {
528
                    id:                 toolColumn
529
                    anchors.topMargin:  parent.height - ScreenTools.availableHeight + ScreenTools.defaultFontPixelHeight
530 531 532 533
                    anchors.margins:    ScreenTools.defaultFontPixelHeight
                    anchors.left:       parent.left
                    anchors.top:        parent.top
                    spacing:            ScreenTools.defaultFontPixelHeight
Don Gagne's avatar
Don Gagne committed
534
                    z:                  QGroundControl.zOrderWidgets
535 536

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

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

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

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

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

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

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

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

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

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

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

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

679 680 681 682 683 684 685 686 687
                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
                }

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

703 704 705 706
    Component {
        id: syncLoadFromVehicleOverwrite
        QGCViewMessage {
            id:         syncLoadFromVehicleCheck
707
            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?")
708 709
            function accept() {
                hideDialog()
710
                loadFromVehicle()
711 712 713 714 715 716 717 718
            }
        }
    }

    Component {
        id: syncLoadFromFileOverwrite
        QGCViewMessage {
            id:         syncLoadFromVehicleCheck
719
            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?")
720 721
            function accept() {
                hideDialog()
722
                loadFromFile()
723 724 725 726
            }
        }
    }

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

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

dogmaphobic's avatar
dogmaphobic committed
812

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

            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
            }
830
*/
831 832
        }
    }
Don Gagne's avatar
Don Gagne committed
833
} // QGCVIew