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

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

// Editor for Survery mission items
Rectangle {
    id:         _root
19
    height:     visible ? (editorColumn.height + (_margin * 2)) : 0
20 21 22 23
    width:      availableWidth
    color:      qgcPal.windowShadeDark
    radius:     _radius

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

28
    property real   _margin:            ScreenTools.defaultFontPixelWidth / 2
29 30 31 32 33
    property int    _cameraIndex:       1
    property real   _fieldWidth:        ScreenTools.defaultFontPixelWidth * 10.5
    property var    _cameraList:        [ qsTr("Manual Grid (no camera specs)"), qsTr("Custom Camera Grid") ]
    property var    _vehicle:           QGroundControl.multiVehicleManager.activeVehicle ? QGroundControl.multiVehicleManager.activeVehicle : QGroundControl.multiVehicleManager.offlineEditingVehicle
    property var    _vehicleCameraList: _vehicle.cameraList
Don Gagne's avatar
Don Gagne committed
34 35 36 37 38

    readonly property int _gridTypeManual:          0
    readonly property int _gridTypeCustomCamera:    1
    readonly property int _gridTypeCamera:          2

39 40 41
    Component.onCompleted: {
        for (var i=0; i<_vehicle.cameraList.length; i++) {
            _cameraList.push(_vehicle.cameraList[i].name)
Don Gagne's avatar
Don Gagne committed
42
        }
43
        gridTypeCombo.model = _cameraList
44
        if (missionItem.manualGrid.value) {
45 46
            gridTypeCombo.currentIndex = _gridTypeManual
        } else {
47 48 49 50 51 52
            var index = -1
            for (index=0; index<_cameraList.length; index++) {
                if (_cameraList[index] == missionItem.camera.value) {
                    break;
                }
            }
53
            missionItem.cameraOrientationFixed = false
Don Gagne's avatar
Don Gagne committed
54 55
            if (index == _cameraList.length) {
                gridTypeCombo.currentIndex = _gridTypeCustomCamera
56 57
            } else {
                gridTypeCombo.currentIndex = index
58 59
                if (index != 1) {
                    // Specific camera is selected
60 61 62
                    var camera = _vehicleCameraList[index - _gridTypeCamera]
                    missionItem.cameraOrientationFixed = camera.fixedOrientation
                    missionItem.cameraMinTriggerInterval = camera.minTriggerInterval
63
                }
64
            }
Don Gagne's avatar
Don Gagne committed
65 66
        }
    }
Don Gagne's avatar
Don Gagne committed
67 68

    function recalcFromCameraValues() {
69 70 71 72 73
        var focalLength     = missionItem.cameraFocalLength.rawValue
        var sensorWidth     = missionItem.cameraSensorWidth.rawValue
        var sensorHeight    = missionItem.cameraSensorHeight.rawValue
        var imageWidth      = missionItem.cameraResolutionWidth.rawValue
        var imageHeight     = missionItem.cameraResolutionHeight.rawValue
Don Gagne's avatar
Don Gagne committed
74

75 76 77 78
        var altitude        = missionItem.gridAltitude.rawValue
        var groundResolution= missionItem.groundResolution.rawValue
        var frontalOverlap  = missionItem.frontalOverlap.rawValue
        var sideOverlap     = missionItem.sideOverlap.rawValue
Don Gagne's avatar
Don Gagne committed
79 80

        if (focalLength <= 0 || sensorWidth <= 0 || sensorHeight <= 0 || imageWidth <= 0 || imageHeight <= 0 || groundResolution <= 0) {
Don Gagne's avatar
Don Gagne committed
81 82 83
            return
        }

Don Gagne's avatar
Don Gagne committed
84 85
        var imageSizeSideGround     //size in side (non flying) direction of the image on the ground
        var imageSizeFrontGround    //size in front (flying) direction of the image on the ground
Don Gagne's avatar
Don Gagne committed
86 87
        var gridSpacing
        var cameraTriggerDistance
88

89
        if (missionItem.fixedValueIsAltitude.value) {
90
            groundResolution = (altitude * sensorWidth * 100) / (imageWidth * focalLength)
Don Gagne's avatar
Don Gagne committed
91 92 93
        } else {
            altitude = (imageWidth * groundResolution * focalLength) / (sensorWidth * 100)
        }
94

95
        if (missionItem.cameraOrientationLandscape.value) {
96
            imageSizeSideGround  = (imageWidth  * groundResolution) / 100
Don Gagne's avatar
Don Gagne committed
97
            imageSizeFrontGround = (imageHeight * groundResolution) / 100
Don Gagne's avatar
Don Gagne committed
98
        } else {
99 100
            imageSizeSideGround  = (imageHeight * groundResolution) / 100
            imageSizeFrontGround = (imageWidth  * groundResolution) / 100
Don Gagne's avatar
Don Gagne committed
101 102
        }

103 104 105
        gridSpacing = imageSizeSideGround * ( (100-sideOverlap) / 100 )
        cameraTriggerDistance = imageSizeFrontGround * ( (100-frontalOverlap) / 100 )

106
        if (missionItem.fixedValueIsAltitude.value) {
Don Gagne's avatar
Don Gagne committed
107 108 109 110
            missionItem.groundResolution.rawValue = groundResolution
        } else {
            missionItem.gridAltitude.rawValue = altitude
        }
Don Gagne's avatar
Don Gagne committed
111 112 113 114
        missionItem.gridSpacing.rawValue = gridSpacing
        missionItem.cameraTriggerDistance.rawValue = cameraTriggerDistance
    }

115
    function polygonCaptureStarted() {
Don Gagne's avatar
Don Gagne committed
116
        missionItem.clearPolygon()
117
    }
Don Gagne's avatar
Don Gagne committed
118

119 120 121
    function polygonCaptureFinished(coordinates) {
        for (var i=0; i<coordinates.length; i++) {
            missionItem.addPolygonCoordinate(coordinates[i])
Don Gagne's avatar
Don Gagne committed
122
        }
123
    }
Don Gagne's avatar
Don Gagne committed
124

125 126
    function polygonAdjustVertex(vertexIndex, vertexCoordinate) {
        missionItem.adjustPolygonCoordinate(vertexIndex, vertexCoordinate)
Don Gagne's avatar
Don Gagne committed
127 128
    }

129 130 131
    function polygonAdjustStarted() { }
    function polygonAdjustFinished() { }

Don Gagne's avatar
Don Gagne committed
132 133
    property bool _noCameraValueRecalc: false   ///< Prevents uneeded recalcs

134 135 136 137 138 139 140 141 142 143
    Connections {
        target: missionItem.camera

        onValueChanged: {
            if (gridTypeCombo.currentIndex >= _gridTypeCustomCamera && !_noCameraValueRecalc) {
                recalcFromCameraValues()
            }
        }
    }

Don Gagne's avatar
Don Gagne committed
144 145 146 147
    Connections {
        target: missionItem.gridAltitude

        onValueChanged: {
148
            if (gridTypeCombo.currentIndex >= _gridTypeCustomCamera && missionItem.fixedValueIsAltitude.value && !_noCameraValueRecalc) {
149 150 151 152 153 154 155 156 157 158
                recalcFromCameraValues()
            }
        }
    }

    Connections {
        target: missionItem

        onCameraValueChanged: {
            if (gridTypeCombo.currentIndex >= _gridTypeCustomCamera && !_noCameraValueRecalc) {
Don Gagne's avatar
Don Gagne committed
159 160 161 162 163
                recalcFromCameraValues()
            }
        }
    }

164 165
    QGCPalette { id: qgcPal; colorGroupEnabled: true }

Don Gagne's avatar
Don Gagne committed
166
    ExclusiveGroup {
Don Gagne's avatar
Don Gagne committed
167 168 169 170 171 172
        id: cameraOrientationGroup

        onCurrentChanged: {
            if (gridTypeCombo.currentIndex >= _gridTypeCustomCamera) {
                recalcFromCameraValues()
            }
173
        }
Don Gagne's avatar
Don Gagne committed
174 175
    }

Don Gagne's avatar
Don Gagne committed
176 177
    ExclusiveGroup { id: fixedValueGroup }

178 179 180 181 182
    Column {
        id:                 editorColumn
        anchors.margins:    _margin
        anchors.top:        parent.top
        anchors.left:       parent.left
183
        anchors.right:      parent.right
184 185
        spacing:            _margin

186 187 188 189 190 191 192 193 194
        QGCLabel {
            anchors.left:   parent.left
            anchors.right:  parent.right
            text:           qsTr("WARNING: Photo interval is below minimum interval (%1 secs) supported by camera.").arg(missionItem.cameraMinTriggerInterval.toFixed(1))
            wrapMode:       Text.WordWrap
            color:          qgcPal.warningText
            visible:        missionItem.manualGrid.value !== true && missionItem.cameraShots > 0 && missionItem.cameraMinTriggerInterval !== 0 && missionItem.cameraMinTriggerInterval > missionItem.timeBetweenShots
        }

195
        SectionHeader {
196
            id:         cameraHeader
197 198 199
            text:       qsTr("Camera")
            showSpacer: false
        }
200

201
        Column {
Don Gagne's avatar
Don Gagne committed
202 203
            anchors.left:   parent.left
            anchors.right:  parent.right
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
            spacing:        _margin
            visible:        cameraHeader.checked

            QGCComboBox {
                id:             gridTypeCombo
                anchors.left:   parent.left
                anchors.right:  parent.right
                model:          _cameraList
                currentIndex:   -1

                onActivated: {
                    if (index == _gridTypeManual) {
                        missionItem.manualGrid.value = true
                    } else if (index == _gridTypeCustomCamera) {
                        missionItem.manualGrid.value = false
                        missionItem.camera.value = gridTypeCombo.textAt(index)
                        missionItem.cameraOrientationFixed = false
221
                        missionItem.cameraMinTriggerInterval = 0
222 223 224 225 226 227 228 229 230 231 232 233
                    } else {
                        missionItem.manualGrid.value = false
                        missionItem.camera.value = gridTypeCombo.textAt(index)
                        _noCameraValueRecalc = true
                        var listIndex = index - _gridTypeCamera
                        missionItem.cameraSensorWidth.rawValue          = _vehicleCameraList[listIndex].sensorWidth
                        missionItem.cameraSensorHeight.rawValue         = _vehicleCameraList[listIndex].sensorHeight
                        missionItem.cameraResolutionWidth.rawValue      = _vehicleCameraList[listIndex].imageWidth
                        missionItem.cameraResolutionHeight.rawValue     = _vehicleCameraList[listIndex].imageHeight
                        missionItem.cameraFocalLength.rawValue          = _vehicleCameraList[listIndex].focalLength
                        missionItem.cameraOrientationLandscape.rawValue = _vehicleCameraList[listIndex].landscape ? 1 : 0
                        missionItem.cameraOrientationFixed              = _vehicleCameraList[listIndex].fixedOrientation
234
                        missionItem.cameraMinTriggerInterval            = _vehicleCameraList[listIndex].minTriggerInterval
235 236 237 238 239 240 241 242 243 244 245 246
                        _noCameraValueRecalc = false
                        recalcFromCameraValues()
                    }
                }
            }

            RowLayout {
                anchors.left:   parent.left
                anchors.right:  parent.right
                spacing:        _margin
                visible:        missionItem.manualGrid.value == true

247 248
                QGCCheckBox {
                    id:                 cameraTriggerDistanceCheckBox
249 250
                    anchors.baseline:   cameraTriggerDistanceField.baseline
                    text:               qsTr("Trigger Distance")
251 252 253 254 255 256 257 258
                    checked:            missionItem.cameraTriggerDistance.rawValue > 0
                    onClicked: {
                        if (checked) {
                            missionItem.cameraTriggerDistance.value = missionItem.cameraTriggerDistance.defaultValue
                        } else {
                            missionItem.cameraTriggerDistance.value = 0
                        }
                    }
259 260 261 262 263 264
                }

                FactTextField {
                    id:                 cameraTriggerDistanceField
                    Layout.fillWidth:   true
                    fact:               missionItem.cameraTriggerDistance
265
                    enabled:            cameraTriggerDistanceCheckBox.checked
266 267 268 269
                }
            }
        }

Don Gagne's avatar
Don Gagne committed
270 271
        // Camera based grid ui
        Column {
Don Gagne's avatar
Don Gagne committed
272
            anchors.left:   parent.left
Don Gagne's avatar
Don Gagne committed
273 274 275
            anchors.right:  parent.right
            spacing:        _margin
            visible:        gridTypeCombo.currentIndex != _gridTypeManual
Don Gagne's avatar
Don Gagne committed
276

Don Gagne's avatar
Don Gagne committed
277
            Row {
278 279 280
                spacing:                    _margin
                anchors.horizontalCenter:   parent.horizontalCenter
                visible:                    !missionItem.cameraOrientationFixed
281

Don Gagne's avatar
Don Gagne committed
282 283 284
                QGCRadioButton {
                    width:          _editFieldWidth
                    text:           "Landscape"
285
                    checked:        !!missionItem.cameraOrientationLandscape.value
Don Gagne's avatar
Don Gagne committed
286
                    exclusiveGroup: cameraOrientationGroup
287
                    onClicked:      missionItem.cameraOrientationLandscape.value = 1
Don Gagne's avatar
Don Gagne committed
288
                }
289

Don Gagne's avatar
Don Gagne committed
290 291 292
                QGCRadioButton {
                    id:             cameraOrientationPortrait
                    text:           "Portrait"
293
                    checked:        !missionItem.cameraOrientationLandscape.value
Don Gagne's avatar
Don Gagne committed
294
                    exclusiveGroup: cameraOrientationGroup
295
                    onClicked:      missionItem.cameraOrientationLandscape.value = 0
Don Gagne's avatar
Don Gagne committed
296
                }
297 298
            }

Don Gagne's avatar
Don Gagne committed
299
            Column {
300
                id:             custCameraCol
Don Gagne's avatar
Don Gagne committed
301 302 303
                anchors.left:   parent.left
                anchors.right:  parent.right
                spacing:        _margin
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
                visible:        gridTypeCombo.currentIndex === _gridTypeCustomCamera

                RowLayout {
                    anchors.left:   parent.left
                    anchors.right:  parent.right
                    spacing:        _margin
                    Item { Layout.fillWidth: true }
                    QGCLabel {
                        Layout.preferredWidth:  _root._fieldWidth
                        text:                   qsTr("Width")
                    }
                    QGCLabel {
                        Layout.preferredWidth:  _root._fieldWidth
                        text:                   qsTr("Height")
                    }
                }
Don Gagne's avatar
Don Gagne committed
320

321 322 323 324
                RowLayout {
                    anchors.left:   parent.left
                    anchors.right:  parent.right
                    spacing:        _margin
325
                    QGCLabel { text: qsTr("Sensor"); Layout.fillWidth: true }
Don Gagne's avatar
Don Gagne committed
326
                    FactTextField {
327
                        Layout.preferredWidth:  _root._fieldWidth
Don Gagne's avatar
Don Gagne committed
328 329 330
                        fact:                   missionItem.cameraSensorWidth
                    }
                    FactTextField {
331
                        Layout.preferredWidth:  _root._fieldWidth
Don Gagne's avatar
Don Gagne committed
332 333
                        fact:                   missionItem.cameraSensorHeight
                    }
334
                }
Don Gagne's avatar
Don Gagne committed
335

336 337 338 339
                RowLayout {
                    anchors.left:   parent.left
                    anchors.right:  parent.right
                    spacing:        _margin
340
                    QGCLabel { text: qsTr("Image"); Layout.fillWidth: true }
Don Gagne's avatar
Don Gagne committed
341
                    FactTextField {
342
                        Layout.preferredWidth:  _root._fieldWidth
Don Gagne's avatar
Don Gagne committed
343 344 345
                        fact:                   missionItem.cameraResolutionWidth
                    }
                    FactTextField {
346
                        Layout.preferredWidth:  _root._fieldWidth
Don Gagne's avatar
Don Gagne committed
347 348 349 350
                        fact:                   missionItem.cameraResolutionHeight
                    }
                }

351 352 353 354 355
                RowLayout {
                    anchors.left:   parent.left
                    anchors.right:  parent.right
                    spacing:        _margin
                    QGCLabel {
356
                        text:                   qsTr("Focal length")
357 358 359 360 361 362
                        Layout.fillWidth:       true
                    }
                    FactTextField {
                        Layout.preferredWidth:  _root._fieldWidth
                        fact:                   missionItem.cameraFocalLength
                    }
Don Gagne's avatar
Don Gagne committed
363 364
                }

365
            } // Column - custom camera
Don Gagne's avatar
Don Gagne committed
366

367 368 369
            RowLayout {
                anchors.left:   parent.left
                anchors.right:  parent.right
Don Gagne's avatar
Don Gagne committed
370
                spacing:        _margin
371 372 373
                Item { Layout.fillWidth: true }
                QGCLabel {
                    Layout.preferredWidth:  _root._fieldWidth
374
                    text:                   qsTr("Front Lap")
Don Gagne's avatar
Don Gagne committed
375 376
                }
                QGCLabel {
377
                    Layout.preferredWidth:  _root._fieldWidth
378
                    text:                   qsTr("Side Lap")
Don Gagne's avatar
Don Gagne committed
379
                }
380
            }
Don Gagne's avatar
Don Gagne committed
381

382 383 384 385
            RowLayout {
                anchors.left:   parent.left
                anchors.right:  parent.right
                spacing:        _margin
386
                QGCLabel { text: qsTr("Overlap"); Layout.fillWidth: true }
Don Gagne's avatar
Don Gagne committed
387
                FactTextField {
388 389
                    Layout.preferredWidth:  _root._fieldWidth
                    fact:                   missionItem.frontalOverlap
Don Gagne's avatar
Don Gagne committed
390 391
                }
                FactTextField {
392 393
                    Layout.preferredWidth:  _root._fieldWidth
                    fact:                   missionItem.sideOverlap
Don Gagne's avatar
Don Gagne committed
394
                }
Don Gagne's avatar
Don Gagne committed
395 396
            }

397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
            FactCheckBox {
                text:       qsTr("Hover and capture image")
                fact:       missionItem.hoverAndCapture
                visible:    missionItem.hoverAndCaptureAllowed
                onClicked: {
                    if (checked) {
                        missionItem.cameraTriggerInTurnaround.rawValue = false
                    }
                }
            }

            FactCheckBox {
                text:       qsTr("Take images in turnarounds")
                fact:       missionItem.cameraTriggerInTurnaround
                enabled:    !missionItem.hoverAndCapture.rawValue
            }

414 415 416 417
            SectionHeader {
                id:     gridHeader
                text:   qsTr("Grid")
            }
Don Gagne's avatar
Don Gagne committed
418

419
            GridLayout {
Don Gagne's avatar
Don Gagne committed
420 421
                anchors.left:   parent.left
                anchors.right:  parent.right
422 423 424
                columnSpacing:  _margin
                rowSpacing:     _margin
                columns:        2
425
                visible:        gridHeader.checked
426

427 428 429 430 431
                GridLayout {
                    anchors.left:   parent.left
                    anchors.right:  parent.right
                    columnSpacing:  _margin
                    rowSpacing:     _margin
DonLakeFlyer's avatar
DonLakeFlyer committed
432
                    columns:        2
433 434 435
                    visible:        gridHeader.checked

                    QGCLabel {
DonLakeFlyer's avatar
DonLakeFlyer committed
436 437 438
                        id:                 angleText
                        text:               qsTr("Angle")
                        Layout.fillWidth:   true
439 440 441 442 443
                    }

                    ToolButton {
                        id:                     windRoseButton
                        anchors.verticalCenter: angleText.verticalCenter
444
                        iconSource:             qgcPal.globalTheme === QGCPalette.Light ? "/res/wind-roseBlack.svg" : "/res/wind-rose.svg"
445 446
                        // Wind Rose is temporarily turned off until bugs are fixed
                        visible:                false//_vehicle.fixedWing
447 448 449

                        onClicked: {
                            var cords = windRoseButton.mapToItem(_root, 0, 0)
450
                            windRosePie.popup(cords.x + windRoseButton.width / 2, cords.y + windRoseButton.height / 2);
451 452 453 454
                        }
                    }
                }

455
                FactTextField {
456
                    id:                 gridAngleText
457 458
                    fact:               missionItem.gridAngle
                    Layout.fillWidth:   true
459 460
                }

461
                QGCLabel { text: qsTr("Turnaround dist") }
462 463
                FactTextField {
                    fact:                   missionItem.turnaroundDist
464
                    Layout.fillWidth:       true
465
                }
Don Gagne's avatar
Don Gagne committed
466

DonLakeFlyer's avatar
DonLakeFlyer committed
467 468 469 470 471 472 473
                QGCLabel { text: qsTr("Entry") }
                FactComboBox {
                    fact:                   missionItem.gridEntryLocation
                    indexModel:             false
                    Layout.fillWidth:       true
                }

474
                QGCCheckBox {
DonLakeFlyer's avatar
DonLakeFlyer committed
475 476 477 478
                    text:               qsTr("Refly at 90 degree offset")
                    checked:            missionItem.refly90Degrees
                    onClicked:          missionItem.refly90Degrees = checked
                    Layout.columnSpan:  2
479 480
                }

481
                QGCLabel {
DonLakeFlyer's avatar
DonLakeFlyer committed
482 483
                    wrapMode:               Text.WordWrap
                    text:                   qsTr("Select one:")
484
                    Layout.preferredWidth:  parent.width
DonLakeFlyer's avatar
DonLakeFlyer committed
485
                    Layout.columnSpan:      2
486
                }
Don Gagne's avatar
Don Gagne committed
487 488

                QGCRadioButton {
489
                    id:                     fixedAltitudeRadio
490
                    text:                   qsTr("Altitude")
491
                    checked:                !!missionItem.fixedValueIsAltitude.value
492
                    exclusiveGroup:         fixedValueGroup
493
                    onClicked:              missionItem.fixedValueIsAltitude.value = 1
Don Gagne's avatar
Don Gagne committed
494
                }
495

Don Gagne's avatar
Don Gagne committed
496
                FactTextField {
497 498
                    fact:                   missionItem.gridAltitude
                    enabled:                fixedAltitudeRadio.checked
499
                    Layout.fillWidth:       true
500
                }
Don Gagne's avatar
Don Gagne committed
501 502

                QGCRadioButton {
503
                    id:                     fixedGroundResolutionRadio
504
                    text:                   qsTr("Ground res")
505
                    checked:                !missionItem.fixedValueIsAltitude.value
506
                    exclusiveGroup:         fixedValueGroup
507
                    onClicked:              missionItem.fixedValueIsAltitude.value = 0
508 509
                }

Don Gagne's avatar
Don Gagne committed
510
                FactTextField {
511 512
                    fact:                   missionItem.groundResolution
                    enabled:                fixedGroundResolutionRadio.checked
513
                    Layout.fillWidth:       true
Don Gagne's avatar
Don Gagne committed
514 515 516 517 518
                }
            }
        }

        // Manual grid ui
519 520 521 522 523 524
        SectionHeader {
            id:         manualGridHeader
            text:       qsTr("Grid")
            visible:    gridTypeCombo.currentIndex == _gridTypeManual
        }

DonLakeFlyer's avatar
DonLakeFlyer committed
525
        GridLayout {
Don Gagne's avatar
Don Gagne committed
526 527
            anchors.left:   parent.left
            anchors.right:  parent.right
DonLakeFlyer's avatar
DonLakeFlyer committed
528 529 530
            columnSpacing:  _margin
            rowSpacing:     _margin
            columns:        2
531
            visible:        manualGridHeader.visible && manualGridHeader.checked
Don Gagne's avatar
Don Gagne committed
532

DonLakeFlyer's avatar
DonLakeFlyer committed
533 534
            RowLayout {
                spacing: _margin
535 536

                QGCLabel {
DonLakeFlyer's avatar
DonLakeFlyer committed
537 538
                    id:                 manualAngleText
                    text:               qsTr("Angle")
539 540 541 542 543 544 545 546
                    Layout.fillWidth:  true
                }

                ToolButton {
                    id:                     manualWindRoseButton
                    anchors.verticalCenter: manualAngleText.verticalCenter
                    Layout.columnSpan:      1
                    iconSource:             qgcPal.globalTheme === QGCPalette.Light ? "/res/wind-roseBlack.svg" : "/res/wind-rose.svg"
547 548
                    // Wind Rose is temporarily turned off until bugs are fixed
                    visible:                false//_vehicle.fixedWing
549 550 551 552 553 554

                    onClicked: {
                        var cords = manualWindRoseButton.mapToItem(_root, 0, 0)
                        windRosePie.popup(cords.x + manualWindRoseButton.width / 2, cords.y + manualWindRoseButton.height / 2);
                    }
                }
DonLakeFlyer's avatar
DonLakeFlyer committed
555
            }
556

DonLakeFlyer's avatar
DonLakeFlyer committed
557 558 559 560
            FactTextField {
                id:                 manualGridAngleText
                fact:               missionItem.gridAngle
                Layout.fillWidth:   true
561 562
            }

DonLakeFlyer's avatar
DonLakeFlyer committed
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577
            QGCLabel { text: qsTr("Spacing") }
            FactTextField {
                fact:                   missionItem.gridSpacing
                Layout.fillWidth:       true
            }

            QGCLabel { text: qsTr("Altitude") }
            FactTextField {
                fact:                   missionItem.gridAltitude
                Layout.fillWidth:       true
            }
            QGCLabel { text: qsTr("Turnaround dist") }
            FactTextField {
                fact:                   missionItem.turnaroundDist
                Layout.fillWidth:       true
Don Gagne's avatar
Don Gagne committed
578
            }
DonLakeFlyer's avatar
DonLakeFlyer committed
579 580 581 582 583 584 585
            QGCLabel { text: qsTr("Entry") }
            FactComboBox {
                fact:                   missionItem.gridEntryLocation
                indexModel:             false
                Layout.fillWidth:       true
            }

Don Gagne's avatar
Don Gagne committed
586

587
            QGCCheckBox {
DonLakeFlyer's avatar
DonLakeFlyer committed
588 589 590 591
                text:               qsTr("Refly at 90 degree offset")
                checked:            missionItem.refly90Degrees
                onClicked:          missionItem.refly90Degrees = checked
                Layout.columnSpan:  2
592 593
            }

594
            FactCheckBox {
DonLakeFlyer's avatar
DonLakeFlyer committed
595 596 597 598
                anchors.left:       parent.left
                text:               qsTr("Relative altitude")
                fact:               missionItem.gridAltitudeRelative
                Layout.columnSpan:  2
Don Gagne's avatar
Don Gagne committed
599
            }
Don Gagne's avatar
Don Gagne committed
600 601
        }

602 603 604
        SectionHeader {
            id:     statsHeader
            text:   qsTr("Statistics") }
605 606

        Grid {
607 608
            columns:        2
            columnSpacing:  ScreenTools.defaultFontPixelWidth
609
            visible:        statsHeader.checked
610

611
            QGCLabel { text: qsTr("Survey area") }
612 613
            QGCLabel { text: QGroundControl.squareMetersToAppSettingsAreaUnits(missionItem.coveredArea).toFixed(2) + " " + QGroundControl.appSettingsAreaUnitsString }

614
            QGCLabel { text: qsTr("Photo count") }
615
            QGCLabel { text: missionItem.cameraShots }
616

617
            QGCLabel { text: qsTr("Photo interval") }
618 619 620 621 622 623 624 625 626
            QGCLabel {
                text: {
                    var timeVal = missionItem.timeBetweenShots
                    if(!isFinite(timeVal) || missionItem.cameraShots === 0) {
                        return qsTr("N/A")
                    }
                    return timeVal.toFixed(1) + " " + qsTr("secs")
                }
            }
627
        }
628
    }
629

630
    QGCColoredImage {
631 632 633 634 635 636
        id:      windRoseArrow
        source:  "/res/wind-rose-arrow.svg"
        visible: windRosePie.visible
        width:   windRosePie.width / 5
        height:  width * 1.454
        smooth:  true
637
        color:   qgcPal.colorGrey
638 639 640 641
        transform: Rotation {
            origin.x: windRoseArrow.width / 2
            origin.y: windRoseArrow.height / 2
            axis { x: 0; y: 0; z: 1 } angle: windRosePie.angle
642
        }
643 644
        x: windRosePie.x + Math.sin(- windRosePie.angle*Math.PI/180 - Math.PI/2)*(windRosePie.width/2 - windRoseArrow.width/2) + windRosePie.width / 2 - windRoseArrow.width / 2
        y: windRosePie.y + Math.cos(- windRosePie.angle*Math.PI/180 - Math.PI/2)*(windRosePie.width/2 - windRoseArrow.width/2) + windRosePie.height / 2 - windRoseArrow.height / 2
645
        z: windRosePie.z + 1
646 647
    }

648
    QGCColoredImage {
649 650 651 652 653 654
        id:      windGuru
        source:  "/res/wind-guru.svg"
        visible: windRosePie.visible
        width:   windRosePie.width / 3
        height:  width * 4.28e-1
        smooth:  true
655
        color:   qgcPal.colorGrey
656 657 658 659 660
        transform: Rotation {
            origin.x: windGuru.width / 2
            origin.y: windGuru.height / 2
            axis { x: 0; y: 0; z: 1 } angle: windRosePie.angle + 180
        }
661 662 663
        x: windRosePie.x + Math.sin(- windRosePie.angle*Math.PI/180 - 3*Math.PI/2)*(windRosePie.width/2) + windRosePie.width / 2 - windGuru.width / 2
        y: windRosePie.y + Math.cos(- windRosePie.angle*Math.PI/180 - 3*Math.PI/2)*(windRosePie.height/2) + windRosePie.height / 2 - windGuru.height / 2
        z: windRosePie.z + 1
664
    }
665

666 667 668 669 670
    Item {
        id:          windRosePie
        height:      2.6*windRoseButton.height
        width:       2.6*windRoseButton.width
        visible:     false
671
        focus:       true
672

673 674
        property string colorCircle: qgcPal.windowShade
        property string colorBackground: qgcPal.colorGrey
675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702
        property real lineWidth: windRoseButton.width / 3
        property real angle: 0

        Canvas {
            id: windRoseCanvas
            anchors.fill: parent

            onPaint: {
                var ctx = getContext("2d")
                var x = width / 2
                var y = height / 2
                var angleWidth = 0.03 * Math.PI
                var start = windRosePie.angle*Math.PI/180 - angleWidth
                var end = windRosePie.angle*Math.PI/180 + angleWidth
                ctx.reset()

                ctx.beginPath();
                ctx.arc(x, y, (width / 3) - windRosePie.lineWidth / 2, 0, 2*Math.PI, false)
                ctx.lineWidth = windRosePie.lineWidth
                ctx.strokeStyle = windRosePie.colorBackground
                ctx.stroke()

                ctx.beginPath();
                ctx.arc(x, y, (width / 3) - windRosePie.lineWidth / 2, start, end, false)
                ctx.lineWidth = windRosePie.lineWidth
                ctx.strokeStyle = windRosePie.colorCircle
                ctx.stroke()
            }
703 704
        }

705 706 707 708
        onFocusChanged: {
            visible = focus
        }

709 710 711 712 713
        function popup(x, y) {
            if (x !== undefined)
                windRosePie.x = x - windRosePie.width / 2;
            if (y !== undefined)
                windRosePie.y = y - windRosePie.height / 2;
714

715
            windRosePie.visible = true;
716
            windRosePie.focus = true
717
        }
718 719 720 721 722 723 724 725

        MouseArea {
            id: mouseArea
            anchors.fill: parent
            acceptedButtons: Qt.LeftButton | Qt.RightButton

            onClicked: {
                windRosePie.visible = false;
726
            }
727 728 729 730 731
            onPositionChanged: {
                var point = Qt.point(mouseX - parent.width / 2, mouseY - parent.height / 2)
                var angle = Math.round(Math.atan2(point.y, point.x) * 180 / Math.PI)
                windRoseCanvas.requestPaint()
                windRosePie.angle = angle
732
                gridAngleText.text = - angle
733 734 735 736
                gridAngleText.editingFinished();
            }
        }
    }
737
}