diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index e3e0b17f03ec774a1b7620674f2b9a65e967f25f..bf57edb25869f8b7509718a723e229ae89b3b8f6 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -138,6 +138,7 @@ src/FactSystem/FactControls/FactTextField.qml src/FactSystem/FactControls/FactTextFieldGrid.qml src/FactSystem/FactControls/FactTextFieldRow.qml + src/FactSystem/FactControls/FactValueSlider.qml src/FactSystem/FactControls/qmldir src/FlightDisplay/FlightDisplayView.qml src/FlightDisplay/FlightDisplayViewMap.qml diff --git a/src/AutoPilotPlugins/PX4/PX4TuningComponentCopter.qml b/src/AutoPilotPlugins/PX4/PX4TuningComponentCopter.qml index d3d87822806636510fefe1034468d461cfbc1a8e..2b780bf0842cb88a46bc4e30785865fd71eca576 100644 --- a/src/AutoPilotPlugins/PX4/PX4TuningComponentCopter.qml +++ b/src/AutoPilotPlugins/PX4/PX4TuningComponentCopter.qml @@ -32,6 +32,11 @@ SetupPage { showAdvanced = !ScreenTools.isMobile } + FactPanelController { + id: controller + factPanel: tuningPage.viewPanel + } + // Standard tuning page FactSliderPanel { width: availableWidth @@ -238,11 +243,6 @@ SetupPage { resetGraphs() } - FactPanelController { - id: controller - factPanel: tuningPage.viewPanel - } - ExclusiveGroup { id: tuneTypeRadios } diff --git a/src/AutoPilotPlugins/PX4/PX4TuningComponentVTOL.qml b/src/AutoPilotPlugins/PX4/PX4TuningComponentVTOL.qml index 3feb7ca67e7c0c25474fb51ccc0a3244b15d1ea4..297f175b3fa9a3ed3f5db70e8b690458f6d131bf 100644 --- a/src/AutoPilotPlugins/PX4/PX4TuningComponentVTOL.qml +++ b/src/AutoPilotPlugins/PX4/PX4TuningComponentVTOL.qml @@ -26,24 +26,6 @@ SetupPage { sliderModel: ListModel { - ListElement { - title: qsTr("Hover Roll sensitivity") - description: qsTr("Slide to the left to make roll control during hover faster and more accurate. Slide to the right if roll oscillates or is too twitchy.") - param: "MC_ROLL_TC" - min: 0.15 - max: 0.25 - step: 0.01 - } - - ListElement { - title: qsTr("Hover Pitch sensitivity") - description: qsTr("Slide to the left to make pitch control during hover faster and more accurate. Slide to the right if pitch oscillates or is too twitchy.") - param: "MC_PITCH_TC" - min: 0.15 - max: 0.25 - step: 0.01 - } - ListElement { title: qsTr("Plane Roll sensitivity") description: qsTr("Slide to the left to make roll control faster and more accurate. Slide to the right if roll oscillates or is too twitchy.") diff --git a/src/FactSystem/Fact.cc b/src/FactSystem/Fact.cc index 3afce178fd287c5a40d106ffde28be1d9a1b8c1d..309b3fd0fbeffddbcb13d63ab5d15d85fd3e19a8 100644 --- a/src/FactSystem/Fact.cc +++ b/src/FactSystem/Fact.cc @@ -643,6 +643,16 @@ double Fact::increment(void) const return std::numeric_limits::quiet_NaN(); } +double Fact::cookedIncrement(void) const +{ + if (_metaData) { + return _metaData->cookedIncrement(); + } else { + qWarning() << kMissingMetadata << name(); + } + return std::numeric_limits::quiet_NaN(); +} + bool Fact::hasControl(void) const { if (_metaData) { diff --git a/src/FactSystem/Fact.h b/src/FactSystem/Fact.h index cc0336ee80de34e289b58ae89fc77d5a51bc86c5..6257bb399143c22a667cc6088a4386b5fb0b403b 100644 --- a/src/FactSystem/Fact.h +++ b/src/FactSystem/Fact.h @@ -66,7 +66,7 @@ public: Q_PROPERTY(bool valueEqualsDefault READ valueEqualsDefault NOTIFY valueChanged) Q_PROPERTY(QString valueString READ cookedValueString NOTIFY valueChanged) Q_PROPERTY(QString enumOrValueString READ enumOrValueString NOTIFY valueChanged) - Q_PROPERTY(double increment READ increment CONSTANT) + Q_PROPERTY(double increment READ cookedIncrement CONSTANT) Q_PROPERTY(bool typeIsString READ typeIsString CONSTANT) Q_PROPERTY(bool typeIsBool READ typeIsBool CONSTANT) Q_PROPERTY(bool hasControl READ hasControl CONSTANT) @@ -116,6 +116,7 @@ public: bool rebootRequired (void) const; QString enumOrValueString (void); // This is not const, since an unknown value can modify the enum lists double increment (void) const; + double cookedIncrement (void) const; bool typeIsString (void) const { return type() == FactMetaData::valueTypeString; } bool typeIsBool (void) const { return type() == FactMetaData::valueTypeBool; } bool hasControl (void) const; diff --git a/src/FactSystem/FactControls/FactValueSlider.qml b/src/FactSystem/FactControls/FactValueSlider.qml new file mode 100644 index 0000000000000000000000000000000000000000..f94db519768d33f21d0c6d9714f159b85d6d6373 --- /dev/null +++ b/src/FactSystem/FactControls/FactValueSlider.qml @@ -0,0 +1,134 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.2 + +import QGroundControl.Palette 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.FactSystem 1.0 + +Rectangle { + height: _itemHeight + width: _totalSlots * _itemWidth + color: qgcPal.textField + + property Fact fact: undefined + property int digitCount: 4 ///< The number of digits to show for each value + property int incrementSlots: 1 ///< The number of visible slots to left/right of center value + + property int _totalDigitCount: digitCount + 1 + fact.units.length + property real _margins: (ScreenTools.implicitTextFieldHeight - ScreenTools.defaultFontPixelHeight) / 2 + property real _increment: fact.increment + property real _value: fact.value + property int _decimalPlaces: fact.decimalPlaces + property string _units: fact.units + property real _prevValue: _value - _increment + property real _nextValue: _value + _increment + property real _itemWidth: (_totalDigitCount * ScreenTools.defaultFontPixelWidth) + (_margins * 2) + property real _itemHeight: ScreenTools.implicitTextFieldHeight + property var _valueModel + property int _totalSlots: (incrementSlots * 2) + 1 + property int _currentIndex: _totalSlots / 2 + property int _currentRelativeIndex: _currentIndex + property int _prevIncrementSlots: incrementSlots + property int _nextIncrementSlots: incrementSlots + property int _selectionWidth: 3 + + QGCPalette { id: qgcPal; colorGroupEnabled: parent.enabled } + QGCPalette { id: qgcPalDisabled; colorGroupEnabled: false } + + function firstVisibleIndex() { + return valueListView.contentX / _itemWidth + } + + function recalcRelativeIndex() { + _currentRelativeIndex = _currentIndex - firstVisibleIndex() + _prevIncrementSlots = _currentRelativeIndex + _nextIncrementSlots = _totalSlots - _currentRelativeIndex - 1 + } + + Component.onCompleted: { + var currentValue = _value + _valueModel = [ _value.toFixed(_decimalPlaces) ] + + var addCount = 0 + var minValue = fact.min + currentValue -= _increment + while (currentValue >= minValue) { + _valueModel.unshift(currentValue.toFixed(_decimalPlaces)) + currentValue -= _increment + addCount++ + } + + var maxValue = fact.max + currentValue = _value + _increment + while (currentValue <= maxValue) { + _valueModel.push(currentValue.toFixed(_decimalPlaces)) + currentValue += _increment + } + + _currentIndex = addCount + valueListView.model = _valueModel + valueListView.positionViewAtIndex(_currentIndex, ListView.Center) + recalcRelativeIndex() + } + + QGCListView { + id: valueListView + anchors.fill: parent + orientation: ListView.Horizontal + snapMode: ListView.SnapToItem + clip: true + + delegate: QGCLabel { + width: _itemWidth + height: _itemHeight + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + text: modelData + " " + _units + color: qgcPal.textFieldText + + MouseArea { + anchors.fill: parent + onClicked: { + _currentIndex = index + valueListView.positionViewAtIndex(_currentIndex, ListView.Center) + recalcRelativeIndex() + fact.value = valueListView.model[_currentIndex] + } + } + } + + onMovementEnded: { + _currentIndex = firstVisibleIndex() + _currentRelativeIndex + fact.value = model[_currentIndex] + } + } + + Rectangle { + id: leftOverlay + width: _itemWidth * _prevIncrementSlots + height: _itemHeight + color: qgcPal.textField + opacity: 0.5 + } + + Rectangle { + width: _itemWidth * _nextIncrementSlots + height: _itemHeight + anchors.right: parent.right + color: qgcPal.textField + opacity: 0.5 + } + + Rectangle { + x: _currentRelativeIndex * _itemWidth - _borderWidth + y: -_borderWidth + width: _itemWidth + (_borderWidth * 2) + height: _itemHeight + (_borderWidth * 2) + border.width: _borderWidth + border.color: qgcPal.brandingBlue + color: "transparent" + + readonly property int _borderWidth: 3 + } +} diff --git a/src/FactSystem/FactControls/qmldir b/src/FactSystem/FactControls/qmldir index 6bf7d2359c1bfc007565d9bea2571d2754b128a5..02efebba4da263b96e4b77562d843e954197717e 100644 --- a/src/FactSystem/FactControls/qmldir +++ b/src/FactSystem/FactControls/qmldir @@ -8,3 +8,4 @@ FactPanel 1.0 FactPanel.qml FactTextField 1.0 FactTextField.qml FactTextFieldGrid 1.0 FactTextFieldGrid.qml FactTextFieldRow 1.0 FactTextFieldRow.qml +FactValueSlider 1.0 FactValueSlider.qml diff --git a/src/FactSystem/FactMetaData.cc b/src/FactSystem/FactMetaData.cc index 167c68101f4ef653021a07b11cdd00eacbbf03b3..b726c6038dbcad382a69eb9854423194984fdf9a 100644 --- a/src/FactSystem/FactMetaData.cc +++ b/src/FactSystem/FactMetaData.cc @@ -973,6 +973,11 @@ QString FactMetaData::appSettingsAreaUnitsString(void) } } +double FactMetaData::cookedIncrement(void) const +{ + return _rawTranslator(this->increment()).toDouble(); +} + int FactMetaData::decimalPlaces(void) const { int actualDecimalPlaces = defaultDecimalPlaces; diff --git a/src/FactSystem/FactMetaData.h b/src/FactSystem/FactMetaData.h index 4b298ca2422b2407b6b9c3b0fc5e814fc48756f8..8f99bb3f40b5957faad7a7fb8dfa2ed95792eef2 100644 --- a/src/FactSystem/FactMetaData.h +++ b/src/FactSystem/FactMetaData.h @@ -112,6 +112,7 @@ public: /// Amount to increment value when used in controls such as spin button or slider with detents. /// NaN for no increment available. double increment (void) const { return _increment; } + double cookedIncrement (void) const; Translator rawTranslator (void) const { return _rawTranslator; } Translator cookedTranslator (void) const { return _cookedTranslator; } diff --git a/src/QmlControls/FactSliderPanel.qml b/src/QmlControls/FactSliderPanel.qml index 98f037ca1b9f529b3aa209ea95504eabd4c78bf7..ac4cc10d722d69cda79475f30eefd20087e0eca9 100644 --- a/src/QmlControls/FactSliderPanel.qml +++ b/src/QmlControls/FactSliderPanel.qml @@ -41,18 +41,6 @@ Column { QGCPalette { id: palette; colorGroupEnabled: enabled } - 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. - for (var i=0; i