CustomCameraControl.qml 55.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/****************************************************************************
 *
 * (c) 2009-2019 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 * @file
 *   @author Gus Grubba <gus@auterion.com>
 */

import QtQuick                  2.11
import QtQuick.Controls         2.4
import QtQuick.Layouts          1.11
import QtQuick.Dialogs          1.3
16
import QtGraphicalEffects       1.0
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

import QtMultimedia             5.9
import QtPositioning            5.2

import QGroundControl                   1.0
import QGroundControl.Controls          1.0
import QGroundControl.FactControls      1.0
import QGroundControl.FactSystem        1.0
import QGroundControl.FlightMap         1.0
import QGroundControl.Palette           1.0
import QGroundControl.ScreenTools       1.0
import QGroundControl.Vehicle           1.0

import CustomQuickInterface             1.0
import Custom.Widgets                   1.0
32
import Custom.Camera                    1.0
33 34

Item {
35
    id:             _root
36 37
    height:         mainColumn.height
    width:          mainColumn.width + (ScreenTools.defaultFontPixelWidth * 2)
38 39
    visible:        !QGroundControl.videoManager.fullScreen

40
    readonly property string _commLostStr:  qsTr("NO CAMERA")
41
    readonly property real   buttonSize:    ScreenTools.defaultFontPixelWidth * 5
42

43
    property real   _spacers:               ScreenTools.defaultFontPixelHeight * 0.5
Gus Grubba's avatar
Gus Grubba committed
44 45 46
    property real   _labelFieldWidth:       ScreenTools.defaultFontPixelWidth  * 28
    property real   _editFieldWidth:        ScreenTools.defaultFontPixelWidth  * 30
    property real   _editFieldHeight:       ScreenTools.defaultFontPixelHeight * 2
47 48
    property var    _videoReceiver:         QGroundControl.videoManager.videoReceiver
    property bool   _recordingLocalVideo:   _videoReceiver && _videoReceiver.recording
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

    property var    _dynamicCameras:        activeVehicle ? activeVehicle.dynamicCameras : null
    property bool   _isCamera:              _dynamicCameras ? _dynamicCameras.cameras.count > 0 : false
    property int    _curCameraIndex:        _dynamicCameras ? _dynamicCameras.currentCamera : 0
    property var    _camera:                _isCamera ? _dynamicCameras.cameras.get(_curCameraIndex) : null
    property bool   _communicationLost:     activeVehicle ? activeVehicle.connectionLost : false
    property bool   _noSdCard:              _camera && _camera.storageTotal === 0
    property bool   _fullSD:                _camera && _camera.storageTotal !== 0 && _camera.storageFree > 0 && _camera.storageFree < 250 // We get kiB from the camera
    property bool   _cameraVideoMode:       !_communicationLost && (_noSdCard ? false : _camera && _camera.cameraMode   === QGCCameraControl.CAM_MODE_VIDEO)
    property bool   _cameraPhotoMode:       !_communicationLost && (_noSdCard ? false : _camera && (_camera.cameraMode  === QGCCameraControl.CAM_MODE_PHOTO || _camera.cameraMode === QGCCameraControl.CAM_MODE_SURVEY))
    property bool   _cameraPhotoIdle:       !_communicationLost && (_noSdCard ? false : _camera && _camera.photoStatus  === QGCCameraControl.PHOTO_CAPTURE_IDLE)
    property bool   _cameraElapsedMode:     !_communicationLost && (_noSdCard ? false : _camera && _camera.cameraMode   === QGCCameraControl.CAM_MODE_PHOTO && _camera.photoMode === QGCCameraControl.PHOTO_CAPTURE_TIMELAPSE)
    property bool   _cameraModeUndefined:   !_cameraPhotoMode && !_cameraVideoMode
    property bool   _recordingVideo:        _cameraVideoMode && _camera.videoStatus === QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING
    property bool   _settingsEnabled:       !_communicationLost && _camera && _camera.cameraMode !== QGCCameraControl.CAM_MODE_UNDEFINED && _camera.photoStatus === QGCCameraControl.PHOTO_CAPTURE_IDLE && !_recordingVideo
    property bool   _hasZoom:               _camera && _camera.hasZoom
65
    property Fact   _irPaletteFact:         _camera ? _camera.irPalette : null
66 67 68 69
    property bool   _isShortScreen:         mainWindow.height / ScreenTools.realPixelDensity < 120
    property real   _gimbalPitch:           activeVehicle ? -activeVehicle.gimbalPitch : 0
    property real   _gimbalYaw:             activeVehicle ? activeVehicle.gimbalYaw : 0
    property bool   _hasGimbal:             activeVehicle && activeVehicle.gimbalData
70 71 72 73 74 75 76 77 78 79 80 81 82
    Connections {
        target: QGroundControl.multiVehicleManager.activeVehicle
        onConnectionLostChanged: {
            if(_communicationLost && cameraSettings.visible) {
                cameraSettings.close()
            }
        }
    }

    DeadMouseArea {
        anchors.fill:   parent
    }

83 84 85 86
    //-------------------------------------------------------------------------
    //-- Main Column
    Column {
        id:             mainColumn
87
        spacing:        _spacers
88 89 90
        anchors.centerIn: parent
        //---------------------------------------------------------------------
        //-- Quick Thermal Modes
91
        Item {
92
            id:             thermalBackgroundRect
93 94
            width:          buttonsRow.width  + (ScreenTools.defaultFontPixelWidth  * 4)
            height:         buttonsRow.height + (ScreenTools.defaultFontPixelHeight)
95
            visible:        QGroundControl.videoManager.hasThermal || _irPaletteFact || _camera.vendor === "NextVision"
96
            anchors.horizontalCenter: parent.horizontalCenter
97 98 99 100 101 102 103 104 105
            Component.onCompleted: {
                if(_irPaletteFact && QGroundControl.videoManager.hasThermal) {
                    if(_camera.thermalMode === QGCCameraControl.THERMAL_OFF)
                        standardMode.checked = true
                    if(_camera.thermalMode === QGCCameraControl.THERMAL_PIP)
                        thermalPip.checked = true
                    if(_camera.thermalMode === QGCCameraControl.THERMAL_FULL)
                        thermalFull.checked = true
                }
106 107
                else
                    standardMode.checked = true
108
            }
109 110 111 112
            ButtonGroup {
                id:         buttonGroup
                exclusive:  true
                buttons:    buttonsRow.children
113
            }
114 115
            Row {
                id:                     buttonsRow
116
                spacing:                ScreenTools.defaultFontPixelWidth * 0.5
117 118
                anchors.centerIn:       parent
                //-- Standard
119 120
                CustomQuickButton {
                    id:                 standardMode
121
                    width:              buttonSize
122 123
                    height:             buttonSize
                    iconSource:        "/custom/img/thermal-standard.svg"
124 125
                    onClicked:  {
                        _camera.thermalMode = QGCCameraControl.THERMAL_OFF
126 127
                    }
                }
128
                //-- PIP
129 130
                CustomQuickButton {
                    id:                 thermalPip
131
                    width:              buttonSize
132 133 134 135 136
                    height:             buttonSize
                    visible:            _camera.vendor !== "NextVision"
                    iconSource:        "/custom/img/thermal-pip.svg"
                    onClicked:  {
                        _camera.thermalMode = QGCCameraControl.THERMAL_PIP
137 138
                    }
                }
139 140 141
                // Thermal
                CustomQuickButton {
                    id:                 thermalFull
142
                    width:              buttonSize
143 144 145 146
                    height:             buttonSize
                    iconSource:         "/custom/img/thermal-brightness.svg"
                    onClicked:  {
                        _camera.thermalMode = QGCCameraControl.THERMAL_FULL
147 148
                    }
                }
149 150 151
                // Thermal palette options
                CustomQuickButton {
                    checkable:          false
152
                    width:              buttonSize
153
                    height:             buttonSize
154
                    visible:            _irPaletteFact
155 156
                    iconSource:        "/custom/img/thermal-palette.svg"
                    onClicked:  {
157
                        thermalPalettes.open()
158 159 160 161 162 163
                    }
                }
            }
        }
        //---------------------------------------------------------------------
        //-- Main Camera Control
164 165
        Row {
            spacing:            ScreenTools.defaultFontPixelWidth * 0.5
166
            anchors.horizontalCenter: parent.horizontalCenter
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
            Rectangle {
                id:             cameraRect
                height:         cameraCol.height
                width:          cameraCol.width + (ScreenTools.defaultFontPixelWidth * 4)
                color:          qgcPal.window
                radius:         ScreenTools.defaultFontPixelWidth * 0.5
                Column {
                    id:         cameraCol
                    spacing:    _spacers
                    anchors.centerIn: parent
                    Item {
                        height:     1
                        width:      1
                    }
                    //-----------------------------------------------------------------
                    //-- Camera Name
                    QGCLabel {
                        text:                   activeVehicle ? (_camera && _camera.modelName !== "" ? _camera.modelName : _commLostStr) : _commLostStr
                        font.pointSize:         ScreenTools.smallFontPointSize
                        anchors.horizontalCenter: parent.horizontalCenter
187
                    }
188 189 190 191 192
                    QGCLabel {
                        text: {
                            if(_noSdCard)   return qsTr("NONE")
                            if(_fullSD)     return qsTr("FULL")
                            return _camera ? _camera.storageFreeStr : ""
193
                        }
194 195 196 197
                        visible:                _isShortScreen
                        color:                  (_noSdCard || _fullSD) ? qgcPal.colorOrange : qgcPal.text
                        font.pointSize:         ScreenTools.smallFontPointSize
                        anchors.horizontalCenter: parent.horizontalCenter
198
                    }
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
                    //-----------------------------------------------------------------
                    //-- Camera Mode
                    Item {
                        width:                  modeCol.width
                        height:                 modeCol.height
                        anchors.horizontalCenter: parent.horizontalCenter
                        Column {
                            id:                 modeCol
                            spacing:            _spacers
                            QGCColoredImage {
                                height:         ScreenTools.defaultFontPixelHeight * 1.25
                                width:          height
                                source:         (_cameraModeUndefined || _cameraPhotoMode) ? "/custom/img/camera_photo.svg" : "/custom/img/camera_video.svg"
                                color:          qgcPal.text
                                fillMode:       Image.PreserveAspectFit
                                sourceSize.height:  height
                                anchors.horizontalCenter: parent.horizontalCenter
216
                            }
217 218 219 220
                            QGCLabel {
                                text:           _cameraVideoMode ? qsTr("Video") : qsTr("Photo")
                                font.pointSize: ScreenTools.smallFontPointSize
                                anchors.horizontalCenter: parent.horizontalCenter
221 222
                            }
                        }
223 224 225 226 227 228
                        MouseArea {
                            anchors.fill:       parent
                            enabled:            !_cameraModeUndefined && _camera && _camera.videoStatus !== QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING && _cameraPhotoIdle
                            onClicked: {
                                _camera.toggleMode()
                            }
229 230
                        }
                    }
231 232
                    //-----------------------------------------------------------------
                    //-- Shutter
233
                    Rectangle {
234 235 236 237 238
                        color:                  Qt.rgba(0,0,0,0)
                        width:                  height
                        height:                 ScreenTools.defaultFontPixelHeight * 4
                        radius:                 width * 0.5
                        border.color:           qgcPal.buttonText
Yasen's avatar
Yasen committed
239
                        border.width:           1
240 241
                        anchors.horizontalCenter: parent.horizontalCenter
                        Rectangle {
Yasen's avatar
Yasen committed
242
                            width:              parent.width * 0.85
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
                            height:             width
                            radius:             width * 0.5
                            color:              _cameraModeUndefined ? qgcPal.colorGrey : ( _cameraVideoMode ? qgcPal.colorRed : qgcPal.text )
                            visible:            !pauseVideo.visible
                            anchors.centerIn:   parent
                            QGCColoredImage {
                                id:                 busyIndicator
                                height:             parent.height * 0.75
                                width:              height
                                source:             "/qmlimages/MapSync.svg"
                                sourceSize.height:  height
                                fillMode:           Image.PreserveAspectFit
                                mipmap:             true
                                smooth:             true
                                color:              qgcPal.window
                                visible: {
                                    if(_cameraPhotoMode && !_cameraPhotoIdle && !_cameraElapsedMode) {
                                        return true
                                    }
                                    return false
                                }
                                anchors.centerIn:   parent
                                RotationAnimation on rotation {
                                    loops:          Animation.Infinite
                                    from:           360
                                    to:             0
                                    duration:       740
                                    running:        busyIndicator.visible
                                }
                            }
                            QGCLabel {
                                text:               _camera ? _camera.photoLapse.toFixed(0) + 's' : qsTr('N/A')
                                font.family:        ScreenTools.demiboldFontFamily
                                color:              qgcPal.colorBlue
                                visible:            _cameraElapsedMode
                                anchors.centerIn:   parent
                            }
                        }
                        Rectangle {
                            id:         pauseVideo
                            width:      parent.width * 0.5
                            height:     width
                            color:      _cameraModeUndefined ? qgcPal.colorGrey : qgcPal.colorRed
                            visible: {
                               if(_cameraVideoMode && _camera.videoStatus === QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING) {
288 289
                                   return true
                               }
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
                               if(_cameraPhotoMode) {
                                   if(_camera.photoStatus === QGCCameraControl.PHOTO_CAPTURE_INTERVAL_IDLE || _camera.photoStatus === QGCCameraControl.PHOTO_CAPTURE_INTERVAL_IN_PROGRESS) {
                                       return true
                                   }
                               }
                               return false
                            }
                            anchors.centerIn:   parent
                        }
                        MouseArea {
                            anchors.fill:   parent
                            enabled:        !_noSdCard
                            onClicked: {
                                if(_cameraVideoMode) {
                                    if(_camera.videoStatus === QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING) {
                                        _camera.stopVideo()
306 307 308 309
                                        //-- Local video as well
                                        if (_recordingVideo) {
                                            _videoReceiver.stopRecording()
                                        }
310 311 312 313
                                    } else {
                                        if(!_fullSD) {
                                            _camera.startVideo()
                                        }
314 315 316 317
                                        //-- Local video as well
                                        if(_videoReceiver) {
                                            _videoReceiver.startRecording()
                                        }
318 319
                                    }
                                } else {
320 321 322 323 324 325
                                    if(_camera.photoStatus === QGCCameraControl.PHOTO_CAPTURE_INTERVAL_IDLE || _camera.photoStatus === QGCCameraControl.PHOTO_CAPTURE_INTERVAL_IN_PROGRESS) {
                                        _camera.stopTakePhoto()
                                    } else {
                                        if(!_fullSD) {
                                            _camera.takePhoto()
                                        }
326
                                    }
327 328 329 330
                                }
                            }
                        }
                    }
331 332 333 334 335
                    //-----------------------------------------------------------------
                    //-- Settings
                    Item {
                        width:                  settingsCol.width
                        height:                 settingsCol.height
336
                        anchors.horizontalCenter: parent.horizontalCenter
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
                        Column {
                            id:                 settingsCol
                            spacing:            _spacers
                            anchors.horizontalCenter: parent.horizontalCenter
                            QGCColoredImage {
                                width:                      ScreenTools.defaultFontPixelHeight * 1.25
                                height:                     width
                                sourceSize.width:           width
                                source:                     "qrc:/custom/img/camera_settings.svg"
                                color:                      qgcPal.text
                                fillMode:                   Image.PreserveAspectFit
                                opacity:                    _settingsEnabled ? 1 : 0.5
                                anchors.horizontalCenter:   parent.horizontalCenter
                            }
                            QGCLabel {
                                text:                       qsTr("Settings")
                                font.pointSize:             ScreenTools.smallFontPointSize
                                anchors.horizontalCenter:   parent.horizontalCenter
                            }
                        }
                        MouseArea {
                            anchors.fill:       parent
                            enabled:            _settingsEnabled
                            onClicked: {
                                cameraSettings.open()
                            }
                        }
                    }
                    //-----------------------------------------------------------------
                    //-- microSD Card
                    Column {
                        spacing:                        _spacers
                        visible:                        !_isShortScreen
                        anchors.horizontalCenter:       parent.horizontalCenter
371 372 373 374
                        QGCColoredImage {
                            width:                      ScreenTools.defaultFontPixelHeight * 1.25
                            height:                     width
                            sourceSize.width:           width
375
                            source:                     "qrc:/custom/img/microSD.svg"
376 377 378 379 380 381
                            color:                      qgcPal.text
                            fillMode:                   Image.PreserveAspectFit
                            opacity:                    _settingsEnabled ? 1 : 0.5
                            anchors.horizontalCenter:   parent.horizontalCenter
                        }
                        QGCLabel {
382 383 384 385 386 387 388 389
                            text: {
                                if(_noSdCard)   return qsTr("NONE")
                                if(_fullSD)     return qsTr("FULL")
                                return _camera ? _camera.storageFreeStr : ""
                            }
                            color:          (_noSdCard || _fullSD) ? qgcPal.colorOrange : qgcPal.text
                            font.pointSize: ScreenTools.smallFontPointSize
                            anchors.horizontalCenter: parent.horizontalCenter
390 391
                        }
                    }
392 393
                    //-----------------------------------------------------------------
                    //-- Recording Time / Images Captured
394
                    QGCLabel {
395 396
                        text:               (_cameraVideoMode && _camera.videoStatus === QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING) ? _camera.recordTimeStr : "00:00:00"
                        visible:            _cameraVideoMode
397
                        font.pointSize:     ScreenTools.smallFontPointSize
398 399
                        anchors.horizontalCenter: parent.horizontalCenter
                    }
400
                    QGCLabel {
401 402
                        text:               activeVehicle && _cameraPhotoMode ? ('00000' + activeVehicle.cameraTriggerPoints.count).slice(-5) : "00000"
                        visible:            _cameraPhotoMode
403
                        font.pointSize:     ScreenTools.smallFontPointSize
404 405 406 407 408
                        anchors.horizontalCenter: parent.horizontalCenter
                    }
                    Item {
                        height:     1
                        width:      1
409 410
                    }
                }
411 412 413
            }
            //-- Gimbal Indicator
            Rectangle {
414
                id: gimbalBackground
415 416 417
                width:                  _hasGimbal ? ScreenTools.defaultFontPixelWidth * 6 : 0
                height:                 _hasGimbal ? (gimbalCol.height + (ScreenTools.defaultFontPixelHeight * 2)) : 0
                visible:                _hasGimbal
418
                color:                  Qt.rgba(qgcPal.window.r, qgcPal.window.g, qgcPal.window.b, 0.75)
419 420
                radius:                 ScreenTools.defaultFontPixelWidth * 0.5
                anchors.verticalCenter: cameraRect.verticalCenter
421
                Column {
422 423 424
                    id:                 gimbalCol
                    spacing:            ScreenTools.defaultFontPixelHeight * 0.75
                    anchors.centerIn:   parent
425
                    QGCColoredImage {
426
                        id:             gimbalIcon
427
                        source:         "/custom/img/gimbal_icon.svg"
428
                        color:          qgcPal.text
429 430 431 432 433 434 435 436
                        width:          ScreenTools.defaultFontPixelWidth * 2
                        height:         width
                        smooth:         true
                        mipmap:         true
                        antialiasing:   true
                        fillMode:       Image.PreserveAspectFit
                        sourceSize.width: width
                        anchors.horizontalCenter: parent.horizontalCenter
437
                    }
438 439 440
                    Image {
                        id:                 pitchScale
                        height:             cameraRect.height * 0.65
441
                        source:             qgcPal.globalTheme === QGCPalette.Light ? "/custom/img/gimbal_pitch_indoors.svg" : "/custom/img/gimbal_pitch_outdoors.svg"
442 443 444 445 446
                        fillMode:           Image.PreserveAspectFit
                        sourceSize.height:  height
                        smooth:             true
                        mipmap:             true
                        antialiasing:       true
447

448 449 450 451 452 453
                        Image {
                            id:                 yawIndicator
                            width:              ScreenTools.defaultFontPixelWidth * 4
                            source:             "/custom/img/gimbal_position.svg"
                            fillMode:           Image.PreserveAspectFit
                            sourceSize.width:   width
454 455
                            x:                  pitchScale.width/2
                            y:                  (pitchScale.height * pitchScale.scaleRatio) + (pitchScale._pitch / pitchScale.rangeValue) * pitchScale.height
456 457
                            smooth:             true
                            mipmap:             true
458 459 460 461 462 463 464 465 466
                            transform: [
                                Translate {
                                    x: -yawIndicator.width / 2
                                    y: -yawIndicator.height / 2
                                },
                                Rotation {
                                    angle: _gimbalYaw
                                }
                            ]
467
                        }
468 469 470 471 472 473
                        readonly property real minValue: -15
                        readonly property real centerValue: 0
                        readonly property real maxValue: 90
                        readonly property real rangeValue: maxValue - minValue
                        readonly property real scaleRatio: 1/7
                        property real          _pitch: _gimbalPitch < minValue ? minValue  : (_gimbalPitch > maxValue ? maxValue : _gimbalPitch)
474 475 476
                    }
                    QGCLabel {
                        id:             gimbalLabel
477
                        width:          gimbalCol.width
478
                        color:          qgcPal.text
479 480 481
                        font.pointSize: ScreenTools.smallFontPointSize
                        text:           activeVehicle ? activeVehicle.gimbalPitch.toFixed(0) : "-"
                        horizontalAlignment: Text.AlignHCenter
482 483
                    }
                }
484
            } // Gimbal Indicator
485
        }
486 487 488 489
        //-- Zoom Buttons
        ZoomControl {
            id:             zoomControl
            visible:        _hasZoom
490
            mainColor:      qgcPal.window
491
            contentColor:   qgcPal.text
492
            fontPointSize:  ScreenTools.defaultFontPointSize * 1.75
493 494 495
            zoomLevelVisible: false
            zoomLevel:      _hasZoom ? _camera.zoomLevel : NaN
            anchors.horizontalCenter: parent.horizontalCenter
496
            onlyContinousZoom: true
497 498 499 500 501 502 503 504 505 506 507 508 509
            onZoomIn: {
                _camera.stepZoom(1)
            }
            onZoomOut: {
                _camera.stepZoom(-1)
            }
            onContinuousZoomStart: {
                _camera.startZoom(zoomIn ? 1 : -1)
            }
            onContinuousZoomStop: {
                _camera.stopZoom()
            }
        }
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 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
    }
    //-------------------------------------------------------------------------
    //-- Camera Settings
    Popup {
        id:                 cameraSettings
        width:              Math.min(mainWindow.width  * 0.666, ScreenTools.defaultFontPixelWidth * 80)
        height:             mainWindow.height * 0.666
        modal:              true
        focus:              true
        parent:             Overlay.overlay
        x:                  Math.round((mainWindow.width  - width)  * 0.5)
        y:                  Math.round((mainWindow.height - height) * 0.5)
        closePolicy:        Popup.CloseOnEscape | Popup.CloseOnPressOutside
        background: Rectangle {
            anchors.fill:   parent
            color:          qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(1,1,1,0.95) : Qt.rgba(0,0,0,0.75)
            border.color:   qgcPal.text
            radius:         ScreenTools.defaultFontPixelWidth
        }
        Item {
            anchors.fill:       parent
            anchors.margins:    ScreenTools.defaultFontPixelHeight
            function showEditFact(fact) {
                factEditor.text = fact.valueString
                factEdit.fact = fact
                factEdit.visible = true
            }
            function hideEditFact() {
                factEdit.visible = false
                factEdit.fact = null
            }
            QGCLabel {
                id:                 cameraSettingsLabel
                text:               _noSdCard ? qsTr("Settings") : (_cameraVideoMode ? qsTr("Video Settings") : qsTr("Photo Settings"))
                font.family:        ScreenTools.demiboldFontFamily
                font.pointSize:     ScreenTools.mediumFontPointSize
                anchors.margins:    ScreenTools.defaultFontPixelWidth
                anchors.top:        parent.top
                anchors.left:       parent.left
            }
            QGCFlickable {
                clip:               true
                anchors.top:        cameraSettingsLabel.bottom
                anchors.bottom:     parent.bottom
                anchors.margins:    ScreenTools.defaultFontPixelWidth
                width:              cameraSettingsCol.width + (ScreenTools.defaultFontPixelWidth * 2)
                contentHeight:      cameraSettingsCol.height
                contentWidth:       cameraSettingsCol.width
                anchors.horizontalCenter: parent.horizontalCenter
                Column {
                    id:                 cameraSettingsCol
561
                    spacing:            _spacers
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577
                    anchors.margins:    ScreenTools.defaultFontPixelHeight
                    anchors.horizontalCenter: parent.horizontalCenter
                    //-------------------------------------------
                    //-- Camera Selector
                    Row {
                        spacing:        ScreenTools.defaultFontPixelWidth
                        visible:        _isCamera && _dynamicCameras.cameraLabels.length > 1
                        anchors.horizontalCenter: parent.horizontalCenter
                        QGCLabel {
                            text:           qsTr("Camera Selector:")
                            width:          _labelFieldWidth
                            anchors.verticalCenter: parent.verticalCenter
                        }
                        QGCComboBox {
                            model:          _isCamera ? _dynamicCameras.cameraLabels : []
                            width:          _editFieldWidth
Gus Grubba's avatar
Gus Grubba committed
578
                            height:         _editFieldHeight
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
                            onActivated:    _dynamicCameras.currentCamera = index
                            currentIndex:   _dynamicCameras ? _dynamicCameras.currentCamera : 0
                        }
                    }
                    Rectangle {
                        color:      qgcPal.button
                        height:     1
                        width:      cameraSettingsCol.width
                        visible:    _isCamera && _dynamicCameras.cameraLabels.length > 1
                    }
                    //-------------------------------------------
                    //-- Stream Selector
                    Row {
                        spacing:        ScreenTools.defaultFontPixelWidth
                        visible:        _isCamera && _camera.streamLabels.length > 1
                        anchors.horizontalCenter: parent.horizontalCenter
                        QGCLabel {
                            text:           qsTr("Stream Selector:")
                            width:          _labelFieldWidth
                            anchors.verticalCenter: parent.verticalCenter
                        }
                        QGCComboBox {
                            model:          _camera ? _camera.streamLabels : []
                            width:          _editFieldWidth
Gus Grubba's avatar
Gus Grubba committed
603
                            height:         _editFieldHeight
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
                            onActivated:    _camera.currentStream = index
                            currentIndex:   _camera ? _camera.currentStream : 0
                        }
                    }
                    Rectangle {
                        color:      qgcPal.button
                        height:     1
                        width:      cameraSettingsCol.width
                        visible:    _isCamera && _camera.streamLabels.length > 1
                    }
                    //-------------------------------------------
                    //-- Thermal Modes
                    Row {
                        spacing:            ScreenTools.defaultFontPixelWidth
                        anchors.horizontalCenter: parent.horizontalCenter
                        visible:            QGroundControl.videoManager.hasThermal
                        property var thermalModes: [qsTr("Off"), qsTr("Blend"), qsTr("Full"), qsTr("Picture In Picture")]
                        QGCLabel {
                            text:           qsTr("Thermal View Mode")
                            width:          _labelFieldWidth
                            anchors.verticalCenter: parent.verticalCenter
                        }
                        QGCComboBox {
                            width:          _editFieldWidth
Gus Grubba's avatar
Gus Grubba committed
628
                            height:         _editFieldHeight
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652
                            model:          parent.thermalModes
                            currentIndex:   _camera ? _camera.thermalMode : 0
                            onActivated:    _camera.thermalMode = index
                        }
                    }
                    Rectangle {
                        color:      qgcPal.button
                        height:     1
                        width:      cameraSettingsCol.width
                        visible:            QGroundControl.videoManager.hasThermal
                    }
                    //-------------------------------------------
                    //-- Thermal Video Opacity
                    Row {
                        spacing:            ScreenTools.defaultFontPixelWidth
                        anchors.horizontalCenter: parent.horizontalCenter
                        visible:            QGroundControl.videoManager.hasThermal && _camera.thermalMode === QGCCameraControl.THERMAL_BLEND
                        QGCLabel {
                            text:           qsTr("Blend Opacity")
                            width:          _labelFieldWidth
                            anchors.verticalCenter: parent.verticalCenter
                        }
                        Slider {
                            width:          _editFieldWidth
Gus Grubba's avatar
Gus Grubba committed
653
                            height:         _editFieldHeight
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677
                            to:             100
                            from:           0
                            value:          _camera ? _camera.thermalOpacity : 0
                            live:           true
                            onValueChanged: {
                                _camera.thermalOpacity = value
                            }
                        }
                    }
                    Rectangle {
                        color:      qgcPal.button
                        height:     1
                        width:      cameraSettingsCol.width
                        visible:            QGroundControl.videoManager.hasThermal && _camera.thermalMode === QGCCameraControl.THERMAL_BLEND
                    }
                    //-------------------------------------------
                    //-- Settings from Camera Definition File
                    Repeater {
                        model:      _camera ? _camera.activeSettings : []
                        Item {
                            width:   repCol.width
                            height:  repCol.height
                            Column {
                                id:                 repCol
678
                                spacing:            _spacers
679 680 681 682 683 684 685 686 687 688 689 690 691 692 693
                                property var _fact: _camera.getFact(modelData)
                                Row {
                                    height:         visible ? undefined : 0
                                    spacing:        ScreenTools.defaultFontPixelWidth
                                    anchors.horizontalCenter: parent.horizontalCenter
                                    property bool   _isBool:    parent._fact.typeIsBool
                                    property bool   _isCombo:   !_isBool && parent._fact.enumStrings.length > 0
                                    property bool   _isSlider:  parent._fact && !isNaN(parent._fact.increment)
                                    property bool   _isEdit:    !_isBool && !_isSlider && parent._fact.enumStrings.length < 1
                                    QGCLabel {
                                        text:       parent.parent._fact.shortDescription
                                        width:      _labelFieldWidth
                                        anchors.verticalCenter: parent.verticalCenter
                                    }
                                    FactComboBox {
Gus Grubba's avatar
Gus Grubba committed
694 695
                                        width:      parent._isCombo ? _editFieldWidth  : 0
                                        height:     parent._isCombo ? _editFieldHeight : 0
696 697 698 699 700 701 702
                                        fact:       parent.parent._fact
                                        indexModel: false
                                        visible:    parent._isCombo
                                        anchors.verticalCenter: parent.verticalCenter
                                    }
                                    QGCButton {
                                        visible:    parent._isEdit
Gus Grubba's avatar
Gus Grubba committed
703 704
                                        width:      parent._isEdit ? _editFieldWidth  : 0
                                        height:     parent._isEdit ? _editFieldHeight : 0
705 706 707 708 709 710
                                        text:       parent.parent._fact.valueString
                                        onClicked: {
                                            showEditFact(parent.parent._fact)
                                        }
                                    }
                                    QGCSlider {
Gus Grubba's avatar
Gus Grubba committed
711 712
                                        width:          parent._isSlider ? _editFieldWidth  : 0
                                        height:         parent._isSlider ? _editFieldHeight : 0
713 714 715 716 717 718 719 720 721 722 723 724 725 726
                                        maximumValue:   parent.parent._fact.max
                                        minimumValue:   parent.parent._fact.min
                                        stepSize:       parent.parent._fact.increment
                                        visible:        parent._isSlider
                                        updateValueWhileDragging:   false
                                        anchors.verticalCenter:     parent.verticalCenter
                                        Component.onCompleted: {
                                            value = parent.parent._fact.value
                                        }
                                        onValueChanged: {
                                            parent.parent._fact.value = value
                                        }
                                    }
                                    CustomOnOffSwitch {
Gus Grubba's avatar
Gus Grubba committed
727 728
                                        width:      parent._isBool ? _editFieldWidth  : 0
                                        height:     parent._isBool ? _editFieldHeight : 0
729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756
                                        checked:    parent.parent._fact ? parent.parent._fact.value : false
                                        onClicked:  parent.parent._fact.value = checked ? 1 : 0
                                        visible:    parent._isBool
                                        anchors.verticalCenter: parent.verticalCenter
                                    }
                                }
                                Rectangle {
                                    color:      qgcPal.button
                                    height:     1
                                    width:      cameraSettingsCol.width
                                }
                            }
                        }
                    }
                    //-------------------------------------------
                    //-- Time Lapse
                    Row {
                        spacing:        ScreenTools.defaultFontPixelWidth
                        anchors.horizontalCenter: parent.horizontalCenter
                        visible:        _cameraPhotoMode && !_noSdCard
                        property var photoModes: [qsTr("Single"), qsTr("Time Lapse")]
                        QGCLabel {
                            text:       qsTr("Photo Mode")
                            width:      _labelFieldWidth
                            anchors.verticalCenter: parent.verticalCenter
                        }
                        QGCComboBox {
                            width:          _editFieldWidth
Gus Grubba's avatar
Gus Grubba committed
757
                            height:         _editFieldHeight
758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781
                            model:          parent.photoModes
                            currentIndex:   _camera ? _camera.photoMode : 0
                            onActivated:    _camera.photoMode = index
                        }
                    }
                    Rectangle {
                        color:      qgcPal.button
                        height:     1
                        width:      cameraSettingsCol.width
                        visible:    _cameraPhotoMode && !_noSdCard
                    }
                    //-------------------------------------------
                    //-- Time Lapse Interval
                    Row {
                        spacing:        ScreenTools.defaultFontPixelWidth
                        anchors.horizontalCenter: parent.horizontalCenter
                        visible:        _cameraPhotoMode && _camera.photoMode === QGCCameraControl.PHOTO_CAPTURE_TIMELAPSE && !_noSdCard
                        QGCLabel {
                            text:       qsTr("Photo Interval (seconds)")
                            width:      _labelFieldWidth
                            anchors.verticalCenter: parent.verticalCenter
                        }
                        QGCSlider {
                            width:          _editFieldWidth
Gus Grubba's avatar
Gus Grubba committed
782
                            height:         _editFieldHeight
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802
                            maximumValue:   60
                            minimumValue:   _camera ? (_camera.isE90 ? 3 : 5) : 5
                            stepSize:       1
                            value:          _camera ? _camera.photoLapse : 5
                            updateValueWhileDragging:   true
                            anchors.verticalCenter:     parent.verticalCenter
                            onValueChanged: {
                                if(_camera) {
                                    _camera.photoLapse = value
                                }
                            }
                        }
                    }
                    Rectangle {
                        color:      qgcPal.button
                        height:     1
                        width:      cameraSettingsCol.width
                        visible:    _cameraPhotoMode && _camera.photoMode === QGCCameraControl.PHOTO_CAPTURE_TIMELAPSE && !_noSdCard
                    }
                    //-------------------------------------------
Gus Grubba's avatar
Gus Grubba committed
803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
                    //-- Gimbal Control
                    Row {
                        spacing:        ScreenTools.defaultFontPixelWidth
                        visible:        _camera && !_camera.isThermal
                        anchors.horizontalCenter: parent.horizontalCenter
                        QGCLabel {
                            text:       qsTr("Show Gimbal Control")
                            width:      _labelFieldWidth
                            anchors.verticalCenter: parent.verticalCenter
                        }
                        CustomOnOffSwitch {
                            checked:    CustomQuickInterface.showGimbalControl
                            width:      _editFieldWidth
                            height:     _editFieldHeight
                            anchors.verticalCenter: parent.verticalCenter
                            onClicked:  CustomQuickInterface.showGimbalControl = checked
                        }
                    }
                    Rectangle {
                        color:      qgcPal.button
                        height:     1
                        width:      cameraSettingsCol.width
                        visible:    _camera && !_camera.isThermal
                    }
                    //-------------------------------------------
828 829 830 831 832 833 834 835 836 837 838 839 840
                    //-- Screen Grid
                    Row {
                        spacing:        ScreenTools.defaultFontPixelWidth
                        visible:        _camera && !_camera.isThermal
                        anchors.horizontalCenter: parent.horizontalCenter
                        QGCLabel {
                            text:       qsTr("Screen Grid")
                            width:      _labelFieldWidth
                            anchors.verticalCenter: parent.verticalCenter
                        }
                        CustomOnOffSwitch {
                            checked:     QGroundControl.settingsManager.videoSettings.gridLines.rawValue
                            width:      _editFieldWidth
Gus Grubba's avatar
Gus Grubba committed
841
                            height:     _editFieldHeight
842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864
                            anchors.verticalCenter: parent.verticalCenter
                            onClicked:  QGroundControl.settingsManager.videoSettings.gridLines.rawValue = checked
                        }
                    }
                    Rectangle {
                        color:      qgcPal.button
                        height:     1
                        width:      cameraSettingsCol.width
                        visible:    _camera && !_camera.isThermal
                    }
                    //-------------------------------------------
                    //-- Video Fit
                    Row {
                        spacing:        ScreenTools.defaultFontPixelWidth
                        visible:        _camera
                        anchors.horizontalCenter: parent.horizontalCenter
                        QGCLabel {
                            text:       qsTr("Video Screen Fit")
                            width:      _labelFieldWidth
                            anchors.verticalCenter: parent.verticalCenter
                        }
                        FactComboBox {
                            width:      _editFieldWidth
Gus Grubba's avatar
Gus Grubba committed
865
                            height:     _editFieldHeight
866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890
                            fact:       QGroundControl.settingsManager.videoSettings.videoFit
                            indexModel: false
                            anchors.verticalCenter: parent.verticalCenter
                        }
                    }
                    Rectangle {
                        color:      qgcPal.button
                        height:     1
                        width:      cameraSettingsCol.width
                        visible:    _camera && !_camera.isThermal
                    }
                    //-------------------------------------------
                    //-- Reset Camera
                    Row {
                        spacing:        ScreenTools.defaultFontPixelWidth
                        anchors.horizontalCenter: parent.horizontalCenter
                        QGCLabel {
                            text:       qsTr("Reset Camera Defaults")
                            width:      _labelFieldWidth
                            anchors.verticalCenter: parent.verticalCenter
                        }
                        QGCButton {
                            text:       qsTr("Reset")
                            onClicked:  resetPrompt.open()
                            width:      _editFieldWidth
Gus Grubba's avatar
Gus Grubba committed
891
                            height:     _editFieldHeight
892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962
                            enabled:    !_recordingVideo
                            anchors.verticalCenter: parent.verticalCenter
                            MessageDialog {
                                id:                 resetPrompt
                                title:              qsTr("Reset Camera to Factory Settings")
                                text:               qsTr("Confirm resetting all settings?")
                                standardButtons:    StandardButton.Yes | StandardButton.No
                                onNo: resetPrompt.close()
                                onYes: {
                                    _camera.resetSettings()
                                    QGroundControl.settingsManager.videoSettings.gridLines.rawValue = false
                                    _camera.photoMode = QGCCameraControl.PHOTO_CAPTURE_SINGLE
                                    _camera.photoLapse = 5.0
                                    _camera.photoLapseCount = 0
                                    resetPrompt.close()
                                }
                            }
                        }
                    }
                    Rectangle {
                        color:      qgcPal.button
                        height:     1
                        width:      cameraSettingsCol.width
                    }
                }
            }
            Rectangle {
                id:             factEdit
                visible:        false
                color:          qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(1,1,1,0.5) : Qt.rgba(0,0,0,0.5)
                anchors.fill:   parent
                property var fact: null
                DeadMouseArea {
                    anchors.fill:   parent
                }
                Rectangle {
                    width:      factEditCol.width  * 1.25
                    height:     factEditCol.height * 1.25
                    color:      qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(1,1,1,0.95) : Qt.rgba(0,0,0,0.75)
                    border.width:       1
                    border.color:       qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(0,0,0,0.35) : Qt.rgba(1,1,1,0.35)
                    anchors.top:        parent.top
                    anchors.topMargin:  ScreenTools.defaultFontPixelHeight * 8
                    anchors.horizontalCenter: parent.horizontalCenter
                    Column {
                        id:             factEditCol
                        spacing:        ScreenTools.defaultFontPixelHeight
                        anchors.centerIn: parent
                        QGCLabel {
                            text:       factEdit.fact ? factEdit.fact.shortDescription : ""
                            anchors.horizontalCenter: parent.horizontalCenter
                        }
                        FactTextField {
                            id:         factEditor
                            width:      _editFieldWidth
                            fact:       factEdit.fact
                            anchors.horizontalCenter: parent.horizontalCenter
                        }
                        QGCButton {
                            text: qsTr("Close")
                            anchors.horizontalCenter: parent.horizontalCenter
                            onClicked: {
                                factEditor.completeEditing()
                                hideEditFact()
                            }
                        }
                    }
                }
            }
        }
    }
963 964 965 966 967 968
    //-------------------------------------------------------------------------
    //-- Thermal Palettes
    Popup {
        id:                     thermalPalettes
        width:                  Math.min(mainWindow.width * 0.666, ScreenTools.defaultFontPixelWidth * 40)
        height:                 mainWindow.height * 0.5
969
        modal:                  true
970 971 972 973 974
        focus:                  true
        parent:                 Overlay.overlay
        x:                      Math.round((mainWindow.width  - width)  * 0.5)
        y:                      Math.round((mainWindow.height - height) * 0.5)
        closePolicy:            Popup.CloseOnEscape | Popup.CloseOnPressOutside
975

976 977 978 979
        background: Rectangle {
            anchors.fill:       parent
            color:              qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(1,1,1,0.95) : Qt.rgba(0,0,0,0.75)
            border.color:       qgcPal.text
980
            radius:             ScreenTools.defaultFontPixelWidth * 0.5
981 982 983 984 985 986 987 988 989 990 991
        }
        Item {
            anchors.fill:       parent
            anchors.margins:    ScreenTools.defaultFontPixelHeight
            QGCFlickable {
                clip:               true
                anchors.fill:       parent
                width:              comboListCol.width + (ScreenTools.defaultFontPixelWidth * 2)
                contentHeight:      comboListCol.height
                contentWidth:       comboListCol.width
                anchors.horizontalCenter: parent.horizontalCenter
Gus Grubba's avatar
Gus Grubba committed
992
                ColumnLayout {
993 994 995 996
                    id:                 comboListCol
                    spacing:            ScreenTools.defaultFontPixelHeight
                    anchors.margins:    ScreenTools.defaultFontPixelHeight
                    anchors.horizontalCenter: parent.horizontalCenter
997
                    QGCLabel {
Gus Grubba's avatar
Gus Grubba committed
998 999
                        text:           qsTr("Thermal Palettes")
                        Layout.alignment: Qt.AlignHCenter
1000
                    }
1001 1002 1003
                    Repeater {
                        model:          _irPaletteFact ? _irPaletteFact.enumStrings : []
                        QGCButton {
Gus Grubba's avatar
Gus Grubba committed
1004 1005 1006 1007 1008 1009 1010
                            text:                   modelData
                            Layout.minimumHeight:   ScreenTools.defaultFontPixelHeight * 3
                            Layout.minimumWidth:    ScreenTools.defaultFontPixelWidth  * 30
                            Layout.fillHeight:      true
                            Layout.fillWidth:       true
                            Layout.alignment:       Qt.AlignHCenter
                            checked:                index === _irPaletteFact.value
1011 1012
                            onClicked: {
                                _irPaletteFact.value = index
1013 1014 1015
                                if(thermalBackgroundRect.visible) {
                                    if(_camera.thermalMode !== QGCCameraControl.THERMAL_PIP && _camera.thermalMode !== QGCCameraControl.THERMAL_FULL) {
                                        _camera.thermalMode = QGCCameraControl.THERMAL_FULL
1016
                                        thermalFull.checked = true
1017 1018 1019
                                    }
                                }

1020 1021 1022 1023 1024 1025 1026 1027
                                thermalPalettes.close()
                            }
                        }
                    }
                }
            }
        }
    }
1028 1029
}