SurveyItemEditor.qml 28.1 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 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
                }
            }
        }

Don Gagne's avatar
Don Gagne committed
257 258
        // Camera based grid ui
        Column {
Don Gagne's avatar
Don Gagne committed
259
            anchors.left:   parent.left
Don Gagne's avatar
Don Gagne committed
260 261 262
            anchors.right:  parent.right
            spacing:        _margin
            visible:        gridTypeCombo.currentIndex != _gridTypeManual
Don Gagne's avatar
Don Gagne committed
263

Don Gagne's avatar
Don Gagne committed
264
            Row {
265 266 267
                spacing:                    _margin
                anchors.horizontalCenter:   parent.horizontalCenter
                visible:                    !missionItem.cameraOrientationFixed
268

Don Gagne's avatar
Don Gagne committed
269 270 271
                QGCRadioButton {
                    width:          _editFieldWidth
                    text:           "Landscape"
272
                    checked:        !!missionItem.cameraOrientationLandscape.value
Don Gagne's avatar
Don Gagne committed
273
                    exclusiveGroup: cameraOrientationGroup
274
                    onClicked:      missionItem.cameraOrientationLandscape.value = 1
Don Gagne's avatar
Don Gagne committed
275
                }
276

Don Gagne's avatar
Don Gagne committed
277 278 279
                QGCRadioButton {
                    id:             cameraOrientationPortrait
                    text:           "Portrait"
280
                    checked:        !missionItem.cameraOrientationLandscape.value
Don Gagne's avatar
Don Gagne committed
281
                    exclusiveGroup: cameraOrientationGroup
282
                    onClicked:      missionItem.cameraOrientationLandscape.value = 0
Don Gagne's avatar
Don Gagne committed
283
                }
284 285
            }

Don Gagne's avatar
Don Gagne committed
286
            Column {
287
                id:             custCameraCol
Don Gagne's avatar
Don Gagne committed
288 289 290
                anchors.left:   parent.left
                anchors.right:  parent.right
                spacing:        _margin
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
                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
307

308 309 310 311
                RowLayout {
                    anchors.left:   parent.left
                    anchors.right:  parent.right
                    spacing:        _margin
312
                    QGCLabel { text: qsTr("Sensor"); Layout.fillWidth: true }
Don Gagne's avatar
Don Gagne committed
313
                    FactTextField {
314
                        Layout.preferredWidth:  _root._fieldWidth
Don Gagne's avatar
Don Gagne committed
315 316 317
                        fact:                   missionItem.cameraSensorWidth
                    }
                    FactTextField {
318
                        Layout.preferredWidth:  _root._fieldWidth
Don Gagne's avatar
Don Gagne committed
319 320
                        fact:                   missionItem.cameraSensorHeight
                    }
321
                }
Don Gagne's avatar
Don Gagne committed
322

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

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

352
            } // Column - custom camera
Don Gagne's avatar
Don Gagne committed
353

354 355 356
            RowLayout {
                anchors.left:   parent.left
                anchors.right:  parent.right
Don Gagne's avatar
Don Gagne committed
357
                spacing:        _margin
358 359 360
                Item { Layout.fillWidth: true }
                QGCLabel {
                    Layout.preferredWidth:  _root._fieldWidth
361
                    text:                   qsTr("Front Lap")
Don Gagne's avatar
Don Gagne committed
362 363
                }
                QGCLabel {
364
                    Layout.preferredWidth:  _root._fieldWidth
365
                    text:                   qsTr("Side Lap")
Don Gagne's avatar
Don Gagne committed
366
                }
367
            }
Don Gagne's avatar
Don Gagne committed
368

369 370 371 372
            RowLayout {
                anchors.left:   parent.left
                anchors.right:  parent.right
                spacing:        _margin
373
                QGCLabel { text: qsTr("Overlap"); Layout.fillWidth: true }
Don Gagne's avatar
Don Gagne committed
374
                FactTextField {
375 376
                    Layout.preferredWidth:  _root._fieldWidth
                    fact:                   missionItem.frontalOverlap
Don Gagne's avatar
Don Gagne committed
377 378
                }
                FactTextField {
379 380
                    Layout.preferredWidth:  _root._fieldWidth
                    fact:                   missionItem.sideOverlap
Don Gagne's avatar
Don Gagne committed
381
                }
Don Gagne's avatar
Don Gagne committed
382 383
            }

384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
            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
            }

401 402 403 404
            SectionHeader {
                id:     gridHeader
                text:   qsTr("Grid")
            }
Don Gagne's avatar
Don Gagne committed
405

