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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    Connections {
        target: missionItem

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

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

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

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

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

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

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

190
        Column {
Don Gagne's avatar
Don Gagne committed
191 192
            anchors.left:   parent.left
            anchors.right:  parent.right
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
            spacing:        _margin
            visible:        cameraHeader.checked

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

                onActivated: {
                    if (index == _gridTypeManual) {
                        missionItem.manualGrid.value = true
                    } else if (index == _gridTypeCustomCamera) {
                        missionItem.manualGrid.value = false
                        missionItem.camera.value = gridTypeCombo.textAt(index)
                        missionItem.cameraOrientationFixed = false
                    } else {
                        missionItem.manualGrid.value = false
                        missionItem.camera.value = gridTypeCombo.textAt(index)
                        _noCameraValueRecalc = true
                        var listIndex = index - _gridTypeCamera
                        missionItem.cameraSensorWidth.rawValue          = _vehicleCameraList[listIndex].sensorWidth
                        missionItem.cameraSensorHeight.rawValue         = _vehicleCameraList[listIndex].sensorHeight
                        missionItem.cameraResolutionWidth.rawValue      = _vehicleCameraList[listIndex].imageWidth
                        missionItem.cameraResolutionHeight.rawValue     = _vehicleCameraList[listIndex].imageHeight
                        missionItem.cameraFocalLength.rawValue          = _vehicleCameraList[listIndex].focalLength
                        missionItem.cameraOrientationLandscape.rawValue = _vehicleCameraList[listIndex].landscape ? 1 : 0
                        missionItem.cameraOrientationFixed              = _vehicleCameraList[listIndex].fixedOrientation
                        _noCameraValueRecalc = false
                        recalcFromCameraValues()
                    }
                }
            }

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

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

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

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

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

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

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

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

Don Gagne's avatar
Don Gagne committed
292
            Column {
293
                id:             custCameraCol
Don Gagne's avatar
Don Gagne committed
294 295 296
                anchors.left:   parent.left
                anchors.right:  parent.right
                spacing:        _margin
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
                visible:        gridTypeCombo.currentIndex === _gridTypeCustomCamera

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

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

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

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

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

360 361 362
            RowLayout {
                anchors.left:   parent.left
                anchors.right:  parent.right
Don Gagne's avatar
Don Gagne committed
363
                spacing:        _margin
364 365 366 367
                Item { Layout.fillWidth: true }
                QGCLabel {
                    Layout.preferredWidth:  _root._fieldWidth
                    text:                   qsTr("Frontal")
Don Gagne's avatar
Don Gagne committed
368 369
                }
                QGCLabel {
370 371
                    Layout.preferredWidth:  _root._fieldWidth
                    text:                   qsTr("Side")
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 408 409 410 411 412 413 414 415 416 417
                GridLayout {
                    anchors.left:   parent.left
                    anchors.right:  parent.right
                    columnSpacing:  _margin
                    rowSpacing:     _margin
                    columns:        3
                    visible:        gridHeader.checked

                    QGCLabel {
                        id:         angleText
                        text:       qsTr("Angle")
                    }

                    Item { Layout.fillWidth: true }

418
                    property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
419 420 421
                    ToolButton {
                        id:                     windRoseButton
                        anchors.verticalCenter: angleText.verticalCenter
422
                        iconSource:             qgcPal.globalTheme === QGCPalette.Light ? "/res/wind-roseBlack.svg" : "/res/wind-rose.svg"
423
                        visible: _activeVehicle ? _activeVehicle.fixedWing : true
424 425 426

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

432
                FactTextField {
433
                    id:                 gridAngleText
434 435
                    fact:               missionItem.gridAngle
                    Layout.fillWidth:   true
436
                    Layout.columnSpan:  1
437 438
                }

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

445 446 447 448 449 450 451
                QGCCheckBox {
                    text:       qsTr("Refly at 90 degree offset")
                    checked:    missionItem.refly90Degrees
                    onClicked:  missionItem.refly90Degrees = checked
                    Layout.columnSpan: 2
                }

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

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

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

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

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

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

496
        Column {
Don Gagne's avatar
Don Gagne committed
497 498 499
            anchors.left:   parent.left
            anchors.right:  parent.right
            spacing:        _margin
500
            visible:        manualGridHeader.visible && manualGridHeader.checked
Don Gagne's avatar
Don Gagne committed
501

502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
            GridLayout {
                anchors.left:   parent.left
                anchors.right:  parent.right
                columnSpacing:  _margin
                rowSpacing:     _margin
                columns:        4
                visible:        gridHeader.checked

                QGCLabel {
                    id:         manualAngleText
                    text:       qsTr("Angle")
                    Layout.columnSpan: 1
                    Layout.fillWidth:  true
                }

                property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
                ToolButton {
                    id:                     manualWindRoseButton
                    anchors.verticalCenter: manualAngleText.verticalCenter
                    Layout.columnSpan:      1
                    iconSource:             qgcPal.globalTheme === QGCPalette.Light ? "/res/wind-roseBlack.svg" : "/res/wind-rose.svg"
                    visible: _activeVehicle ? _activeVehicle.fixedWing : true

                    onClicked: {
                        var cords = manualWindRoseButton.mapToItem(_root, 0, 0)
                        windRosePie.popup(cords.x + manualWindRoseButton.width / 2, cords.y + manualWindRoseButton.height / 2);
                    }
                }

                FactTextField {
                    id:                 manualGridAngleText
                    fact:               missionItem.gridAngle
                    Layout.columnSpan:  2
                }
            }

Don Gagne's avatar
Don Gagne committed
538 539 540
            FactTextFieldGrid {
                anchors.left:   parent.left
                anchors.right:  parent.right
541
                columnSpacing:  ScreenTools.defaultFontPixelWidth
Don Gagne's avatar
Don Gagne committed
542
                rowSpacing:     _margin
543 544
                factList:       [ missionItem.gridSpacing, missionItem.gridAltitude, missionItem.turnaroundDist ]
                factLabels:     [ qsTr("Spacing"), qsTr("Altitude"), qsTr("Turnaround dist")]
Don Gagne's avatar
Don Gagne committed
545
            }
Don Gagne's avatar
Don Gagne committed
546

547 548 549 550 551 552
            QGCCheckBox {
                text:       qsTr("Refly at 90 degree offset")
                checked:    missionItem.refly90Degrees
                onClicked:  missionItem.refly90Degrees = checked
            }

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

560 561 562
        SectionHeader {
            id:     statsHeader
            text:   qsTr("Statistics") }
563 564

        Grid {
565 566
            columns:        2
            columnSpacing:  ScreenTools.defaultFontPixelWidth
567
            visible:        statsHeader.checked
568

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

572
            QGCLabel { text: qsTr("Photo count") }
573
            QGCLabel { text: missionItem.cameraShots }
574

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

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

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

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

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

663 664 665 666
        onFocusChanged: {
            visible = focus
        }

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

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

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

            onClicked: {
                windRosePie.visible = false;
684
            }
685 686 687 688 689 690
            onPositionChanged: {
                var point = Qt.point(mouseX - parent.width / 2, mouseY - parent.height / 2)
                var angle = Math.round(Math.atan2(point.y, point.x) * 180 / Math.PI)
                windRoseCanvas.requestPaint()
                windRosePie.angle = angle
                gridAngleText.text = angle
691 692 693 694
                gridAngleText.editingFinished();
            }
        }
    }
695
}