From 27b0db4e6a92bc406de3b3eb8d6897083d96cb21 Mon Sep 17 00:00:00 2001
From: Gus Grubba <gus@auterion.com>
Date: Sun, 28 Jul 2019 01:00:01 -0400
Subject: [PATCH] Quick access to thermal modes

---
 custom-example/custom.qrc                          |   4 +
 custom-example/res/CustomCameraControl.qml         | 487 +++++++++++++--------
 custom-example/res/CustomFlyView.qml               |   5 +-
 custom-example/res/Images/thermal-brightness.svg   |  19 +
 custom-example/res/Images/thermal-palette.svg      |  17 +
 custom-example/res/Images/thermal-pip.svg          |  11 +
 custom-example/res/Images/thermal-standard.svg     |   9 +
 custom-example/src/CustomPlugin.cc                 |   4 +-
 .../src/FirmwarePlugin/CustomCameraControl.cc      |  40 +-
 .../src/FirmwarePlugin/CustomCameraControl.h       |  28 +-
 10 files changed, 376 insertions(+), 248 deletions(-)
 create mode 100644 custom-example/res/Images/thermal-brightness.svg
 create mode 100644 custom-example/res/Images/thermal-palette.svg
 create mode 100644 custom-example/res/Images/thermal-pip.svg
 create mode 100644 custom-example/res/Images/thermal-standard.svg

diff --git a/custom-example/custom.qrc b/custom-example/custom.qrc
index 8b2ffc7..ad84746 100644
--- a/custom-example/custom.qrc
+++ b/custom-example/custom.qrc
@@ -27,6 +27,10 @@
         <file alias="horizontal_speed.svg">res/Images/horizontal_speed.svg</file>
         <file alias="microSD.svg">res/Images/microSD.svg</file>
         <file alias="odometer.svg">res/Images/odometer.svg</file>
+        <file alias="thermal-brightness.svg">res/images/thermal-brightness.svg</file>
+        <file alias="thermal-palette.svg">res/images/thermal-palette.svg</file>
+        <file alias="thermal-pip.svg">res/images/thermal-pip.svg</file>
+        <file alias="thermal-standard.svg">res/images/thermal-standard.svg</file>
         <file alias="vertical_speed.svg">res/Images/vertical_speed.svg</file>
         <file alias="void.png">res/Images/void.png</file>
     </qresource>
