SurveyItemEditor.qml 27.5 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
    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
33
    property var    _vehicleCameraList: _vehicle.staticCcameraList
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
    Component.onCompleted: {
40 41
        for (var i=0; i<_vehicle.staticCcameraList.length; i++) {
            _cameraList.push(_vehicle.staticCcameraList[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

            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

DonLakeFlyer's avatar
DonLakeFlyer committed
442 443 444 445 446 447 448
                QGCLabel { text: qsTr("Entry") }
                FactComboBox {
                    fact:                   missionItem.gridEntryLocation
                    indexModel:             false
                    Layout.fillWidth:       true
                }

449
                QGCCheckBox {
DonLakeFlyer's avatar
DonLakeFlyer committed
450 451 452 453
                    text:               qsTr("Refly at 90 degree offset")
                    checked:            missionItem.refly90Degrees
                    onClicked:          missionItem.refly90Degrees = checked
                    Layout.columnSpan:  2
454 455
                }

456
                QGCLabel {
DonLakeFlyer's avatar
DonLakeFlyer committed
457 458
                    wrapMode:               Text.WordWrap
                    text:                   qsTr("Select one:")
459
                    Layout.preferredWidth:  parent.width
DonLakeFlyer's avatar
DonLakeFlyer committed
460
                    Layout.columnSpan:      2
461
                }
Don Gagne's avatar
Don Gagne committed
462 463

                QGCRadioButton {
464
                    id:                     fixedAltitudeRadio
465
                    text:                   qsTr("Altitude")
466
                    checked:                !!missionItem.fixedValueIsAltitude.value
467
                    exclusiveGroup:         fixedValueGroup
468
                    onClicked:              missionItem.fixedValueIsAltitude.value = 1
Don Gagne's avatar
Don Gagne committed
469
                }
470

Don Gagne's avatar
Don Gagne committed
471
                FactTextField {
472 473
                    fact:                   missionItem.gridAltitude
                    enabled:                fixedAltitudeRadio.checked
474
                    Layout.fillWidth:       true
475
                }
Don Gagne's avatar
Don Gagne committed
476 477

                QGCRadioButton {
478
                    id:                     fixedGroundResolutionRadio
479
                    text:                   qsTr("Ground res")
480
                    checked:                !missionItem.fixedValueIsAltitude.value
481
                    exclusiveGroup:         fixedValueGroup
482
                    onClicked:              missionItem.fixedValueIsAltitude.value = 0
483 484
                }

Don Gagne's avatar
Don Gagne committed
485
                FactTextField {
486 487
                    fact:                   missionItem.groundResolution
                    enabled:                fixedGroundResolutionRadio.checked
488
                    Layout.fillWidth:       true
Don Gagne's avatar
Don Gagne committed
489 490 491 492 493
                }
            }
        }

        // Manual grid ui
494 495 496 497 498 499
        SectionHeader {
            id:         manualGridHeader
            text:       qsTr("Grid")
            visible:    gridTypeCombo.currentIndex == _gridTypeManual
        }

DonLakeFlyer's avatar
DonLakeFlyer committed
500
        GridLayout {
Don Gagne's avatar
Don Gagne committed
501 502
            anchors.left:   parent.left
            anchors.right:  parent.right
DonLakeFlyer's avatar
DonLakeFlyer committed
503 504 505
            columnSpacing:  _margin
            rowSpacing:     _margin
            columns:        2
506
            visible:        manualGridHeader.visible && manualGridHeader.checked
Don Gagne's avatar
Don Gagne committed
507

DonLakeFlyer's avatar
DonLakeFlyer committed
508 509
            RowLayout {
                spacing: _margin
510 511

                QGCLabel {
DonLakeFlyer's avatar
DonLakeFlyer committed
512 513
                    id:                 manualAngleText
                    text:               qsTr("Angle")
514 515 516 517 518 519 520 521
                    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
522
                    visible:                _vehicle.fixedWing
523 524 525 526 527 528

                    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
529
            }
530

DonLakeFlyer's avatar
DonLakeFlyer committed
531 532 533 534
            FactTextField {
                id:                 manualGridAngleText
                fact:               missionItem.gridAngle
                Layout.fillWidth:   true
535 536
            }

DonLakeFlyer's avatar
DonLakeFlyer committed
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
            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
552
            }
DonLakeFlyer's avatar
DonLakeFlyer committed
553 554 555 556 557 558 559
            QGCLabel { text: qsTr("Entry") }
            FactComboBox {
                fact:                   missionItem.gridEntryLocation
                indexModel:             false
                Layout.fillWidth:       true
            }

Don Gagne's avatar
Don Gagne committed
560

561
            QGCCheckBox {
DonLakeFlyer's avatar
DonLakeFlyer committed
562 563 564 565
                text:               qsTr("Refly at 90 degree offset")
                checked:            missionItem.refly90Degrees
                onClicked:          missionItem.refly90Degrees = checked
                Layout.columnSpan:  2
566 567
            }

568
            FactCheckBox {
DonLakeFlyer's avatar
DonLakeFlyer committed
569 570 571 572
                anchors.left:       parent.left
                text:               qsTr("Relative altitude")
                fact:               missionItem.gridAltitudeRelative
                Layout.columnSpan:  2
Don Gagne's avatar
Don Gagne committed
573
            }
Don Gagne's avatar
Don Gagne committed
574 575
        }

576 577 578
        SectionHeader {
            id:     statsHeader
            text:   qsTr("Statistics") }
579 580

        Grid {
581 582
            columns:        2
            columnSpacing:  ScreenTools.defaultFontPixelWidth
583
            visible:        statsHeader.checked
584

585
            QGCLabel { text: qsTr("Survey area") }
586 587
            QGCLabel { text: QGroundControl.squareMetersToAppSettingsAreaUnits(missionItem.coveredArea).toFixed(2) + " " + QGroundControl.appSettingsAreaUnitsString }

588
            QGCLabel { text: qsTr("Photo count") }
589
            QGCLabel { text: missionItem.cameraShots }
590

591
            QGCLabel { text: qsTr("Photo interval") }
592 593 594 595 596 597 598 599 600
            QGCLabel {
                text: {
                    var timeVal = missionItem.timeBetweenShots
                    if(!isFinite(timeVal) || missionItem.cameraShots === 0) {
                        return qsTr("N/A")
                    }
                    return timeVal.toFixed(1) + " " + qsTr("secs")
                }
            }
601
        }
602
    }
603

604
    QGCColoredImage {
605 606 607 608 609 610
        id:      windRoseArrow
        source:  "/res/wind-rose-arrow.svg"
        visible: windRosePie.visible
        width:   windRosePie.width / 5
        height:  width * 1.454
        smooth:  true
611
        color:   qgcPal.colorGrey
612 613 614 615
        transform: Rotation {
            origin.x: windRoseArrow.width / 2
            origin.y: windRoseArrow.height / 2
            axis { x: 0; y: 0; z: 1 } angle: windRosePie.angle
616
        }
617 618
        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
619
        z: windRosePie.z + 1
620 621
    }

622
    QGCColoredImage {
623 624 625 626 627 628
        id:      windGuru
        source:  "/res/wind-guru.svg"
        visible: windRosePie.visible
        width:   windRosePie.width / 3
        height:  width * 4.28e-1
        smooth:  true
629
        color:   qgcPal.colorGrey
630 631 632 633 634
        transform: Rotation {
            origin.x: windGuru.width / 2
            origin.y: windGuru.height / 2
            axis { x: 0; y: 0; z: 1 } angle: windRosePie.angle + 180
        }
635 636 637
        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
638
    }
639

640 641 642 643 644
    Item {
        id:          windRosePie
        height:      2.6*windRoseButton.height
        width:       2.6*windRoseButton.width
        visible:     false
645
        focus:       true
646

647 648
        property string colorCircle: qgcPal.windowShade
        property string colorBackground: qgcPal.colorGrey
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676
        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()
            }
677 678
        }

679 680 681 682
        onFocusChanged: {
            visible = focus
        }

683 684 685 686 687
        function popup(x, y) {
            if (x !== undefined)
                windRosePie.x = x - windRosePie.width / 2;
            if (y !== undefined)
                windRosePie.y = y - windRosePie.height / 2;
688

689
            windRosePie.visible = true;
690
            windRosePie.focus = true
691
        }
692 693 694 695 696 697 698 699

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

            onClicked: {
                windRosePie.visible = false;
700
            }
701 702 703 704 705
            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
706
                gridAngleText.text = - angle
707 708 709 710
                gridAngleText.editingFinished();
            }
        }
    }
711
}