SurveyItemEditor.qml 14.4 KB
Newer Older
1 2
import QtQuick          2.3
import QtQuick.Controls 1.2
Don Gagne's avatar
Don Gagne committed
3
import QtQuick.Dialogs  1.2
4
import QtQuick.Extras   1.4
5
import QtQuick.Layouts  1.2
6

7
import QGroundControl               1.0
8 9 10
import QGroundControl.ScreenTools   1.0
import QGroundControl.Vehicle       1.0
import QGroundControl.Controls      1.0
11
import QGroundControl.FactSystem    1.0
12 13
import QGroundControl.FactControls  1.0
import QGroundControl.Palette       1.0
14
import QGroundControl.FlightMap     1.0
15 16 17

Rectangle {
    id:         _root
18
    height:     visible ? (editorColumn.height + (_margin * 2)) : 0
19 20 21 22
    width:      availableWidth
    color:      qgcPal.windowShadeDark
    radius:     _radius

Ricardo de Almeida Gonzaga's avatar
Ricardo de Almeida Gonzaga committed
23
    // The following properties must be available up the hierarchy chain
24 25 26
    //property real   availableWidth    ///< Width for control
    //property var    missionItem       ///< Mission Item for editor

27 28 29 30
    property real   _margin:                    ScreenTools.defaultFontPixelWidth / 2
    property real   _fieldWidth:                ScreenTools.defaultFontPixelWidth * 10.5
    property var    _vehicle:                   QGroundControl.multiVehicleManager.activeVehicle ? QGroundControl.multiVehicleManager.activeVehicle : QGroundControl.multiVehicleManager.offlineEditingVehicle
    property real   _cameraMinTriggerInterval:  missionItem.cameraCalc.minTriggerInterval.rawValue
Don Gagne's avatar
Don Gagne committed
31 32
    property string _currentPreset:             missionItem.currentPreset
    property bool   _usingPreset:               _currentPreset !== ""
Don Gagne's avatar
Don Gagne committed
33

34
    function polygonCaptureStarted() {
Don Gagne's avatar
Don Gagne committed
35
        missionItem.clearPolygon()
36
    }
Don Gagne's avatar
Don Gagne committed
37

38 39 40
    function polygonCaptureFinished(coordinates) {
        for (var i=0; i<coordinates.length; i++) {
            missionItem.addPolygonCoordinate(coordinates[i])
Don Gagne's avatar
Don Gagne committed
41
        }
42
    }
Don Gagne's avatar
Don Gagne committed
43

44 45
    function polygonAdjustVertex(vertexIndex, vertexCoordinate) {
        missionItem.adjustPolygonCoordinate(vertexIndex, vertexCoordinate)
Don Gagne's avatar
Don Gagne committed
46 47
    }

48 49 50
    function polygonAdjustStarted() { }
    function polygonAdjustFinished() { }

51 52 53 54 55 56 57
    QGCPalette { id: qgcPal; colorGroupEnabled: true }

    Column {
        id:                 editorColumn
        anchors.margins:    _margin
        anchors.top:        parent.top
        anchors.left:       parent.left
58
        anchors.right:      parent.right
59 60
        spacing:            _margin

61 62 63
        QGCLabel {
            anchors.left:   parent.left
            anchors.right:  parent.right
64
            text:           qsTr("WARNING: Photo interval is below minimum interval (%1 secs) supported by camera.").arg(_cameraMinTriggerInterval.toFixed(1))
65 66
            wrapMode:       Text.WordWrap
            color:          qgcPal.warningText
67
            visible:        missionItem.cameraShots > 0 && _cameraMinTriggerInterval !== 0 && _cameraMinTriggerInterval > missionItem.timeBetweenShots
68 69
        }

Don Gagne's avatar
Don Gagne committed
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
        QGCLabel {
            text: qsTr("Presets")
        }

        QGCComboBox {
            id:                 presetCombo
            anchors.left:       parent.left
            anchors.right:      parent.right
            model:              _presetList

            property var _presetList:   []

            readonly property int _indexCustom:         0
            readonly property int _indexCreate:         1
            readonly property int _indexDelete:         2
            readonly property int _indexLabel:          3
            readonly property int _indexFirstPreset:    4

            Component.onCompleted: _updateList()

            onActivated: {
                if (index == _indexCustom) {
                    missionItem.clearCurrentPreset()
                } else if (index == _indexCreate) {
94
                    mainWindow.showComponentDialog(savePresetDialog, qsTr("Save Preset"), mainWindow.showDialogDefaultWidth, StandardButton.Save | StandardButton.Cancel)
Don Gagne's avatar
Don Gagne committed
95 96
                } else if (index == _indexDelete) {
                    if (missionItem.builtInPreset) {
97
                        mainWindow.showMessage(qsTr("Delete Preset"), qsTr("This preset cannot be deleted."))
Don Gagne's avatar
Don Gagne committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
                    } else {
                        missionItem.deleteCurrentPreset()
                    }
                } else if (index >= _indexFirstPreset) {
                    missionItem.loadPreset(textAt(index))
                } else {
                    _selectCurrentPreset()
                }
            }

            Connections {
                target: missionItem

                onPresetNamesChanged:   presetCombo._updateList()
                onCurrentPresetChanged: presetCombo._selectCurrentPreset()
            }

            // There is some major strangeness going on with programatically changing the index of a combo box in this scenario.
            // If you just set currentIndex directly it will just change back 1o -1 magically. Has something to do with resetting
            // model on the fly I think. But not sure. To work around I delay the currentIndex changes to let things unwind.
            Timer {
                id:         delayedIndexChangeTimer
                interval:   10

                property int newIndex

                onTriggered:  presetCombo.currentIndex = newIndex

            }

            function delayedIndexChange(index) {
                delayedIndexChangeTimer.newIndex = index
                delayedIndexChangeTimer.start()
            }

            function _updateList() {
                _presetList = []
                _presetList.push(qsTr("Custom (specify all settings)"))
                _presetList.push(qsTr("Save Settings As Preset"))
                _presetList.push(qsTr("Delete Current Preset"))
                if (missionItem.presetNames.length !== 0) {
                    _presetList.push(qsTr("Presets:"))
                }

                for (var i=0; i<missionItem.presetNames.length; i++) {
                    _presetList.push(missionItem.presetNames[i])
                }
                model = _presetList
                _selectCurrentPreset()
            }

            function _selectCurrentPreset() {
                if (_usingPreset) {
                    var newIndex = find(_currentPreset)
                    if (newIndex !== -1) {
                        delayedIndexChange(newIndex)
                        return
                    }
                }
                delayedIndexChange(presetCombo._indexCustom)
            }
        }

161
        CameraCalc {
162 163 164
            cameraCalc:                     missionItem.cameraCalc
            vehicleFlightIsFrontal:         true
            distanceToSurfaceLabel:         qsTr("Altitude")
165 166 167
            distanceToSurfaceAltitudeMode:  missionItem.followTerrain ?
                                                QGroundControl.AltitudeModeAboveTerrain :
                                                missionItem.cameraCalc.distanceToSurfaceRelative
168 169
            frontalDistanceLabel:           qsTr("Trigger Dist")
            sideDistanceLabel:              qsTr("Spacing")
Don Gagne's avatar
Don Gagne committed
170 171
            usingPreset:                    _usingPreset
            cameraSpecifiedInPreset:        missionItem.cameraInPreset
Don Gagne's avatar
Don Gagne committed
172 173
        }

174
        SectionHeader {
Don Gagne's avatar
Don Gagne committed
175
            id:     transectsHeader
176
            text:   qsTr("Transects")
177 178
        }

DonLakeFlyer's avatar
DonLakeFlyer committed
179
        GridLayout {
Don Gagne's avatar
Don Gagne committed
180 181
            anchors.left:   parent.left
            anchors.right:  parent.right
DonLakeFlyer's avatar
DonLakeFlyer committed
182 183 184
            columnSpacing:  _margin
            rowSpacing:     _margin
            columns:        2
Don Gagne's avatar
Don Gagne committed
185
            visible:        transectsHeader.checked
186

187
            QGCLabel { text: qsTr("Angle") }
DonLakeFlyer's avatar
DonLakeFlyer committed
188
            FactTextField {
189
                fact:                   missionItem.gridAngle
DonLakeFlyer's avatar
DonLakeFlyer committed
190
                Layout.fillWidth:       true
191 192
                onUpdated:              angleSlider.value = missionItem.gridAngle.value
            }
Don Gagne's avatar
Don Gagne committed
193

194 195 196 197 198 199 200 201 202 203 204 205
            QGCSlider {
                id:                     angleSlider
                minimumValue:           0
                maximumValue:           359
                stepSize:               1
                tickmarksEnabled:       false
                Layout.fillWidth:       true
                Layout.columnSpan:      2
                Layout.preferredHeight: ScreenTools.defaultFontPixelHeight * 1.5
                onValueChanged:         missionItem.gridAngle.value = value
                Component.onCompleted:  value = missionItem.gridAngle.value
                updateValueWhileDragging: true
DonLakeFlyer's avatar
DonLakeFlyer committed
206 207
            }

Don Gagne's avatar
Don Gagne committed
208 209 210 211
            QGCLabel {
                text:       qsTr("Turnaround dist")
                visible:    !_usingPreset
            }
DonLakeFlyer's avatar
DonLakeFlyer committed
212
            FactTextField {
Don Gagne's avatar
Don Gagne committed
213 214
                fact:               missionItem.turnAroundDistance
                Layout.fillWidth:   true
Don Gagne's avatar
Don Gagne committed
215
                visible:            !_usingPreset
Don Gagne's avatar
Don Gagne committed
216
            }
Don Gagne's avatar
Don Gagne committed
217 218
        }

Don Gagne's avatar
Don Gagne committed
219 220 221 222 223
        QGCButton {
            text:               qsTr("Rotate Entry Point")
            onClicked:          missionItem.rotateEntryPoint();
        }

Don Gagne's avatar
Don Gagne committed
224 225 226 227
        ColumnLayout {
            anchors.left:   parent.left
            anchors.right:  parent.right
            spacing:        _margin
Don Gagne's avatar
Don Gagne committed
228
            visible:        transectsHeader.checked && !_usingPreset
DonLakeFlyer's avatar
DonLakeFlyer committed
229

230 231
            /*
              Temporarily removed due to bug https://github.com/mavlink/qgroundcontrol/issues/7005
232 233 234 235
            FactCheckBox {
                text:       qsTr("Split concave polygons")
                fact:       _splitConcave
                visible:    _splitConcave.visible
236
                property Fact _splitConcave: missionItem.splitConcavePolygons
237
            }
238
            */
239

240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
            QGCOptionsComboBox {
                Layout.fillWidth: true

                model: [
                    {
                        text:       qsTr("Hover and capture image"),
                        fact:       missionItem.hoverAndCapture,
                        enabled:    !missionItem.followTerrain,
                        visible:    missionItem.hoverAndCaptureAllowed
                    },
                    {
                        text:       qsTr("Refly at 90 deg offset"),
                        fact:       missionItem.refly90Degrees,
                        enabled:    !missionItem.followTerrain,
                        visible:    true
                    },
                    {
                        text:       qsTr("Images in turnarounds"),
                        fact:       missionItem.cameraTriggerInTurnAround,
                        enabled:    missionItem.hoverAndCaptureAllowed ? !missionItem.hoverAndCapture.rawValue : true,
                        visible:    true
                    },
                    {
                        text:       qsTr("Fly alternate transects"),
                        fact:       missionItem.flyAlternateTransects,
                        enabled:    true,
                        visible:    _vehicle ? (_vehicle.fixedWing || _vehicle.vtol) : false
                    },
                    {
                        text:       qsTr("Relative altitude"),
                        enabled:    missionItem.cameraCalc.isManualCamera && !missionItem.followTerrain,
                        visible:    QGroundControl.corePlugin.options.showMissionAbsoluteAltitude || (!missionItem.cameraCalc.distanceToSurfaceRelative && !missionItem.followTerrain),
                        checked:    missionItem.cameraCalc.distanceToSurfaceRelative
273
                    }
274
                ]
275

276 277 278 279 280
                onItemClicked: {
                    if (index == 4) {
                        missionItem.cameraCalc.distanceToSurfaceRelative = !missionItem.cameraCalc.distanceToSurfaceRelative
                        console.log(missionItem.cameraCalc.distanceToSurfaceRelative)
                    }
281 282
                }
            }
283
        }
284

285 286 287 288
        SectionHeader {
            id:         terrainHeader
            text:       qsTr("Terrain")
            checked:    missionItem.followTerrain
Don Gagne's avatar
Don Gagne committed
289
            visible:    !_usingPreset
290
        }
291

292 293 294 295
        ColumnLayout {
            anchors.left:   parent.left
            anchors.right:  parent.right
            spacing:        _margin
Don Gagne's avatar
Don Gagne committed
296 297
            visible:        terrainHeader.checked && !_usingPreset

298

299 300 301 302 303 304
            QGCCheckBox {
                id:         followsTerrainCheckBox
                text:       qsTr("Vehicle follows terrain")
                checked:    missionItem.followTerrain
                onClicked:  missionItem.followTerrain = checked
            }
305

306
            GridLayout {
307 308 309 310 311
                Layout.fillWidth:   true
                columnSpacing:      _margin
                rowSpacing:         _margin
                columns:            2
                visible:            followsTerrainCheckBox.checked
312

313 314 315 316 317
                QGCLabel { text: qsTr("Tolerance") }
                FactTextField {
                    fact:               missionItem.terrainAdjustTolerance
                    Layout.fillWidth:   true
                }
318

319 320 321 322 323
                QGCLabel { text: qsTr("Max Climb Rate") }
                FactTextField {
                    fact:               missionItem.terrainAdjustMaxClimbRate
                    Layout.fillWidth:   true
                }
324

325 326 327 328 329
                QGCLabel { text: qsTr("Max Descent Rate") }
                FactTextField {
                    fact:               missionItem.terrainAdjustMaxDescentRate
                    Layout.fillWidth:   true
                }
330
            }
331 332
        }

333 334 335
        SectionHeader {
            id:     statsHeader
            text:   qsTr("Statistics")
336
        }
337

338 339
        TransectStyleComplexItemStats { }
    } // Column
Don Gagne's avatar
Don Gagne committed
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380

    Component {
        id: savePresetDialog

        QGCViewDialog {
            function accept() {
                if (presetNameField.text != "") {
                    missionItem.savePreset(presetNameField.text)
                    hideDialog()
                }
            }

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

                QGCLabel {
                    Layout.fillWidth:   true
                    text:               qsTr("Save the current settings as a named preset.")
                    wrapMode:           Text.WordWrap
                }

                QGCLabel {
                    text: qsTr("Preset Name")
                }

                QGCTextField {
                    id:                 presetNameField
                    Layout.fillWidth:   true
                    text:               _currentPreset
                }

                QGCCheckBox {
                    text:       qsTr("Save Camera In Preset")
                    checked:    missionItem.cameraInPreset
                    onClicked:  missionItem.cameraInPreset = checked
                }
            }
        }
    }
381
} // Rectangle