Unverified Commit 1dcbcf61 authored by Don Gagne's avatar Don Gagne Committed by GitHub

Merge pull request #6385 from DonLakeFlyer/SliderModel

Use new FactValueSlider control for simple mission item altitudes
parents d56013ef ee3269f7
......@@ -1057,7 +1057,7 @@ HEADERS += \
src/FactSystem/FactGroup.h \
src/FactSystem/FactMetaData.h \
src/FactSystem/FactSystem.h \
src/FactSystem/FactValidator.h \
src/FactSystem/FactValueSliderListModel.h \
src/FactSystem/ParameterManager.h \
src/FactSystem/SettingsFact.h \
......@@ -1067,7 +1067,7 @@ SOURCES += \
src/FactSystem/FactGroup.cc \
src/FactSystem/FactMetaData.cc \
src/FactSystem/FactSystem.cc \
src/FactSystem/FactValidator.cc \
src/FactSystem/FactValueSliderListModel.cc \
src/FactSystem/ParameterManager.cc \
src/FactSystem/SettingsFact.cc \
......
......@@ -790,7 +790,7 @@ QGCCameraControl::_loadSettings(const QDomNodeList nodeList)
QVariant typedValue;
QString errorString;
if (metaData->convertAndValidateRaw(attr, true /* convertOnly */, typedValue, errorString)) {
metaData->setIncrement(typedValue.toDouble());
metaData->setRawIncrement(typedValue.toDouble());
} else {
qWarning() << "Invalid step value for" << factName
<< " type:" << metaData->type()
......
......@@ -8,6 +8,7 @@
****************************************************************************/
#include "Fact.h"
#include "FactValueSliderListModel.h"
#include "QGCMAVLink.h"
#include "QGCApplication.h"
#include "QGCCorePlugin.h"
......@@ -18,13 +19,14 @@
static const char* kMissingMetadata = "Meta data pointer missing";
Fact::Fact(QObject* parent)
: QObject(parent)
, _componentId(-1)
, _rawValue(0)
, _type(FactMetaData::valueTypeInt32)
, _metaData(NULL)
, _sendValueChangedSignals(true)
: QObject (parent)
, _componentId (-1)
, _rawValue (0)
, _type (FactMetaData::valueTypeInt32)
, _metaData (NULL)
, _sendValueChangedSignals (true)
, _deferredValueChangeSignal(false)
, _valueSliderModel (NULL)
{
FactMetaData* metaData = new FactMetaData(_type, this);
setMetaData(metaData);
......@@ -34,14 +36,15 @@ Fact::Fact(QObject* parent)
}
Fact::Fact(int componentId, QString name, FactMetaData::ValueType_t type, QObject* parent)
: QObject(parent)
, _name(name)
, _componentId(componentId)
, _rawValue(0)
, _type(type)
, _metaData(NULL)
, _sendValueChangedSignals(true)
: QObject (parent)
, _name (name)
, _componentId (componentId)
, _rawValue (0)
, _type (type)
, _metaData (NULL)
, _sendValueChangedSignals (true)
, _deferredValueChangeSignal(false)
, _valueSliderModel (NULL)
{
FactMetaData* metaData = new FactMetaData(_type, this);
setMetaData(metaData);
......@@ -57,6 +60,7 @@ Fact::Fact(FactMetaData* metaData, QObject* parent)
, _metaData (NULL)
, _sendValueChangedSignals (true)
, _deferredValueChangeSignal(false)
, _valueSliderModel (NULL)
{
// Allow core plugin a chance to override the default value
qgcApp()->toolbox()->corePlugin()->adjustSettingMetaData(*metaData);
......@@ -78,7 +82,7 @@ const Fact& Fact::operator=(const Fact& other)
_type = other._type;
_sendValueChangedSignals = other._sendValueChangedSignals;
_deferredValueChangeSignal = other._deferredValueChangeSignal;
_valueSliderModel = NULL;
if (_metaData && other._metaData) {
*_metaData = *other._metaData;
} else {
......@@ -633,10 +637,10 @@ QString Fact::enumOrValueString(void)
return QString();
}
double Fact::increment(void) const
double Fact::rawIncrement(void) const
{
if (_metaData) {
return _metaData->increment();
return _metaData->rawIncrement();
} else {
qWarning() << kMissingMetadata << name();
}
......@@ -692,3 +696,12 @@ bool Fact::volatileValue(void) const
return false;
}
}
FactValueSliderListModel* Fact::valueSliderModel(void)
{
if (!_valueSliderModel) {
_valueSliderModel = new FactValueSliderListModel(*this);
QQmlEngine::setObjectOwnership(_valueSliderModel, QQmlEngine::JavaScriptOwnership);
}
return _valueSliderModel;
}
......@@ -20,6 +20,9 @@
#include <QString>
#include <QVariant>
#include <QDebug>
#include <QAbstractListModel>
class FactValueSliderListModel;
/// @brief A Fact is used to hold a single value within the system.
class Fact : public QObject
......@@ -115,7 +118,7 @@ public:
bool valueEqualsDefault (void) const;
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 rawIncrement (void) const;
double cookedIncrement (void) const;
bool typeIsString (void) const { return type() == FactMetaData::valueTypeString; }
bool typeIsBool (void) const { return type() == FactMetaData::valueTypeBool; }
......@@ -124,6 +127,8 @@ public:
bool writeOnly (void) const;
bool volatileValue (void) const;
Q_INVOKABLE FactValueSliderListModel* valueSliderModel(void);
/// Returns the values as a string with full 18 digit precision if float/double.
QString rawValueStringFullPrecision(void) const;
......@@ -193,6 +198,7 @@ protected:
FactMetaData* _metaData;
bool _sendValueChangedSignals;
bool _deferredValueChangeSignal;
FactValueSliderListModel* _valueSliderModel;
};
#endif
......@@ -20,16 +20,11 @@ QGCTextField {
property string _validateString
// At this point all Facts are numeric
inputMethodHints: ((fact && fact.typeIsString) || ScreenTools.isiOS) ?
Qt.ImhNone : // iOS numeric keyboard has no done button, we can't use it
Qt.ImhFormattedNumbersOnly // Forces use of virtual numeric keyboard
onEditingFinished: {
if (ScreenTools.isMobile) {
// Toss focus on mobile after Done on virtual keyboard. Prevent strange interactions.
focus = false
}
if (typeof qgcView !== 'undefined' && qgcView) {
var errorString = fact.validate(text, false /* convertOnly */)
if (errorString === "") {
......
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
......@@ -11,9 +12,9 @@ Rectangle {
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 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
......@@ -32,6 +33,8 @@ Rectangle {
property int _prevIncrementSlots: incrementSlots
property int _nextIncrementSlots: incrementSlots
property int _selectionWidth: 3
property var _model: fact.valueSliderModel()
property var _fact: fact
QGCPalette { id: qgcPal; colorGroupEnabled: parent.enabled }
QGCPalette { id: qgcPalDisabled; colorGroupEnabled: false }
......@@ -46,61 +49,63 @@ Rectangle {
_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
function reset() {
valueListView.positionViewAtIndex(0, ListView.Beginning)
_currentIndex = _model.resetInitialValue()
valueListView.positionViewAtIndex(_currentIndex, ListView.Center)
recalcRelativeIndex()
}
Component.onCompleted: valueListView.maximumFlickVelocity = valueListView.maximumFlickVelocity / 2
Component {
id: editDialogComponent
ParameterEditorDialog {
fact: _fact
onValueChanged: reset()
}
}
QGCListView {
id: valueListView
anchors.fill: parent
orientation: ListView.Horizontal
snapMode: ListView.SnapToItem
clip: true
model: _model
Component.onCompleted: reset()
delegate: QGCLabel {
width: _itemWidth
height: _itemHeight
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: modelData + " " + _units
text: value + " " + _units
color: qgcPal.textFieldText
MouseArea {
anchors.fill: parent
onClicked: {
_currentIndex = index
valueListView.positionViewAtIndex(_currentIndex, ListView.Center)
recalcRelativeIndex()
fact.value = valueListView.model[_currentIndex]
valueListView.focus = true
if (_currentIndex === index) {
qgcView.showDialog(editDialogComponent, qsTr("Value Details"), qgcView.showDialogDefaultWidth, StandardButton.Save | StandardButton.Cancel)
} else {
_currentIndex = index
valueListView.positionViewAtIndex(_currentIndex, ListView.Center)
recalcRelativeIndex()
fact.value = value
}
}
}
}
onMovementStarted: valueListView.focus = true
onMovementEnded: {
_currentIndex = firstVisibleIndex() + _currentRelativeIndex
fact.value = model[_currentIndex]
fact.value = _model.valueAtModelIndex(_currentIndex)
}
}
......
......@@ -78,6 +78,7 @@ const char* FactMetaData::_defaultValueJsonKey = "defaultValue";
const char* FactMetaData::_mobileDefaultValueJsonKey = "mobileDefaultValue";
const char* FactMetaData::_minJsonKey = "min";
const char* FactMetaData::_maxJsonKey = "max";
const char* FactMetaData::_incrementJsonKey = "increment";
const char* FactMetaData::_hasControlJsonKey = "control";
FactMetaData::FactMetaData(QObject* parent)
......@@ -93,7 +94,7 @@ FactMetaData::FactMetaData(QObject* parent)
, _rawTranslator (_defaultTranslator)
, _cookedTranslator (_defaultTranslator)
, _rebootRequired (false)
, _increment (std::numeric_limits<double>::quiet_NaN())
, _rawIncrement (std::numeric_limits<double>::quiet_NaN())
, _hasControl (true)
, _readOnly (false)
, _writeOnly (false)
......@@ -116,7 +117,7 @@ FactMetaData::FactMetaData(ValueType_t type, QObject* parent)
, _rawTranslator (_defaultTranslator)
, _cookedTranslator (_defaultTranslator)
, _rebootRequired (false)
, _increment (std::numeric_limits<double>::quiet_NaN())
, _rawIncrement (std::numeric_limits<double>::quiet_NaN())
, _hasControl (true)
, _readOnly (false)
, _writeOnly (false)
......@@ -146,7 +147,7 @@ FactMetaData::FactMetaData(ValueType_t type, const QString name, QObject* parent
, _rawTranslator (_defaultTranslator)
, _cookedTranslator (_defaultTranslator)
, _rebootRequired (false)
, _increment (std::numeric_limits<double>::quiet_NaN())
, _rawIncrement (std::numeric_limits<double>::quiet_NaN())
, _hasControl (true)
, _readOnly (false)
, _writeOnly (false)
......@@ -180,7 +181,7 @@ const FactMetaData& FactMetaData::operator=(const FactMetaData& other)
_rawTranslator = other._rawTranslator;
_cookedTranslator = other._cookedTranslator;
_rebootRequired = other._rebootRequired;
_increment = other._increment;
_rawIncrement = other._rawIncrement;
_hasControl = other._hasControl;
_readOnly = other._readOnly;
_writeOnly = other._writeOnly;
......@@ -975,7 +976,7 @@ QString FactMetaData::appSettingsAreaUnitsString(void)
double FactMetaData::cookedIncrement(void) const
{
return _rawTranslator(this->increment()).toDouble();
return _rawTranslator(this->rawIncrement()).toDouble();
}
int FactMetaData::decimalPlaces(void) const
......@@ -984,7 +985,7 @@ int FactMetaData::decimalPlaces(void) const
int incrementDecimalPlaces = unknownDecimalPlaces;
// First determine decimal places from increment
double increment = _rawTranslator(this->increment()).toDouble();
double increment = _rawTranslator(this->rawIncrement()).toDouble();
if (!qIsNaN(increment)) {
double integralPart;
......@@ -1029,12 +1030,18 @@ FactMetaData* FactMetaData::createFromJsonObject(const QJsonObject& json, QObjec
return new FactMetaData(valueTypeUint32, metaDataParent);
}
// Validate key types
QStringList keys;
QList<QJsonValue::Type> types;
keys << _nameJsonKey << _decimalPlacesJsonKey << _typeJsonKey << _shortDescriptionJsonKey << _longDescriptionJsonKey << _unitsJsonKey << _minJsonKey << _maxJsonKey << _hasControlJsonKey;
types << QJsonValue::String << QJsonValue::Double << QJsonValue::String << QJsonValue::String << QJsonValue::String << QJsonValue::String << QJsonValue::Double << QJsonValue::Double << QJsonValue::Bool;
if (!JsonHelper::validateKeyTypes(json, keys, types, errorString)) {
QList<JsonHelper::KeyValidateInfo> keyInfoList = {
{ _nameJsonKey, QJsonValue::String, true },
{ _typeJsonKey, QJsonValue::String, true },
{ _shortDescriptionJsonKey, QJsonValue::String, false },
{ _longDescriptionJsonKey, QJsonValue::String, false },
{ _unitsJsonKey, QJsonValue::String, false },
{ _decimalPlacesJsonKey, QJsonValue::Double, false },
{ _minJsonKey, QJsonValue::Double, false },
{ _maxJsonKey, QJsonValue::Double, false },
{ _hasControlJsonKey, QJsonValue::Bool, false },
};
if (!JsonHelper::validateKeys(json, keyInfoList, errorString)) {
qWarning() << errorString;
return new FactMetaData(valueTypeUint32, metaDataParent);
}
......@@ -1100,6 +1107,20 @@ FactMetaData* FactMetaData::createFromJsonObject(const QJsonObject& json, QObjec
}
}
if (json.contains(_incrementJsonKey)) {
QVariant typedValue;
QString errorString;
QVariant initialValue = json[_incrementJsonKey].toVariant();
if (metaData->convertAndValidateRaw(initialValue, true /* convertOnly */, typedValue, errorString)) {
metaData->setRawIncrement(typedValue.toDouble());
} else {
qWarning() << "Invalid increment value, name:" << metaData->name()
<< " type:" << metaData->type()
<< " value:" << initialValue
<< " error:" << errorString;
}
}
if (json.contains(_minJsonKey)) {
QVariant typedValue;
QString errorString;
......
......@@ -111,7 +111,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 rawIncrement (void) const { return _rawIncrement; }
double cookedIncrement (void) const;
Translator rawTranslator (void) const { return _rawTranslator; }
......@@ -136,7 +136,7 @@ public:
void setShortDescription(const QString& shortDescription) { _shortDescription = shortDescription; }
void setRawUnits (const QString& rawUnits);
void setRebootRequired (bool rebootRequired) { _rebootRequired = rebootRequired; }
void setIncrement (double increment) { _increment = increment; }
void setRawIncrement (double increment) { _rawIncrement = increment; }
void setHasControl (bool bValue) { _hasControl = bValue; }
void setReadOnly (bool bValue) { _readOnly = bValue; }
void setWriteOnly (bool bValue) { _writeOnly = bValue; }
......@@ -249,7 +249,7 @@ private:
Translator _rawTranslator;
Translator _cookedTranslator;
bool _rebootRequired;
double _increment;
double _rawIncrement;
bool _hasControl;
bool _readOnly;
bool _writeOnly;
......@@ -286,6 +286,7 @@ private:
static const char* _mobileDefaultValueJsonKey;
static const char* _minJsonKey;
static const char* _maxJsonKey;
static const char* _incrementJsonKey;
static const char* _hasControlJsonKey;
};
......
......@@ -20,10 +20,6 @@
/// The components of the FactSystem are a Fact which holds an individual value. FactMetaData holds
/// additional meta data associated with a Fact such as description, min/max ranges and so forth.
/// The FactValidator object is a QML validator which validates input according to the FactMetaData
/// settings. Client code can then use this system to expose sets of Facts to QML code. An example
/// of this is the PX4ParameterMetaData onbject which is part of the PX4 AutoPilot plugin. It exposes
/// the firmware parameters to QML such that you can bind QML ui elements directly to parameters.
class FactSystem : public QGCTool
{
......
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include "FactValidator.h"
FactValidator::FactValidator(QObject* parent) :
QValidator(parent)
{
}
void FactValidator::fixup(QString& input) const
{
Q_UNUSED(input);
}
FactValidator::State FactValidator::validate(QString& input, int& pos) const
{
Q_UNUSED(input);
Q_UNUSED(pos);
return Acceptable;
}
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#ifndef FactValidator_H
#define FactValidator_H
#include <QValidator>
class Fact;
/// QML Validator for Facts (Work In Progress)
///
/// The validator uses the FactMetaData to impose restrictions on the input. It is used as follows:
/// @code{.unparsed}
/// TextInput {
/// validator: FactValidator { fact: parameters["RC_MAP_THROTTLE"]; }
/// }
/// @endcode
class FactValidator : public QValidator
{
Q_OBJECT
Q_PROPERTY(Fact* fact READ fact WRITE setFact)
public:
FactValidator(QObject* parent = NULL);
// Property system methods
/// Read accessor for fact property
Fact* fact(void) { return _fact; }
/// Write accessor for fact property
void setFact(Fact* fact) { _fact = fact; }
/// Override from QValidator
virtual void fixup(QString& input) const;
/// Override from QValidator
virtual State validate(QString& input, int& pos) const;
private:
Fact* _fact; ///< Fact that the validator is working on
};
#endif
\ No newline at end of file
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "FactValueSliderListModel.h"
#include <QDebug>
#include <QQmlEngine>
#include <QtMath>
#include <math.h>
const int FactValueSliderListModel::_valueRole = Qt::UserRole;
const int FactValueSliderListModel::_valueIndexRole = Qt::UserRole + 1;
FactValueSliderListModel::FactValueSliderListModel(Fact& fact, QObject* parent)
: QAbstractListModel (parent)
, _fact (fact)
, _cValues (0)
, _firstValueIndexInWindow (0)
, _initialValueIndex (0)
, _cPrevValues (0)
, _cNextValues (0)
, _initialValue (0)
, _initialValueRounded (0)
, _increment (0)
{
}
FactValueSliderListModel::~FactValueSliderListModel()
{
}
int FactValueSliderListModel::resetInitialValue(void)
{
// Remove any old rows
beginRemoveRows(QModelIndex(), 0, _cValues - 1);
_cValues = 0;
endRemoveRows();
_initialValue = _fact.cookedValue().toDouble();
_initialValueRounded = qRound(_initialValue);
if (qRound(_fact.rawIncrement()) == _fact.rawIncrement()) {
_increment = qRound(_fact.cookedIncrement());
} else {
_increment = _fact.cookedIncrement();
}
_cPrevValues = qMin((_initialValue - _fact.cookedMin().toDouble()), 1000.0) / _increment;
_cNextValues = qMin((_fact.cookedMax().toDouble() - _initialValue), 1000.0) / _increment;
_initialValueIndex = _cPrevValues;
int totalValueCount = _cPrevValues + 1 + _cNextValues;
beginInsertRows(QModelIndex(), 0, totalValueCount - 1);
_cValues = totalValueCount;
endInsertRows();
return _initialValueIndex;
}
int FactValueSliderListModel::rowCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
return _cValues;
}
QVariant FactValueSliderListModel::data(const QModelIndex &index, int role) const
{
Q_UNUSED(role);
if (!index.isValid()) {
return QVariant();
}
int valueIndex = index.row();
if (valueIndex >= _cValues) {
return QVariant();
}
if (role == _valueRole) {
double value;
int cIncrementCount = valueIndex - _initialValueIndex;
if (cIncrementCount == 0) {
value = _initialValue;
} else {
value = _initialValueRounded + (cIncrementCount * _increment);
}
double precision = qPow(10, _fact.decimalPlaces());
double atPrecision = qRound(value * precision) / precision;
//qDebug() << value << precision << atPrecision << _fact.decimalPlaces() << _fact.name();
return QVariant(atPrecision);
} else if (role == _valueIndexRole) {
return QVariant::fromValue(valueIndex);
} else {
return QVariant();
}
}
QHash<int, QByteArray> FactValueSliderListModel::roleNames(void) const
{
QHash<int, QByteArray> hash;
hash[_valueRole] = "value";
hash[_valueIndexRole] = "valueIndex";
return hash;
}
double FactValueSliderListModel::valueAtModelIndex(int index)
{
return data(createIndex(index, 0), _valueRole).toDouble();
}
int FactValueSliderListModel::valueIndexAtModelIndex(int index)
{
return data(createIndex(index, 0), _valueIndexRole).toInt();
}
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#pragma once
#include <QAbstractListModel>
#include "Fact.h"
/// Provides a list model of values for incrementing/decrementing the value of a Fact
class FactValueSliderListModel : public QAbstractListModel
{
Q_OBJECT
public:
FactValueSliderListModel(Fact& fact, QObject* parent = NULL);
~FactValueSliderListModel();
Q_INVOKABLE int resetInitialValue(void);
Q_INVOKABLE double valueAtModelIndex(int index);
Q_INVOKABLE int valueIndexAtModelIndex(int index);
private:
// Overrides from QAbstractListModel
int rowCount(const QModelIndex & parent = QModelIndex()) const override;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames(void) const override;
Fact& _fact;
int _cValues;
int _firstValueIndexInWindow;
int _initialValueIndex;
int _cPrevValues;
int _cNextValues;
int _windowSize;
double _initialValue;
double _initialValueRounded;
double _increment;
static const int _valueRole;
static const int _valueIndexRole;
};
......@@ -584,7 +584,7 @@ void APMParameterMetaData::addMetaDataToFact(Fact* fact, MAV_TYPE vehicleType)
bool ok;
increment = rawMetaData->incrementSize.toDouble(&ok);
if (ok) {
metaData->setIncrement(increment);
metaData->setRawIncrement(increment);
} else {
qCDebug(APMParameterMetaDataLog) << "Invalid value for increment, name:" << metaData->name() << " increment:" << rawMetaData->incrementSize;
}
......
......@@ -332,7 +332,7 @@ void PX4ParameterMetaData::loadParameterFactMetaDataFile(const QString& metaData
QString text = xml.readElementText();
increment = text.toDouble(&ok);
if (ok) {
metaData->setIncrement(increment);
metaData->setRawIncrement(increment);
} else {
qCWarning(PX4ParameterMetaDataLog) << "Invalid value for increment, name:" << metaData->name() << " increment:" << text;
}
......
......@@ -73,15 +73,7 @@ Item {
break;
}
} else {
// Note: We currently show alternate instruments all the time. This is a trial change for daily builds.
// Leaving non-alternate code in for now in case the trial fails.
var useAlternateInstruments = true//QGroundControl.settingsManager.appSettings.virtualJoystick.value || ScreenTools.isTinyScreen
if(useAlternateInstruments) {
instrumentsLoader.source = "qrc:/qml/QGCInstrumentWidgetAlternate.qml"
} else {
instrumentsLoader.source = "qrc:/qml/QGCInstrumentWidget.qml"
instrumentsLoader.state = QGroundControl.settingsManager.appSettings.showLargeCompass.value === 1 ? "centerRightMode" : "topRightMode"
}
instrumentsLoader.source = "qrc:/qml/QGCInstrumentWidgetAlternate.qml"
}
} else {
instrumentsLoader.source = ""
......
......@@ -32,6 +32,7 @@
"units": "gimbal-degrees",
"min": -90,
"max": 0,
"increment": 5,
"decimalPlaces": 0,
"defaultValue": 0
},
......@@ -42,6 +43,7 @@
"units": "deg",
"min": -180.0,
"max": 180.0,
"increment": 5,
"decimalPlaces": 0,
"defaultValue": 0
},
......
......@@ -462,7 +462,7 @@ void MissionController::removeMissionItem(int index)
// Determine if the mission still has another survey style item in it
bool foundSurvey = false;
for (int i=1; i<_visualItems->count(); i++) {
if (_visualItems->value<SurveyMissionItem*>(i) || _visualItems->value<CorridorScanComplexItem*>(index)) {
if (_visualItems->value<SurveyMissionItem*>(i) || _visualItems->value<CorridorScanComplexItem*>(i)) {
foundSurvey = true;
break;
}
......
......@@ -220,6 +220,7 @@ void SimpleMissionItem::_setupMetaData(void)
if (!_altitudeMetaData) {
_altitudeMetaData = new FactMetaData(FactMetaData::valueTypeDouble);
_altitudeMetaData->setRawUnits("m");
_altitudeMetaData->setRawIncrement(1);
_altitudeMetaData->setDecimalPlaces(2);
enumStrings.clear();
......@@ -259,6 +260,7 @@ void SimpleMissionItem::_setupMetaData(void)
_missionItem._commandFact.setMetaData(_commandMetaData);
_missionItem._frameFact.setMetaData(_frameMetaData);
_altitudeFact.setMetaData(_altitudeMetaData);
_amslAltAboveTerrainFact.setMetaData(_altitudeMetaData);
}
SimpleMissionItem::~SimpleMissionItem()
......@@ -659,6 +661,7 @@ void SimpleMissionItem::_altitudeChanged(void)
}
if (_altitudeMode == AltitudeAboveTerrain) {
_amslAltAboveTerrainFact.setRawValue(qQNaN());
_terrainAltChanged();
} else {
_missionItem._param7Fact.setRawValue(_altitudeFact.rawValue());
......
......@@ -74,6 +74,26 @@ Column {
}
}
RowLayout {
anchors.left: parent.left
anchors.right: parent.right
spacing: ScreenTools.defaultFontPixelWidth
visible: _camera.cameraModeSupported
QGCCheckBox {
id: modeCheckBox
text: qsTr("Mode")
checked: _camera.specifyCameraMode
onClicked: _camera.specifyCameraMode = checked
}
FactComboBox {
fact: _camera.cameraMode
indexModel: false
enabled: modeCheckBox.checked
Layout.fillWidth: true
}
}
GridLayout {
anchors.left: parent.left
anchors.right: parent.right
......@@ -104,25 +124,5 @@ Column {
enabled: gimbalCheckBox.checked
}
}
RowLayout {
anchors.left: parent.left
anchors.right: parent.right
spacing: ScreenTools.defaultFontPixelWidth
visible: _camera.cameraModeSupported
QGCCheckBox {
id: modeCheckBox
text: qsTr("Mode")
checked: _camera.specifyCameraMode
onClicked: _camera.specifyCameraMode = checked
}
FactComboBox {
fact: _camera.cameraMode
indexModel: false
enabled: modeCheckBox.checked
Layout.fillWidth: true
}
}
}
}
......@@ -19,6 +19,12 @@ Rectangle {
property bool _specifiesAltitude: missionItem.specifiesAltitude
property bool _altModeIsTerrain: missionItem.altitudeMode === 2
property real _margin: ScreenTools.defaultFontPixelHeight / 2
ExclusiveGroup {
id: altRadios
onCurrentChanged: missionItem.altitudeMode = current.value
}
Column {
id: valuesColumn
......@@ -67,31 +73,63 @@ Rectangle {
}
}
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
height: altColumn.y + altColumn.height + _margin
color: qgcPal.windowShade
Column {
id: altColumn
anchors.margins: _margin
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
QGCLabel {
font.pointSize: ScreenTools.smallFontPointSize
text: qsTr("Altitude")
}
RowLayout {
QGCRadioButton { text: qsTr("Rel"); exclusiveGroup: altRadios; checked: missionItem.altitudeMode === value; readonly property int value: 0 }
QGCRadioButton { text: qsTr("Abs"); exclusiveGroup: altRadios; checked: missionItem.altitudeMode === value; readonly property int value: 1 }
QGCRadioButton { text: qsTr("AGL"); exclusiveGroup: altRadios; checked: missionItem.altitudeMode === value; readonly property int value: 2 }
}
FactValueSlider {
fact: missionItem.altitude
digitCount: 3
incrementSlots: 1
visible: _specifiesAltitude
}
RowLayout {
spacing: _margin
QGCLabel {
text: qsTr("Calculated Abs Alt")
font.pointSize: ScreenTools.smallFontPointSize
visible: _altModeIsTerrain
}
QGCLabel {
text: missionItem.amslAltAboveTerrain.valueString + " " + missionItem.amslAltAboveTerrain.units
visible: _altModeIsTerrain
}
}
}
}
GridLayout {
anchors.left: parent.left
anchors.right: parent.right
flow: GridLayout.TopToBottom
rows: missionItem.textFieldFacts.count +
missionItem.nanFacts.count +
(missionItem.speedSection.available ? 1 : 0) +
(_specifiesAltitude ? 1 : 0) +
(_altModeIsTerrain ? 1 : 0)
(missionItem.speedSection.available ? 1 : 0)
columns: 2
QGCComboBox {
id: altCombo
model: [ qsTr("Alt (Rel)"), qsTr("AMSL"), qsTr("Above Terrain") ]
currentIndex: missionItem.altitudeMode
Layout.fillWidth: true
onActivated: missionItem.altitudeMode = index
visible: _specifiesAltitude
}
QGCLabel {
text: qsTr("Actual AMSL Alt")
visible: _altModeIsTerrain
}
Repeater {
model: missionItem.textFieldFacts
......@@ -117,18 +155,6 @@ Rectangle {
}
FactTextField {
showUnits: true
fact: missionItem.altitude
Layout.fillWidth: true
visible: _specifiesAltitude
}
FactLabel {
fact: missionItem.amslAltAboveTerrain
visible: _altModeIsTerrain
}
Repeater {
model: missionItem.textFieldFacts
......
......@@ -83,6 +83,7 @@
#include "CameraCalc.h"
#include "VisualMissionItem.h"
#include "EditPositionDialogController.h"
#include "FactValueSliderListModel.h"
#ifndef NO_SERIAL_LINK
#include "SerialLink.h"
......@@ -368,6 +369,7 @@ void QGCApplication::_initCommon(void)
qmlRegisterUncreatableType<GeoFenceController> ("QGroundControl.Controllers", 1, 0, "GeoFenceController", "Reference only");
qmlRegisterUncreatableType<RallyPointController>("QGroundControl.Controllers", 1, 0, "RallyPointController", "Reference only");
qmlRegisterUncreatableType<VisualMissionItem> ("QGroundControl.Controllers", 1, 0, "VisualMissionItem", "Reference only");
qmlRegisterUncreatableType<FactValueSliderListModel>("QGroundControl.FactControls", 1, 0, "FactValueSliderListModel","Reference only");
qmlRegisterType<ParameterEditorController> ("QGroundControl.Controllers", 1, 0, "ParameterEditorController");
qmlRegisterType<ESP8266ComponentController> ("QGroundControl.Controllers", 1, 0, "ESP8266ComponentController");
......
......@@ -20,13 +20,16 @@ import QGroundControl.FactControls 1.0
import QGroundControl.ScreenTools 1.0
QGCViewDialog {
id: root
id: root
focus: true
property Fact fact
property bool showRCToParam: false
property bool validate: false
property string validateValue
signal valueChanged
property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 20
property bool _longDescriptionAvailable: fact.longDescription != ""
property bool _editingParameter: fact.componentId != 0
......@@ -41,15 +44,18 @@ QGCViewDialog {
if (bitmaskColumn.visible && !manualEntry.checked) {
fact.value = bitmaskValue();
fact.valueChanged(fact.value)
valueChanged()
hideDialog();
} else if (factCombo.visible && !manualEntry.checked) {
fact.enumIndex = factCombo.currentIndex
valueChanged()
hideDialog()
} else {
var errorString = fact.validate(valueField.text, forceSave.checked)
if (errorString === "") {
fact.value = valueField.text
fact.valueChanged(fact.value)
valueChanged()
hideDialog()
} else {
validationError.text = errorString
......@@ -85,12 +91,8 @@ QGCViewDialog {
}
}
// set focus to the text field when becoming visible (in case of an Enum,
// the valueField is not visible, but it's not an issue because the combo
// box cannot have a focus)
onVisibleChanged: if (visible && !ScreenTools.isMobile) valueField.forceActiveFocus()
QGCFlickable {
id: flickable
anchors.fill: parent
contentHeight: _column.y + _column.height
flickableDirection: Flickable.VerticalFlick
......@@ -120,9 +122,10 @@ QGCViewDialog {
unitsLabel: fact.units
showUnits: fact.units != ""
Layout.fillWidth: true
inputMethodHints: ScreenTools.isiOS ?
Qt.ImhNone : // iOS numeric keyboard has not done button, we can't use it
Qt.ImhFormattedNumbersOnly // Forces use of virtual numeric keyboard
focus: true
inputMethodHints: (fact.typeIsString || ScreenTools.isiOS) ?
Qt.ImhNone : // iOS numeric keyboard has no done button, we can't use it
Qt.ImhFormattedNumbersOnly // Forces use of virtual numeric keyboard
}
QGCButton {
......
......@@ -7,7 +7,10 @@ import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
TextField {
id: root
id: root
textColor: qgcPal.textFieldText
implicitHeight: ScreenTools.implicitTextFieldHeight
activeFocusOnPress: true
property bool showUnits: false
property bool showHelp: false
......@@ -17,18 +20,11 @@ TextField {
property real _helpLayoutWidth: 0
Component.onCompleted: {
if (typeof qgcTextFieldforwardKeysTo !== 'undefined') {
root.Keys.forwardTo = [qgcTextFieldforwardKeysTo]
}
}
Component.onCompleted: selectAllIfActiveFocus()
onActiveFocusChanged: selectAllIfActiveFocus()
QGCPalette { id: qgcPal; colorGroupEnabled: enabled }
textColor: qgcPal.textFieldText
implicitHeight: ScreenTools.implicitTextFieldHeight
onEditingFinished: {
if (ScreenTools.isMobile) {
// Toss focus on mobile after Done on virtual keyboard. Prevent strange interactions.
......@@ -36,6 +32,12 @@ TextField {
}
}
function selectAllIfActiveFocus() {
if (activeFocus) {
selectAll()
}
}
QGCLabel {
id: unitsLabelWidthGenerator
text: unitsLabel
......@@ -59,7 +61,7 @@ TextField {
Rectangle {
anchors.fill: parent
border.color: control.activeFocus ? "#47b" : "#999"
border.color: root.activeFocus ? "#47b" : "#999"
color: qgcPal.textField
}
......@@ -114,10 +116,4 @@ TextField {
padding.right: control._helpLayoutWidth //control.showUnits ? unitsLabelWidthGenerator.width : control.__contentHeight * 0.333
}
onActiveFocusChanged: {
if (activeFocus) {
selectAll()
}
}
}
......@@ -68,6 +68,7 @@ FactPanel {
"viewPanel": viewPanel
})
dialog.setupDialogButtons(buttons)
dialog.focus = true
viewPanel.enabled = false
}
......
......@@ -17,8 +17,6 @@ import QGroundControl.FactControls 1.0
import QGroundControl.ScreenTools 1.0
FactPanel {
property var qgcTextFieldforwardKeysTo: this ///< Causes all QGCTextFields to forward keys here if they have focus
property real defaultTextWidth: ScreenTools.defaultFontPixelWidth
property real defaultTextHeight: ScreenTools.defaultFontPixelHeight
......
......@@ -15,9 +15,10 @@ import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
Item {
id: _root
z: 5000
FocusScope {
id: _root
z: 5000
focus: true
property alias dialogWidth: _dialogPanel.width
property alias dialogTitle: titleLabel.text
......@@ -182,6 +183,7 @@ Item {
anchors.top: _spacer.bottom
anchors.bottom: parent.bottom
sourceComponent: _dialogComponent
focus: true
property bool acceptAllowed: _acceptButton.visible
property bool rejectAllowed: _rejectButton.visible
......
......@@ -107,8 +107,6 @@ bool QmlObjectListModel::removeRows(int position, int rows, const QModelIndex& p
beginRemoveRows(QModelIndex(), position, position + rows - 1);
for (int row=0; row<rows; row++) {
// FIXME: Need to figure our correct memory management for here
//_objectList[position]->deleteLater();
_objectList.removeAt(position);
}
endRemoveRows();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment