SurveyItemEditor.qml 26.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
54 55 56 57
            if (index == -1) {
                gridTypeCombo.currentIndex = _gridTypeManual
            } else {
                gridTypeCombo.currentIndex = index
58 59 60 61
                if (index != 1) {
                    // Specific camera is selected
                    missionItem.cameraOrientationFixed = _vehicleCameraList[index - _gridTypeCamera].fixedOrientation
                }
62
            }
Don Gagne's avatar
Don Gagne committed
63 64
        }
    }
Don Gagne's avatar
Don Gagne committed
65 66

    function recalcFromCameraValues() {
67 68 69 70 71
        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
72

73 74 75 76
        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
77 78

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

Don Gagne's avatar
Don Gagne committed
82 83
        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
84 85
        var gridSpacing
        var cameraTriggerDistance
86

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

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

101 102 103
        gridSpacing = imageSizeSideGround * ( (100-sideOverlap) / 100 )
        cameraTriggerDistance = imageSizeFrontGround * ( (100-frontalOverlap) / 100 )

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

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

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

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

127 128 129
    function polygonAdjustStarted() { }
    function polygonAdjustFinished() { }

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

132 133 134 135 136 137 138 139 140 141
    Connections {
        target: missionItem.camera

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

Don Gagne's avatar
Don Gagne committed
142 143 144 145
    Connections {
        target: missionItem.gridAltitude

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

    Connections {
        target: missionItem

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

162 163
    QGCPalette { id: qgcPal; colorGroupEnabled: true }

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

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

Don Gagne's avatar
Don Gagne committed
174 175
    ExclusiveGroup { id: fixedValueGroup }

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

184
        SectionHeader {
185
            id:         cameraHeader
186 187 188
            text:       qsTr("Camera")
            showSpacer: false
        }
189

190
        Column {
Don Gagne's avatar
Don Gagne committed
191 192
            anchors.left:   parent.left
            anchors.right:  parent.right
193 194 195 196 197 198 199 200 201 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 229 230 231 232 233
            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
                    } 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
                        _noCameraValueRecalc = false
                        recalcFromCameraValues()
                    }
                }
            }

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

234 235
                QGCCheckBox {
                    id:                 cameraTriggerDistanceCheckBox
236 237
                    anchors.baseline:   cameraTriggerDistanceField.baseline
                    text:               qsTr("Trigger Distance")
238 239 240 241 242 243 244 245
                    checked:            missionItem.cameraTriggerDistance.rawValue > 0
                    onClicked: {
                        if (checked) {
                            missionItem.cameraTriggerDistance.value = missionItem.cameraTriggerDistance.defaultValue
                        } else {
                            missionItem.cameraTriggerDistance.value = 0
                        }
                    }
246 247 248 249 250 251
                }

                FactTextField {
                    id:                 cameraTriggerDistanceField
                    Layout.fillWidth:   true
                    fact:               missionItem.cameraTriggerDistance
252
                    enabled:            cameraTriggerDistanceCheckBox.checked
253 254
                }
            }
255 256

            FactCheckBox {
DonLakeFlyer's avatar
DonLakeFlyer committed
257 258 259
                text:       qsTr("Hover and capture image")
                fact:       missionItem.hoverAndCapture
                visible:    missionItem.hoverAndCaptureAllowed
260
            }
261 262
        }

Don Gagne's avatar
Don Gagne committed
263 264
        // Camera based grid ui
        Column {
Don Gagne's avatar
Don Gagne committed
265
            anchors.left:   parent.left
Don Gagne's avatar
Don Gagne committed
266 267 268
            anchors.right:  parent.right
            spacing:        _margin
            visible:        gridTypeCombo.currentIndex != _gridTypeManual
Don Gagne's avatar
Don Gagne committed
269

Don Gagne's avatar
Don Gagne committed
270
            Row {
271 272 273
                spacing:                    _margin
                anchors.horizontalCenter:   parent.horizontalCenter
                visible:                    !missionItem.cameraOrientationFixed
274

Don Gagne's avatar
Don Gagne committed
275 276 277
                QGCRadioButton {
                    width:          _editFieldWidth
                    text:           "Landscape"
278
                    checked:        !!missionItem.cameraOrientationLandscape.value
Don Gagne's avatar
Don Gagne committed
279
                    exclusiveGroup: cameraOrientationGroup
280
                    onClicked:      missionItem.cameraOrientationLandscape.value = 1
Don Gagne's avatar
Don Gagne committed
281
                }
282

Don Gagne's avatar
Don Gagne committed
283 284 285
                QGCRadioButton {
                    id:             cameraOrientationPortrait
                    text:           "Portrait"
286
                    checked:        !missionItem.cameraOrientationLandscape.value
Don Gagne's avatar
Don Gagne committed
287
                    exclusiveGroup: cameraOrientationGroup
288
                    onClicked:      missionItem.cameraOrientationLandscape.value = 0
Don Gagne's avatar
Don Gagne committed
289
                }
290 291
            }

Don Gagne's avatar
Don Gagne committed
292
            Column {
293
                id:             custCameraCol
Don Gagne's avatar
Don Gagne committed
294 295 296
                anchors.left:   parent.left
                anchors.right:  parent.right
                spacing:        _margin
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
                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
313

314 315 316 317
                RowLayout {
                    anchors.left:   parent.left
                    anchors.right:  parent.right
                    spacing:        _margin
318
                    QGCLabel { text: qsTr("Sensor"); Layout.fillWidth: true }
Don Gagne's avatar
Don Gagne committed
319
                    FactTextField {
320
                        Layout.preferredWidth:  _root._fieldWidth
Don Gagne's avatar
Don Gagne committed
321 322 323
                        fact:                   missionItem.cameraSensorWidth
                    }
                    FactTextField {
324
                        Layout.preferredWidth:  _root._fieldWidth
Don Gagne's avatar
Don Gagne committed
325 326
                        fact:                   missionItem.cameraSensorHeight
                    }
327
                }
Don Gagne's avatar
Don Gagne committed
328

329 330 331 332
                RowLayout {
                    anchors.left:   parent.left
                    anchors.right:  parent.right
                    spacing:        _margin
333
                    QGCLabel { text: qsTr("Image"); Layout.fillWidth: true }
Don Gagne's avatar
Don Gagne committed
334
                    FactTextField {
335
                        Layout.preferredWidth:  _root._fieldWidth
Don Gagne's avatar
Don Gagne committed
336 337 338
                        fact:                   missionItem.cameraResolutionWidth
                    }
                    FactTextField {
339
                        Layout.preferredWidth:  _root._fieldWidth
Don Gagne's avatar
Don Gagne committed
340 341 342 343
                        fact:                   missionItem.cameraResolutionHeight
                    }
                }

344 345 346 347 348
                RowLayout {
                    anchors.left:   parent.left
                    anchors.right:  parent.right
                    spacing:        _margin
                    QGCLabel {
349
                        text:                   qsTr("Focal length")
350 351 352 353 354 355
                        Layout.fillWidth:       true
                    }
                    FactTextField {
                        Layout.preferredWidth:  _root._fieldWidth
                        fact:                   missionItem.cameraFocalLength
                    }
Don Gagne's avatar
Don Gagne committed
356 357
                }

358
            } // Column - custom camera
Don Gagne's avatar
Don Gagne committed
359

360 361 362
            RowLayout {
                anchors.left:   parent.left
                anchors.right:  parent.right
Don Gagne's avatar
Don Gagne committed
363
                spacing:        _margin
364 365 366
                Item { Layout.fillWidth: true }
                QGCLabel {
                    Layout.preferredWidth:  _root._fieldWidth
367
                    text:                   qsTr("Front Lap")
Don Gagne's avatar
Don Gagne committed
368 369
                }
                QGCLabel {
370
                    Layout.preferredWidth:  _root._fieldWidth
371
                    text:                   qsTr("Side Lap")
Don Gagne's avatar
Don Gagne committed
372
                }
373
            }
Don Gagne's avatar
Don Gagne committed
374

375 376 377 378
            RowLayout {
                anchors.left:   parent.left
                anchors.right:  parent.right
                spacing:        _margin
379
                QGCLabel { text: qsTr("Overlap"); Layout.fillWidth: true }
Don Gagne's avatar
Don Gagne committed
380
                FactTextField {
381 382
                    Layout.preferredWidth:  _root._fieldWidth
                    fact:                   missionItem.frontalOverlap
Don Gagne's avatar
Don Gagne committed
383 384
                }
                FactTextField {
385 386
                    Layout.preferredWidth:  _root._fieldWidth
                    fact:                   missionItem.sideOverlap
Don Gagne's avatar
Don Gagne committed
387
                }
Don Gagne's avatar
Don Gagne committed
388 389
            }

390 391 392 393
            SectionHeader {
                id:     gridHeader
                text:   qsTr("Grid")
            }
Don Gagne's avatar
Don Gagne committed
394

395
            GridLayout {
Don Gagne's avatar
Don Gagne committed
396 397
                anchors.left:   parent.left
                anchors.right:  parent.right
398 399 400
                columnSpacing:  _margin
                rowSpacing:     _margin
                columns:        2
401
                visible:        gridHeader.checked
402

403 404 405 406 407
                GridLayout {
                    anchors.left:   parent.left
                    anchors.right:  parent.right
                    columnSpacing:  _margin
                    rowSpacing:     _margin
DonLakeFlyer's avatar
DonLakeFlyer committed
408
                    columns:        2
409 410 411
                    visible:        gridHeader.checked

                    QGCLabel {
DonLakeFlyer's avatar
DonLakeFlyer committed
412 413 414
                        id:                 angleText
                        text:               qsTr("Angle")
                        Layout.fillWidth:   true
415 416 417 418 419
                    }

                    ToolButton {
                        id:                     windRoseButton
                        anchors.verticalCenter: angleText.verticalCenter
420
                        iconSource:             qgcPal.globalTheme === QGCPalette.Light ? "/res/wind-roseBlack.svg" : "/res/wind-rose.svg"
DonLakeFlyer's avatar
DonLakeFlyer committed
421
                        visible:                _vehicle.fixedWing
422 423 424

                        onClicked: {
                            var cords = windRoseButton.mapToItem(_root, 0, 0)
425
                            windRosePie.popup(cords.x + windRoseButton.width / 2, cords.y + windRoseButton.height / 2);
426 427 428 429
                        }
                    }
                }

430
                FactTextField {
431
                    id:                 gridAngleText
432 433
                    fact:               missionItem.gridAngle
                    Layout.fillWidth:   true
434 435
                }

436
                QGCLabel { text: qsTr("Turnaround dist") }
437 438
                FactTextField {
                    fact:                   missionItem.turnaroundDist
439
                    Layout.fillWidth:       true
440
                }
Don Gagne's avatar
Don Gagne committed
441

442
                QGCCheckBox {
DonLakeFlyer's avatar
DonLakeFlyer committed
443 444 445 446
                    text:               qsTr("Refly at 90 degree offset")
                    checked:            missionItem.refly90Degrees
                    onClicked:          missionItem.refly90Degrees = checked
                    Layout.columnSpan:  2
447 448
                }

449
                QGCLabel {
DonLakeFlyer's avatar
DonLakeFlyer committed
450 451
                    wrapMode:               Text.WordWrap
                    text:                   qsTr("Select one:")
452
                    Layout.preferredWidth:  parent.width
DonLakeFlyer's avatar
DonLakeFlyer committed
453
                    Layout.columnSpan:      2
454
                }
Don Gagne's avatar
Don Gagne committed
455 456

                QGCRadioButton {
457
                    id:                     fixedAltitudeRadio
458
                    text:                   qsTr("Altitude")
459
                    checked:                !!missionItem.fixedValueIsAltitude.value
460
                    exclusiveGroup:         fixedValueGroup
461
                    onClicked:              missionItem.fixedValueIsAltitude.value = 1
Don Gagne's avatar
Don Gagne committed
462
                }
463

Don Gagne's avatar
Don Gagne committed
464
                FactTextField {
465 466
                    fact:                   missionItem.gridAltitude
                    enabled:                fixedAltitudeRadio.checked
467
                    Layout.fillWidth:       true
468
                }
Don Gagne's avatar
Don Gagne committed
469 470

                QGCRadioButton {
471
                    id:                     fixedGroundResolutionRadio
472
                    text:                   qsTr("Ground res")
473
                    checked:                !missionItem.fixedValueIsAltitude.value
474
                    exclusiveGroup:         fixedValueGroup
475
                    onClicked:              missionItem.fixedValueIsAltitude.value = 0
476 477
                }

Don Gagne's avatar
Don Gagne committed
478
                FactTextField {
479 480
                    fact:                   missionItem.groundResolution
                    enabled:                fixedGroundResolutionRadio.checked
481
                    Layout.fillWidth:       true
Don Gagne's avatar
Don Gagne committed
482 483 484 485 486
                }
            }
        }

        // Manual grid ui
