SurveyItemEditor.qml 14.3 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 94 95 96 97 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
        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) {
                    rootQgcView.showDialog(savePresetDialog, qsTr("Save Preset"), rootQgcView.showDialogDefaultWidth, StandardButton.Save | StandardButton.Cancel)
                } else if (index == _indexDelete) {
                    if (missionItem.builtInPreset) {
                        rootQgcView.showMessage(qsTr("Delete Preset"), qsTr("This preset cannot be deleted."), StandardButton.Ok)
                    } 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 165 166 167
            cameraCalc:                     missionItem.cameraCalc
            vehicleFlightIsFrontal:         true
            distanceToSurfaceLabel:         qsTr("Altitude")
            distanceToSurfaceAltitudeMode:  missionItem.followTerrain ? QGroundControl.AltitudeModeAboveTerrain : QGroundControl.AltitudeModeRelative
            frontalDistanceLabel:           qsTr("Trigger Dist")
            sideDistanceLabel:              qsTr("Spacing")
Don Gagne's avatar
Don Gagne committed
168 169
            usingPreset:                    _usingPreset
            cameraSpecifiedInPreset:        missionItem.cameraInPreset
Don Gagne's avatar
Don Gagne committed
170 171
        }

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

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

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

192 193 194 195 196 197 198 199 200 201 202 203
            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
204 205
            }

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

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

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

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

238 239 240 241
            FactCheckBox {
                text:               qsTr("Hover and capture image")
                fact:               missionItem.hoverAndCapture
                visible:            missionItem.hoverAndCaptureAllowed
242
                enabled:            !missionItem.followTerrain
243 244
                onClicked: {
                    if (checked) {
DonLakeFlyer's avatar
DonLakeFlyer committed
245
                        missionItem.cameraTriggerInTurnAround.rawValue = false
246 247 248 249 250
                    }
                }
            }

            FactCheckBox {
Don Gagne's avatar
Don Gagne committed
251
                text:               qsTr("Refly at 90 deg offset")
252 253
                fact:               missionItem.refly90Degrees
                enabled:            !missionItem.followTerrain
254
            }
Don Gagne's avatar
Don Gagne committed
255

256
            FactCheckBox {
Don Gagne's avatar
Don Gagne committed
257
                text:               qsTr("Images in turnarounds")
258 259
                fact:               missionItem.cameraTriggerInTurnAround
                enabled:            missionItem.hoverAndCaptureAllowed ? !missionItem.hoverAndCapture.rawValue : true
260 261
            }

262 263 264
            FactCheckBox {
                text:               qsTr("Fly alternate transects")
                fact:               missionItem.flyAlternateTransects
265
                visible:            _vehicle.fixedWing || _vehicle.vtol
266 267
            }

268 269
            QGCCheckBox {
                id:                 relAlt
270
                Layout.alignment:   Qt.AlignLeft
DonLakeFlyer's avatar
DonLakeFlyer committed
271
                text:               qsTr("Relative altitude")
272 273
                checked:            missionItem.cameraCalc.distanceToSurfaceRelative
                enabled:            missionItem.cameraCalc.isManualCamera && !missionItem.followTerrain
274
                visible:            QGroundControl.corePlugin.options.showMissionAbsoluteAltitude || (!missionItem.cameraCalc.distanceToSurfaceRelative && !missionItem.followTerrain)
275
                onClicked:          missionItem.cameraCalc.distanceToSurfaceRelative = checked
Don Gagne's avatar
Don Gagne committed
276

277 278 279
                Connections {
                    target: missionItem.cameraCalc
                    onDistanceToSurfaceRelativeChanged: relAlt.checked = missionItem.cameraCalc.distanceToSurfaceRelative
280 281
                }
            }
282
        }
283

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

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

297

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

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

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

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

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

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

337 338
        TransectStyleComplexItemStats { }
    } // Column
Don Gagne's avatar
Don Gagne committed
339 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

    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
                }
            }
        }
    }
380
} // Rectangle