406
            GridLayout {
Don Gagne's avatar
Don Gagne committed
407 408
                anchors.left:   parent.left
                anchors.right:  parent.right
409 410 411
                columnSpacing:  _margin
                rowSpacing:     _margin
                columns:        2
412
                visible:        gridHeader.checked
413

414 415 416 417 418
                GridLayout {
                    anchors.left:   parent.left
                    anchors.right:  parent.right
                    columnSpacing:  _margin
                    rowSpacing:     _margin
DonLakeFlyer's avatar
DonLakeFlyer committed
419
                    columns:        2
420 421 422
                    visible:        gridHeader.checked

                    QGCLabel {
DonLakeFlyer's avatar
DonLakeFlyer committed
423 424 425
                        id:                 angleText
                        text:               qsTr("Angle")
                        Layout.fillWidth:   true
426 427 428 429 430
                    }

                    ToolButton {
                        id:                     windRoseButton
                        anchors.verticalCenter: angleText.verticalCenter
431
                        iconSource:             qgcPal.globalTheme === QGCPalette.Light ? "/res/wind-roseBlack.svg" : "/res/wind-rose.svg"
432 433
                        // Wind Rose is temporarily turned off until bugs are fixed
                        visible:                false//_vehicle.fixedWing
434 435 436

                        onClicked: {
                            var cords = windRoseButton.mapToItem(_root, 0, 0)
437
                            windRosePie.popup(cords.x + windRoseButton.width / 2, cords.y + windRoseButton.height / 2);
438 439 440 441
                        }
                    }
                }

442
                FactTextField {
443
                    id:                 gridAngleText
444 445
                    fact:               missionItem.gridAngle
                    Layout.fillWidth:   true
446 447
                }

448
                QGCLabel { text: qsTr("Turnaround dist") }
449 450
                FactTextField {
                    fact:                   missionItem.turnaroundDist
451
                    Layout.fillWidth:       true
452
                }
Don Gagne's avatar
Don Gagne committed
453

DonLakeFlyer's avatar
DonLakeFlyer committed
454 455 456 457 458 459 460
                QGCLabel { text: qsTr("Entry") }
                FactComboBox {
                    fact:                   missionItem.gridEntryLocation
                    indexModel:             false
                    Layout.fillWidth:       true
                }

461
                QGCCheckBox {
DonLakeFlyer's avatar
DonLakeFlyer committed
462 463 464 465
                    text:               qsTr("Refly at 90 degree offset")
                    checked:            missionItem.refly90Degrees
                    onClicked:          missionItem.refly90Degrees = checked
                    Layout.columnSpan:  2
466 467
                }

468
                QGCLabel {
DonLakeFlyer's avatar
DonLakeFlyer committed
469 470
                    wrapMode:               Text.WordWrap
                    text:                   qsTr("Select one:")
471
                    Layout.preferredWidth:  parent.width
DonLakeFlyer's avatar
DonLakeFlyer committed
472
                    Layout.columnSpan:      2
473
                }
Don Gagne's avatar
Don Gagne committed
474 475

                QGCRadioButton {
476
                    id:                     fixedAltitudeRadio
477
                    text:                   qsTr("Altitude")
478
                    checked:                !!missionItem.fixedValueIsAltitude.value
479
                    exclusiveGroup:         fixedValueGroup
480
                    onClicked:              missionItem.fixedValueIsAltitude.value = 1
Don Gagne's avatar
Don Gagne committed
481
                }
482

Don Gagne's avatar
Don Gagne committed
483
                FactTextField {
484 485
                    fact:                   missionItem.gridAltitude
                    enabled:                fixedAltitudeRadio.checked
486
                    Layout.fillWidth:       true
487
                }
Don Gagne's avatar
Don Gagne committed
488 489

                QGCRadioButton {
490
                    id:                     fixedGroundResolutionRadio
491
                    text:                   qsTr("Ground res")
492
                    checked:                !missionItem.fixedValueIsAltitude.value
493
                    exclusiveGroup:         fixedValueGroup
494
                    onClicked:              missionItem.fixedValueIsAltitude.value = 0
495 496
                }

Don Gagne's avatar
Don Gagne committed
497
                FactTextField {
498 499
                    fact:                   missionItem.groundResolution
                    enabled:                fixedGroundResolutionRadio.checked
500
                    Layout.fillWidth:       true
Don Gagne's avatar
Don Gagne committed
501 502 503 504 505
                }
            }
        }

        // Manual grid ui
506 507 508 509 510 511
        SectionHeader {
            id:         manualGridHeader
            text:       qsTr("Grid")
            visible:    gridTypeCombo.currentIndex == _gridTypeManual
        }

DonLakeFlyer's avatar
DonLakeFlyer committed
512
        GridLayout {
Don Gagne's avatar
Don Gagne committed
513 514
            anchors.left:   parent.left
            anchors.right:  parent.right
DonLakeFlyer's avatar
DonLakeFlyer committed
515 516 517
            columnSpacing:  _margin
            rowSpacing:     _margin
            columns:        2
518
            visible:        manualGridHeader.visible && manualGridHeader.checked
Don Gagne's avatar
Don Gagne committed
519

DonLakeFlyer's avatar
DonLakeFlyer committed
520 521
            RowLayout {
                spacing: _margin
522 523

                QGCLabel {
DonLakeFlyer's avatar
DonLakeFlyer committed
524 525
                    id:                 manualAngleText
                    text:               qsTr("Angle")
526 527 528 529 530 531 532 533
                    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"
534 535
                    // Wind Rose is temporarily turned off until bugs are fixed
                    visible:                false//_vehicle.fixedWing
536 537 538 539 540 541

                    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
542
            }
543

DonLakeFlyer's avatar
DonLakeFlyer committed
544 545 546 547
            FactTextField {
                id:                 manualGridAngleText
                fact:               missionItem.gridAngle
                Layout.fillWidth:   true
548 549
            }

DonLakeFlyer's avatar
DonLakeFlyer committed
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564
            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
565
            }
DonLakeFlyer's avatar
DonLakeFlyer committed
566 567 568 569 570 571 572
            QGCLabel { text: qsTr("Entry") }
            FactComboBox {
                fact:                   missionItem.gridEntryLocation
                indexModel:             false
                Layout.fillWidth:       true
            }

Don Gagne's avatar
Don Gagne committed
573

574
            QGCCheckBox {
DonLakeFlyer's avatar
DonLakeFlyer committed
575 576 577 578
                text:               qsTr("Refly at 90 degree offset")
                checked:            missionItem.refly90Degrees
                onClicked:          missionItem.refly90Degrees = checked
                Layout.columnSpan:  2
579 580
            }

581
            FactCheckBox {
DonLakeFlyer's avatar
DonLakeFlyer committed
582 583 584 585
                anchors.left:       parent.left
                text:               qsTr("Relative altitude")
                fact:               missionItem.gridAltitudeRelative
                Layout.columnSpan:  2
Don Gagne's avatar
Don Gagne committed
586
            }
Don Gagne's avatar
Don Gagne committed
587 588
        }

589 590 591
        SectionHeader {
            id:     statsHeader
            text:   qsTr("Statistics") }
592 593

        Grid {
594 595
            columns:        2
            columnSpacing:  ScreenTools.defaultFontPixelWidth
596
            visible:        statsHeader.checked
597

598
            QGCLabel { text: qsTr("Survey area") }
599 600
            QGCLabel { text: QGroundControl.squareMetersToAppSettingsAreaUnits(missionItem.coveredArea).toFixed(2) + " " + QGroundControl.appSettingsAreaUnitsString }

601
            QGCLabel { text: qsTr("Photo count") }
602
            QGCLabel { text: missionItem.cameraShots }
603

604
            QGCLabel { text: qsTr("Photo interval") }
605 606 607 608 609 610 611 612 613
            QGCLabel {
                text: {
                    var timeVal = missionItem.timeBetweenShots
                    if(!isFinite(timeVal) || missionItem.cameraShots === 0) {
                        return qsTr("N/A")
                    }
                    return timeVal.toFixed(1) + " " + qsTr("secs")
                }
            }
614
        }
615
    }
616

617
    QGCColoredImage {
618 619 620 621 622 623
        id:      windRoseArrow
        source:  "/res/wind-rose-arrow.svg"
        visible: windRosePie.visible
        width:   windRosePie.width / 5
        height:  width * 1.454
        smooth:  true
624
        color:   qgcPal.colorGrey
625 626 627 628
        transform: Rotation {
            origin.x: windRoseArrow.width / 2
            origin.y: windRoseArrow.height / 2
            axis { x: 0; y: 0; z: 1 } angle: windRosePie.angle
629
        }
630 631
        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
632
        z: windRosePie.z + 1
633 634
    }

635
    QGCColoredImage {
636 637 638 639 640 641
        id:      windGuru
        source:  "/res/wind-guru.svg"
        visible: windRosePie.visible
        width:   windRosePie.width / 3
        height:  width * 4.28e-1
        smooth:  true
642
        color:   qgcPal.colorGrey
643 644 645 646 647
        transform: Rotation {
            origin.x: windGuru.width / 2
            origin.y: windGuru.height / 2
            axis { x: 0; y: 0; z: 1 } angle: windRosePie.angle + 180
        }
648 649 650
        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
651
    }
652

653 654 655 656 657
    Item {
        id:          windRosePie
        height:      2.6*windRoseButton.height
        width:       2.6*windRoseButton.width
        visible:     false
658
        focus:       true
659

660 661
        property string colorCircle: qgcPal.windowShade
        property string colorBackground: qgcPal.colorGrey
662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
        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()
            }
690 691
        }

692 693 694 695
        onFocusChanged: {
            visible = focus
        }

696 697 698 699 700
        function popup(x, y) {
            if (x !== undefined)
                windRosePie.x = x - windRosePie.width / 2;
            if (y !== undefined)
                windRosePie.y = y - windRosePie.height / 2;
701

702
            windRosePie.visible = true;
703
            windRosePie.focus = true
704
        }
705 706 707 708 709 710 711 712

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

            onClicked: {
                windRosePie.visible = false;
713
            }
714 715 716 717 718
            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
719
                gridAngleText.text = - angle
720 721 722 723
                gridAngleText.editingFinished();
            }
        }
    }
724
}