diff --git a/qgcresources.qrc b/qgcresources.qrc index 360b9c4111b1f6d943c68c3e3155919ee5bda887..23b8afa32c3db2d7f8c0a76feeb324cce3621b27 100644 --- a/qgcresources.qrc +++ b/qgcresources.qrc @@ -152,6 +152,8 @@ src/AutoPilotPlugins/Common/Images/ArrowDirection.svg src/AutoPilotPlugins/Common/Images/ArrowCW.svg src/AutoPilotPlugins/Common/Images/ArrowCCW.svg + src/FirmwarePlugin/APM/APMBrandImage.png + src/FirmwarePlugin/PX4/PX4BrandImage.png resources/Antenna_RC.svg diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponent.cc b/src/AutoPilotPlugins/APM/APMAirframeComponent.cc index ccbb3ee0c22135e1008187d8f70c76ee82d2a6cd..d6aedc86dbb505558b1e98e69a94d0d72912538b 100644 --- a/src/AutoPilotPlugins/APM/APMAirframeComponent.cc +++ b/src/AutoPilotPlugins/APM/APMAirframeComponent.cc @@ -32,8 +32,8 @@ QString APMAirframeComponent::name(void) const QString APMAirframeComponent::description(void) const { - return tr("The Airframe Component is used to select the airframe which matches your vehicle. " - "This will in turn set up the various tuning values for flight parameters."); + return tr("Airframe Setup is used to select the airframe which matches your vehicle. " + "You can also the load default parameter values associated with known vehicle types."); } QString APMAirframeComponent::iconResource(void) const diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponent.qml b/src/AutoPilotPlugins/APM/APMAirframeComponent.qml index 62ae84b3e65f5839c9569a06e6b2f10c40bdd58d..29ec60771b88b6792b49e2b2013c6aca916d96f7 100644 --- a/src/AutoPilotPlugins/APM/APMAirframeComponent.qml +++ b/src/AutoPilotPlugins/APM/APMAirframeComponent.qml @@ -11,26 +11,24 @@ import QtQuick 2.5 import QtQuick.Controls 1.2 import QtQuick.Dialogs 1.2 +import QtQuick.Layouts 1.2 import QGroundControl.FactSystem 1.0 -import QGroundControl.FactControls 1.0 import QGroundControl.Palette 1.0 import QGroundControl.Controls 1.0 import QGroundControl.Controllers 1.0 import QGroundControl.ScreenTools 1.0 -QGCView { - id: qgcView - viewPanel: panel - - QGCPalette { id: qgcPal; colorGroupEnabled: panel.enabled } +SetupPage { + id: airframePage + pageComponent: airframePageComponent property real _margins: ScreenTools.defaultFontPixelWidth property Fact _frame: controller.getParameterFact(-1, "FRAME") APMAirframeComponentController { id: controller - factPanel: panel + factPanel: airframePage.viewPanel } ExclusiveGroup { @@ -89,73 +87,47 @@ QGCView { } } - QGCViewPanel { - id: panel - anchors.fill: parent - - Item { - id: helpApplyRow - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - height: Math.max(helpText.contentHeight, applyButton.height) + Component { + id: airframePageComponent - QGCLabel { - id: helpText - anchors.rightMargin: _margins - anchors.left: parent.left - anchors.right: applyButton.right - text: qsTr("Please select your airframe type") - font.pointSize: ScreenTools.mediumFontPointSize - wrapMode: Text.WordWrap - } + Column { + width: availableWidth + height: 1000 + spacing: _margins - QGCButton { - id: applyButton + RowLayout { + anchors.left: parent.left anchors.right: parent.right - text: qsTr("Load common parameters") - onClicked: showDialog(applyRestartDialogComponent, qsTr("Load common parameters"), qgcView.showDialogDefaultWidth, StandardButton.Close) - } - } - - Item { - id: helpSpacer - anchors.top: helpApplyRow.bottom - height: parent.spacerHeight - width: 10 - } - - QGCFlickable { - id: scroll - anchors.top: helpSpacer.bottom - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - contentHeight: frameColumn.height - contentWidth: frameColumn.width - + spacing: _margins + QGCLabel { + font.pointSize: ScreenTools.mediumFontPointSize + wrapMode: Text.WordWrap + text: qsTr("Please select your airframe type") + Layout.fillWidth: true + } - Column { - id: frameColumn - spacing: _margins + QGCButton { + text: qsTr("Load common parameters") + onClicked: showDialog(applyRestartDialogComponent, qsTr("Load common parameters"), qgcView.showDialogDefaultWidth, StandardButton.Close) + } + } - Repeater { - model: controller.airframeTypesModel + Repeater { + model: controller.airframeTypesModel - QGCRadioButton { - text: object.name - checked: controller.currentAirframeType == object - exclusiveGroup: airframeTypeExclusive + QGCRadioButton { + text: object.name + checked: controller.currentAirframeType == object + exclusiveGroup: airframeTypeExclusive - onCheckedChanged: { - if (checked) { - controller.currentAirframeType = object - } + onCheckedChanged: { + if (checked) { + controller.currentAirframeType = object } } } } - } - } // QGCViewPanel -} // QGCView + } // Column + } // Component - pageComponent +} // SetupPage diff --git a/src/AutoPilotPlugins/APM/APMCameraComponent.cc b/src/AutoPilotPlugins/APM/APMCameraComponent.cc index 8a850bb3c9ae1ef1e44ed2bc32bf0c7345125dd1..5d597b5e8daab302fd4fb57b935e8d24b310babf 100644 --- a/src/AutoPilotPlugins/APM/APMCameraComponent.cc +++ b/src/AutoPilotPlugins/APM/APMCameraComponent.cc @@ -29,7 +29,7 @@ QString APMCameraComponent::name(void) const QString APMCameraComponent::description(void) const { - return tr("The Camera Component is used to setup camera and gimbal settings."); + return tr("Camera setup is used to adjust camera and gimbal settings."); } QString APMCameraComponent::iconResource(void) const diff --git a/src/AutoPilotPlugins/APM/APMCameraComponent.qml b/src/AutoPilotPlugins/APM/APMCameraComponent.qml index 1e7699f477c8229ae25b64e888081dd23a7ef9eb..6ff44a5ceb300fdc94ac9b7ef8eca860cb4cbd13 100644 --- a/src/AutoPilotPlugins/APM/APMCameraComponent.qml +++ b/src/AutoPilotPlugins/APM/APMCameraComponent.qml @@ -17,440 +17,436 @@ import QGroundControl.Palette 1.0 import QGroundControl.Controls 1.0 import QGroundControl.ScreenTools 1.0 -QGCView { - id: _cameraView - viewPanel: panel - anchors.fill: parent - - FactPanelController { id: controller; factPanel: panel } - - QGCPalette { id: palette; colorGroupEnabled: enabled } - - property Fact _mountRetractX: controller.getParameterFact(-1, "MNT_RETRACT_X") - property Fact _mountRetractY: controller.getParameterFact(-1, "MNT_RETRACT_Y") - property Fact _mountRetractZ: controller.getParameterFact(-1, "MNT_RETRACT_Z") - - property Fact _mountNeutralX: controller.getParameterFact(-1, "MNT_NEUTRAL_X") - property Fact _mountNeutralY: controller.getParameterFact(-1, "MNT_NEUTRAL_Y") - property Fact _mountNeutralZ: controller.getParameterFact(-1, "MNT_NEUTRAL_Z") - - property Fact _mountRCInTilt: controller.getParameterFact(-1, "MNT_RC_IN_TILT") - property Fact _mountStabTilt: controller.getParameterFact(-1, "MNT_STAB_TILT") - property Fact _mountAngMinTilt: controller.getParameterFact(-1, "MNT_ANGMIN_TIL") - property Fact _mountAngMaxTilt: controller.getParameterFact(-1, "MNT_ANGMAX_TIL") - - property Fact _mountRCInRoll: controller.getParameterFact(-1, "MNT_RC_IN_ROLL") - property Fact _mountStabRoll: controller.getParameterFact(-1, "MNT_STAB_ROLL") - property Fact _mountAngMinRoll: controller.getParameterFact(-1, "MNT_ANGMIN_ROL") - property Fact _mountAngMaxRoll: controller.getParameterFact(-1, "MNT_ANGMAX_ROL") - - property Fact _mountRCInPan: controller.getParameterFact(-1, "MNT_RC_IN_PAN") - property Fact _mountStabPan: controller.getParameterFact(-1, "MNT_STAB_PAN") - property Fact _mountAngMinPan: controller.getParameterFact(-1, "MNT_ANGMIN_PAN") - property Fact _mountAngMaxPan: controller.getParameterFact(-1, "MNT_ANGMAX_PAN") - - property Fact _rc5Function: controller.getParameterFact(-1, "RC5_FUNCTION") - property Fact _rc6Function: controller.getParameterFact(-1, "RC6_FUNCTION") - property Fact _rc7Function: controller.getParameterFact(-1, "RC7_FUNCTION") - property Fact _rc8Function: controller.getParameterFact(-1, "RC8_FUNCTION") - property Fact _rc9Function: controller.getParameterFact(-1, "RC9_FUNCTION") - property Fact _rc10Function: controller.getParameterFact(-1, "RC10_FUNCTION") - property Fact _rc11Function: controller.getParameterFact(-1, "RC11_FUNCTION") - property Fact _rc12Function: controller.getParameterFact(-1, "RC12_FUNCTION") - property Fact _rc13Function: controller.getParameterFact(-1, "RC13_FUNCTION") - property Fact _rc14Function: controller.getParameterFact(-1, "RC14_FUNCTION") - - property bool _tiltEnabled: false - property bool _panEnabled: false - property bool _rollEnabled: false - - // Gimbal Settings not available on older firmware - property bool _showGimbaLSettings: controller.parameterExists(-1, "MNT_DEFLT_MODE") - - readonly property real _margins: ScreenTools.defaultFontPixelHeight - readonly property int _rcFunctionDisabled: 0 - readonly property int _rcFunctionMountPan: 6 - readonly property int _rcFunctionMountTilt: 7 - readonly property int _rcFunctionMountRoll: 8 - readonly property int _firstGimbalOutChannel: 5 - readonly property int _lastGimbalOutChannel: 14 - readonly property int _mountDefaultModeRCTargetting: 3 - - Component.onCompleted: { - if (_showGimbaLSettings) { - gimbalSettingsLoader.sourceComponent = gimbalSettings - } - calcGimbalOutValues() - } - - function setGimbalSettingsServoInfo(loader, channel) { - var rcPrefix = "RC" + channel + "_" - - loader.gimbalOutIndex = channel - 4 - loader.servoPWMMinFact = controller.getParameterFact(-1, rcPrefix + "MIN") - loader.servoPWMMaxFact = controller.getParameterFact(-1, rcPrefix + "MAX") - loader.servoReverseFact = controller.getParameterFact(-1, rcPrefix + "REV") - } - - /// Gimbal output channels are stored in RC#_FUNCTION parameters. We need to loop through those - /// to find them and setup the ui accordindly. - function calcGimbalOutValues() { - gimbalDirectionTiltLoader.gimbalOutIndex = 0 - gimbalDirectionPanLoader.gimbalOutIndex = 0 - gimbalDirectionRollLoader.gimbalOutIndex = 0 - _tiltEnabled = false - _panEnabled = false - _rollEnabled = false - for (var channel=_firstGimbalOutChannel; channel<=_lastGimbalOutChannel; channel++) { - var functionFact = controller.getParameterFact(-1, "RC" + channel + "_FUNCTION") - if (functionFact.value == _rcFunctionMountTilt) { - _tiltEnabled = true - setGimbalSettingsServoInfo(gimbalDirectionTiltLoader, channel) - } else if (functionFact.value == _rcFunctionMountPan) { - _panEnabled = true - setGimbalSettingsServoInfo(gimbalDirectionPanLoader, channel) - } else if (functionFact.value == _rcFunctionMountRoll) { - _rollEnabled = true - setGimbalSettingsServoInfo(gimbalDirectionRollLoader, channel) - } - } - } - - function setRCFunction(channel, rcFunction) { - // First clear any previous settings for this function - for (var index=_firstGimbalOutChannel; index<=_lastGimbalOutChannel; index++) { - var functionFact = controller.getParameterFact(-1, "RC" + index + "_FUNCTION") - if (functionFact.value != _rcFunctionDisabled && functionFact.value == rcFunction) { - functionFact.value = _rcFunctionDisabled - } - } - - // Now set the function into the new channel - if (channel != 0) { - var functionFact = controller.getParameterFact(-1, "RC" + channel + "_FUNCTION") - functionFact.value = rcFunction - } - } - - // Whenever any RC#_FUNCTION parameters chagnes we need to go looking for gimbal output channels again - Connections { target: _rc5Function; onValueChanged: calcGimbalOutValues() } - Connections { target: _rc6Function; onValueChanged: calcGimbalOutValues() } - Connections { target: _rc7Function; onValueChanged: calcGimbalOutValues() } - Connections { target: _rc8Function; onValueChanged: calcGimbalOutValues() } - Connections { target: _rc9Function; onValueChanged: calcGimbalOutValues() } - Connections { target: _rc10Function; onValueChanged: calcGimbalOutValues() } - Connections { target: _rc11Function; onValueChanged: calcGimbalOutValues() } - Connections { target: _rc12Function; onValueChanged: calcGimbalOutValues() } - Connections { target: _rc13Function; onValueChanged: calcGimbalOutValues() } - Connections { target: _rc14Function; onValueChanged: calcGimbalOutValues() } - - // Whenever an MNT_RC_IN_* setting is changed make sure to turn on RC targeting - Connections { - target: _mountRCInPan - onValueChanged: _mountDefaultMode.value = _mountDefaultModeRCTargetting - } - - Connections { - target: _mountRCInRoll - onValueChanged: _mountDefaultMode.value = _mountDefaultModeRCTargetting - } - - Connections { - target: _mountRCInTilt - onValueChanged: _mountDefaultMode.value = _mountDefaultModeRCTargetting - } - - ListModel { - id: gimbalOutModel - ListElement { text: qsTr("Disabled"); value: 0 } - ListElement { text: qsTr("Channel 5"); value: 5 } - ListElement { text: qsTr("Channel 6"); value: 6 } - ListElement { text: qsTr("Channel 7"); value: 7 } - ListElement { text: qsTr("Channel 8"); value: 8 } - ListElement { text: qsTr("Channel 9"); value: 9 } - ListElement { text: qsTr("Channel 10"); value: 10 } - ListElement { text: qsTr("Channel 11"); value: 11 } - ListElement { text: qsTr("Channel 12"); value: 12 } - ListElement { text: qsTr("Channel 13"); value: 13 } - ListElement { text: qsTr("Channel 14"); value: 14 } - } +SetupPage { + id: cameraPage + pageComponent: cameraPageComponent Component { - id: gimbalDirectionSettings - - // The following properties must be set in the Loader - // property string directionTitle - // property bool directionEnabled - // property int gimbalOutIndex - // property Fact mountRcInFact - // property Fact mountStabFact - // property Fact mountAngMinFact - // property Fact mountAngMaxFact - // property Fact servoPWMMinFact - // property Fact servoPWMMaxFact - // property Fact servoReverseFact - // property int rcFunction - - Item { - width: rectangle.x + rectangle.width - height: rectangle.y + rectangle.height - - QGCLabel { - id: directionLabel - text: qsTr("Gimbal ") + directionTitle - font.family: ScreenTools.demiboldFontFamily - } - - Rectangle { - id: rectangle - anchors.topMargin: _margins / 2 - anchors.left: parent.left - anchors.top: directionLabel.bottom - width: mountAngMaxField.x + mountAngMaxField.width + _margins - height: servoPWMMaxField.y + servoPWMMaxField.height + _margins - color: palette.windowShade - - FactCheckBox { - id: mountStabCheckBox - anchors.topMargin: _margins - anchors.left: servoReverseCheckBox.left - anchors.top: parent.top - text: qsTr("Stabilize") - fact: mountStabFact - checkedValue: 1 - uncheckedValue: 0 - enabled: directionEnabled - } - - FactCheckBox { - id: servoReverseCheckBox - anchors.margins: _margins - anchors.top: mountStabCheckBox.bottom - anchors.right: parent.right - text: qsTr("Servo reverse") - checkedValue: 1 - uncheckedValue: 0 - fact: servoReverseFact - enabled: directionEnabled - } - - QGCLabel { - id: gimbalOutLabel - anchors.margins: _margins - anchors.left: parent.left - anchors.baseline: gimbalOutCombo.baseline - text: qsTr("Output channel:") - } - - QGCComboBox { - id: gimbalOutCombo - anchors.margins: _margins - anchors.top: parent.top - anchors.left: gimbalOutLabel.right - width: mountAngMinField.width - model: gimbalOutModel - currentIndex: gimbalOutIndex - - onActivated: setRCFunction(gimbalOutModel.get(index).value, rcFunction) - } - - QGCLabel { - id: mountRcInLabel - anchors.margins: _margins - anchors.left: parent.left - anchors.baseline: mountRcInCombo.baseline - text: qsTr("Input channel:") - enabled: directionEnabled - } - - FactComboBox { - id: mountRcInCombo - anchors.topMargin: _margins / 2 - anchors.top: gimbalOutCombo.bottom - anchors.left: gimbalOutCombo.left - width: mountAngMinField.width - fact: mountRcInFact - indexModel: false - enabled: directionEnabled - } - - QGCLabel { - id: mountAngLabel - anchors.margins: _margins - anchors.left: parent.left - anchors.baseline: mountAngMinField.baseline - text: qsTr("Gimbal angle limits:") - enabled: directionEnabled - } - - QGCLabel { - id: mountAngMinLabel - anchors.margins: _margins - anchors.left: mountAngLabel.right - anchors.baseline: mountAngMinField.baseline - text: qsTr("min") - enabled: directionEnabled - } - - FactTextField { - id: mountAngMinField - anchors.margins: _margins - anchors.top: mountRcInCombo.bottom - anchors.left: mountAngMinLabel.right - fact: mountAngMinFact - enabled: directionEnabled - } - - QGCLabel { - id: mountAngMaxLabel - anchors.margins: _margins - anchors.left: mountAngMinField.right - anchors.baseline: mountAngMinField.baseline - text: qsTr("max") - enabled: directionEnabled - } - - FactTextField { - id: mountAngMaxField - anchors.leftMargin: _margins - anchors.top: mountAngMinField.top - anchors.left: mountAngMaxLabel.right - fact: mountAngMaxFact - enabled: directionEnabled - } - - QGCLabel { - id: servoPWMLabel - anchors.margins: _margins - anchors.left: parent.left - anchors.baseline: servoPWMMinField.baseline - text: qsTr("Servo PWM limits:") - enabled: directionEnabled - } - - QGCLabel { - id: servoPWMMinLabel - anchors.left: mountAngMinLabel.left - anchors.baseline: servoPWMMinField.baseline - text: qsTr("min") - enabled: directionEnabled + id: cameraPageComponent + + Column { + spacing: _margins + width: availableWidth + + FactPanelController { id: controller; factPanel: cameraPage.viewPanel } + + QGCPalette { id: palette; colorGroupEnabled: true } + + property Fact _mountRetractX: controller.getParameterFact(-1, "MNT_RETRACT_X") + property Fact _mountRetractY: controller.getParameterFact(-1, "MNT_RETRACT_Y") + property Fact _mountRetractZ: controller.getParameterFact(-1, "MNT_RETRACT_Z") + + property Fact _mountNeutralX: controller.getParameterFact(-1, "MNT_NEUTRAL_X") + property Fact _mountNeutralY: controller.getParameterFact(-1, "MNT_NEUTRAL_Y") + property Fact _mountNeutralZ: controller.getParameterFact(-1, "MNT_NEUTRAL_Z") + + property Fact _mountRCInTilt: controller.getParameterFact(-1, "MNT_RC_IN_TILT") + property Fact _mountStabTilt: controller.getParameterFact(-1, "MNT_STAB_TILT") + property Fact _mountAngMinTilt: controller.getParameterFact(-1, "MNT_ANGMIN_TIL") + property Fact _mountAngMaxTilt: controller.getParameterFact(-1, "MNT_ANGMAX_TIL") + + property Fact _mountRCInRoll: controller.getParameterFact(-1, "MNT_RC_IN_ROLL") + property Fact _mountStabRoll: controller.getParameterFact(-1, "MNT_STAB_ROLL") + property Fact _mountAngMinRoll: controller.getParameterFact(-1, "MNT_ANGMIN_ROL") + property Fact _mountAngMaxRoll: controller.getParameterFact(-1, "MNT_ANGMAX_ROL") + + property Fact _mountRCInPan: controller.getParameterFact(-1, "MNT_RC_IN_PAN") + property Fact _mountStabPan: controller.getParameterFact(-1, "MNT_STAB_PAN") + property Fact _mountAngMinPan: controller.getParameterFact(-1, "MNT_ANGMIN_PAN") + property Fact _mountAngMaxPan: controller.getParameterFact(-1, "MNT_ANGMAX_PAN") + + property Fact _rc5Function: controller.getParameterFact(-1, "RC5_FUNCTION") + property Fact _rc6Function: controller.getParameterFact(-1, "RC6_FUNCTION") + property Fact _rc7Function: controller.getParameterFact(-1, "RC7_FUNCTION") + property Fact _rc8Function: controller.getParameterFact(-1, "RC8_FUNCTION") + property Fact _rc9Function: controller.getParameterFact(-1, "RC9_FUNCTION") + property Fact _rc10Function: controller.getParameterFact(-1, "RC10_FUNCTION") + property Fact _rc11Function: controller.getParameterFact(-1, "RC11_FUNCTION") + property Fact _rc12Function: controller.getParameterFact(-1, "RC12_FUNCTION") + property Fact _rc13Function: controller.getParameterFact(-1, "RC13_FUNCTION") + property Fact _rc14Function: controller.getParameterFact(-1, "RC14_FUNCTION") + + property bool _tiltEnabled: false + property bool _panEnabled: false + property bool _rollEnabled: false + + // Gimbal Settings not available on older firmware + property bool _showGimbaLSettings: controller.parameterExists(-1, "MNT_DEFLT_MODE") + + readonly property real _margins: ScreenTools.defaultFontPixelHeight + readonly property int _rcFunctionDisabled: 0 + readonly property int _rcFunctionMountPan: 6 + readonly property int _rcFunctionMountTilt: 7 + readonly property int _rcFunctionMountRoll: 8 + readonly property int _firstGimbalOutChannel: 5 + readonly property int _lastGimbalOutChannel: 14 + readonly property int _mountDefaultModeRCTargetting: 3 + + Component.onCompleted: { + if (_showGimbaLSettings) { + gimbalSettingsLoader.sourceComponent = gimbalSettings } + calcGimbalOutValues() + } - FactTextField { - id: servoPWMMinField - anchors.topMargin: _margins / 2 - anchors.leftMargin: _margins - anchors.top: mountAngMaxField.bottom - anchors.left: servoPWMMinLabel.right - fact: servoPWMMinFact - enabled: directionEnabled - } + function setGimbalSettingsServoInfo(loader, channel) { + var rcPrefix = "RC" + channel + "_" - QGCLabel { - id: servoPWMMaxLabel - anchors.margins: _margins - anchors.left: servoPWMMinField.right - anchors.baseline: servoPWMMinField.baseline - text: qsTr("max") - enabled: directionEnabled - } + loader.gimbalOutIndex = channel - 4 + loader.servoPWMMinFact = controller.getParameterFact(-1, rcPrefix + "MIN") + loader.servoPWMMaxFact = controller.getParameterFact(-1, rcPrefix + "MAX") + loader.servoReverseFact = controller.getParameterFact(-1, rcPrefix + "REV") + } - FactTextField { - id: servoPWMMaxField - anchors.leftMargin: _margins - anchors.top: servoPWMMinField.top - anchors.left: servoPWMMaxLabel.right - fact: servoPWMMaxFact - enabled: directionEnabled + /// Gimbal output channels are stored in RC#_FUNCTION parameters. We need to loop through those + /// to find them and setup the ui accordindly. + function calcGimbalOutValues() { + gimbalDirectionTiltLoader.gimbalOutIndex = 0 + gimbalDirectionPanLoader.gimbalOutIndex = 0 + gimbalDirectionRollLoader.gimbalOutIndex = 0 + _tiltEnabled = false + _panEnabled = false + _rollEnabled = false + for (var channel=_firstGimbalOutChannel; channel<=_lastGimbalOutChannel; channel++) { + var functionFact = controller.getParameterFact(-1, "RC" + channel + "_FUNCTION") + if (functionFact.value == _rcFunctionMountTilt) { + _tiltEnabled = true + setGimbalSettingsServoInfo(gimbalDirectionTiltLoader, channel) + } else if (functionFact.value == _rcFunctionMountPan) { + _panEnabled = true + setGimbalSettingsServoInfo(gimbalDirectionPanLoader, channel) + } else if (functionFact.value == _rcFunctionMountRoll) { + _rollEnabled = true + setGimbalSettingsServoInfo(gimbalDirectionRollLoader, channel) + } } - } // Rectangle - } // Item - } // Component - gimbalDirectionSettings - - Component { - id: gimbalSettings - - Item { - width: rectangle.x + rectangle.width - height: rectangle.y + rectangle.height - - property Fact _mountDefaultMode: controller.getParameterFact(-1, "MNT_DEFLT_MODE") - property Fact _mountType: controller.getParameterFact(-1, "MNT_TYPE") - - QGCLabel { - id: settingsLabel - text: qsTr("Gimbal Settings") - font.family: ScreenTools.demiboldFontFamily } - Rectangle { - id: rectangle - anchors.topMargin: _margins / 2 - anchors.top: settingsLabel.bottom - width: gimbalModeCombo.x + gimbalModeCombo.width + _margins - height: gimbalModeCombo.y + gimbalModeCombo.height + _margins - color: palette.windowShade - - QGCLabel { - id: gimbalTypeLabel - anchors.margins: _margins - anchors.left: parent.left - anchors.baseline: gimbalTypeCombo.baseline - text: qsTr("Type:") + function setRCFunction(channel, rcFunction) { + // First clear any previous settings for this function + for (var index=_firstGimbalOutChannel; index<=_lastGimbalOutChannel; index++) { + var functionFact = controller.getParameterFact(-1, "RC" + index + "_FUNCTION") + if (functionFact.value != _rcFunctionDisabled && functionFact.value == rcFunction) { + functionFact.value = _rcFunctionDisabled + } } - FactComboBox { - id: gimbalTypeCombo - anchors.topMargin: _margins - anchors.top: parent.top - anchors.left: gimbalModeCombo.left - width: gimbalModeCombo.width - fact: _mountType - indexModel: false + // Now set the function into the new channel + if (channel != 0) { + var functionFact = controller.getParameterFact(-1, "RC" + channel + "_FUNCTION") + functionFact.value = rcFunction } + } - QGCLabel { - id: rebootLabel - anchors.topMargin: _margins / 2 - anchors.leftMargin: _margins - anchors.rightMargin: _margins - anchors.left: parent.left - anchors.right: parent.right - anchors.top: gimbalTypeCombo.bottom - wrapMode: Text.WordWrap - text: qsTr("Gimbal Type changes takes affect next reboot of autopilot") - } + // Whenever any RC#_FUNCTION parameters chagnes we need to go looking for gimbal output channels again + Connections { target: _rc5Function; onValueChanged: calcGimbalOutValues() } + Connections { target: _rc6Function; onValueChanged: calcGimbalOutValues() } + Connections { target: _rc7Function; onValueChanged: calcGimbalOutValues() } + Connections { target: _rc8Function; onValueChanged: calcGimbalOutValues() } + Connections { target: _rc9Function; onValueChanged: calcGimbalOutValues() } + Connections { target: _rc10Function; onValueChanged: calcGimbalOutValues() } + Connections { target: _rc11Function; onValueChanged: calcGimbalOutValues() } + Connections { target: _rc12Function; onValueChanged: calcGimbalOutValues() } + Connections { target: _rc13Function; onValueChanged: calcGimbalOutValues() } + Connections { target: _rc14Function; onValueChanged: calcGimbalOutValues() } + + // Whenever an MNT_RC_IN_* setting is changed make sure to turn on RC targeting + Connections { + target: _mountRCInPan + onValueChanged: _mountDefaultMode.value = _mountDefaultModeRCTargetting + } - QGCLabel { - id: gimbalModeLabel - anchors.margins: _margins - anchors.left: parent.left - anchors.baseline: gimbalModeCombo.baseline - text: qsTr("Default Mode:") - } + Connections { + target: _mountRCInRoll + onValueChanged: _mountDefaultMode.value = _mountDefaultModeRCTargetting + } - FactComboBox { - id: gimbalModeCombo - anchors.margins: _margins - anchors.top: rebootLabel.bottom - anchors.left: gimbalModeLabel.right - width: ScreenTools.defaultFontPixelWidth * 15 - fact: _mountDefaultMode - indexModel: false - } - } // Rectangle - } // Item - } // Component - gimbalSettings + Connections { + target: _mountRCInTilt + onValueChanged: _mountDefaultMode.value = _mountDefaultModeRCTargetting + } - QGCViewPanel { - id: panel - anchors.fill: parent + ListModel { + id: gimbalOutModel + ListElement { text: qsTr("Disabled"); value: 0 } + ListElement { text: qsTr("Channel 5"); value: 5 } + ListElement { text: qsTr("Channel 6"); value: 6 } + ListElement { text: qsTr("Channel 7"); value: 7 } + ListElement { text: qsTr("Channel 8"); value: 8 } + ListElement { text: qsTr("Channel 9"); value: 9 } + ListElement { text: qsTr("Channel 10"); value: 10 } + ListElement { text: qsTr("Channel 11"); value: 11 } + ListElement { text: qsTr("Channel 12"); value: 12 } + ListElement { text: qsTr("Channel 13"); value: 13 } + ListElement { text: qsTr("Channel 14"); value: 14 } + } - QGCFlickable { - clip: true - anchors.fill: parent - contentWidth: gimbalDirectionTiltLoader.x + gimbalDirectionTiltLoader.width - contentHeight: _showGimbaLSettings ? gimbalSettingsLoader.y + gimbalSettingsLoader.height : gimbalDirectionPanLoader.y + gimbalDirectionPanLoader.height + Component { + id: gimbalDirectionSettings + + // The following properties must be set in the Loader + // property string directionTitle + // property bool directionEnabled + // property int gimbalOutIndex + // property Fact mountRcInFact + // property Fact mountStabFact + // property Fact mountAngMinFact + // property Fact mountAngMaxFact + // property Fact servoPWMMinFact + // property Fact servoPWMMaxFact + // property Fact servoReverseFact + // property int rcFunction + + Item { + width: rectangle.x + rectangle.width + height: rectangle.y + rectangle.height + + QGCLabel { + id: directionLabel + text: qsTr("Gimbal ") + directionTitle + font.family: ScreenTools.demiboldFontFamily + } + + Rectangle { + id: rectangle + anchors.topMargin: _margins / 2 + anchors.left: parent.left + anchors.top: directionLabel.bottom + width: mountAngMaxField.x + mountAngMaxField.width + _margins + height: servoPWMMaxField.y + servoPWMMaxField.height + _margins + color: palette.windowShade + + FactCheckBox { + id: mountStabCheckBox + anchors.topMargin: _margins + anchors.left: servoReverseCheckBox.left + anchors.top: parent.top + text: qsTr("Stabilize") + fact: mountStabFact + checkedValue: 1 + uncheckedValue: 0 + enabled: directionEnabled + } + + FactCheckBox { + id: servoReverseCheckBox + anchors.margins: _margins + anchors.top: mountStabCheckBox.bottom + anchors.right: parent.right + text: qsTr("Servo reverse") + checkedValue: 1 + uncheckedValue: 0 + fact: servoReverseFact + enabled: directionEnabled + } + + QGCLabel { + id: gimbalOutLabel + anchors.margins: _margins + anchors.left: parent.left + anchors.baseline: gimbalOutCombo.baseline + text: qsTr("Output channel:") + } + + QGCComboBox { + id: gimbalOutCombo + anchors.margins: _margins + anchors.top: parent.top + anchors.left: gimbalOutLabel.right + width: mountAngMinField.width + model: gimbalOutModel + currentIndex: gimbalOutIndex + + onActivated: setRCFunction(gimbalOutModel.get(index).value, rcFunction) + } + + QGCLabel { + id: mountRcInLabel + anchors.margins: _margins + anchors.left: parent.left + anchors.baseline: mountRcInCombo.baseline + text: qsTr("Input channel:") + enabled: directionEnabled + } + + FactComboBox { + id: mountRcInCombo + anchors.topMargin: _margins / 2 + anchors.top: gimbalOutCombo.bottom + anchors.left: gimbalOutCombo.left + width: mountAngMinField.width + fact: mountRcInFact + indexModel: false + enabled: directionEnabled + } + + QGCLabel { + id: mountAngLabel + anchors.margins: _margins + anchors.left: parent.left + anchors.baseline: mountAngMinField.baseline + text: qsTr("Gimbal angle limits:") + enabled: directionEnabled + } + + QGCLabel { + id: mountAngMinLabel + anchors.margins: _margins + anchors.left: mountAngLabel.right + anchors.baseline: mountAngMinField.baseline + text: qsTr("min") + enabled: directionEnabled + } + + FactTextField { + id: mountAngMinField + anchors.margins: _margins + anchors.top: mountRcInCombo.bottom + anchors.left: mountAngMinLabel.right + fact: mountAngMinFact + enabled: directionEnabled + } + + QGCLabel { + id: mountAngMaxLabel + anchors.margins: _margins + anchors.left: mountAngMinField.right + anchors.baseline: mountAngMinField.baseline + text: qsTr("max") + enabled: directionEnabled + } + + FactTextField { + id: mountAngMaxField + anchors.leftMargin: _margins + anchors.top: mountAngMinField.top + anchors.left: mountAngMaxLabel.right + fact: mountAngMaxFact + enabled: directionEnabled + } + + QGCLabel { + id: servoPWMLabel + anchors.margins: _margins + anchors.left: parent.left + anchors.baseline: servoPWMMinField.baseline + text: qsTr("Servo PWM limits:") + enabled: directionEnabled + } + + QGCLabel { + id: servoPWMMinLabel + anchors.left: mountAngMinLabel.left + anchors.baseline: servoPWMMinField.baseline + text: qsTr("min") + enabled: directionEnabled + } + + FactTextField { + id: servoPWMMinField + anchors.topMargin: _margins / 2 + anchors.leftMargin: _margins + anchors.top: mountAngMaxField.bottom + anchors.left: servoPWMMinLabel.right + fact: servoPWMMinFact + enabled: directionEnabled + } + + QGCLabel { + id: servoPWMMaxLabel + anchors.margins: _margins + anchors.left: servoPWMMinField.right + anchors.baseline: servoPWMMinField.baseline + text: qsTr("max") + enabled: directionEnabled + } + + FactTextField { + id: servoPWMMaxField + anchors.leftMargin: _margins + anchors.top: servoPWMMinField.top + anchors.left: servoPWMMaxLabel.right + fact: servoPWMMaxFact + enabled: directionEnabled + } + } // Rectangle + } // Item + } // Component - gimbalDirectionSettings + + Component { + id: gimbalSettings + + Item { + width: rectangle.x + rectangle.width + height: rectangle.y + rectangle.height + + property Fact _mountDefaultMode: controller.getParameterFact(-1, "MNT_DEFLT_MODE") + property Fact _mountType: controller.getParameterFact(-1, "MNT_TYPE") + + QGCLabel { + id: settingsLabel + text: qsTr("Gimbal Settings") + font.family: ScreenTools.demiboldFontFamily + } + + Rectangle { + id: rectangle + anchors.topMargin: _margins / 2 + anchors.top: settingsLabel.bottom + width: gimbalModeCombo.x + gimbalModeCombo.width + _margins + height: gimbalModeCombo.y + gimbalModeCombo.height + _margins + color: palette.windowShade + + QGCLabel { + id: gimbalTypeLabel + anchors.margins: _margins + anchors.left: parent.left + anchors.baseline: gimbalTypeCombo.baseline + text: qsTr("Type:") + } + + FactComboBox { + id: gimbalTypeCombo + anchors.topMargin: _margins + anchors.top: parent.top + anchors.left: gimbalModeCombo.left + width: gimbalModeCombo.width + fact: _mountType + indexModel: false + } + + QGCLabel { + id: rebootLabel + anchors.topMargin: _margins / 2 + anchors.leftMargin: _margins + anchors.rightMargin: _margins + anchors.left: parent.left + anchors.right: parent.right + anchors.top: gimbalTypeCombo.bottom + wrapMode: Text.WordWrap + text: qsTr("Gimbal Type changes takes affect next reboot of autopilot") + } + + QGCLabel { + id: gimbalModeLabel + anchors.margins: _margins + anchors.left: parent.left + anchors.baseline: gimbalModeCombo.baseline + text: qsTr("Default Mode:") + } + + FactComboBox { + id: gimbalModeCombo + anchors.margins: _margins + anchors.top: rebootLabel.bottom + anchors.left: gimbalModeLabel.right + width: ScreenTools.defaultFontPixelWidth * 15 + fact: _mountDefaultMode + indexModel: false + } + } // Rectangle + } // Item + } // Component - gimbalSettings Loader { id: gimbalDirectionTiltLoader @@ -471,8 +467,6 @@ QGCView { Loader { id: gimbalDirectionRollLoader - anchors.margins: _margins - anchors.top: gimbalDirectionTiltLoader.bottom sourceComponent: gimbalDirectionSettings property string directionTitle: qsTr("Roll") @@ -490,8 +484,6 @@ QGCView { Loader { id: gimbalDirectionPanLoader - anchors.margins: _margins - anchors.top: gimbalDirectionRollLoader.bottom sourceComponent: gimbalDirectionSettings property string directionTitle: qsTr("Pan") @@ -508,10 +500,8 @@ QGCView { } Loader { - id: gimbalSettingsLoader - anchors.margins: _margins - anchors.top: gimbalDirectionPanLoader.bottom + id: gimbalSettingsLoader } - } // Flickable - } // QGCViewPanel -} // QGCView + } // Column + } // Component +} // SetupPage diff --git a/src/AutoPilotPlugins/APM/APMFlightModesComponent.cc b/src/AutoPilotPlugins/APM/APMFlightModesComponent.cc index 7229a8ad9b8bcce2c975f054c4d7fa43c414c60f..6a2babe08130cdec1778db342810532e205ae12d 100644 --- a/src/AutoPilotPlugins/APM/APMFlightModesComponent.cc +++ b/src/AutoPilotPlugins/APM/APMFlightModesComponent.cc @@ -26,7 +26,7 @@ QString APMFlightModesComponent::name(void) const QString APMFlightModesComponent::description(void) const { - return QStringLiteral("The Flight Modes Component is used to assign FLight Modes to Channel 5."); + return tr("Flight Modes Setup is used to configure the transmitter switches associated with Flight Modes."); } QString APMFlightModesComponent::iconResource(void) const diff --git a/src/AutoPilotPlugins/APM/APMFlightModesComponent.qml b/src/AutoPilotPlugins/APM/APMFlightModesComponent.qml index f958c3c231d77e6fd4c7add02a0353828bd14857..623be09030f195daaa3c7ec4b20d05bc86f576c0 100644 --- a/src/AutoPilotPlugins/APM/APMFlightModesComponent.qml +++ b/src/AutoPilotPlugins/APM/APMFlightModesComponent.qml @@ -18,9 +18,9 @@ import QGroundControl.Controls 1.0 import QGroundControl.Controllers 1.0 import QGroundControl.ScreenTools 1.0 -QGCView { - id: rootQGCView - viewPanel: panel +SetupPage { + id: flightModePage + pageComponent: flightModePageComponent readonly property string _modeChannelParam: controller.modeChannelParam readonly property string _modeParamPrefix: controller.modeParamPrefix @@ -33,26 +33,19 @@ QGCView { property bool _fltmodeChExists: controller.parameterExists(-1, _modeChannelParam) property Fact _fltmodeCh: _fltmodeChExists ? controller.getParameterFact(-1, _modeChannelParam) : _nullFact - QGCPalette { id: qgcPal; colorGroupEnabled: panel.enabled } + QGCPalette { id: qgcPal; colorGroupEnabled: true } APMFlightModesComponentController { id: controller - factPanel: panel + factPanel: flightModePage.viewPanel } - QGCViewPanel { - id: panel - anchors.fill: parent - - QGCFlickable { - anchors.fill: parent - clip: true - contentHeight: flowLayout.height - contentWidth: flowLayout.width + Component { + id: flightModePageComponent Flow { id: flowLayout - width: panel.width // parent.width doesn't work here for some reason! + width: availableWidth spacing: _margins Column { @@ -181,6 +174,5 @@ QGCView { } // Rectangle - Channel options } // Column - Channel options } // Flow - } // QGCFlickable - } // QGCViewPanel -} // QGCView + } // Component - flightModePageComponent +} // SetupPage diff --git a/src/AutoPilotPlugins/APM/APMPowerComponent.qml b/src/AutoPilotPlugins/APM/APMPowerComponent.qml index 410945bf72cc780507470f2ea1be7c8c96eaa862..9a1c6b19e965c190174543d6d75ea50581922574 100644 --- a/src/AutoPilotPlugins/APM/APMPowerComponent.qml +++ b/src/AutoPilotPlugins/APM/APMPowerComponent.qml @@ -11,6 +11,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.2 import QtQuick.Dialogs 1.2 +import QtQuick.Layouts 1.2 import QGroundControl.FactSystem 1.0 import QGroundControl.FactControls 1.0 @@ -18,384 +19,327 @@ import QGroundControl.Palette 1.0 import QGroundControl.Controls 1.0 import QGroundControl.ScreenTools 1.0 -QGCView { - id: rootQGCView - viewPanel: panel - - property Fact battAmpPerVolt: controller.getParameterFact(-1, "BATT_AMP_PERVOLT") - property Fact battCapacity: controller.getParameterFact(-1, "BATT_CAPACITY") - property Fact battCurrPin: controller.getParameterFact(-1, "BATT_CURR_PIN") - property Fact battMonitor: controller.getParameterFact(-1, "BATT_MONITOR") - property Fact battVoltMult: controller.getParameterFact(-1, "BATT_VOLT_MULT") - property Fact battVoltPin: controller.getParameterFact(-1, "BATT_VOLT_PIN") - - property real _margins: ScreenTools.defaultFontPixelHeight - property bool _showAdvanced: sensorCombo.currentIndex == sensorModel.count - 1 - - Component.onCompleted: calcSensor() - - function calcSensor() { - for (var i=0; i 0 - text: qsTr("Loiter above Home for:") + QGCRadioButton { + id: returnAltRadio + anchors.topMargin: _margins + anchors.left: returnAtCurrentRadio.left + anchors.top: returnAtCurrentRadio.bottom + text: qsTr("Return at specified altitude:") + exclusiveGroup: returnAltRadioGroup + checked: _rtlAltFact.value != 0 - onClicked: _rtlLoitTimeFact.value = (checked ? 60 : 0) - } + onClicked: _rtlAltFact.value = 1500 + } - FactTextField { - id: landDelayField - anchors.topMargin: _margins * 1.5 - anchors.left: rltAltField.left - anchors.top: rltAltField.bottom - fact: _rtlLoitTimeFact - showUnits: true - enabled: homeLoiterCheckbox.checked === true - } + FactTextField { + id: rltAltField + anchors.leftMargin: _margins + anchors.left: returnAltRadio.right + anchors.baseline: returnAltRadio.baseline + fact: _rtlAltFact + showUnits: true + enabled: returnAltRadio.checked + } - QGCRadioButton { - id: landRadio - anchors.left: returnAtCurrentRadio.left - anchors.baseline: landSpeedField.baseline - text: qsTr("Land with descent speed:") - checked: _rtlAltFinalFact.value == 0 - exclusiveGroup: landLoiterRadioGroup + QGCCheckBox { + id: homeLoiterCheckbox + anchors.left: returnAtCurrentRadio.left + anchors.baseline: landDelayField.baseline + checked: _rtlLoitTimeFact.value > 0 + text: qsTr("Loiter above Home for:") - onClicked: _rtlAltFinalFact.value = 0 - } + onClicked: _rtlLoitTimeFact.value = (checked ? 60 : 0) + } - FactTextField { - id: landSpeedField - anchors.topMargin: _margins * 1.5 - anchors.top: landDelayField.bottom - anchors.left: rltAltField.left - fact: _landSpeedFact - showUnits: true - enabled: landRadio.checked - } + FactTextField { + id: landDelayField + anchors.topMargin: _margins * 1.5 + anchors.left: rltAltField.left + anchors.top: rltAltField.bottom + fact: _rtlLoitTimeFact + showUnits: true + enabled: homeLoiterCheckbox.checked === true + } - QGCRadioButton { - id: finalLoiterRadio - anchors.left: returnAtCurrentRadio.left - anchors.baseline: rltAltFinalField.baseline - text: qsTr("Final loiter altitude:") - exclusiveGroup: landLoiterRadioGroup + QGCRadioButton { + id: landRadio + anchors.left: returnAtCurrentRadio.left + anchors.baseline: landSpeedField.baseline + text: qsTr("Land with descent speed:") + checked: _rtlAltFinalFact.value == 0 + exclusiveGroup: landLoiterRadioGroup - onClicked: _rtlAltFinalFact.value = _rtlAltFact.value - } + onClicked: _rtlAltFinalFact.value = 0 + } - FactTextField { - id: rltAltFinalField - anchors.topMargin: _margins / 2 - anchors.left: rltAltField.left - anchors.top: landSpeedField.bottom - fact: _rtlAltFinalFact - enabled: finalLoiterRadio.checked - showUnits: true - } - } // Rectangle - RTL Settings - } // Column - RTL Settings + FactTextField { + id: landSpeedField + anchors.topMargin: _margins * 1.5 + anchors.top: landDelayField.bottom + anchors.left: rltAltField.left + fact: _landSpeedFact + showUnits: true + enabled: landRadio.checked + } - Column { - spacing: _margins / 2 + QGCRadioButton { + id: finalLoiterRadio + anchors.left: returnAtCurrentRadio.left + anchors.baseline: rltAltFinalField.baseline + text: qsTr("Final loiter altitude:") + exclusiveGroup: landLoiterRadioGroup - QGCLabel { - text: qsTr("Arming Checks") - font.family: ScreenTools.demiboldFontFamily + onClicked: _rtlAltFinalFact.value = _rtlAltFact.value } - Rectangle { - width: flowLayout.width - height: armingCheckInnerColumn.height + (_margins * 2) - color: ggcPal.windowShade - - Column { - id: armingCheckInnerColumn - anchors.margins: _margins - anchors.top: parent.top + FactTextField { + id: rltAltFinalField + anchors.topMargin: _margins / 2 + anchors.left: rltAltField.left + anchors.top: landSpeedField.bottom + fact: _rtlAltFinalFact + enabled: finalLoiterRadio.checked + showUnits: true + } + } // Rectangle - RTL Settings + } // Column - RTL Settings + + Column { + spacing: _margins / 2 + + QGCLabel { + text: qsTr("Arming Checks") + font.family: ScreenTools.demiboldFontFamily + } + + Rectangle { + width: flowLayout.width + height: armingCheckInnerColumn.height + (_margins * 2) + color: ggcPal.windowShade + + Column { + id: armingCheckInnerColumn + anchors.margins: _margins + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + spacing: _margins + + FactBitmask { + id: armingCheckBitmask anchors.left: parent.left anchors.right: parent.right - spacing: _margins - - FactBitmask { - id: armingCheckBitmask - anchors.left: parent.left - anchors.right: parent.right - firstEntryIsAll: true - fact: _armingCheck - } + firstEntryIsAll: true + fact: _armingCheck + } - QGCLabel { - id: armingCheckWarning - anchors.left: parent.left - anchors.right: parent.right - wrapMode: Text.WordWrap - color: qgcPal.warningText - text: qsTr("Warning: Turning off arming checks can lead to loss of Vehicle control.") - visible: _armingCheck.value != 1 - } + QGCLabel { + id: armingCheckWarning + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + color: qgcPal.warningText + text: qsTr("Warning: Turning off arming checks can lead to loss of Vehicle control.") + visible: _armingCheck.value != 1 } - } // Rectangle - Arming checks - } // Column - Arming Checks - } // Flow - } // QGCFlickable - } // QGCViewPanel -} // QGCView + } + } // Rectangle - Arming checks + } // Column - Arming Checks + } // Flow + } // Component - safetyPageComponent +} // SetupView diff --git a/src/AutoPilotPlugins/APM/APMSafetyComponentPlane.qml b/src/AutoPilotPlugins/APM/APMSafetyComponentPlane.qml index d1934d3d18309d225f67375bdd076cfe918715cb..6b1515b38c4f01ce8bd07649c16a47aa5e5f0bde 100644 --- a/src/AutoPilotPlugins/APM/APMSafetyComponentPlane.qml +++ b/src/AutoPilotPlugins/APM/APMSafetyComponentPlane.qml @@ -18,180 +18,171 @@ import QGroundControl.Palette 1.0 import QGroundControl.Controls 1.0 import QGroundControl.ScreenTools 1.0 -QGCView { - id: _safetyView - viewPanel: panel - anchors.fill: parent +SetupPage { + id: safetyPage + pageComponent: safetyPageComponent - FactPanelController { id: controller; factPanel: panel } + Component { + id: safetyPageComponent - QGCPalette { id: palette; colorGroupEnabled: enabled } + Flow { + id: flowLayout + width: availableWidth + spacing: _margins - property Fact _failsafeBattMah: controller.getParameterFact(-1, "FS_BATT_MAH") - property Fact _failsafeBattVoltage: controller.getParameterFact(-1, "FS_BATT_VOLTAGE") - property Fact _failsafeThrEnable: controller.getParameterFact(-1, "THR_FAILSAFE") - property Fact _failsafeThrValue: controller.getParameterFact(-1, "THR_FS_VALUE") - property Fact _failsafeGCSEnable: controller.getParameterFact(-1, "FS_GCS_ENABL") + FactPanelController { id: controller; factPanel: safetyPage.viewPanel } - property Fact _rtlAltFact: controller.getParameterFact(-1, "ALT_HOLD_RTL") + QGCPalette { id: palette; colorGroupEnabled: true } - property real _margins: ScreenTools.defaultFontPixelHeight + property Fact _failsafeBattMah: controller.getParameterFact(-1, "FS_BATT_MAH") + property Fact _failsafeBattVoltage: controller.getParameterFact(-1, "FS_BATT_VOLTAGE") + property Fact _failsafeThrEnable: controller.getParameterFact(-1, "THR_FAILSAFE") + property Fact _failsafeThrValue: controller.getParameterFact(-1, "THR_FS_VALUE") + property Fact _failsafeGCSEnable: controller.getParameterFact(-1, "FS_GCS_ENABL") - ExclusiveGroup { id: returnAltRadioGroup } + property Fact _rtlAltFact: controller.getParameterFact(-1, "ALT_HOLD_RTL") - QGCViewPanel { - id: panel - anchors.fill: parent + property real _margins: ScreenTools.defaultFontPixelHeight - QGCFlickable { - clip: true - anchors.fill: parent - contentWidth: flowLayout.width - contentHeight: flowLayout.height + ExclusiveGroup { id: returnAltRadioGroup } - Flow { - id: flowLayout - width: panel.width // parent.width doesn't work for some reason - spacing: _margins + Column { + spacing: _margins / 2 - Column { - spacing: _margins / 2 + QGCLabel { + text: qsTr("Failsafe Triggers") + font.family: ScreenTools.demiboldFontFamily + } - QGCLabel { - text: qsTr("Failsafe Triggers") - font.family: ScreenTools.demiboldFontFamily + Rectangle { + width: throttlePWMField.x + throttlePWMField.width + _margins + height: gcsCheckbox.y + gcsCheckbox.height + _margins + color: palette.windowShade + + QGCCheckBox { + id: throttleEnableCheckBox + anchors.margins: _margins + anchors.left: parent.left + anchors.baseline: throttlePWMField.baseline + text: qsTr("Throttle PWM threshold:") + checked: _failsafeThrEnable.value == 1 + + onClicked: _failsafeThrEnable.value = (checked ? 1 : 0) + } + + FactTextField { + id: throttlePWMField + anchors.margins: _margins + anchors.left: throttleEnableCheckBox.right + anchors.top: parent.top + fact: _failsafeThrValue + showUnits: true + enabled: throttleEnableCheckBox.checked + } + + QGCCheckBox { + id: voltageCheckBox + anchors.margins: _margins + anchors.left: parent.left + anchors.baseline: voltageField.baseline + text: qsTr("Voltage threshold:") + checked: _failsafeBattVoltage.value != 0 + + onClicked: _failsafeBattVoltage.value = checked ? 10.5 : 0 + } + + FactTextField { + id: voltageField + anchors.topMargin: _margins + anchors.left: throttlePWMField.left + anchors.top: throttlePWMField.bottom + fact: _failsafeBattVoltage + showUnits: true + enabled: voltageCheckBox.checked + } + + QGCCheckBox { + id: mahCheckBox + anchors.margins: _margins + anchors.left: parent.left + anchors.baseline: mahField.baseline + text: qsTr("MAH threshold:") + checked: _failsafeBattMah.value != 0 + + onClicked: _failsafeBattMah.value = checked ? 600 : 0 + } + + FactTextField { + id: mahField + anchors.topMargin: _margins / 2 + anchors.left: throttlePWMField.left + anchors.top: voltageField.bottom + fact: _failsafeBattMah + showUnits: true + enabled: mahCheckBox.checked + } + + QGCCheckBox { + id: gcsCheckbox + anchors.margins: _margins + anchors.left: parent.left + anchors.top: mahField.bottom + text: qsTr("GCS failsafe") + checked: _failsafeGCSEnable.value != 0 + + onClicked: _failsafeGCSEnable.value = checked ? 1 : 0 + } + } // Rectangle - Failsafe trigger settings + } // Column - Failsafe trigger settings + + Column { + spacing: _margins / 2 + + QGCLabel { + text: qsTr("Return to Launch") + font.family: ScreenTools.demiboldFontFamily + } + + Rectangle { + width: rltAltField.x + rltAltField.width + _margins + height: rltAltField.y + rltAltField.height + _margins + color: palette.windowShade + + QGCRadioButton { + id: returnAtCurrentRadio + anchors.margins: _margins + anchors.left: parent.left + anchors.top: parent.top + text: qsTr("Return at current altitude") + checked: _rtlAltFact.value < 0 + exclusiveGroup: returnAltRadioGroup + + onClicked: _rtlAltFact.value = -1 } - Rectangle { - width: throttlePWMField.x + throttlePWMField.width + _margins - height: gcsCheckbox.y + gcsCheckbox.height + _margins - color: palette.windowShade - - QGCCheckBox { - id: throttleEnableCheckBox - anchors.margins: _margins - anchors.left: parent.left - anchors.baseline: throttlePWMField.baseline - text: qsTr("Throttle PWM threshold:") - checked: _failsafeThrEnable.value == 1 - - onClicked: _failsafeThrEnable.value = (checked ? 1 : 0) - } - - FactTextField { - id: throttlePWMField - anchors.margins: _margins - anchors.left: throttleEnableCheckBox.right - anchors.top: parent.top - fact: _failsafeThrValue - showUnits: true - enabled: throttleEnableCheckBox.checked - } - - QGCCheckBox { - id: voltageCheckBox - anchors.margins: _margins - anchors.left: parent.left - anchors.baseline: voltageField.baseline - text: qsTr("Voltage threshold:") - checked: _failsafeBattVoltage.value != 0 - - onClicked: _failsafeBattVoltage.value = checked ? 10.5 : 0 - } - - FactTextField { - id: voltageField - anchors.topMargin: _margins - anchors.left: throttlePWMField.left - anchors.top: throttlePWMField.bottom - fact: _failsafeBattVoltage - showUnits: true - enabled: voltageCheckBox.checked - } - - QGCCheckBox { - id: mahCheckBox - anchors.margins: _margins - anchors.left: parent.left - anchors.baseline: mahField.baseline - text: qsTr("MAH threshold:") - checked: _failsafeBattMah.value != 0 - - onClicked: _failsafeBattMah.value = checked ? 600 : 0 - } - - FactTextField { - id: mahField - anchors.topMargin: _margins / 2 - anchors.left: throttlePWMField.left - anchors.top: voltageField.bottom - fact: _failsafeBattMah - showUnits: true - enabled: mahCheckBox.checked - } - - QGCCheckBox { - id: gcsCheckbox - anchors.margins: _margins - anchors.left: parent.left - anchors.top: mahField.bottom - text: qsTr("GCS failsafe") - checked: _failsafeGCSEnable.value != 0 - - onClicked: _failsafeGCSEnable.value = checked ? 1 : 0 - } - } // Rectangle - Failsafe trigger settings - } // Column - Failsafe trigger settings - - Column { - spacing: _margins / 2 - - QGCLabel { - text: qsTr("Return to Launch") - font.family: ScreenTools.demiboldFontFamily + QGCRadioButton { + id: returnAltRadio + anchors.topMargin: _margins / 2 + anchors.left: returnAtCurrentRadio.left + anchors.top: returnAtCurrentRadio.bottom + text: qsTr("Return at specified altitude:") + exclusiveGroup: returnAltRadioGroup + checked: _rtlAltFact.value >= 0 + + onClicked: _rtlAltFact.value = 10000 } - Rectangle { - width: rltAltField.x + rltAltField.width + _margins - height: rltAltField.y + rltAltField.height + _margins - color: palette.windowShade - - QGCRadioButton { - id: returnAtCurrentRadio - anchors.margins: _margins - anchors.left: parent.left - anchors.top: parent.top - text: qsTr("Return at current altitude") - checked: _rtlAltFact.value < 0 - exclusiveGroup: returnAltRadioGroup - - onClicked: _rtlAltFact.value = -1 - } - - QGCRadioButton { - id: returnAltRadio - anchors.topMargin: _margins / 2 - anchors.left: returnAtCurrentRadio.left - anchors.top: returnAtCurrentRadio.bottom - text: qsTr("Return at specified altitude:") - exclusiveGroup: returnAltRadioGroup - checked: _rtlAltFact.value >= 0 - - onClicked: _rtlAltFact.value = 10000 - } - - FactTextField { - id: rltAltField - anchors.leftMargin: _margins - anchors.left: returnAltRadio.right - anchors.baseline: returnAltRadio.baseline - fact: _rtlAltFact - showUnits: true - enabled: returnAltRadio.checked - } - } // Rectangle - RTL Settings - } // Column - RTL Settings - } // Flow - } // QGCFlickable - } // QGCViewPanel -} // QGCView + FactTextField { + id: rltAltField + anchors.leftMargin: _margins + anchors.left: returnAltRadio.right + anchors.baseline: returnAltRadio.baseline + fact: _rtlAltFact + showUnits: true + enabled: returnAltRadio.checked + } + } // Rectangle - RTL Settings + } // Column - RTL Settings + } // Flow + } // Component +} // SetupView diff --git a/src/AutoPilotPlugins/APM/APMSensorsComponent.cc b/src/AutoPilotPlugins/APM/APMSensorsComponent.cc index 3f45eeca450d91b7fb00055f71be99845f133d86..e5933b554142c6040528b8616ef5f3b8df8aea1a 100644 --- a/src/AutoPilotPlugins/APM/APMSensorsComponent.cc +++ b/src/AutoPilotPlugins/APM/APMSensorsComponent.cc @@ -30,8 +30,7 @@ QString APMSensorsComponent::name(void) const QString APMSensorsComponent::description(void) const { - return tr("The Sensors Component allows you to calibrate the sensors within your vehicle. " - "Prior to flight you must calibrate the Magnetometer, Gyroscope and Accelerometer."); + return tr("Sensors Setup is used to calibrate the sensors within your vehicle."); } QString APMSensorsComponent::iconResource(void) const diff --git a/src/AutoPilotPlugins/APM/APMSensorsComponent.qml b/src/AutoPilotPlugins/APM/APMSensorsComponent.qml index 533e0b143a68b8f5a12189e9a370f4b97bc4f889..bb87f6985f408875725ee5f8afd3d805b9d7e526 100644 --- a/src/AutoPilotPlugins/APM/APMSensorsComponent.qml +++ b/src/AutoPilotPlugins/APM/APMSensorsComponent.qml @@ -8,624 +8,628 @@ ****************************************************************************/ -import QtQuick 2.2 -import QtQuick.Controls 1.2 -import QtQuick.Controls.Styles 1.2 -import QtQuick.Dialogs 1.2 - -import QGroundControl.FactSystem 1.0 -import QGroundControl.FactControls 1.0 -import QGroundControl.Palette 1.0 -import QGroundControl.Controls 1.0 -import QGroundControl.ScreenTools 1.0 -import QGroundControl.Controllers 1.0 - -QGCView { - id: qgcView - viewPanel: panel - - // Help text which is shown both in the status text area prior to pressing a cal button and in the - // pre-calibration dialog. - - readonly property string orientationHelpSet: "If the orientation is in the direction of flight, select None." - readonly property string orientationHelpCal: "Before calibrating make sure orientation settings are correct. " + orientationHelpSet - readonly property string compassRotationText: "If the compass or GPS module is mounted in flight direction, leave the default value (None)" - - readonly property string compassHelp: "For Compass calibration you will need to rotate your vehicle through a number of positions." - readonly property string gyroHelp: "For Gyroscope calibration you will need to place your vehicle on a surface and leave it still." - readonly property string accelHelp: "For Accelerometer calibration you will need to place your vehicle on all six sides on a perfectly level surface and hold it still in each orientation for a few seconds." - readonly property string levelHelp: "To level the horizon you need to place the vehicle in its level flight position and press OK." - readonly property string airspeedHelp: "For Airspeed calibration you will need to keep your airspeed sensor out of any wind and then blow across the sensor." - - readonly property string statusTextAreaDefaultText: "Start the individual calibration steps by clicking one of the buttons to the left." - - // Used to pass help text to the preCalibrationDialog dialog - property string preCalibrationDialogHelp - - property string _postCalibrationDialogText - property var _postCalibrationDialogParams - - readonly property string _badCompassCalText: "The calibration for Compass %1 appears to be poor. " + - "Check the compass position within your vehicle and re-do the calibration." - - readonly property int sideBarH1PointSize: ScreenTools.mediumFontPointSize - readonly property int mainTextH1PointSize: ScreenTools.mediumFontPointSize // Seems to be unused - - readonly property int rotationColumnWidth: 250 - - property Fact compass1Id: controller.getParameterFact(-1, "COMPASS_DEV_ID") - property Fact compass2Id: controller.getParameterFact(-1, "COMPASS_DEV_ID2") - property Fact compass3Id: controller.getParameterFact(-1, "COMPASS_DEV_ID3") - property Fact compass1ExternalFact: controller.getParameterFact(-1, "COMPASS_EXTERNAL") - property Fact compass1Rot: controller.getParameterFact(-1, "COMPASS_ORIENT") - - property Fact boardRot: controller.getParameterFact(-1, "AHRS_ORIENTATION") - - property bool accelCalNeeded: controller.accelSetupNeeded - property bool compassCalNeeded: controller.compassSetupNeeded - - - // The following parameters are not available in olders firmwares - - property bool compass2ExternalParamAvailable: controller.parameterExists(-1, "COMPASS_EXTERN2") - property bool compass3ExternalParamAvailable: controller.parameterExists(-1, "COMPASS_EXTERN3") - property bool compass2RotParamAvailable: controller.parameterExists(-1, "COMPASS_ORIENT2") - property bool compass3RotParamAvailable: controller.parameterExists(-1, "COMPASS_ORIENT3") - property bool compass1UseParamAvailable: controller.parameterExists(-1, "COMPASS_USE") - property bool compass2UseParamAvailable: controller.parameterExists(-1, "COMPASS_USE2") - property bool compass3UseParamAvailable: controller.parameterExists(-1, "COMPASS_USE3") - - property Fact noFact: Fact { } - property Fact compass2ExternalFact: compass2ExternalParamAvailable ? controller.getParameterFact(-1, "COMPASS_EXTERN2") : noFact - property Fact compass3ExternalFact: compass3ExternalParamAvailable ? controller.getParameterFact(-1, "COMPASS_EXTERN3") : noFact - property Fact compass2Rot: compass2RotParamAvailable ? controller.getParameterFact(-1, "COMPASS_ORIENT2") : noFact - property Fact compass3Rot: compass3RotParamAvailable ? controller.getParameterFact(-1, "COMPASS_ORIENT3") : noFact - property Fact compass1UseFact: compass1UseParamAvailable ? controller.getParameterFact(-1, "COMPASS_USE") : noFact - property Fact compass2UseFact: compass2UseParamAvailable ? controller.getParameterFact(-1, "COMPASS_USE2") : noFact - property Fact compass3UseFact: compass3UseParamAvailable ? controller.getParameterFact(-1, "COMPASS_USE3") : noFact - - // We track these values by binding through a separate property so we can handle missing params - property bool compass1External: compass1ExternalFact.value - property bool compass2External: compass2ExternalParamAvailable ? compass2ExternalFact.value : false // false: Simulate internal so we don't show rotation combos - property bool compass3External: compass3ExternalParamAvailable ? compass3ExternalFact.value : false // false: Simulate internal so we don't show rotation combos - property bool compass1Use: compass1UseParamAvailable ? compass1UseFact.value : true - property bool compass2Use: compass2UseParamAvailable ? compass2UseFact.value : true - property bool compass3Use: compass3UseParamAvailable ? compass3UseFact.value : true - - // Id > = signals compass available, rot < 0 signals internal compass - property bool showCompass1: compass1Id.value > 0 - property bool showCompass2: compass2Id.value > 0 - property bool showCompass3: compass3Id.value > 0 - - readonly property int _calTypeCompass: 1 ///< Calibrate compass - readonly property int _calTypeAccel: 2 ///< Calibrate accel - readonly property int _calTypeSet: 3 ///< Set orientations only - - property bool _orientationsDialogShowCompass: true - property string _orientationDialogHelp: orientationHelpSet - property int _orientationDialogCalType - - function validCompassOffsets(compassParamPrefix) { - var ofsX = controller.getParameterFact(-1, compassParamPrefix + "X") - var ofsY = controller.getParameterFact(-1, compassParamPrefix + "Y") - var ofsZ = controller.getParameterFact(-1, compassParamPrefix + "Z") - return Math.sqrt(ofsX.value^2 + ofsY.value^2 + ofsZ.value^2) < 600 - } - - function showOrientationsDialog(calType) { - var dialogTitle - var buttons = StandardButton.Ok - - _orientationDialogCalType = calType - switch (calType) { - case _calTypeCompass: - _orientationsDialogShowCompass = true - _orientationDialogHelp = orientationHelpCal - dialogTitle = qsTr("Calibrate Compass") - buttons |= StandardButton.Cancel - break - case _calTypeAccel: - _orientationsDialogShowCompass = false - _orientationDialogHelp = orientationHelpCal - dialogTitle = qsTr("Calibrate Accelerometer") - buttons |= StandardButton.Cancel - break - case _calTypeSet: - _orientationsDialogShowCompass = true - _orientationDialogHelp = orientationHelpSet - dialogTitle = qsTr("Sensor Settings") - break - } - - showDialog(orientationsDialogComponent, dialogTitle, qgcView.showDialogDefaultWidth, buttons) - } - - APMSensorsComponentController { - id: controller - factPanel: panel - statusLog: statusTextArea - progressBar: progressBar - compassButton: compassButton - accelButton: accelButton - compassMotButton: motorInterferenceButton - nextButton: nextButton - cancelButton: cancelButton - setOrientationsButton: setOrientationsButton - orientationCalAreaHelpText: orientationCalAreaHelpText - - onResetStatusTextArea: statusLog.text = statusTextAreaDefaultText - - onWaitingForCancelChanged: { - if (controller.waitingForCancel) { - showMessage(qsTr("Calibration Cancel"), qsTr("Waiting for Vehicle to response to Cancel. This may take a few seconds."), 0) - } else { - hideDialog() - } - } - - onCalibrationComplete: { - if (_orientationDialogCalType == _calTypeAccel) { - _postCalibrationDialogText = qsTr("Accelerometer calibration complete.") - _postCalibrationDialogParams = [ "INS_ACCSCAL_X", "INS_ACCSCAL_Y", "INS_ACCSCAL_Z", - "INS_ACC2SCAL_X", "INS_ACC2SCAL_Y", "INS_ACC2SCAL_Z", - "INS_ACC3SCAL_X", "INS_ACC3SCAL_Y", "INS_ACC3SCAL_Z", - "INS_GYROFFS_X", "INS_GYROFFS_Y", "INS_GYROFFS_Z", - "INS_GYR2OFFS_X", "INS_GYR2OFFS_Y", "INS_GYR2OFFS_Z", - "INS_GYR3OFFS_X", "INS_GYR3OFFS_Y", "INS_GYR3OFFS_Z" ] - showDialog(postCalibrationDialogComponent, qsTr("Calibration complete"), qgcView.showDialogDefaultWidth, StandardButton.Ok) - } else if (_orientationDialogCalType == _calTypeCompass) { - _postCalibrationDialogText = qsTr("Compass calibration complete. ") - _postCalibrationDialogParams = []; - if (compass1Id.value > 0) { - if (!validCompassOffsets("COMPASS_OFS_")) { - _postCalibrationDialogText += _badCompassCalText.replace("%1", 1) - } - _postCalibrationDialogParams.push("COMPASS_OFS_X") - _postCalibrationDialogParams.push("COMPASS_OFS_Y") - _postCalibrationDialogParams.push("COMPASS_OFS_Z") - } - if (compass2Id.value > 0) { - if (!validCompassOffsets("COMPASS_OFS_")) { - _postCalibrationDialogText += _badCompassCalText.replace("%1", 2) - } - _postCalibrationDialogParams.push("COMPASS_OFS2_X") - _postCalibrationDialogParams.push("COMPASS_OFS2_Y") - _postCalibrationDialogParams.push("COMPASS_OFS2_Z") - } - if (compass3Id.value > 0) { - if (!validCompassOffsets("COMPASS_OFS_")) { - _postCalibrationDialogText += _badCompassCalText.replace("%1", 3) - } - _postCalibrationDialogParams.push("COMPASS_OFS3_X") - _postCalibrationDialogParams.push("COMPASS_OFS3_Y") - _postCalibrationDialogParams.push("COMPASS_OFS3_Z") - } - showDialog(postCalibrationDialogComponent, qsTr("Calibration complete"), qgcView.showDialogDefaultWidth, StandardButton.Ok) - } - } - } - - Component.onCompleted: { - var usingUDP = controller.usingUDPLink() - if (usingUDP) { - console.log("onUsingUDPLink") - showMessage("Sensor Calibration", "Performing sensor calibration over a WiFi connection is known to be unreliable. You should disconnect and perform calibration using a direct USB connection instead.", StandardButton.Ok) - } - } - - QGCPalette { id: qgcPal; colorGroupEnabled: panel.enabled } +import QtQuick 2.2 +import QtQuick.Controls 1.2 +import QtQuick.Controls.Styles 1.2 +import QtQuick.Dialogs 1.2 +import QtQuick.Layouts 1.2 + +import QGroundControl.FactSystem 1.0 +import QGroundControl.FactControls 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controllers 1.0 + +SetupPage { + id: sensorsPage + pageComponent: sensorsPageComponent Component { - id: postCalibrationDialogComponent - - QGCViewDialog { - QGCLabel { - id: textLabel - anchors.left: parent.left - anchors.right: parent.right - wrapMode: Text.WordWrap - text: _postCalibrationDialogText - } - - QGCCheckBox { - id: showValues - anchors.topMargin: ScreenTools.defaultFontPixelHeight - anchors.top: textLabel.bottom - text: qsTr("Show values") + id: sensorsPageComponent + + RowLayout { + width: 1000//availableWidth + height: 1000//availableHeight + spacing: ScreenTools.defaultFontPixelWidth / 2 + + // Help text which is shown both in the status text area prior to pressing a cal button and in the + // pre-calibration dialog. + + readonly property string orientationHelpSet: "If the orientation is in the direction of flight, select None." + readonly property string orientationHelpCal: "Before calibrating make sure orientation settings are correct. " + orientationHelpSet + readonly property string compassRotationText: "If the compass or GPS module is mounted in flight direction, leave the default value (None)" + + readonly property string compassHelp: "For Compass calibration you will need to rotate your vehicle through a number of positions." + readonly property string gyroHelp: "For Gyroscope calibration you will need to place your vehicle on a surface and leave it still." + readonly property string accelHelp: "For Accelerometer calibration you will need to place your vehicle on all six sides on a perfectly level surface and hold it still in each orientation for a few seconds." + readonly property string levelHelp: "To level the horizon you need to place the vehicle in its level flight position and press OK." + readonly property string airspeedHelp: "For Airspeed calibration you will need to keep your airspeed sensor out of any wind and then blow across the sensor." + + readonly property string statusTextAreaDefaultText: "Start the individual calibration steps by clicking one of the buttons to the left." + + // Used to pass help text to the preCalibrationDialog dialog + property string preCalibrationDialogHelp + + property string _postCalibrationDialogText + property var _postCalibrationDialogParams + + readonly property string _badCompassCalText: "The calibration for Compass %1 appears to be poor. " + + "Check the compass position within your vehicle and re-do the calibration." + + readonly property int sideBarH1PointSize: ScreenTools.mediumFontPointSize + readonly property int mainTextH1PointSize: ScreenTools.mediumFontPointSize // Seems to be unused + + readonly property int rotationColumnWidth: 250 + + property Fact compass1Id: controller.getParameterFact(-1, "COMPASS_DEV_ID") + property Fact compass2Id: controller.getParameterFact(-1, "COMPASS_DEV_ID2") + property Fact compass3Id: controller.getParameterFact(-1, "COMPASS_DEV_ID3") + property Fact compass1ExternalFact: controller.getParameterFact(-1, "COMPASS_EXTERNAL") + property Fact compass1Rot: controller.getParameterFact(-1, "COMPASS_ORIENT") + + property Fact boardRot: controller.getParameterFact(-1, "AHRS_ORIENTATION") + + property bool accelCalNeeded: controller.accelSetupNeeded + property bool compassCalNeeded: controller.compassSetupNeeded + + + // The following parameters are not available in olders firmwares + + property bool compass2ExternalParamAvailable: controller.parameterExists(-1, "COMPASS_EXTERN2") + property bool compass3ExternalParamAvailable: controller.parameterExists(-1, "COMPASS_EXTERN3") + property bool compass2RotParamAvailable: controller.parameterExists(-1, "COMPASS_ORIENT2") + property bool compass3RotParamAvailable: controller.parameterExists(-1, "COMPASS_ORIENT3") + property bool compass1UseParamAvailable: controller.parameterExists(-1, "COMPASS_USE") + property bool compass2UseParamAvailable: controller.parameterExists(-1, "COMPASS_USE2") + property bool compass3UseParamAvailable: controller.parameterExists(-1, "COMPASS_USE3") + + property Fact noFact: Fact { } + property Fact compass2ExternalFact: compass2ExternalParamAvailable ? controller.getParameterFact(-1, "COMPASS_EXTERN2") : noFact + property Fact compass3ExternalFact: compass3ExternalParamAvailable ? controller.getParameterFact(-1, "COMPASS_EXTERN3") : noFact + property Fact compass2Rot: compass2RotParamAvailable ? controller.getParameterFact(-1, "COMPASS_ORIENT2") : noFact + property Fact compass3Rot: compass3RotParamAvailable ? controller.getParameterFact(-1, "COMPASS_ORIENT3") : noFact + property Fact compass1UseFact: compass1UseParamAvailable ? controller.getParameterFact(-1, "COMPASS_USE") : noFact + property Fact compass2UseFact: compass2UseParamAvailable ? controller.getParameterFact(-1, "COMPASS_USE2") : noFact + property Fact compass3UseFact: compass3UseParamAvailable ? controller.getParameterFact(-1, "COMPASS_USE3") : noFact + + // We track these values by binding through a separate property so we can handle missing params + property bool compass1External: compass1ExternalFact.value + property bool compass2External: compass2ExternalParamAvailable ? compass2ExternalFact.value : false // false: Simulate internal so we don't show rotation combos + property bool compass3External: compass3ExternalParamAvailable ? compass3ExternalFact.value : false // false: Simulate internal so we don't show rotation combos + property bool compass1Use: compass1UseParamAvailable ? compass1UseFact.value : true + property bool compass2Use: compass2UseParamAvailable ? compass2UseFact.value : true + property bool compass3Use: compass3UseParamAvailable ? compass3UseFact.value : true + + // Id > = signals compass available, rot < 0 signals internal compass + property bool showCompass1: compass1Id.value > 0 + property bool showCompass2: compass2Id.value > 0 + property bool showCompass3: compass3Id.value > 0 + + readonly property int _calTypeCompass: 1 ///< Calibrate compass + readonly property int _calTypeAccel: 2 ///< Calibrate accel + readonly property int _calTypeSet: 3 ///< Set orientations only + + property bool _orientationsDialogShowCompass: true + property string _orientationDialogHelp: orientationHelpSet + property int _orientationDialogCalType + + function validCompassOffsets(compassParamPrefix) { + var ofsX = controller.getParameterFact(-1, compassParamPrefix + "X") + var ofsY = controller.getParameterFact(-1, compassParamPrefix + "Y") + var ofsZ = controller.getParameterFact(-1, compassParamPrefix + "Z") + return Math.sqrt(ofsX.value^2 + ofsY.value^2 + ofsZ.value^2) < 600 } - QGCFlickable { - anchors.topMargin: ScreenTools.defaultFontPixelHeight - anchors.top: showValues.bottom - anchors.bottom: parent.bottom - contentHeight: valueColumn.height - flickableDirection: Flickable.VerticalFlick - visible: showValues.checked - - Column { - id: valueColumn + function showOrientationsDialog(calType) { + var dialogTitle + var buttons = StandardButton.Ok + + _orientationDialogCalType = calType + switch (calType) { + case _calTypeCompass: + _orientationsDialogShowCompass = true + _orientationDialogHelp = orientationHelpCal + dialogTitle = qsTr("Calibrate Compass") + buttons |= StandardButton.Cancel + break + case _calTypeAccel: + _orientationsDialogShowCompass = false + _orientationDialogHelp = orientationHelpCal + dialogTitle = qsTr("Calibrate Accelerometer") + buttons |= StandardButton.Cancel + break + case _calTypeSet: + _orientationsDialogShowCompass = true + _orientationDialogHelp = orientationHelpSet + dialogTitle = qsTr("Sensor Settings") + break + } - Repeater { - model: _postCalibrationDialogParams + showDialog(orientationsDialogComponent, dialogTitle, qgcView.showDialogDefaultWidth, buttons) + } - QGCLabel { - text: fact.name +": " + fact.valueString + APMSensorsComponentController { + id: controller + factPanel: sensorsPage.viewPanel + statusLog: statusTextArea + progressBar: progressBar + compassButton: compassButton + accelButton: accelButton + compassMotButton: motorInterferenceButton + nextButton: nextButton + cancelButton: cancelButton + setOrientationsButton: setOrientationsButton + orientationCalAreaHelpText: orientationCalAreaHelpText + + onResetStatusTextArea: statusLog.text = statusTextAreaDefaultText + + onWaitingForCancelChanged: { + if (controller.waitingForCancel) { + showMessage(qsTr("Calibration Cancel"), qsTr("Waiting for Vehicle to response to Cancel. This may take a few seconds."), 0) + } else { + hideDialog() + } + } - property Fact fact: controller.getParameterFact(-1, modelData) + onCalibrationComplete: { + if (_orientationDialogCalType == _calTypeAccel) { + _postCalibrationDialogText = qsTr("Accelerometer calibration complete.") + _postCalibrationDialogParams = [ "INS_ACCSCAL_X", "INS_ACCSCAL_Y", "INS_ACCSCAL_Z", + "INS_ACC2SCAL_X", "INS_ACC2SCAL_Y", "INS_ACC2SCAL_Z", + "INS_ACC3SCAL_X", "INS_ACC3SCAL_Y", "INS_ACC3SCAL_Z", + "INS_GYROFFS_X", "INS_GYROFFS_Y", "INS_GYROFFS_Z", + "INS_GYR2OFFS_X", "INS_GYR2OFFS_Y", "INS_GYR2OFFS_Z", + "INS_GYR3OFFS_X", "INS_GYR3OFFS_Y", "INS_GYR3OFFS_Z" ] + showDialog(postCalibrationDialogComponent, qsTr("Calibration complete"), qgcView.showDialogDefaultWidth, StandardButton.Ok) + } else if (_orientationDialogCalType == _calTypeCompass) { + _postCalibrationDialogText = qsTr("Compass calibration complete. ") + _postCalibrationDialogParams = []; + if (compass1Id.value > 0) { + if (!validCompassOffsets("COMPASS_OFS_")) { + _postCalibrationDialogText += _badCompassCalText.replace("%1", 1) + } + _postCalibrationDialogParams.push("COMPASS_OFS_X") + _postCalibrationDialogParams.push("COMPASS_OFS_Y") + _postCalibrationDialogParams.push("COMPASS_OFS_Z") } + if (compass2Id.value > 0) { + if (!validCompassOffsets("COMPASS_OFS_")) { + _postCalibrationDialogText += _badCompassCalText.replace("%1", 2) + } + _postCalibrationDialogParams.push("COMPASS_OFS2_X") + _postCalibrationDialogParams.push("COMPASS_OFS2_Y") + _postCalibrationDialogParams.push("COMPASS_OFS2_Z") + } + if (compass3Id.value > 0) { + if (!validCompassOffsets("COMPASS_OFS_")) { + _postCalibrationDialogText += _badCompassCalText.replace("%1", 3) + } + _postCalibrationDialogParams.push("COMPASS_OFS3_X") + _postCalibrationDialogParams.push("COMPASS_OFS3_Y") + _postCalibrationDialogParams.push("COMPASS_OFS3_Z") + } + showDialog(postCalibrationDialogComponent, qsTr("Calibration complete"), qgcView.showDialogDefaultWidth, StandardButton.Ok) } } } - } - } - Component { - id: orientationsDialogComponent - - QGCViewDialog { - id: orientationsDialog - - function accept() { - if (_orientationDialogCalType == _calTypeAccel) { - controller.calibrateAccel() - } else if (_orientationDialogCalType == _calTypeCompass) { - controller.calibrateCompass() + Component.onCompleted: { + var usingUDP = controller.usingUDPLink() + if (usingUDP) { + console.log("onUsingUDPLink") + showMessage("Sensor Calibration", "Performing sensor calibration over a WiFi connection is known to be unreliable. You should disconnect and perform calibration using a direct USB connection instead.", StandardButton.Ok) } - orientationsDialog.hideDialog() } - QGCFlickable { - anchors.fill: parent - contentHeight: columnLayout.height - clip: true + QGCPalette { id: qgcPal; colorGroupEnabled: true } - Column { - id: columnLayout - anchors.margins: ScreenTools.defaultFontPixelWidth - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - spacing: ScreenTools.defaultFontPixelHeight + Component { + id: postCalibrationDialogComponent + QGCViewDialog { QGCLabel { - width: parent.width - wrapMode: Text.WordWrap - text: _orientationDialogHelp + id: textLabel + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + text: _postCalibrationDialogText } - Column { - QGCLabel { - text: qsTr("Autopilot Orientation:") - } - - FactComboBox { - width: rotationColumnWidth - indexModel: false - fact: boardRot - } + QGCCheckBox { + id: showValues + anchors.topMargin: ScreenTools.defaultFontPixelHeight + anchors.top: textLabel.bottom + text: qsTr("Show values") } - Column { - visible: _orientationsDialogShowCompass && showCompass1 - - FactCheckBox { - text: "Use Compass 1" - fact: compass1UseFact - } + QGCFlickable { + anchors.topMargin: ScreenTools.defaultFontPixelHeight + anchors.top: showValues.bottom + anchors.bottom: parent.bottom + contentHeight: valueColumn.height + flickableDirection: Flickable.VerticalFlick + visible: showValues.checked Column { - visible: showCompass1Rot + id: valueColumn - QGCLabel { - text: qsTr("Compass 1 Orientation:") - } + Repeater { + model: _postCalibrationDialogParams + + QGCLabel { + text: fact.name +": " + fact.valueString - FactComboBox { - width: rotationColumnWidth - indexModel: false - fact: compass1Rot + property Fact fact: controller.getParameterFact(-1, modelData) + } } } } + } + } - Column { - visible: _orientationsDialogShowCompass && showCompass2 + Component { + id: orientationsDialogComponent - FactCheckBox { - text: "Use Compass 2" - fact: compass2UseFact + QGCViewDialog { + id: orientationsDialog + + function accept() { + if (_orientationDialogCalType == _calTypeAccel) { + controller.calibrateAccel() + } else if (_orientationDialogCalType == _calTypeCompass) { + controller.calibrateCompass() } + orientationsDialog.hideDialog() + } + + QGCFlickable { + anchors.fill: parent + contentHeight: columnLayout.height + clip: true Column { - visible: showCompass1Rot + id: columnLayout + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + spacing: ScreenTools.defaultFontPixelHeight QGCLabel { - text: qsTr("Compass 2 Orientation:") + width: parent.width + wrapMode: Text.WordWrap + text: _orientationDialogHelp } - FactComboBox { - width: rotationColumnWidth - indexModel: false - fact: compass2Rot + Column { + QGCLabel { + text: qsTr("Autopilot Orientation:") + } + + FactComboBox { + width: rotationColumnWidth + indexModel: false + fact: boardRot + } } - } - } - Column { - visible: _orientationsDialogShowCompass && showCompass3 + Column { + visible: _orientationsDialogShowCompass && showCompass1 - FactCheckBox { - text: "Use Compass 3" - fact: compass3UseFact - } + FactCheckBox { + text: "Use Compass 1" + fact: compass1UseFact + } - Column { - visible: showCompass3Rot + Column { + visible: showCompass1Rot - QGCLabel { - text: qsTr("Compass 3 Orientation:") + QGCLabel { + text: qsTr("Compass 1 Orientation:") + } + + FactComboBox { + width: rotationColumnWidth + indexModel: false + fact: compass1Rot + } + } } - FactComboBox { - width: rotationColumnWidth - indexModel: false - fact: compass3Rot + Column { + visible: _orientationsDialogShowCompass && showCompass2 + + FactCheckBox { + text: "Use Compass 2" + fact: compass2UseFact + } + + Column { + visible: showCompass1Rot + + QGCLabel { + text: qsTr("Compass 2 Orientation:") + } + + FactComboBox { + width: rotationColumnWidth + indexModel: false + fact: compass2Rot + } + } } - } - } - } // Column - } // QGCFlickable - } // QGCViewDialog - } // Component - orientationsDialogComponent - Component { - id: compassMotDialogComponent + Column { + visible: _orientationsDialogShowCompass && showCompass3 - QGCViewDialog { - id: compassMotDialog + FactCheckBox { + text: "Use Compass 3" + fact: compass3UseFact + } - function accept() { - controller.calibrateMotorInterference() - compassMotDialog.hideDialog() - } + Column { + visible: showCompass3Rot - QGCFlickable { - anchors.fill: parent - contentHeight: columnLayout.height - clip: true + QGCLabel { + text: qsTr("Compass 3 Orientation:") + } - Column { - id: columnLayout - anchors.margins: ScreenTools.defaultFontPixelWidth - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - spacing: ScreenTools.defaultFontPixelHeight + FactComboBox { + width: rotationColumnWidth + indexModel: false + fact: compass3Rot + } + } + } + } // Column + } // QGCFlickable + } // QGCViewDialog + } // Component - orientationsDialogComponent - QGCLabel { - anchors.left: parent.left - anchors.right: parent.right - wrapMode: Text.WordWrap - text: "This is recommended for vehicles that have only an internal compass and on vehicles where there is significant interference on the compass from the motors, power wires, etc. " + - "CompassMot only works well if you have a battery current monitor because the magnetic interference is linear with current drawn. " + - "It is technically possible to set-up CompassMot using throttle but this is not recommended." - } + Component { + id: compassMotDialogComponent - QGCLabel { - anchors.left: parent.left - anchors.right: parent.right - wrapMode: Text.WordWrap - text: "Disconnect your props, flip them over and rotate them one position around the frame. " + - "In this configuration they should push the copter down into the ground when the throttle is raised." - } + QGCViewDialog { + id: compassMotDialog - QGCLabel { - anchors.left: parent.left - anchors.right: parent.right - wrapMode: Text.WordWrap - text: "Secure the copter (perhaps with tape) so that it does not move." + function accept() { + controller.calibrateMotorInterference() + compassMotDialog.hideDialog() } - QGCLabel { - anchors.left: parent.left - anchors.right: parent.right - wrapMode: Text.WordWrap - text: "Turn on your transmitter and keep throttle at zero." - } + QGCFlickable { + anchors.fill: parent + contentHeight: columnLayout.height + clip: true - QGCLabel { - anchors.left: parent.left - anchors.right: parent.right - wrapMode: Text.WordWrap - text: "Click Ok to start CompassMot calibration." - } - } // Column - } // QGCFlickable - } // QGCViewDialog - } + Column { + id: columnLayout + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + spacing: ScreenTools.defaultFontPixelHeight - QGCViewPanel { - id: panel - anchors.fill: parent + QGCLabel { + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + text: "This is recommended for vehicles that have only an internal compass and on vehicles where there is significant interference on the compass from the motors, power wires, etc. " + + "CompassMot only works well if you have a battery current monitor because the magnetic interference is linear with current drawn. " + + "It is technically possible to set-up CompassMot using throttle but this is not recommended." + } - Column { - id: buttonColumn - spacing: ScreenTools.defaultFontPixelHeight / 2 + QGCLabel { + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + text: "Disconnect your props, flip them over and rotate them one position around the frame. " + + "In this configuration they should push the copter down into the ground when the throttle is raised." + } - readonly property int buttonWidth: ScreenTools.defaultFontPixelWidth * 15 + QGCLabel { + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + text: "Secure the copter (perhaps with tape) so that it does not move." + } - IndicatorButton { - id: accelButton - width: parent.buttonWidth - text: qsTr("Accelerometer") - indicatorGreen: !accelCalNeeded + QGCLabel { + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + text: "Turn on your transmitter and keep throttle at zero." + } - onClicked: showOrientationsDialog(_calTypeAccel) - } + QGCLabel { + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + text: "Click Ok to start CompassMot calibration." + } + } // Column + } // QGCFlickable + } // QGCViewDialog + } // Component - compassMotDialogComponent - IndicatorButton { - id: compassButton - width: parent.buttonWidth - text: qsTr("Compass") - indicatorGreen: !compassCalNeeded + Column { + spacing: ScreenTools.defaultFontPixelHeight / 2 + Layout.alignment: Qt.AlignLeft | Qt.AlignTop - onClicked: { - if (controller.accelSetupNeeded) { - showMessage(qsTr("Calibrate Compass"), qsTr("Accelerometer must be calibrated prior to Compass."), StandardButton.Ok) - } else { - showOrientationsDialog(_calTypeCompass) + readonly property int buttonWidth: ScreenTools.defaultFontPixelWidth * 15 + + IndicatorButton { + id: accelButton + width: parent.buttonWidth + text: qsTr("Accelerometer") + indicatorGreen: !accelCalNeeded + + onClicked: showOrientationsDialog(_calTypeAccel) + } + + IndicatorButton { + id: compassButton + width: parent.buttonWidth + text: qsTr("Compass") + indicatorGreen: !compassCalNeeded + + onClicked: { + if (controller.accelSetupNeeded) { + showMessage(qsTr("Calibrate Compass"), qsTr("Accelerometer must be calibrated prior to Compass."), StandardButton.Ok) + } else { + showOrientationsDialog(_calTypeCompass) + } } } - } - QGCButton { - id: motorInterferenceButton - width: parent.buttonWidth - text: qsTr("CompassMot") - onClicked: showDialog(compassMotDialogComponent, qsTr("CompassMot - Compass Motor Interference Calibration"), qgcView.showDialogFullWidth, StandardButton.Cancel | StandardButton.Ok) - } + QGCButton { + id: motorInterferenceButton + width: parent.buttonWidth + text: qsTr("CompassMot") + onClicked: showDialog(compassMotDialogComponent, qsTr("CompassMot - Compass Motor Interference Calibration"), qgcView.showDialogFullWidth, StandardButton.Cancel | StandardButton.Ok) + } - QGCButton { - id: nextButton - width: parent.buttonWidth - text: qsTr("Next") - enabled: false - onClicked: controller.nextClicked() - } + QGCButton { + id: nextButton + width: parent.buttonWidth + text: qsTr("Next") + enabled: false + onClicked: controller.nextClicked() + } - QGCButton { - id: cancelButton - width: parent.buttonWidth - text: qsTr("Cancel") - enabled: false - onClicked: controller.cancelCalibration() - } + QGCButton { + id: cancelButton + width: parent.buttonWidth + text: qsTr("Cancel") + enabled: false + onClicked: controller.cancelCalibration() + } - QGCButton { - id: setOrientationsButton - width: parent.buttonWidth - text: qsTr("Sensor Settings") - onClicked: showOrientationsDialog(_calTypeSet) - } - } // Column - Buttons - - Column { - anchors.leftMargin: ScreenTools.defaultFontPixelWidth / 2 - anchors.left: buttonColumn.right - anchors.right: parent.right - anchors.top: parent.top - anchors.bottom: parent.bottom - - ProgressBar { - id: progressBar - anchors.left: parent.left - anchors.right: parent.right - } + QGCButton { + id: setOrientationsButton + width: parent.buttonWidth + text: qsTr("Sensor Settings") + onClicked: showOrientationsDialog(_calTypeSet) + } + } // Column - Buttons - Item { height: ScreenTools.defaultFontPixelHeight; width: 10 } // spacer + Column { + anchors.top: parent.top + anchors.bottom: parent.bottom + Layout.fillWidth: true - Item { - id: centerPanel - width: parent.width - height: parent.height - y + ProgressBar { + id: progressBar + anchors.left: parent.left + anchors.right: parent.right + } - TextArea { - id: statusTextArea - anchors.fill: parent - readOnly: true - frameVisible: false - text: statusTextAreaDefaultText + Item { height: ScreenTools.defaultFontPixelHeight; width: 10 } // spacer - style: TextAreaStyle { - textColor: qgcPal.text - backgroundColor: qgcPal.windowShade - } - } + Item { + id: centerPanel + width: parent.width + height: parent.height - y - Rectangle { - id: orientationCalArea - anchors.fill: parent - visible: controller.showOrientationCalArea - color: qgcPal.windowShade + TextArea { + id: statusTextArea + anchors.fill: parent + readOnly: true + frameVisible: false + text: statusTextAreaDefaultText - QGCLabel { - id: orientationCalAreaHelpText - anchors.margins: ScreenTools.defaultFontPixelWidth - anchors.top: orientationCalArea.top - anchors.left: orientationCalArea.left - width: parent.width - wrapMode: Text.WordWrap - font.pointSize: ScreenTools.mediumFontPointSize + style: TextAreaStyle { + textColor: qgcPal.text + backgroundColor: qgcPal.windowShade + } } - Flow { - anchors.topMargin: ScreenTools.defaultFontPixelWidth - anchors.top: orientationCalAreaHelpText.bottom - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - spacing: ScreenTools.defaultFontPixelWidth - - property real indicatorWidth: (width / 3) - (spacing * 2) - property real indicatorHeight: (height / 2) - spacing - - VehicleRotationCal { - width: parent.indicatorWidth - height: parent.indicatorHeight - visible: controller.orientationCalDownSideVisible - calValid: controller.orientationCalDownSideDone - calInProgress: controller.orientationCalDownSideInProgress - calInProgressText: controller.orientationCalDownSideRotate ? qsTr("Rotate") : qsTr("Hold Still") - imageSource: controller.orientationCalDownSideRotate ? "qrc:///qmlimages/VehicleDownRotate.png" : "qrc:///qmlimages/VehicleDown.png" - } - VehicleRotationCal { - width: parent.indicatorWidth - height: parent.indicatorHeight - visible: controller.orientationCalUpsideDownSideVisible - calValid: controller.orientationCalUpsideDownSideDone - calInProgress: controller.orientationCalUpsideDownSideInProgress - calInProgressText: controller.orientationCalUpsideDownSideRotate ? qsTr("Rotate") : qsTr("Hold Still") - imageSource: controller.orientationCalUpsideDownSideRotate ? "qrc:///qmlimages/VehicleUpsideDownRotate.png" : "qrc:///qmlimages/VehicleUpsideDown.png" - } - VehicleRotationCal { - width: parent.indicatorWidth - height: parent.indicatorHeight - visible: controller.orientationCalNoseDownSideVisible - calValid: controller.orientationCalNoseDownSideDone - calInProgress: controller.orientationCalNoseDownSideInProgress - calInProgressText: controller.orientationCalNoseDownSideRotate ? qsTr("Rotate") : qsTr("Hold Still") - imageSource: controller.orientationCalNoseDownSideRotate ? "qrc:///qmlimages/VehicleNoseDownRotate.png" : "qrc:///qmlimages/VehicleNoseDown.png" - } - VehicleRotationCal { - width: parent.indicatorWidth - height: parent.indicatorHeight - visible: controller.orientationCalTailDownSideVisible - calValid: controller.orientationCalTailDownSideDone - calInProgress: controller.orientationCalTailDownSideInProgress - calInProgressText: controller.orientationCalTailDownSideRotate ? qsTr("Rotate") : qsTr("Hold Still") - imageSource: controller.orientationCalTailDownSideRotate ? "qrc:///qmlimages/VehicleTailDownRotate.png" : "qrc:///qmlimages/VehicleTailDown.png" - } - VehicleRotationCal { - width: parent.indicatorWidth - height: parent.indicatorHeight - visible: controller.orientationCalLeftSideVisible - calValid: controller.orientationCalLeftSideDone - calInProgress: controller.orientationCalLeftSideInProgress - calInProgressText: controller.orientationCalLeftSideRotate ? qsTr("Rotate") : qsTr("Hold Still") - imageSource: controller.orientationCalLeftSideRotate ? "qrc:///qmlimages/VehicleLeftRotate.png" : "qrc:///qmlimages/VehicleLeft.png" + Rectangle { + id: orientationCalArea + anchors.fill: parent + visible: controller.showOrientationCalArea + color: qgcPal.windowShade + + QGCLabel { + id: orientationCalAreaHelpText + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.top: orientationCalArea.top + anchors.left: orientationCalArea.left + width: parent.width + wrapMode: Text.WordWrap + font.pointSize: ScreenTools.mediumFontPointSize } - VehicleRotationCal { - width: parent.indicatorWidth - height: parent.indicatorHeight - visible: controller.orientationCalRightSideVisible - calValid: controller.orientationCalRightSideDone - calInProgress: controller.orientationCalRightSideInProgress - calInProgressText: controller.orientationCalRightSideRotate ? qsTr("Rotate") : qsTr("Hold Still") - imageSource: controller.orientationCalRightSideRotate ? "qrc:///qmlimages/VehicleRightRotate.png" : "qrc:///qmlimages/VehicleRight.png" + + Flow { + anchors.topMargin: ScreenTools.defaultFontPixelWidth + anchors.top: orientationCalAreaHelpText.bottom + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + spacing: ScreenTools.defaultFontPixelWidth + + property real indicatorWidth: (width / 3) - (spacing * 2) + property real indicatorHeight: (height / 2) - spacing + + VehicleRotationCal { + width: parent.indicatorWidth + height: parent.indicatorHeight + visible: controller.orientationCalDownSideVisible + calValid: controller.orientationCalDownSideDone + calInProgress: controller.orientationCalDownSideInProgress + calInProgressText: controller.orientationCalDownSideRotate ? qsTr("Rotate") : qsTr("Hold Still") + imageSource: controller.orientationCalDownSideRotate ? "qrc:///qmlimages/VehicleDownRotate.png" : "qrc:///qmlimages/VehicleDown.png" + } + VehicleRotationCal { + width: parent.indicatorWidth + height: parent.indicatorHeight + visible: controller.orientationCalUpsideDownSideVisible + calValid: controller.orientationCalUpsideDownSideDone + calInProgress: controller.orientationCalUpsideDownSideInProgress + calInProgressText: controller.orientationCalUpsideDownSideRotate ? qsTr("Rotate") : qsTr("Hold Still") + imageSource: controller.orientationCalUpsideDownSideRotate ? "qrc:///qmlimages/VehicleUpsideDownRotate.png" : "qrc:///qmlimages/VehicleUpsideDown.png" + } + VehicleRotationCal { + width: parent.indicatorWidth + height: parent.indicatorHeight + visible: controller.orientationCalNoseDownSideVisible + calValid: controller.orientationCalNoseDownSideDone + calInProgress: controller.orientationCalNoseDownSideInProgress + calInProgressText: controller.orientationCalNoseDownSideRotate ? qsTr("Rotate") : qsTr("Hold Still") + imageSource: controller.orientationCalNoseDownSideRotate ? "qrc:///qmlimages/VehicleNoseDownRotate.png" : "qrc:///qmlimages/VehicleNoseDown.png" + } + VehicleRotationCal { + width: parent.indicatorWidth + height: parent.indicatorHeight + visible: controller.orientationCalTailDownSideVisible + calValid: controller.orientationCalTailDownSideDone + calInProgress: controller.orientationCalTailDownSideInProgress + calInProgressText: controller.orientationCalTailDownSideRotate ? qsTr("Rotate") : qsTr("Hold Still") + imageSource: controller.orientationCalTailDownSideRotate ? "qrc:///qmlimages/VehicleTailDownRotate.png" : "qrc:///qmlimages/VehicleTailDown.png" + } + VehicleRotationCal { + width: parent.indicatorWidth + height: parent.indicatorHeight + visible: controller.orientationCalLeftSideVisible + calValid: controller.orientationCalLeftSideDone + calInProgress: controller.orientationCalLeftSideInProgress + calInProgressText: controller.orientationCalLeftSideRotate ? qsTr("Rotate") : qsTr("Hold Still") + imageSource: controller.orientationCalLeftSideRotate ? "qrc:///qmlimages/VehicleLeftRotate.png" : "qrc:///qmlimages/VehicleLeft.png" + } + VehicleRotationCal { + width: parent.indicatorWidth + height: parent.indicatorHeight + visible: controller.orientationCalRightSideVisible + calValid: controller.orientationCalRightSideDone + calInProgress: controller.orientationCalRightSideInProgress + calInProgressText: controller.orientationCalRightSideRotate ? qsTr("Rotate") : qsTr("Hold Still") + imageSource: controller.orientationCalRightSideRotate ? "qrc:///qmlimages/VehicleRightRotate.png" : "qrc:///qmlimages/VehicleRight.png" + } } } - } - } // Item - Cal display area - } // Column - cal display - } // QGCViewPanel -} // QGCView + } // Item - Cal display area + } // Column - cal display + } // Row + } // Component - sensorsPageComponent +} // SetupPage diff --git a/src/AutoPilotPlugins/APM/APMTuningComponent.cc b/src/AutoPilotPlugins/APM/APMTuningComponent.cc index 32bd528b9f619e3b89c661d39e7d3e11e9c443b1..980b576243fe628d809cbcafd078e2940a3eed6a 100644 --- a/src/AutoPilotPlugins/APM/APMTuningComponent.cc +++ b/src/AutoPilotPlugins/APM/APMTuningComponent.cc @@ -26,7 +26,7 @@ QString APMTuningComponent::name(void) const QString APMTuningComponent::description(void) const { - return tr("The Tuning Component is used to tune the flight characteristics of the Vehicle."); + return tr("Tuning Setup is used to tune the flight characteristics of the Vehicle."); } QString APMTuningComponent::iconResource(void) const diff --git a/src/AutoPilotPlugins/APM/APMTuningComponentCopter.qml b/src/AutoPilotPlugins/APM/APMTuningComponentCopter.qml index d1e70721e6a139217befe6accc8fe70d0595ff51..2bb09e601575cd4a0efb35ac1c86024b50a03def 100644 --- a/src/AutoPilotPlugins/APM/APMTuningComponentCopter.qml +++ b/src/AutoPilotPlugins/APM/APMTuningComponentCopter.qml @@ -17,113 +17,109 @@ import QGroundControl.Palette 1.0 import QGroundControl.Controls 1.0 import QGroundControl.ScreenTools 1.0 -QGCView { - id: _safetyView - viewPanel: panel - anchors.fill: parent - - FactPanelController { id: controller; factPanel: panel } - - QGCPalette { id: palette; colorGroupEnabled: enabled } - - // Older firmwares use THR_MODE, newer use MOT_THST_HOVER - property bool _throttleMidExists: controller.parameterExists(-1, "THR_MID") - property Fact _hoverTuneParam: controller.getParameterFact(-1, _throttleMidExists ? "THR_MID" : "MOT_THST_HOVER") - property real _hoverTuneMin: _throttleMidExists ? 200 : 0 - property real _hoverTuneMax: _throttleMidExists ? 800 : 1 - property real _hoverTuneStep: _throttleMidExists ? 10 : 0.01 - - property Fact _rcFeel: controller.getParameterFact(-1, "RC_FEEL_RP") - property Fact _rateRollP: controller.getParameterFact(-1, "r.ATC_RAT_RLL_P") - property Fact _rateRollI: controller.getParameterFact(-1, "r.ATC_RAT_RLL_I") - property Fact _ratePitchP: controller.getParameterFact(-1, "r.ATC_RAT_PIT_P") - property Fact _ratePitchI: controller.getParameterFact(-1, "r.ATC_RAT_PIT_I") - property Fact _rateClimbP: controller.getParameterFact(-1, "ACCEL_Z_P") - property Fact _rateClimbI: controller.getParameterFact(-1, "ACCEL_Z_I") - - property Fact _ch7Opt: controller.getParameterFact(-1, "CH7_OPT") - property Fact _ch8Opt: controller.getParameterFact(-1, "CH8_OPT") - property Fact _ch9Opt: controller.getParameterFact(-1, "CH9_OPT") - property Fact _ch10Opt: controller.getParameterFact(-1, "CH10_OPT") - property Fact _ch11Opt: controller.getParameterFact(-1, "CH11_OPT") - property Fact _ch12Opt: controller.getParameterFact(-1, "CH12_OPT") - - readonly property int _firstOptionChannel: 7 - readonly property int _lastOptionChannel: 12 - - property Fact _autoTuneAxes: controller.getParameterFact(-1, "AUTOTUNE_AXES") - property int _autoTuneSwitchChannelIndex: 0 - readonly property int _autoTuneOption: 17 - - property real _margins: ScreenTools.defaultFontPixelHeight - - property bool _loadComplete: false - - ExclusiveGroup { id: fenceActionRadioGroup } - ExclusiveGroup { id: landLoiterRadioGroup } - ExclusiveGroup { id: returnAltRadioGroup } - - Component.onCompleted: { - // Qml Sliders have a strange behavior in which they first set Slider::value to some internal - // setting and then set Slider::value to the bound properties value. If you have an onValueChanged - // handler which updates your property with the new value, this first value change will trash - // your bound values. In order to work around this we don't set the values into the Sliders until - // after Qml load is done. We also don't track value changes until Qml load completes. - throttleHover.value = _hoverTuneParam.value - rollPitch.value = _rateRollP.value - climb.value = _rateClimbP.value - rcFeel.value = _rcFeel.value - _loadComplete = true - - calcAutoTuneChannel() - } - - /// The AutoTune switch is stored in one of the RC#_FUNCTION parameters. We need to loop through those - /// to find them and setup the ui accordindly. - function calcAutoTuneChannel() { - _autoTuneSwitchChannelIndex = 0 - for (var channel=_firstOptionChannel; channel<=_lastOptionChannel; channel++) { - var optionFact = controller.getParameterFact(-1, "CH" + channel + "_OPT") - if (optionFact.value == _autoTuneOption) { - _autoTuneSwitchChannelIndex = channel - _firstOptionChannel + 1 - break +SetupPage { + id: tuningPage + pageComponent: tuningPageComponent + + Component { + id: tuningPageComponent + + Column { + width: availableWidth + spacing: _margins + + FactPanelController { id: controller; factPanel: tuningPage.viewPanel } + + QGCPalette { id: palette; colorGroupEnabled: true } + + // Older firmwares use THR_MODE, newer use MOT_THST_HOVER + property bool _throttleMidExists: controller.parameterExists(-1, "THR_MID") + property Fact _hoverTuneParam: controller.getParameterFact(-1, _throttleMidExists ? "THR_MID" : "MOT_THST_HOVER") + property real _hoverTuneMin: _throttleMidExists ? 200 : 0 + property real _hoverTuneMax: _throttleMidExists ? 800 : 1 + property real _hoverTuneStep: _throttleMidExists ? 10 : 0.01 + + property Fact _rcFeel: controller.getParameterFact(-1, "RC_FEEL_RP") + property Fact _rateRollP: controller.getParameterFact(-1, "r.ATC_RAT_RLL_P") + property Fact _rateRollI: controller.getParameterFact(-1, "r.ATC_RAT_RLL_I") + property Fact _ratePitchP: controller.getParameterFact(-1, "r.ATC_RAT_PIT_P") + property Fact _ratePitchI: controller.getParameterFact(-1, "r.ATC_RAT_PIT_I") + property Fact _rateClimbP: controller.getParameterFact(-1, "ACCEL_Z_P") + property Fact _rateClimbI: controller.getParameterFact(-1, "ACCEL_Z_I") + + property Fact _ch7Opt: controller.getParameterFact(-1, "CH7_OPT") + property Fact _ch8Opt: controller.getParameterFact(-1, "CH8_OPT") + property Fact _ch9Opt: controller.getParameterFact(-1, "CH9_OPT") + property Fact _ch10Opt: controller.getParameterFact(-1, "CH10_OPT") + property Fact _ch11Opt: controller.getParameterFact(-1, "CH11_OPT") + property Fact _ch12Opt: controller.getParameterFact(-1, "CH12_OPT") + + readonly property int _firstOptionChannel: 7 + readonly property int _lastOptionChannel: 12 + + property Fact _autoTuneAxes: controller.getParameterFact(-1, "AUTOTUNE_AXES") + property int _autoTuneSwitchChannelIndex: 0 + readonly property int _autoTuneOption: 17 + + property real _margins: ScreenTools.defaultFontPixelHeight + + property bool _loadComplete: false + + ExclusiveGroup { id: fenceActionRadioGroup } + ExclusiveGroup { id: landLoiterRadioGroup } + ExclusiveGroup { id: returnAltRadioGroup } + + Component.onCompleted: { + // Qml Sliders have a strange behavior in which they first set Slider::value to some internal + // setting and then set Slider::value to the bound properties value. If you have an onValueChanged + // handler which updates your property with the new value, this first value change will trash + // your bound values. In order to work around this we don't set the values into the Sliders until + // after Qml load is done. We also don't track value changes until Qml load completes. + throttleHover.value = _hoverTuneParam.value + rollPitch.value = _rateRollP.value + climb.value = _rateClimbP.value + rcFeel.value = _rcFeel.value + _loadComplete = true + + calcAutoTuneChannel() } - } - } - - /// We need to clear AutoTune from any previous channel before setting it to a new one - function setChannelAutoTuneOption(channel) { - // First clear any previous settings for AutTune - for (var optionChannel=_firstOptionChannel; optionChannel<=_lastOptionChannel; optionChannel++) { - var optionFact = controller.getParameterFact(-1, "CH" + optionChannel + "_OPT") - if (optionFact.value == _autoTuneOption) { - optionFact.value = 0 + + /// The AutoTune switch is stored in one of the RC#_FUNCTION parameters. We need to loop through those + /// to find them and setup the ui accordindly. + function calcAutoTuneChannel() { + _autoTuneSwitchChannelIndex = 0 + for (var channel=_firstOptionChannel; channel<=_lastOptionChannel; channel++) { + var optionFact = controller.getParameterFact(-1, "CH" + channel + "_OPT") + if (optionFact.value == _autoTuneOption) { + _autoTuneSwitchChannelIndex = channel - _firstOptionChannel + 1 + break + } + } } - } - - // Now set the function into the new channel - if (channel != 0) { - var optionFact = controller.getParameterFact(-1, "CH" + channel + "_OPT") - optionFact.value = _autoTuneOption - } - } - - Connections { target: _ch7Opt; onValueChanged: calcAutoTuneChannel() } - Connections { target: _ch8Opt; onValueChanged: calcAutoTuneChannel() } - Connections { target: _ch9Opt; onValueChanged: calcAutoTuneChannel() } - Connections { target: _ch10Opt; onValueChanged: calcAutoTuneChannel() } - Connections { target: _ch11Opt; onValueChanged: calcAutoTuneChannel() } - Connections { target: _ch12Opt; onValueChanged: calcAutoTuneChannel() } - - QGCViewPanel { - id: panel - anchors.fill: parent - - QGCFlickable { - clip: true - anchors.fill: parent - contentHeight: autoTuneRect.y + autoTuneRect.height - flickableDirection: Flickable.VerticalFlick + + /// We need to clear AutoTune from any previous channel before setting it to a new one + function setChannelAutoTuneOption(channel) { + // First clear any previous settings for AutTune + for (var optionChannel=_firstOptionChannel; optionChannel<=_lastOptionChannel; optionChannel++) { + var optionFact = controller.getParameterFact(-1, "CH" + optionChannel + "_OPT") + if (optionFact.value == _autoTuneOption) { + optionFact.value = 0 + } + } + + // Now set the function into the new channel + if (channel != 0) { + var optionFact = controller.getParameterFact(-1, "CH" + channel + "_OPT") + optionFact.value = _autoTuneOption + } + } + + Connections { target: _ch7Opt; onValueChanged: calcAutoTuneChannel() } + Connections { target: _ch8Opt; onValueChanged: calcAutoTuneChannel() } + Connections { target: _ch9Opt; onValueChanged: calcAutoTuneChannel() } + Connections { target: _ch10Opt; onValueChanged: calcAutoTuneChannel() } + Connections { target: _ch11Opt; onValueChanged: calcAutoTuneChannel() } + Connections { target: _ch12Opt; onValueChanged: calcAutoTuneChannel() } QGCLabel { id: basicLabel @@ -133,10 +129,8 @@ QGCView { Rectangle { id: basicTuningRect - anchors.topMargin: _margins / 2 anchors.left: parent.left anchors.right: parent.right - anchors.top: basicLabel.bottom height: basicTuningColumn.y + basicTuningColumn.height + _margins color: palette.windowShade @@ -276,16 +270,15 @@ QGCView { } // Rectangle - Basic tuning Flow { - id: flowLayout - anchors.topMargin: _margins / 2 - width: panel.width // parent.width doesn't work here for some reason! - anchors.top: basicTuningRect.bottom - spacing: _margins + id: flowLayout + anchors.left: parent.left + anchors.right: parent.right + spacing: _margins Rectangle { - height: autoTuneLabel.height + autoTuneRect.height - width: autoTuneRect.width - color: palette.window + height: autoTuneLabel.height + autoTuneRect.height + width: autoTuneRect.width + color: palette.window QGCLabel { id: autoTuneLabel @@ -294,11 +287,11 @@ QGCView { } Rectangle { - id: autoTuneRect - width: autoTuneColumn.x + autoTuneColumn.width + _margins - height: autoTuneColumn.y + autoTuneColumn.height + _margins - anchors.top: autoTuneLabel.bottom - color: palette.windowShade + id: autoTuneRect + width: autoTuneColumn.x + autoTuneColumn.width + _margins + height: autoTuneColumn.y + autoTuneColumn.height + _margins + anchors.top: autoTuneLabel.bottom + color: palette.windowShade Column { id: autoTuneColumn @@ -417,6 +410,6 @@ QGCView { } // Rectangle - Channel 6 Tuning options } // Rectangle - Channel 6 Tuning options wrap } // Flow - Tune - } // QGCFlickable - } // QGCViewPanel -} // QGCView + } // Column + } // Component +} // SetupView diff --git a/src/FirmwarePlugin/APM/APMBrandImage.png b/src/FirmwarePlugin/APM/APMBrandImage.png new file mode 100644 index 0000000000000000000000000000000000000000..2c4c59f6498ae43764ec9397c1c9be1eb5825331 Binary files /dev/null and b/src/FirmwarePlugin/APM/APMBrandImage.png differ diff --git a/src/FirmwarePlugin/APM/APMFirmwarePlugin.h b/src/FirmwarePlugin/APM/APMFirmwarePlugin.h index 2c5150d40dfb279255a0bf8a1fb09eb6122c3530..f9ca107ca98399cd9488fa8c3129c26623c5351e 100644 --- a/src/FirmwarePlugin/APM/APMFirmwarePlugin.h +++ b/src/FirmwarePlugin/APM/APMFirmwarePlugin.h @@ -95,6 +95,7 @@ public: QObject* loadParameterMetaData (const QString& metaDataFile); GeoFenceManager* newGeoFenceManager (Vehicle* vehicle) { return new APMGeoFenceManager(vehicle); } RallyPointManager* newRallyPointManager (Vehicle* vehicle) { return new APMRallyPointManager(vehicle); } + QString brandImage (const Vehicle* vehicle) const { Q_UNUSED(vehicle); return QStringLiteral("/qmlimages/APM/BrandImage"); } QString getParameterMetaDataFile(Vehicle* vehicle); diff --git a/src/FirmwarePlugin/FirmwarePlugin.h b/src/FirmwarePlugin/FirmwarePlugin.h index 935cf1de8f43ce36ff5f0c9aeed9ac3013f463e3..6038748b66010a3523fd0c0338e0a5785bac2862 100644 --- a/src/FirmwarePlugin/FirmwarePlugin.h +++ b/src/FirmwarePlugin/FirmwarePlugin.h @@ -222,6 +222,9 @@ public: /// Return the resource file which contains the set of params loaded for offline editing. virtual QString offlineEditingParamFile(Vehicle* vehicle) { Q_UNUSED(vehicle); return QString(); } + + /// Return the resource file which contains the brand image for the vehicle. + virtual QString brandImage(const Vehicle* vehicle) const { Q_UNUSED(vehicle) return QString(); } }; #endif diff --git a/src/FirmwarePlugin/PX4/PX4BrandImage.png b/src/FirmwarePlugin/PX4/PX4BrandImage.png new file mode 100644 index 0000000000000000000000000000000000000000..ae49f7679dc5c2cbb1e8bb35c861f7b100480ba8 Binary files /dev/null and b/src/FirmwarePlugin/PX4/PX4BrandImage.png differ diff --git a/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.h b/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.h index ec59a84079342ca83c9e85dcb00faeb1ff0c740f..47f963e6d51531a191aefb0c1bdd97086040bd72 100644 --- a/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.h +++ b/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.h @@ -58,6 +58,7 @@ public: bool adjustIncomingMavlinkMessage (Vehicle* vehicle, mavlink_message_t* message); GeoFenceManager* newGeoFenceManager (Vehicle* vehicle) { return new PX4GeoFenceManager(vehicle); } QString offlineEditingParamFile(Vehicle* vehicle) final { Q_UNUSED(vehicle); return QStringLiteral(":/FirmwarePlugin/PX4/PX4.OfflineEditing.params"); } + QString brandImage (const Vehicle* vehicle) const { Q_UNUSED(vehicle); return QStringLiteral("/qmlimages/PX4/BrandImage"); } // Use these constants to set flight modes using setFlightMode method. Don't use hardcoded string names since the // names may change. diff --git a/src/Vehicle/Vehicle.cc b/src/Vehicle/Vehicle.cc index 7afa35f0cb942a8f898f87e3e0e13e9204474427..631a93e86fcaa878b8464fd26ef67963470dd2b1 100644 --- a/src/Vehicle/Vehicle.cc +++ b/src/Vehicle/Vehicle.cc @@ -1922,6 +1922,11 @@ void Vehicle::_newGeoFenceAvailable(void) } } +QString Vehicle::brandImage(void) const +{ + return _firmwarePlugin->brandImage(this); +} + const char* VehicleGPSFactGroup::_hdopFactName = "hdop"; const char* VehicleGPSFactGroup::_vdopFactName = "vdop"; const char* VehicleGPSFactGroup::_courseOverGroundFactName = "courseOverGround"; diff --git a/src/Vehicle/Vehicle.h b/src/Vehicle/Vehicle.h index d88bd0e2ee2750be084f822b26b381208aa3ca74..c2b3bfbed2d9ea30c2a06d5cd4bd19b38202f6c7 100644 --- a/src/Vehicle/Vehicle.h +++ b/src/Vehicle/Vehicle.h @@ -279,6 +279,7 @@ public: Q_PROPERTY(bool coaxialMotors READ coaxialMotors CONSTANT) Q_PROPERTY(bool xConfigMotors READ xConfigMotors CONSTANT) Q_PROPERTY(bool isOfflineEditingVehicle READ isOfflineEditingVehicle CONSTANT) + Q_PROPERTY(QString brandImage READ brandImage CONSTANT) /// true: Vehicle is flying, false: Vehicle is on ground Q_PROPERTY(bool flying READ flying WRITE setFlying NOTIFY flyingChanged) @@ -524,6 +525,7 @@ public: uint8_t baseMode () const { return _base_mode; } uint32_t customMode () const { return _custom_mode; } bool isOfflineEditingVehicle () const { return _offlineEditingVehicle; } + QString brandImage () const; Fact* roll (void) { return &_rollFact; } Fact* heading (void) { return &_headingFact; } diff --git a/src/ui/toolbar/MainToolBar.qml b/src/ui/toolbar/MainToolBar.qml index ad45e36ab471b34a43c411721b950cdba032b07a..f8b4170e9401d66c4d2e1d38caee9b0e54b1e227 100644 --- a/src/ui/toolbar/MainToolBar.qml +++ b/src/ui/toolbar/MainToolBar.qml @@ -54,7 +54,7 @@ Rectangle { MainToolBarController { id: _controller } function checkSettingsButton() { - settingsButton.checked = true + settingsButton.checked = true } function checkSetupButton() { @@ -421,6 +421,17 @@ Rectangle { primary: true onClicked: activeVehicle.disconnectInactiveVehicle() } + + Image { + anchors.rightMargin: ScreenTools.defaultFontPixelWidth / 2 + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + visible: parent.x < x && !disconnectButton.visible && source != "" + fillMode: Image.PreserveAspectFit + source: activeVehicle ? activeVehicle.brandImage : "" + } + } // Progress bar