487 488 489 490 491 492
        SectionHeader {
            id:         manualGridHeader
            text:       qsTr("Grid")
            visible:    gridTypeCombo.currentIndex == _gridTypeManual
        }

DonLakeFlyer's avatar
DonLakeFlyer committed
493
        GridLayout {
Don Gagne's avatar
Don Gagne committed
494 495
            anchors.left:   parent.left
            anchors.right:  parent.right
DonLakeFlyer's avatar
DonLakeFlyer committed
496 497 498
            columnSpacing:  _margin
            rowSpacing:     _margin
            columns:        2
499
            visible:        manualGridHeader.visible && manualGridHeader.checked
Don Gagne's avatar
Don Gagne committed
500

DonLakeFlyer's avatar
DonLakeFlyer committed
501 502
            RowLayout {
                spacing: _margin
503 504

                QGCLabel {
DonLakeFlyer's avatar
DonLakeFlyer committed
505 506
                    id:                 manualAngleText
                    text:               qsTr("Angle")
507 508 509 510 511 512 513 514
                    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"
DonLakeFlyer's avatar
DonLakeFlyer committed
515
                    visible:                _vehicle.fixedWing
516 517 518 519 520 521

                    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
522
            }
523

DonLakeFlyer's avatar
DonLakeFlyer committed
524 525 526 527
            FactTextField {
                id:                 manualGridAngleText
                fact:               missionItem.gridAngle
                Layout.fillWidth:   true
528 529
            }

DonLakeFlyer's avatar
DonLakeFlyer committed
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
            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
545
            }
Don Gagne's avatar
Don Gagne committed
546

547
            QGCCheckBox {
DonLakeFlyer's avatar
DonLakeFlyer committed
548 549 550 551
                text:               qsTr("Refly at 90 degree offset")
                checked:            missionItem.refly90Degrees
                onClicked:          missionItem.refly90Degrees = checked
                Layout.columnSpan:  2
552 553
            }

554
            FactCheckBox {
DonLakeFlyer's avatar
DonLakeFlyer committed
555 556 557 558
                anchors.left:       parent.left
                text:               qsTr("Relative altitude")
                fact:               missionItem.gridAltitudeRelative
                Layout.columnSpan:  2
Don Gagne's avatar
Don Gagne committed
559
            }
Don Gagne's avatar
Don Gagne committed
560 561
        }

