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

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

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

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

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

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

39 40 41
    Component.onCompleted: {
        for (var i=0; i<_vehicle.cameraList.length; i++) {
            _cameraList.push(_vehicle.cameraList[i].name)
Don Gagne's avatar
Don Gagne committed
42
        }
43
        gridTypeCombo.model = _cameraList
44
        if (missionItem.manualGrid.value) {
45 46
            gridTypeCombo.currentIndex = _gridTypeManual
        } else {
47 48 49 50 51 52
            var index = -1
            for (index=0; index<_cameraList.length; index++) {
                if (_cameraList[index] == missionItem.camera.value) {
                    break;
                }
            }
53
            missionItem.cameraOrientationFixed = false
Don Gagne's avatar
Don Gagne committed
54 55
            if (index == _cameraList.length) {
                gridTypeCombo.currentIndex = _gridTypeCustomCamera
56 57
            } else {
                gridTypeCombo.currentIndex = index
58 59 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"
DonLakeFlyer's avatar
DonLakeFlyer committed
432
                        visible:                _vehicle.fixedWing
433 434 435

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

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

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

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

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

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

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

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

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

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

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

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

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

                QGCLabel {
DonLakeFlyer's avatar
DonLakeFlyer committed
523 524
                    id:                 manualAngleText
                    text:               qsTr("Angle")
525 526 527 528 529 530 531 532
                    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
533
                    visible:                _vehicle.fixedWing
534 535 536 537 538 539

                    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
540
            }
541

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

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

Don Gagne's avatar
Don Gagne committed
571

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

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

587 588 589
        SectionHeader {
            id:     statsHeader
            text:   qsTr("Statistics") }
590 591

        Grid {
592 593
            columns:        2
            columnSpacing:  ScreenTools.defaultFontPixelWidth
594
            visible:        statsHeader.checked
595

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

599
            QGCLabel { text: qsTr("Photo count") }
600
            QGCLabel { text: missionItem.cameraShots }
601

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

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

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

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

658 659
        property string colorCircle: qgcPal.windowShade
        property string colorBackground: qgcPal.colorGrey
660 661 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
        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()
            }
688 689
        }

690 691 692 693
        onFocusChanged: {
            visible = focus
        }

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

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

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

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