diff --git a/custom-example/res/CustomCameraControl.qml b/custom-example/res/CustomCameraControl.qml
index 7a0225d..aa767e9 100644
--- a/custom-example/res/CustomCameraControl.qml
+++ b/custom-example/res/CustomCameraControl.qml
@@ -30,11 +30,14 @@ import CustomQuickInterface             1.0
 import Custom.Widgets                   1.0
 
 Item {
-    height:         cameraRect.height
-    width:          cameraRect.width + (ScreenTools.defaultFontPixelWidth * 2)
+    height:         mainColumn.height
+    width:          mainColumn.width + (ScreenTools.defaultFontPixelWidth * 2)
     visible:        !QGroundControl.videoManager.fullScreen
 
-    readonly property string _commLostStr: qsTr("NO CAMERA")
+    readonly property string _commLostStr:  qsTr("NO CAMERA")
+    readonly property real   buttonSize:    ScreenTools.defaultFontPixelWidth * 4
+    readonly property real   buttonRadius:  ScreenTools.defaultFontPixelWidth * 0.5
+    readonly property real   iconRatio:     0.666
 
     property real   _spacers:               ScreenTools.defaultFontPixelHeight
     property real   _labelFieldWidth:       ScreenTools.defaultFontPixelWidth  * 28
@@ -56,6 +59,8 @@ Item {
     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
+    property Fact   _evFact:                _camera ? _camera.ev : null
+    property Fact   _irPaletteFact:         _camera ? _camera.irPalette : null
 
     Connections {
         target: QGroundControl.multiVehicleManager.activeVehicle
@@ -70,234 +75,348 @@ Item {
         anchors.fill:   parent
     }
 
-    Rectangle {
-        id:             cameraRect
-        height:         cameraCol.height
-        width:          cameraCol.width + (ScreenTools.defaultFontPixelWidth * 4)
-        color:          qgcPal.windowShade
-        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
+    //-------------------------------------------------------------------------
+    //-- Main Column
+    Column {
+        id:             mainColumn
+        spacing:        ScreenTools.defaultFontPixelHeight
+        anchors.centerIn: parent
+        //---------------------------------------------------------------------
+        //-- Quick Thermal Modes
+        Rectangle {
+            id:             backgroundRect
+            width:          buttonsRow.width  + (ScreenTools.defaultFontPixelWidth  * 4)
+            height:         buttonsRow.height + (ScreenTools.defaultFontPixelHeight)
+            color:          qgcPal.windowShade
+            radius:         height * 0.5
+            visible:        _camera && _camera.modelName === "DSC-QX30" && QGroundControl.videoManager.hasThermal
+            anchors.horizontalCenter: parent.horizontalCenter
+            ButtonGroup {
+                id:         buttonGroup
+                exclusive:  true
+                buttons:    buttonsRow.children
             }
-            //-----------------------------------------------------------------
-            //-- Camera Mode
-            Item {
-                width:                  modeCol.width
-                height:                 modeCol.height
-                anchors.horizontalCenter: parent.horizontalCenter
-                Column {
-                    id:                 modeCol
-                    spacing:            _spacers * 0.5
+            Row {
+                id:                     buttonsRow
+                spacing:                ScreenTools.defaultFontPixelWidth * 0.25
+                anchors.centerIn:       parent
+                //-- Standard
+                QGCHoverButton {
+                    width:              buttonSize
+                    height:             width
+                    checkable:          true
+                    radius:             buttonRadius
+                    onClicked:  {
+                        _camera.thermalMode = QGCCameraControl.THERMAL_OFF
+                        //-- Restore EV to 0
+                        if(_evFact) {
+                            _evFact.value = 6
+                        }
+                    }
                     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
+                        source:         "/custom/img/thermal-standard.svg"
+                        color:          parent.checked ? qgcPal.buttonHighlightText : qgcPal.buttonText
+                        width:          parent.width * iconRatio
+                        height:         width
+                        anchors.centerIn:   parent
                         sourceSize.height:  height
-                        anchors.horizontalCenter: parent.horizontalCenter
-                    }
-                    QGCLabel {
-                        text:           _cameraVideoMode ? qsTr("Video") : qsTr("Photo")
-                        font.pointSize: ScreenTools.smallFontPointSize
-                        anchors.horizontalCenter: parent.horizontalCenter
                     }
                 }
-                MouseArea {
-                    anchors.fill:       parent
-                    enabled:            !_cameraModeUndefined && _camera && _camera.videoStatus !== QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING && _cameraPhotoIdle
-                    onClicked: {
-                        _camera.toggleMode()
+                //-- PIP
+                QGCHoverButton {
+                    width:              buttonSize
+                    height:             width
+                    checkable:          true
+                    radius:             buttonRadius
+                    onClicked:          _camera.thermalMode = QGCCameraControl.THERMAL_PIP
+                    QGCColoredImage {
+                        source:         "/custom/img/thermal-pip.svg"
+                        color:          parent.checked ? qgcPal.buttonHighlightText : qgcPal.buttonText
+                        width:          parent.width * iconRatio
+                        height:         width
+                        anchors.centerIn:   parent
+                        sourceSize.height:  height
                     }
                 }
-            }
-            //-----------------------------------------------------------------
-            //-- Shutter
-            Rectangle {
-                color:                  Qt.rgba(0,0,0,0)
-                width:                  height
-                height:                 ScreenTools.defaultFontPixelHeight * 4
-                radius:                 width * 0.5
-                border.color:           qgcPal.buttonText
-                border.width:           2
-                anchors.horizontalCenter: parent.horizontalCenter
-                Rectangle {
-                    width:              parent.width * 0.75
+                // Visual with high brightness
+                QGCHoverButton {
+                    width:              buttonSize
                     height:             width
-                    radius:             width * 0.5
-                    color:              _cameraModeUndefined ? qgcPal.colorGrey : ( _cameraVideoMode ? qgcPal.colorRed : qgcPal.text )
-                    visible:            !pauseVideo.visible
-                    anchors.centerIn:   parent
+                    checkable:          true
+                    radius:             buttonRadius
+                    onClicked: {
+                        _camera.thermalMode = QGCCameraControl.THERMAL_OFF
+                        //-- Set EV to +1.3
+                        if(_evFact) {
+                            _evFact.value = 10
+                        }
+                    }
                     QGCColoredImage {
-                        id:                 busyIndicator
-                        height:             parent.height * 0.75
-                        width:              height
-                        source:             "/qmlimages/MapSync.svg"
+                        source:         "/custom/img/thermal-brightness.svg"
+                        color:          parent.checked ? qgcPal.buttonHighlightText : qgcPal.buttonText
+                        width:          parent.width * iconRatio
+                        height:         width
+                        anchors.centerIn:   parent
                         sourceSize.height:  height
-                        fillMode:           Image.PreserveAspectFit
-                        mipmap:             true
-                        smooth:             true
-                        color:              qgcPal.windowShade
-                        visible: {
-                            if(_cameraPhotoMode && !_cameraPhotoIdle && !_cameraElapsedMode) {
-                                return true
+                    }
+                }
+                // Thermal with color-map
+                QGCHoverButton {
+                    width:              buttonSize
+                    height:             width
+                    checkable:          true
+                    radius:             buttonRadius
+                    onClicked: {
+                        if(_irPaletteFact) {
+                            var entryIdx = _irPaletteFact.enumStrings.find("Rainbow")
+                            if(entryIdx !== undefined) {
+                                _irPaletteFact.value = entryIdx;
                             }
-                            return false
+                            _camera.thermalMode = QGCCameraControl.THERMAL_FULL
                         }
+                    }
+                    QGCColoredImage {
+                        source:         "/custom/img/thermal-palette.svg"
+                        color:          parent.checked ? qgcPal.buttonHighlightText : qgcPal.buttonText
+                        width:          parent.width * iconRatio
+                        height:         width
                         anchors.centerIn:   parent
-                        RotationAnimation on rotation {
-                            loops:          Animation.Infinite
-                            from:           360
-                            to:             0
-                            duration:       740
-                            running:        busyIndicator.visible
+                        sourceSize.height:  height
+                    }
+                }
+            }
+        }
+        //---------------------------------------------------------------------
+        //-- Main Camera Control
+        Rectangle {
+            id:             cameraRect
+            height:         cameraCol.height
+            width:          cameraCol.width + (ScreenTools.defaultFontPixelWidth * 4)
+            color:          qgcPal.windowShade
+            radius:         ScreenTools.defaultFontPixelWidth * 0.5
+            anchors.horizontalCenter: parent.horizontalCenter
+            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
+                }
+                //-----------------------------------------------------------------
+                //-- Camera Mode
+                Item {
+                    width:                  modeCol.width
+                    height:                 modeCol.height
+                    anchors.horizontalCenter: parent.horizontalCenter
+                    Column {
+                        id:                 modeCol
+                        spacing:            _spacers * 0.5
+                        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
+                        }
+                        QGCLabel {
+                            text:           _cameraVideoMode ? qsTr("Video") : qsTr("Photo")
+                            font.pointSize: ScreenTools.smallFontPointSize
+                            anchors.horizontalCenter: parent.horizontalCenter
                         }
                     }
-                    QGCLabel {
-                        text:               _camera ? _camera.photoLapse.toFixed(0) + 's' : qsTr('N/A')
-                        font.family:        ScreenTools.demiboldFontFamily
-                        color:              qgcPal.colorBlue
-                        visible:            _cameraElapsedMode
-                        anchors.centerIn:   parent
+                    MouseArea {
+                        anchors.fill:       parent
+                        enabled:            !_cameraModeUndefined && _camera && _camera.videoStatus !== QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING && _cameraPhotoIdle
+                        onClicked: {
+                            _camera.toggleMode()
+                        }
                     }
                 }
+                //-----------------------------------------------------------------
+                //-- Shutter
                 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) {
-                           return true
-                       }
-                       if(_cameraPhotoMode) {
-                           if(_camera.photoStatus === QGCCameraControl.PHOTO_CAPTURE_INTERVAL_IDLE || _camera.photoStatus === QGCCameraControl.PHOTO_CAPTURE_INTERVAL_IN_PROGRESS) {
+                    color:                  Qt.rgba(0,0,0,0)
+                    width:                  height
+                    height:                 ScreenTools.defaultFontPixelHeight * 4
+                    radius:                 width * 0.5
+                    border.color:           qgcPal.buttonText
+                    border.width:           2
+                    anchors.horizontalCenter: parent.horizontalCenter
+                    Rectangle {
+                        width:              parent.width * 0.75
+                        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.windowShade
+                            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) {
                                return true
                            }
-                       }
-                       return false
+                           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
                     }
-                    anchors.centerIn:   parent
-                }
-                MouseArea {
-                    anchors.fill:   parent
-                    enabled:        !_noSdCard
-                    onClicked: {
-                        if(_cameraVideoMode) {
-                            if(_camera.videoStatus === QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING) {
-                                _camera.stopVideo()
-                            } else {
-                                if(!_fullSD) {
-                                    _camera.startVideo()
+                    MouseArea {
+                        anchors.fill:   parent
+                        enabled:        !_noSdCard
+                        onClicked: {
+                            if(_cameraVideoMode) {
+                                if(_camera.videoStatus === QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING) {
+                                    _camera.stopVideo()
+                                } else {
+                                    if(!_fullSD) {
+                                        _camera.startVideo()
+                                    }
                                 }
-                            }
-                        } else {
-                            if(_camera.photoStatus === QGCCameraControl.PHOTO_CAPTURE_INTERVAL_IDLE || _camera.photoStatus === QGCCameraControl.PHOTO_CAPTURE_INTERVAL_IN_PROGRESS) {
-                                _camera.stopTakePhoto()
                             } else {
-                                if(!_fullSD) {
-                                    _camera.takePhoto()
+                                if(_camera.photoStatus === QGCCameraControl.PHOTO_CAPTURE_INTERVAL_IDLE || _camera.photoStatus === QGCCameraControl.PHOTO_CAPTURE_INTERVAL_IN_PROGRESS) {
+                                    _camera.stopTakePhoto()
+                                } else {
+                                    if(!_fullSD) {
+                                        _camera.takePhoto()
+                                    }
                                 }
                             }
                         }
                     }
                 }
-            }
-            //-----------------------------------------------------------------
-            //-- Settings
-            Item {
-                width:                  settingsCol.width
-                height:                 settingsCol.height
-                anchors.horizontalCenter: parent.horizontalCenter
-                Column {
-                    id:                 settingsCol
-                    spacing:            _spacers * 0.5
+                //-----------------------------------------------------------------
+                //-- Settings
+                Item {
+                    width:                  settingsCol.width
+                    height:                 settingsCol.height
                     anchors.horizontalCenter: parent.horizontalCenter
+                    Column {
+                        id:                 settingsCol
+                        spacing:            _spacers * 0.5
+                        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 * 0.5
+                    anchors.horizontalCenter:       parent.horizontalCenter
                     QGCColoredImage {
                         width:                      ScreenTools.defaultFontPixelHeight * 1.25
                         height:                     width
                         sourceSize.width:           width
-                        source:                     "qrc:/custom/img/camera_settings.svg"
+                        source:                     "qrc:/custom/img/microSD.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()
+                        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
                     }
                 }
-            }
-            //-----------------------------------------------------------------
-            //-- microSD Card
-            Column {
-                spacing:                        _spacers * 0.5
-                anchors.horizontalCenter:       parent.horizontalCenter
-                QGCColoredImage {
-                    width:                      ScreenTools.defaultFontPixelHeight * 1.25
-                    height:                     width
-                    sourceSize.width:           width
-                    source:                     "qrc:/custom/img/microSD.svg"
-                    color:                      qgcPal.text
-                    fillMode:                   Image.PreserveAspectFit
-                    opacity:                    _settingsEnabled ? 1 : 0.5
-                    anchors.horizontalCenter:   parent.horizontalCenter
+                /*
+                //-----------------------------------------------------------------
+                //-- Recording Time / Images Captured
+                CustomLabel {
+                    text:               (_cameraVideoMode && _camera.videoStatus === QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING) ? _camera.recordTimeStr : "00:00:00"
+                    visible:            _cameraVideoMode
+                    pointSize:          ScreenTools.smallFontPointSize
+                    anchors.horizontalCenter: parent.horizontalCenter
                 }
-                QGCLabel {
-                    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
+                CustomLabel {
+                    text:               activeVehicle && _cameraPhotoMode ? ('00000' + activeVehicle.cameraTriggerPoints.count).slice(-5) : "00000"
+                    visible:            _cameraPhotoMode
+                    pointSize:          ScreenTools.smallFontPointSize
                     anchors.horizontalCenter: parent.horizontalCenter
                 }
-            }
-            /*
-            //-----------------------------------------------------------------
-            //-- Recording Time / Images Captured
-            CustomLabel {
-                text:               (_cameraVideoMode && _camera.videoStatus === QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING) ? _camera.recordTimeStr : "00:00:00"
-                visible:            _cameraVideoMode
-                pointSize:          ScreenTools.smallFontPointSize
-                anchors.horizontalCenter: parent.horizontalCenter
-            }
-            CustomLabel {
-                text:               activeVehicle && _cameraPhotoMode ? ('00000' + activeVehicle.cameraTriggerPoints.count).slice(-5) : "00000"
-                visible:            _cameraPhotoMode
-                pointSize:          ScreenTools.smallFontPointSize
-                anchors.horizontalCenter: parent.horizontalCenter
-            }
-            */
-            Item {
-                height:     1
-                width:      1
+                */
+                Item {
+                    height:     1
+                    width:      1
+                }
             }
         }
     }
-
     //-------------------------------------------------------------------------
     //-- Camera Settings
     Popup {
diff --git a/custom-example/res/CustomFlyView.qml b/custom-example/res/CustomFlyView.qml
index 08d1155..548aafd 100644
--- a/custom-example/res/CustomFlyView.qml
+++ b/custom-example/res/CustomFlyView.qml
@@ -512,10 +512,9 @@ Item {
     Item {
         id:                     gimbalControl
         visible:                camControlLoader.visible && CustomQuickInterface.showGimbalControl
-        anchors.top:            camControlLoader.bottom
-        anchors.topMargin:      height * -0.5
+        anchors.bottom:         camControlLoader.bottom
         anchors.right:          camControlLoader.left
-        anchors.rightMargin:    ScreenTools.defaultFontPixelWidth * 2
+        anchors.rightMargin:    ScreenTools.defaultFontPixelWidth * (QGroundControl.videoManager.hasThermal ? -4 : 2)
         height:                 parent.width * 0.125
         width:                  height
         property real curPitch: 0
diff --git a/custom-example/res/Images/thermal-brightness.svg b/custom-example/res/Images/thermal-brightness.svg
new file mode 100644
index 0000000..7319222
--- /dev/null
+++ b/custom-example/res/Images/thermal-brightness.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 288 288" style="enable-background:new 0 0 288 288;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#FFFFFF;}
+</style>
+<g>
+	<path class="st0" d="M53.3,245.5c-3.1,3.1-7.7,3.1-10.8,0c-3.1-3.1-3.1-7.7,0-10.8l17-17C44,200,34,176.8,32.4,151.3H7.7
+		c-4.6,0-7.7-3.1-7.7-7.7c0-3.9,3.1-7.7,7.7-7.7h24.7C34,111.2,44,88,59.5,70.3l-17-17c-3.1-3.1-3.1-7.7,0-10.8
+		c3.1-3.1,7.7-3.1,10.8,0l17,17C88,44,111.2,34,135.9,32.4V7.7c0-4.6,3.9-7.7,7.7-7.7c4.6,0,7.7,3.1,7.7,7.7v24.7
+		c25.5,1.5,48.6,11.6,66.4,27l17-17c3.1-3.1,7.7-3.1,10.8,0c3.1,3.1,3.1,7.7,0,10.8l-17,17c15.4,17.8,25.5,40.9,27,65.6h24.7
+		c3.9,0,7.7,3.9,7.7,7.7c0,4.6-3.9,7.7-7.7,7.7h-24.7c-1.5,25.5-11.6,48.6-27,66.4l17,17c3.1,3.1,3.1,7.7,0,10.8
+		c-3.1,3.1-7.7,3.1-10.8,0l-17-17c-17.8,15.4-40.9,25.5-66.4,27v24.7c0,3.9-3.1,7.7-7.7,7.7c-3.9,0-7.7-3.9-7.7-7.7v-24.7
+		c-24.7-1.5-47.9-11.6-65.6-27L53.3,245.5z M143.6,47.9c-53.3,0-96.5,42.5-96.5,95.7c0,54,43.2,96.5,96.5,96.5
+		c54,0,96.5-42.5,96.5-96.5C240.1,90.3,197.7,47.9,143.6,47.9z"/>
+	<circle class="st0" cx="144" cy="144" r="72"/>
+</g>
+</svg>
diff --git a/custom-example/res/Images/thermal-palette.svg b/custom-example/res/Images/thermal-palette.svg
new file mode 100644
index 0000000..8615431
--- /dev/null
+++ b/custom-example/res/Images/thermal-palette.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 288 288" style="enable-background:new 0 0 288 288;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#FFFFFF;}
+</style>
+<path class="st0" d="M79.2,0h-72C5.3,0,3.5,0.8,2.1,2.1C0.8,3.5,0,5.3,0,7.2v273.6c0,1.9,0.8,3.8,2.1,5.1c1.4,1.4,3.2,2.1,5.1,2.1
+	h72c1.9,0,3.7-0.8,5.1-2.1c1.4-1.3,2.1-3.2,2.1-5.1V7.2c0-1.9-0.8-3.8-2.1-5.1C82.9,0.8,81.1,0,79.2,0z M43.2,259.2
+	c-5.8,0-11.1-3.5-13.3-8.9c-2.2-5.4-1-11.6,3.1-15.7c4.1-4.1,10.3-5.3,15.7-3.1c5.4,2.2,8.9,7.5,8.9,13.3
+	C57.6,252.7,51.2,259.2,43.2,259.2L43.2,259.2z"/>
+<path class="st0" d="M280.8,201.6h-63l-117,67.6V288h180c1.9,0,3.8-0.8,5.1-2.1c1.4-1.4,2.1-3.2,2.1-5.1v-72c0-1.9-0.8-3.7-2.1-5.1
+	C284.5,202.4,282.7,201.6,280.8,201.6L280.8,201.6z"/>
+<path class="st0" d="M130.3,235.5L278,150.2c3.4-2,4.6-6.4,2.6-9.8l-36-62.4v0c-2-3.4-6.4-4.6-9.8-2.6l-18.1,10.4L130.3,235.5z"/>
+<path class="st0" d="M219.6,37.6l-62.4-36c-3.4-2-7.8-0.8-9.8,2.6L100.8,85v172.8L222.2,47.5c1-1.6,1.2-3.6,0.7-5.5
+	C222.5,40.1,221.3,38.6,219.6,37.6L219.6,37.6z"/>
+</svg>
diff --git a/custom-example/res/Images/thermal-pip.svg b/custom-example/res/Images/thermal-pip.svg
new file mode 100644
index 0000000..22518b1
--- /dev/null
+++ b/custom-example/res/Images/thermal-pip.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 288 288" style="enable-background:new 0 0 288 288;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:none;stroke:#FFFFFF;stroke-width:8;}
+	.st1{fill:#FFFFFF;stroke:#FFFFFF;}
+</style>
+<rect x="3.6" y="40.7" class="st0" width="280.8" height="206.6"/>
+<rect x="122.3" y="144.5" class="st1" width="162.1" height="102.8"/>
+</svg>
diff --git a/custom-example/res/Images/thermal-standard.svg b/custom-example/res/Images/thermal-standard.svg
new file mode 100644
index 0000000..b5ecc3c
--- /dev/null
+++ b/custom-example/res/Images/thermal-standard.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 288 288" style="enable-background:new 0 0 288 288;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:none;stroke:#FFFFFF;stroke-width:8;}
+</style>
+<rect x="3.6" y="40.7" class="st0" width="280.8" height="206.6"/>
+</svg>
diff --git a/custom-example/src/CustomPlugin.cc b/custom-example/src/CustomPlugin.cc
index d09e09f..748cdbd 100644
--- a/custom-example/src/CustomPlugin.cc
+++ b/custom-example/src/CustomPlugin.cc
@@ -395,8 +395,8 @@ CustomPlugin::paletteOverride(QString colorName, QGCPalette::PaletteColorInfo_t&
         colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#585858");
     }
     else if (colorName == QStringLiteral("hoverColor")) {
-        colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled]   = QColor("#E7D8AE");
-        colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled]  = QColor("#E7D8AE");
+        colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled]   = QColor("#746D59");
+        colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled]  = QColor("#746D59");
         colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled]  = QColor("#464f5a");
         colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#464f5a");
     }
diff --git a/custom-example/src/FirmwarePlugin/CustomCameraControl.cc b/custom-example/src/FirmwarePlugin/CustomCameraControl.cc
index ff67b4d..cbb7422 100644
--- a/custom-example/src/FirmwarePlugin/CustomCameraControl.cc
+++ b/custom-example/src/FirmwarePlugin/CustomCameraControl.cc
@@ -17,11 +17,12 @@
 QGC_LOGGING_CATEGORY(CustomCameraLog, "CustomCameraLog")
 QGC_LOGGING_CATEGORY(CustomCameraVerboseLog, "CustomCameraVerboseLog")
 
+static const char* kCAM_IRPALETTE = "CAM_IRPALETTE";
+
 //-----------------------------------------------------------------------------
 CustomCameraControl::CustomCameraControl(const mavlink_camera_information_t *info, Vehicle* vehicle, int compID, QObject* parent)
     : QGCCameraControl(info, vehicle, compID, parent)
 {
-    connect(_vehicle,   &Vehicle::mavlinkMessageReceived,   this, &CustomCameraControl::_mavlinkMessageReceived);
 }
 
 //-----------------------------------------------------------------------------
@@ -94,42 +95,15 @@ CustomCameraControl::_setVideoStatus(VideoStatus status)
 
 //-----------------------------------------------------------------------------
 void
-CustomCameraControl::_mavlinkMessageReceived(const mavlink_message_t& message)
+CustomCameraControl::handleCaptureStatus(const mavlink_camera_capture_status_t& cap)
 {
-    switch (message.msgid) {
-        case MAVLINK_MSG_ID_MOUNT_ORIENTATION:
-            _handleGimbalOrientation(message);
-            break;
-    }
+    QGCCameraControl::handleCaptureStatus(cap);
 }
 
 //-----------------------------------------------------------------------------
-void
-CustomCameraControl::_handleGimbalOrientation(const mavlink_message_t& message)
+Fact*
+CustomCameraControl::irPalette()
 {
-    mavlink_mount_orientation_t o;
-    mavlink_msg_mount_orientation_decode(&message, &o);
-    if(fabsf(_gimbalRoll - o.roll) > 0.5f) {
-        _gimbalRoll = o.roll;
-        emit gimbalRollChanged();
-    }
-    if(fabsf(_gimbalPitch - o.pitch) > 0.5f) {
-        _gimbalPitch = o.pitch;
-        emit gimbalPitchChanged();
-    }
-    if(fabsf(_gimbalYaw - o.yaw) > 0.5f) {
-        _gimbalYaw = o.yaw;
-        emit gimbalYawChanged();
-    }
-    if(!_gimbalData) {
-        _gimbalData = true;
-        emit gimbalDataChanged();
-    }
+    return (_paramComplete && _activeSettings.contains(kCAM_IRPALETTE)) ? getFact(kCAM_IRPALETTE) : nullptr;
 }
 
-//-----------------------------------------------------------------------------
-void
-CustomCameraControl::handleCaptureStatus(const mavlink_camera_capture_status_t& cap)
-{
-    QGCCameraControl::handleCaptureStatus(cap);
-}
diff --git a/custom-example/src/FirmwarePlugin/CustomCameraControl.h b/custom-example/src/FirmwarePlugin/CustomCameraControl.h
index b159c66..42ead7c 100644
--- a/custom-example/src/FirmwarePlugin/CustomCameraControl.h
+++ b/custom-example/src/FirmwarePlugin/CustomCameraControl.h
@@ -28,11 +28,9 @@ class CustomCameraControl : public QGCCameraControl
 public:
     CustomCameraControl(const mavlink_camera_information_t* info, Vehicle* vehicle, int compID, QObject* parent = nullptr);
 
-    Q_PROPERTY(qreal        gimbalRoll      READ    gimbalRoll          NOTIFY gimbalRollChanged)
-    Q_PROPERTY(qreal        gimbalPitch     READ    gimbalPitch         NOTIFY gimbalPitchChanged)
-    Q_PROPERTY(qreal        gimbalYaw       READ    gimbalYaw           NOTIFY gimbalYawChanged)
-    Q_PROPERTY(bool         gimbalData      READ    gimbalData          NOTIFY gimbalDataChanged)
+    Q_PROPERTY(Fact*        irPalette       READ    irPalette           NOTIFY parametersReady)
 
+    Fact*       irPalette           ();
     bool        takePhoto           () override;
     bool        stopTakePhoto       () override;
     bool        startVideo          () override;
@@ -41,29 +39,7 @@ public:
     void        setPhotoMode        () override;
     void        handleCaptureStatus (const mavlink_camera_capture_status_t& capStatus) override;
 
-    qreal       gimbalRoll          () { return static_cast<qreal>(_gimbalRoll);}
-    qreal       gimbalPitch         () { return static_cast<qreal>(_gimbalPitch); }
-    qreal       gimbalYaw           () { return static_cast<qreal>(_gimbalYaw); }
-    bool        gimbalData          () { return _gimbalData; }
-
-private slots:
-    void    _mavlinkMessageReceived (const mavlink_message_t& message);
-
-signals:
-    void    gimbalRollChanged       ();
-    void    gimbalPitchChanged      ();
-    void    gimbalYawChanged        ();
-    void    gimbalDataChanged       ();
-
 protected:
     void    _setVideoStatus         (VideoStatus status) override;
 
-private:
-    void    _handleGimbalOrientation(const mavlink_message_t& message);
-
-private:
-    float                   _gimbalRoll         = 0.0;
-    float                   _gimbalPitch        = 0.0;
-    float                   _gimbalYaw          = 0.0;
-    bool                    _gimbalData         = false;
 };