Unverified Commit 543ba3f3 authored by Don Gagne's avatar Don Gagne Committed by GitHub

Merge pull request #9003 from DonLakeFlyer/PhotoVideoControl

Unified photo/video control which works with mavlink cameras and and video stream
parents 19310246 d6cd32a5
......@@ -36,7 +36,6 @@
<file alias="AnalyzeView.qml">src/AnalyzeView/AnalyzeView.qml</file>
<file alias="AppSettings.qml">src/ui/AppSettings.qml</file>
<file alias="BluetoothSettings.qml">src/ui/preferences/BluetoothSettings.qml</file>
<file alias="CameraPageWidget.qml">src/FlightMap/Widgets/CameraPageWidget.qml</file>
<file alias="CorridorScanEditor.qml">src/PlanView/CorridorScanEditor.qml</file>
<file alias="DebugWindow.qml">src/ui/preferences/DebugWindow.qml</file>
<file alias="ESP8266Component.qml">src/AutoPilotPlugins/Common/ESP8266Component.qml</file>
......@@ -117,7 +116,6 @@
<file alias="QGroundControl/Controls/ModeSwitchDisplay.qml">src/QmlControls/ModeSwitchDisplay.qml</file>
<file alias="QGroundControl/Controls/MultiRotorMotorDisplay.qml">src/QmlControls/MultiRotorMotorDisplay.qml</file>
<file alias="QGroundControl/Controls/OfflineMapButton.qml">src/QmlControls/OfflineMapButton.qml</file>
<file alias="QGroundControl/Controls/PageView.qml">src/QmlControls/PageView.qml</file>
<file alias="QGroundControl/Controls/ParameterEditor.qml">src/QmlControls/ParameterEditor.qml</file>
<file alias="QGroundControl/Controls/ParameterEditorDialog.qml">src/QmlControls/ParameterEditorDialog.qml</file>
<file alias="QGroundControl/Controls/PIDTuning.qml">src/QmlControls/PIDTuning.qml</file>
......@@ -222,7 +220,6 @@
<file alias="QGroundControl/FlightDisplay/GuidedAltitudeSlider.qml">src/FlightDisplay/GuidedAltitudeSlider.qml</file>
<file alias="QGroundControl/FlightDisplay/GuidedToolStripAction.qml">src/FlightDisplay/GuidedToolStripAction.qml</file>
<file alias="QGroundControl/FlightDisplay/MultiVehicleList.qml">src/FlightDisplay/MultiVehicleList.qml</file>
<file alias="QGroundControl/FlightDisplay/MultiVehiclePanel.qml">src/FlightDisplay/MultiVehiclePanel.qml</file>
<file alias="QGroundControl/FlightDisplay/PreFlightBatteryCheck.qml">src/FlightDisplay/PreFlightBatteryCheck.qml</file>
<file alias="QGroundControl/FlightDisplay/PreFlightGPSCheck.qml">src/FlightDisplay/PreFlightGPSCheck.qml</file>
<file alias="QGroundControl/FlightDisplay/PreFlightRCCheck.qml">src/FlightDisplay/PreFlightRCCheck.qml</file>
......@@ -246,6 +243,7 @@
<file alias="QGroundControl/FlightMap/MissionItemIndicatorDrag.qml">src/FlightMap/MapItems/MissionItemIndicatorDrag.qml</file>
<file alias="QGroundControl/FlightMap/MissionItemView.qml">src/FlightMap/MapItems/MissionItemView.qml</file>
<file alias="QGroundControl/FlightMap/MissionLineView.qml">src/FlightMap/MapItems/MissionLineView.qml</file>
<file alias="QGroundControl/FlightMap/PhotoVideoControl.qml">src/FlightMap/Widgets/PhotoVideoControl.qml</file>
<file alias="QGroundControl/FlightMap/PlanMapItems.qml">src/FlightMap/MapItems/PlanMapItems.qml</file>
<file alias="QGroundControl/FlightMap/PolygonEditor.qml">src/FlightMap/MapItems/PolygonEditor.qml</file>
<file alias="QGroundControl/FlightMap/QGCArtificialHorizon.qml">src/FlightMap/Widgets/QGCArtificialHorizon.qml</file>
......@@ -271,10 +269,8 @@
<file alias="TcpSettings.qml">src/ui/preferences/TcpSettings.qml</file>
<file alias="test.qml">src/test.qml</file>
<file alias="UdpSettings.qml">src/ui/preferences/UdpSettings.qml</file>
<file alias="ValuePageWidget.qml">src/FlightMap/Widgets/ValuePageWidget.qml</file>
<file alias="VehicleSummary.qml">src/VehicleSetup/VehicleSummary.qml</file>
<file alias="VibrationPage.qml">src/AnalyzeView/VibrationPage.qml</file>
<file alias="VideoPageWidget.qml">src/FlightMap/Widgets/VideoPageWidget.qml</file>
<file alias="VirtualJoystick.qml">src/FlightDisplay/VirtualJoystick.qml</file>
<file alias="VTOLLandingPatternEditor.qml">src/PlanView/VTOLLandingPatternEditor.qml</file>
</qresource>
......
......@@ -300,17 +300,6 @@ SetupPage {
}
}
} // QGCGroupBox - Hardware Settings
QGCGroupBox {
title: qsTr("Camera Test")
Layout.fillWidth: true
QGCButton {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Trigger Camera")
onClicked: controller.vehicle.triggerCamera()
}
}
}
}
}
......
......@@ -1590,7 +1590,7 @@ QGCCameraControl::handleVideoInfo(const mavlink_video_stream_information_t* vi)
qCDebug(CameraControlLog) << "All stream handlers done";
_streamInfoTimer.stop();
emit autoStreamChanged();
emit _vehicle->dynamicCameras()->streamChanged();
emit _vehicle->cameraManager()->streamChanged();
}
}
......@@ -1636,7 +1636,7 @@ QGCCameraControl::setCurrentStream(int stream)
_requestStreamStatus(static_cast<uint8_t>(pInfo->streamID()));
}
emit currentStreamChanged();
emit _vehicle->dynamicCameras()->streamChanged();
emit _vehicle->cameraManager()->streamChanged();
}
}
}
......@@ -1786,7 +1786,7 @@ QGCCameraControl::_streamTimeout()
//-- If we have at least one stream, work with what we have.
if(_streams.count()) {
emit autoStreamChanged();
emit _vehicle->dynamicCameras()->streamChanged();
emit _vehicle->cameraManager()->streamChanged();
}
return;
}
......@@ -2140,7 +2140,7 @@ QGCCameraControl::wb()
Fact*
QGCCameraControl::mode()
{
return _paramComplete ? getFact(kCAM_MODE) : nullptr;
return _paramComplete && factExists(kCAM_MODE) ? getFact(kCAM_MODE) : nullptr;
}
//-----------------------------------------------------------------------------
......
......@@ -53,6 +53,29 @@ void FactGroup::_setupTimer()
}
}
bool FactGroup::factExists(const QString& name)
{
if (name.contains(".")) {
QStringList parts = name.split(".");
if (parts.count() != 2) {
qWarning() << "Only single level of hierarchy supported";
return false;
}
FactGroup * factGroup = getFactGroup(parts[0]);
if (!factGroup) {
qWarning() << "Unknown FactGroup" << parts[0];
return false;
}
return factGroup->factExists(parts[1]);
}
QString camelCaseName = _ignoreCamelCase ? name : _camelCase(name);
return _nameToFactMap.contains(camelCaseName);
}
Fact* FactGroup::getFact(const QString& name)
{
if (name.contains(".")) {
......
......@@ -32,10 +32,15 @@ public:
Q_PROPERTY(QStringList factNames READ factNames CONSTANT)
Q_PROPERTY(QStringList factGroupNames READ factGroupNames CONSTANT)
/// @ return true: if the fact exists in the group
Q_INVOKABLE bool factExists(const QString& name);
/// @return Fact for specified name, NULL if not found
/// Note: Requesting a fact which doesn't exists is considered an internal error and will spit out a qWarning
Q_INVOKABLE Fact* getFact(const QString& name);
/// @return FactGroup for specified name, NULL if not found
/// Note: Requesting a fact group which doesn't exists is considered an internal error and will spit out a qWarning
Q_INVOKABLE FactGroup* getFactGroup(const QString& name);
/// Turning on live updates will allow value changes to flow through as they are received.
......
......@@ -28,7 +28,7 @@ Item {
property double _ar: QGroundControl.videoManager.aspectRatio
property bool _showGrid: QGroundControl.settingsManager.videoSettings.gridLines.rawValue > 0
property var _dynamicCameras: activeVehicle ? activeVehicle.dynamicCameras : null
property var _dynamicCameras: activeVehicle ? activeVehicle.cameraManager : null
property bool _connected: activeVehicle ? !activeVehicle.connectionLost : false
property int _curCameraIndex: _dynamicCameras ? _dynamicCameras.currentCamera : 0
property bool _isCamera: _dynamicCameras ? _dynamicCameras.cameras.count > 0 : false
......
......@@ -26,15 +26,11 @@ Column {
id: _root
spacing: ScreenTools.defaultFontPixelHeight * 0.25
property var missionController
property real availableHeight
property var missionController
Loader {
width: parent.width
width: parent.width
source: QGroundControl.settingsManager.flyViewSettings.alternateInstrumentPanel.rawValue ?
"qrc:/qml/QGCInstrumentWidgetAlternate.qml" : "qrc:/qml/QGCInstrumentWidget.qml"
property real maxHeight: availableHeight - y
property bool showValues: !QGroundControl.airspaceManager.airspaceVisible
}
}
......@@ -23,12 +23,6 @@ Column {
property real availableHeight
MultiVehiclePanel {
id: multiVehiclePanel
width: parent.width
availableHeight: parent.height - y
}
AirspaceControl {
id: airspaceControl
width: parent.width
......@@ -40,7 +34,5 @@ Column {
id: flightDisplayViewWidgets
width: parent.width
missionController: _missionController
availableHeight: _root.availableHeight - y
visible: multiVehiclePanel.singleVehiclePanel
}
}
......@@ -71,20 +71,61 @@ Item {
rallyPointController: _rallyPointController
}
Row {
id: multiVehiclePanelSelector
anchors.margins: _toolsMargin
anchors.top: parent.top
anchors.right: parent.right
width: _rightPanelWidth
spacing: ScreenTools.defaultFontPixelWidth
visible: QGroundControl.multiVehicleManager.vehicles.count > 1 && QGroundControl.corePlugin.options.flyView.showMultiVehicleList
property bool showSingleVehiclePanel: !visible || singleVehicleRadio.checked
QGCMapPalette { id: mapPal; lightColors: true }
QGCRadioButton {
id: singleVehicleRadio
text: qsTr("Single")
checked: true
textColor: mapPal.text
}
QGCRadioButton {
text: qsTr("Multi-Vehicle")
textColor: mapPal.text
}
}
MultiVehicleList {
anchors.margins: _toolsMargin
anchors.top: multiVehiclePanelSelector.bottom
anchors.right: parent.right
width: _rightPanelWidth
height: parent.height - y - _toolsMargin
visible: !multiVehiclePanelSelector.showSingleVehiclePanel
}
FlyViewInstrumentPanel {
id: instrumentPanel
anchors.margins: _toolsMargin
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.top: multiVehiclePanelSelector.visible ? multiVehiclePanelSelector.bottom : parent.top
anchors.right: parent.right
width: _rightPanelWidth
spacing: _toolsMargin
visible: QGroundControl.corePlugin.options.flyView.showInstrumentPanel
visible: QGroundControl.corePlugin.options.flyView.showInstrumentPanel && multiVehiclePanelSelector.showSingleVehiclePanel
availableHeight: parent.height - y - _toolsMargin
property real rightInset: visible ? parent.width - x : 0
}
PhotoVideoControl {
anchors.margins: _toolsMargin
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
width: _rightPanelWidth
}
TelemetryValuesBar {
id: telemetryPanel
x: recalcXPosition()
......
/****************************************************************************
*
* (c) 2009-2020 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.
*
****************************************************************************/
import QtQuick 2.12
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.12
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FlightDisplay 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
/// Multi vehicle panel for Fly View
Item {
id: _root
height: singleVehiclePanel ? selectorRow.height : availableHeight
visible: QGroundControl.multiVehicleManager.vehicles.count > 1 && QGroundControl.corePlugin.options.flyView.showMultiVehicleList
property alias singleVehiclePanel: singleVehicleView.checked
property real availableHeight
QGCMapPalette { id: mapPal; lightColors: true }
Row {
id: selectorRow
spacing: ScreenTools.defaultFontPixelWidth
QGCRadioButton {
id: singleVehicleView
text: qsTr("Single")
checked: true
textColor: mapPal.text
}
QGCRadioButton {
text: qsTr("Multi-Vehicle")
textColor: mapPal.text
}
}
MultiVehicleList {
anchors.topMargin: ScreenTools.defaultFontPixelHeight / 2
anchors.top: selectorRow.bottom
anchors.bottom: parent.bottom
width: parent.width
visible: !singleVehiclePanel && !QGroundControl.videoManager.fullScreen && QGroundControl.corePlugin.options.showMultiVehicleList
}
}
/****************************************************************************
*
* (c) 2009-2020 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.
*
****************************************************************************/
import QtQuick 2.4
import QtPositioning 5.2
import QtQuick.Layouts 1.2
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
import QtGraphicalEffects 1.0
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Vehicle 1.0
import QGroundControl.Controllers 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
/// Camera page for Instrument Panel PageView
Column {
width: pageWidth
spacing: ScreenTools.defaultFontPixelHeight * 0.25
property bool showSettingsIcon: _camera !== null
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) && _dynamicCameras.cameras.get(_curCameraIndex).paramComplete ? _dynamicCameras.cameras.get(_curCameraIndex) : null) : null
property bool _cameraModeUndefined: _camera ? _camera.cameraMode === QGCCameraControl.CAM_MODE_UNDEFINED : true
property bool _cameraVideoMode: _camera ? _camera.cameraMode === QGCCameraControl.CAM_MODE_VIDEO : false
property bool _cameraPhotoMode: _camera ? _camera.cameraMode === QGCCameraControl.CAM_MODE_PHOTO : false
property bool _cameraElapsedMode: _camera && _camera.cameraMode === QGCCameraControl.CAM_MODE_PHOTO && _camera.photoMode === QGCCameraControl.PHOTO_CAPTURE_TIMELAPSE
property real _spacers: ScreenTools.defaultFontPixelHeight * 0.5
property real _labelFieldWidth: ScreenTools.defaultFontPixelWidth * 30
property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 30
property bool _communicationLost: activeVehicle ? activeVehicle.connectionLost : false
property bool _streamingEnabled: false //TODO: determine what it should be, VideoPageWidget.qml does QGroundControl.settingsManager.videoSettings.streamConfigured
property bool _hasModes: _camera && _camera.hasModes
property bool _videoRecording: _camera && _camera.videoStatus === QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING
property bool _photoIdle: _camera && (_camera.photoStatus === QGCCameraControl.PHOTO_CAPTURE_IDLE || _camera.photoStatus >= QGCCameraControl.PHOTO_CAPTURE_LAST)
property bool _storageReady: _camera && _camera.storageStatus === QGCCameraControl.STORAGE_READY
property bool _batteryReady: _camera && _camera.batteryRemaining >= 0
property bool _storageIgnored: _camera && _camera.storageStatus === QGCCameraControl.STORAGE_NOT_SUPPORTED
property bool _canShoot: !_cameraModeUndefined && ((_storageReady && _camera.storageFree > 0) || _storageIgnored)
property bool _isShooting: (_cameraVideoMode && _videoRecording) || (_cameraPhotoMode && !_photoIdle)
function showSettings() {
mainWindow.showComponentDialog(cameraSettings, _cameraVideoMode ? qsTr("Video Settings") : qsTr("Camera Settings"), 70, StandardButton.Ok)
}
//-- Dumb camera trigger if no actual camera interface exists
QGCButton {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Trigger Camera")
visible: !_camera
onClicked: activeVehicle.triggerCamera()
enabled: activeVehicle
}
Item { width: 1; height: ScreenTools.defaultFontPixelHeight; visible: _camera; }
//-- Actual controller
QGCLabel {
id: cameraLabel
text: _camera ? _camera.modelName : qsTr("Camera")
visible: _camera
font.pointSize: ScreenTools.defaultFontPointSize
anchors.horizontalCenter: parent.horizontalCenter
}
QGCLabel {
text: _camera ? qsTr("Free Space: ") + _camera.storageFreeStr : ""
font.pointSize: ScreenTools.defaultFontPointSize
anchors.horizontalCenter: parent.horizontalCenter
visible: _storageReady
}
QGCLabel {
text: _camera ? qsTr("Battery: ") + _camera.batteryRemainingStr : ""
font.pointSize: ScreenTools.defaultFontPointSize
anchors.horizontalCenter: parent.horizontalCenter
visible: _batteryReady
}
//-- Camera Mode (visible only if camera has modes)
Item { width: 1; height: ScreenTools.defaultFontPixelHeight * 0.75; visible: camMode.visible; }
Rectangle {
id: camMode
width: _hasModes ? ScreenTools.defaultFontPixelWidth * 8 : 0
height: _hasModes ? ScreenTools.defaultFontPixelWidth * 4 : 0
color: qgcPal.windowShadeLight
radius: height * 0.5
visible: _hasModes
anchors.horizontalCenter: parent.horizontalCenter
//-- Video Mode
Rectangle {
width: parent.height
height: parent.height
color: _cameraVideoMode ? qgcPal.window : qgcPal.windowShadeLight
radius: height * 0.5
anchors.left: parent.left
border.color: qgcPal.text
border.width: _cameraVideoMode ? 1 : 0
anchors.verticalCenter: parent.verticalCenter
QGCColoredImage {
height: parent.height * 0.5
width: height
anchors.centerIn: parent
source: "/qmlimages/camera_video.svg"
fillMode: Image.PreserveAspectFit
sourceSize.height: height
color: _cameraVideoMode ? qgcPal.colorGreen : qgcPal.text
MouseArea {
anchors.fill: parent
enabled: _cameraPhotoMode && !_isShooting
onClicked: {
_camera.setVideoMode()
}
}
}
}
//-- Photo Mode
Rectangle {
width: parent.height
height: parent.height
color: _cameraPhotoMode ? qgcPal.window : qgcPal.windowShadeLight
radius: height * 0.5
anchors.right: parent.right
border.color: qgcPal.text
border.width: _cameraPhotoMode ? 1 : 0
anchors.verticalCenter: parent.verticalCenter
QGCColoredImage {
height: parent.height * 0.5
width: height
anchors.centerIn: parent
source: "/qmlimages/camera_photo.svg"
fillMode: Image.PreserveAspectFit
sourceSize.height: height
color: _cameraPhotoMode ? qgcPal.colorGreen : qgcPal.text
MouseArea {
anchors.fill: parent
enabled: _cameraVideoMode && !_isShooting
onClicked: {
_camera.setPhotoMode()
}
}
}
}
}
//-- Shutter
Item { width: 1; height: ScreenTools.defaultFontPixelHeight * 0.75; visible: camShutter.visible; }
Rectangle {
id: camShutter
color: Qt.rgba(0,0,0,0)
width: ScreenTools.defaultFontPixelWidth * 6
height: width
radius: width * 0.5
visible: _camera
border.color: qgcPal.buttonText
border.width: 3
anchors.horizontalCenter: parent.horizontalCenter
Rectangle {
width: parent.width * (_isShooting ? 0.5 : 0.75)
height: width
radius: _isShooting ? 0 : width * 0.5
color: _canShoot ? qgcPal.colorRed : qgcPal.colorGrey
anchors.centerIn: parent
}
MouseArea {
anchors.fill: parent
enabled: _canShoot
onClicked: {
if(_cameraVideoMode) {
_camera.toggleVideo()
} else {
if(_cameraPhotoMode && !_photoIdle && _cameraElapsedMode) {
_camera.stopTakePhoto()
} else {
_camera.takePhoto()
}
}
}
}
}
//-- Timer/Counter
Item { width: 1; height: ScreenTools.defaultFontPixelHeight * 0.75; visible: _camera; }
QGCLabel {
text: (_cameraVideoMode && _camera.videoStatus === QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING) ? _camera.recordTimeStr : "00:00:00"
font.pointSize: ScreenTools.defaultFontPointSize
visible: _cameraVideoMode
anchors.horizontalCenter: parent.horizontalCenter
}
QGCLabel {
text: activeVehicle && _cameraPhotoMode ? ('00000' + activeVehicle.cameraTriggerPoints.count).slice(-5) : "00000"
font.pointSize: ScreenTools.defaultFontPointSize
visible: _cameraPhotoMode
anchors.horizontalCenter: parent.horizontalCenter
}
//-- Settings
Item { width: 1; height: ScreenTools.defaultFontPixelHeight; visible: _camera; }
Component {
id: cameraSettings
QGCViewDialog {
id: _cameraSettingsDialog
QGCFlickable {
anchors.fill: parent
contentHeight: camSettingsCol.height
flickableDirection: Flickable.VerticalFlick
clip: true
Column {
id: camSettingsCol
anchors.left: parent.left
anchors.right: parent.right
spacing: _margins
//-------------------------------------------
//-- 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 {
id: cameraSelector
model: _isCamera ? _dynamicCameras.cameraLabels : []
width: _editFieldWidth
onActivated: _dynamicCameras.currentCamera = index
currentIndex: _dynamicCameras.currentCamera
}
}
//-------------------------------------------
//-- Stream Selector
Row {
spacing: ScreenTools.defaultFontPixelWidth
visible: _camera && _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
onActivated: _camera.currentStream = index
currentIndex: _camera ? _camera.currentStream : 0
}
}
//-------------------------------------------
//-- 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
model: parent.thermalModes
currentIndex: _camera ? _camera.thermalMode : 0
onActivated: _camera.thermalMode = index
}
}
//-------------------------------------------
//-- 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
maximumValue: 100
minimumValue: 0
value: _camera ? _camera.thermalOpacity : 0
updateValueWhileDragging: true
onValueChanged: {
_camera.thermalOpacity = value
}
}
}
//-------------------------------------------
//-- Camera Settings
Repeater {
model: _camera ? _camera.activeSettings : []
Row {
spacing: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
property var _fact: _camera.getFact(modelData)
property bool _isBool: _fact.typeIsBool
property bool _isCombo: !_isBool && _fact.enumStrings.length > 0
property bool _isSlider: _fact && !isNaN(_fact.increment)
property bool _isEdit: !_isBool && !_isSlider && _fact.enumStrings.length < 1
QGCLabel {
text: parent._fact.shortDescription
width: _labelFieldWidth
anchors.verticalCenter: parent.verticalCenter
}
FactComboBox {
width: parent._isCombo ? _editFieldWidth : 0
fact: parent._fact
indexModel: false
visible: parent._isCombo
anchors.verticalCenter: parent.verticalCenter
}
FactTextField {
width: parent._isEdit ? _editFieldWidth : 0
fact: parent._fact
visible: parent._isEdit
}
QGCSlider {
width: parent._isSlider ? _editFieldWidth : 0
maximumValue: parent._fact.max
minimumValue: parent._fact.min
stepSize: parent._fact.increment
visible: parent._isSlider
updateValueWhileDragging: false
anchors.verticalCenter: parent.verticalCenter
Component.onCompleted: {
value = parent._fact.value
}
onValueChanged: {
parent._fact.value = value
}
}
Item {
width: parent._isBool ? _editFieldWidth : 0
height: factSwitch.height
visible: parent._isBool
anchors.verticalCenter: parent.verticalCenter
property var _fact: parent._fact
Switch {
id: factSwitch
anchors.left: parent.left
checked: parent._fact ? parent._fact.value : false
onClicked: parent._fact.value = checked ? 1 : 0
}
}
}
}
//-------------------------------------------
//-- Time Lapse
Row {
spacing: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
visible: _cameraPhotoMode
property var photoModes: [qsTr("Single"), qsTr("Time Lapse")]
QGCLabel {
text: qsTr("Photo Mode")
width: _labelFieldWidth
anchors.verticalCenter: parent.verticalCenter
}
QGCComboBox {
id: photoModeCombo
width: _editFieldWidth
model: parent.photoModes
currentIndex: _camera ? _camera.photoMode : 0
onActivated: _camera.photoMode = index
}
}
//-------------------------------------------
//-- Time Lapse Interval
Row {
spacing: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
visible: _cameraPhotoMode && _camera.photoMode === QGCCameraControl.PHOTO_CAPTURE_TIMELAPSE
QGCLabel {
text: qsTr("Photo Interval (seconds)")