MissionEditor.qml 34.9 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
42
    readonly property real      _editFieldWidth:    ScreenTools.defaultFontPixelWidth * 16
Don Gagne's avatar
Don Gagne committed
43
    readonly property real      _rightPanelWidth:   Math.min(parent.width / 3, ScreenTools.defaultFontPixelWidth * 30)
44 45 46 47
    readonly property real      _rightPanelOpacity: 0.8
    readonly property int       _toolButtonCount:   6
    readonly property string    _autoSyncKey:       "AutoSync"
    readonly property int       _addMissionItemsButtonAutoOffTimeout:   10000
48
    readonly property var       _defaultVehicleCoordinate:   QtPositioning.coordinate(37.803784, -122.462276)
49

50
    property var    _visualItems:          controller.visualItems
Don Gagne's avatar
Don Gagne committed
51
    property var    _currentMissionItem
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 85 86 87 88 89
            fitViewportToMissionItems()
        }
    }

    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 171
                _currentMissionItem.isCurrentItem = true
            } else {
172
                visualItem.isCurrentItem = false
Don Gagne's avatar
Don Gagne committed
173
            }
174 175 176
        }
    }

177 178
    property int _moveDialogMissionItemIndex

179 180 181
    Component {
        id: mobileFilePicker

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

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

    Component {
        id: mobileFileSaver

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

Don Gagne's avatar
Don Gagne committed
200 201
            onFilenameReturned: {
                controller.saveMissionToFile(filename)
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 228
    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
229
                    text:           qsTr("Move the selected mission item to the be after following mission item:")
230 231 232 233
                }

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

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

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

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

259 260
                signal mapClicked(var coordinate)

261 262
                readonly property real animationDuration: 500

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

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

Don Gagne's avatar
Don Gagne committed
273
                MouseArea {
274 275
                    //-- 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
276 277
                    anchors.fill: parent
                    onClicked: {
278 279 280 281 282 283 284 285 286 287 288 289 290 291
                        //-- 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)
                                editorListView.positionViewAtIndex(editorListView.count - 1, ListView.Contain)
                            } else {
                                editorMap.mapClicked(coordinate)
                            }
292
                        }
Don Gagne's avatar
Don Gagne committed
293
                    }
Don Gagne's avatar
Don Gagne committed
294
                }
Don Gagne's avatar
Don Gagne committed
295

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

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

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

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

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

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

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

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

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

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

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

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

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

415 416 417
                        Connections {
                            target: object

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

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

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

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

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

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

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

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

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

                            onClicked:  setCurrentItem(object.sequenceNumber)

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

502
                            onInsert: {
503 504
                                var sequenceNumber = controller.insertSimpleMissionItem(editorMap.center, i)
                                setCurrentItem(sequenceNumber)
505
                            }
506

507
                            onMoveHomeToMapCenter: controller.visualItems.get(0).coordinate = editorMap.center
Don Gagne's avatar
Don Gagne committed
508 509 510 511 512 513 514 515 516 517

                            Connections {
                                target: object

                                onIsCurrentItemChanged: {
                                    if (object.isCurrentItem) {
                                        editorListView.positionViewAtIndex(index, ListView.Contain)
                                    }
                                }
                            }
518
                        }
519 520 521
                    } // ListView
                } // Item - Mission Item editor

522 523 524 525 526 527 528 529 530 531 532 533 534
                //-- 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 {
535
                    id:                 toolColumn
536
                    anchors.topMargin:  parent.height - ScreenTools.availableHeight + ScreenTools.defaultFontPixelHeight
537 538 539 540
                    anchors.margins:    ScreenTools.defaultFontPixelHeight
                    anchors.left:       parent.left
                    anchors.top:        parent.top
                    spacing:            ScreenTools.defaultFontPixelHeight
Don Gagne's avatar
Don Gagne committed
541
                    z:                  QGroundControl.zOrderWidgets
542 543

                    RoundButton {
544 545 546
                        id:             addMissionItemsButton
                        buttonImage:    "/qmlimages/MapAddMission.svg"
                        lightBorders:   _lightWidgetBorders
547 548
                    }