562 563 564
        SectionHeader {
            id:     statsHeader
            text:   qsTr("Statistics") }
565 566

        Grid {
567 568
            columns:        2
            columnSpacing:  ScreenTools.defaultFontPixelWidth
569
            visible:        statsHeader.checked
570

571
            QGCLabel { text: qsTr("Survey area") }
572 573
            QGCLabel { text: QGroundControl.squareMetersToAppSettingsAreaUnits(missionItem.coveredArea).toFixed(2) + " " + QGroundControl.appSettingsAreaUnitsString }

574
            QGCLabel { text: qsTr("Photo count") }
575
            QGCLabel { text: missionItem.cameraShots }
576

577
            QGCLabel { text: qsTr("Photo interval") }
578 579 580 581 582 583 584 585 586
            QGCLabel {
                text: {
                    var timeVal = missionItem.timeBetweenShots
                    if(!isFinite(timeVal) || missionItem.cameraShots === 0) {
                        return qsTr("N/A")
                    }
                    return timeVal.toFixed(1) + " " + qsTr("secs")
                }
            }
587
        }
588
    }
589

590
    QGCColoredImage {
591 592 593 594 595 596
        id:      windRoseArrow
        source:  "/res/wind-rose-arrow.svg"
        visible: windRosePie.visible
        width:   windRosePie.width / 5
        height:  width * 1.454
        smooth:  true
597
        color:   qgcPal.colorGrey
598 599 600 601
        transform: Rotation {
            origin.x: windRoseArrow.width / 2
            origin.y: windRoseArrow.height / 2
            axis { x: 0; y: 0; z: 1 } angle: windRosePie.angle
602
        }
603 604
        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
605
        z: windRosePie.z + 1
606 607
    }

608
    QGCColoredImage {
609 610 611 612 613 614
        id:      windGuru
        source:  "/res/wind-guru.svg"
        visible: windRosePie.visible
        width:   windRosePie.width / 3
        height:  width * 4.28e-1
        smooth:  true
615
        color:   qgcPal.colorGrey
616 617 618 619 620
        transform: Rotation {
            origin.x: windGuru.width / 2
            origin.y: windGuru.height / 2
            axis { x: 0; y: 0; z: 1 } angle: windRosePie.angle + 180
        }
621 622 623
        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
624
    }
625

626 627 628 629 630
    Item {
        id:          windRosePie
        height:      2.6*windRoseButton.height
        width:       2.6*windRoseButton.width
        visible:     false
631
        focus:       true
632

633 634
        property string colorCircle: qgcPal.windowShade
        property string colorBackground: qgcPal.colorGrey
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662
        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()
            }
663 664
        }

665 666 667 668
        onFocusChanged: {
            visible = focus
        }

669 670 671 672 673
        function popup(x, y) {
            if (x !== undefined)
                windRosePie.x = x - windRosePie.width / 2;
            if (y !== undefined)
                windRosePie.y = y - windRosePie.height / 2;
674

675
            windRosePie.visible = true;
676
            windRosePie.focus = true
677
        }
678 679 680 681 682 683 684 685

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

            onClicked: {
                windRosePie.visible = false;
686
            }
687 688 689 690 691 692
            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
                gridAngleText.text = angle
693 694 695 696
                gridAngleText.editingFinished();
            }
        }
    }
697
}