549
                    RoundButton {
550 551 552 553
                        id:             addShapeButton
                        buttonImage:    "/qmlimages/MapDrawShape.svg"
                        visible:        QGroundControl.experimentalSurvey
                        lightBorders:   _lightWidgetBorders
554 555 556 557 558 559

                        onClicked: {
                            var coordinate = editorMap.center
                            coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces)
                            coordinate.longitude = coordinate.longitude.toFixed(_decimalPlaces)
                            coordinate.altitude = coordinate.altitude.toFixed(_decimalPlaces)
560 561
                            var sequenceNumber = controller.insertComplexMissionItem(coordinate, controller.visualItems.count)
                            setCurrentItem(sequenceNumber)
562
                            checked = false
563
                            addMissionItemsButton.checked = false
564 565 566
                        }
                    }

567 568 569
                    DropButton {
                        id:                 syncButton
                        dropDirection:      dropRight
570
                        buttonImage:        syncNeeded ? "/qmlimages/MapSyncChanged.svg" : "/qmlimages/MapSync.svg"
571 572 573
                        viewportMargins:    ScreenTools.defaultFontPixelWidth / 2
                        exclusiveGroup:     _dropButtonsExclusiveGroup
                        dropDownComponent:  syncDropDownComponent
574 575
                        enabled:            !controller.syncInProgress
                        rotateImage:        controller.syncInProgress
576
                        lightBorders:       _lightWidgetBorders
577 578
                    }

579 580 581 582 583 584
                    DropButton {
                        id:                 centerMapButton
                        dropDirection:      dropRight
                        buttonImage:        "/qmlimages/MapCenter.svg"
                        viewportMargins:    ScreenTools.defaultFontPixelWidth / 2
                        exclusiveGroup:     _dropButtonsExclusiveGroup
585
                        lightBorders:       _lightWidgetBorders
586

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

624 625 626 627 628 629
                    DropButton {
                        id:                 mapTypeButton
                        dropDirection:      dropRight
                        buttonImage:        "/qmlimages/MapType.svg"
                        viewportMargins:    ScreenTools.defaultFontPixelWidth / 2
                        exclusiveGroup:     _dropButtonsExclusiveGroup
630
                        lightBorders:       _lightWidgetBorders
631 632 633

                        dropDownComponent: Component {
                            Column {
dogmaphobic's avatar
dogmaphobic committed
634
                                spacing: _margin
635
                                QGCLabel { text: qsTr("Map type:") }
636 637 638 639 640 641
                                Row {
                                    spacing: ScreenTools.defaultFontPixelWidth
                                    Repeater {
                                        model: QGroundControl.flightMapSettings.mapTypes
                                        QGCButton {
                                            checkable:      true
dogmaphobic's avatar
dogmaphobic committed
642
                                            checked:        editorMap.mapType === text
643 644 645 646 647 648 649
                                            text:           modelData
                                            exclusiveGroup: _mapTypeButtonsExclusiveGroup
                                            onClicked: {
                                                editorMap.mapType = text
                                                checked = true
                                                mapTypeButton.hideDropDown()
                                            }
650 651 652 653 654 655 656
                                        }
                                    }
                                }
                            }
                        }
                    }

657 658
                    //-- Zoom Map In
                    RoundButton {
659 660 661 662 663
                        id:             mapZoomPlus
                        visible:        !ScreenTools.isTinyScreen && !ScreenTools.isShortScreen
                        buttonImage:    "/qmlimages/ZoomPlus.svg"
                        lightBorders:   _lightWidgetBorders

664 665 666 667 668 669 670 671 672
                        onClicked: {
                            if(editorMap)
                                editorMap.zoomLevel += 0.5
                            checked = false
                        }
                    }

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

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

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

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

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

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

dogmaphobic's avatar
dogmaphobic committed
809

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

            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
            }
827
*/
828 829
        }
    }
Don Gagne's avatar
Don Gagne committed
830
} // QGCVIew