Newer
Older
/****************************************************************************
*
* (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 <QJsonParseError>
#include <QJsonArray>
// Conversion Constants
// Time
const qreal FactMetaData::UnitConsts_s::secondsPerHour = 3600.0;
// Velocity
const qreal FactMetaData::UnitConsts_s::knotsToKPH = 1.852; // exact, hence weird base for knotsToMetersPerSecond
// Length
const qreal FactMetaData::UnitConsts_s::milesToMeters = 1609.344;
const qreal FactMetaData::UnitConsts_s::feetToMeters = 0.3048;
const qreal FactMetaData::UnitConsts_s::inchesToCentimeters = 2.54;
static const char* kDefaultCategory = QT_TRANSLATE_NOOP("FactMetaData", "Other");
static const char* kDefaultGroup = QT_TRANSLATE_NOOP("FactMetaData", "Misc");
const char* FactMetaData::_jsonMetaDataDefinesName = "QGC.MetaData.Defines";
const char* FactMetaData::_jsonMetaDataFactsName = "QGC.MetaData.Facts";
// Built in translations for all Facts
const FactMetaData::BuiltInTranslation_s FactMetaData::_rgBuiltInTranslations[] = {
{ "centi-degrees", "deg", FactMetaData::_centiDegreesToDegrees, FactMetaData::_degreesToCentiDegrees },
{ "radians", "deg", FactMetaData::_radiansToDegrees, FactMetaData::_degreesToRadians },
{ "gimbal-degrees", "deg", FactMetaData::_mavlinkGimbalDegreesToUserGimbalDegrees, FactMetaData::_userGimbalDegreesToMavlinkGimbalDegrees },
{ "norm", "%", FactMetaData::_normToPercent, FactMetaData::_percentToNorm },
// Translations driven by app settings
const FactMetaData::AppSettingsTranslation_s FactMetaData::_rgAppSettingsTranslations[] = {
{ "m", "m", FactMetaData::UnitDistance, UnitsSettings::DistanceUnitsMeters, FactMetaData::_defaultTranslator, FactMetaData::_defaultTranslator },
{ "meter", "meter", FactMetaData::UnitDistance, UnitsSettings::DistanceUnitsMeters, FactMetaData::_defaultTranslator, FactMetaData::_defaultTranslator },
{ "meters", "meters", FactMetaData::UnitDistance, UnitsSettings::DistanceUnitsMeters, FactMetaData::_defaultTranslator, FactMetaData::_defaultTranslator },
{ "cm/px", "cm/px", FactMetaData::UnitDistance, UnitsSettings::DistanceUnitsMeters, FactMetaData::_defaultTranslator, FactMetaData::_defaultTranslator },
{ "m/s", "m/s", FactMetaData::UnitSpeed, UnitsSettings::SpeedUnitsMetersPerSecond, FactMetaData::_defaultTranslator, FactMetaData::_defaultTranslator },
{ "C", "C", FactMetaData::UnitTemperature, UnitsSettings::TemperatureUnitsCelsius, FactMetaData::_defaultTranslator, FactMetaData::_defaultTranslator },
{ "m^2", "m^2", FactMetaData::UnitArea, UnitsSettings::AreaUnitsSquareMeters, FactMetaData::_defaultTranslator, FactMetaData::_defaultTranslator },
{ "m", "ft", FactMetaData::UnitDistance, UnitsSettings::DistanceUnitsFeet, FactMetaData::_metersToFeet, FactMetaData::_feetToMeters },
{ "meter", "ft", FactMetaData::UnitDistance, UnitsSettings::DistanceUnitsFeet, FactMetaData::_metersToFeet, FactMetaData::_feetToMeters },
{ "meters", "ft", FactMetaData::UnitDistance, UnitsSettings::DistanceUnitsFeet, FactMetaData::_metersToFeet, FactMetaData::_feetToMeters },
{ "cm/px", "in/px", FactMetaData::UnitDistance, UnitsSettings::DistanceUnitsFeet, FactMetaData::_centimetersToInches, FactMetaData::_inchesToCentimeters },
{ "m^2", "km^2", FactMetaData::UnitArea, UnitsSettings::AreaUnitsSquareKilometers, FactMetaData::_squareMetersToSquareKilometers, FactMetaData::_squareKilometersToSquareMeters },
{ "m^2", "ha", FactMetaData::UnitArea, UnitsSettings::AreaUnitsHectares, FactMetaData::_squareMetersToHectares, FactMetaData::_hectaresToSquareMeters },
{ "m^2", "ft^2", FactMetaData::UnitArea, UnitsSettings::AreaUnitsSquareFeet, FactMetaData::_squareMetersToSquareFeet, FactMetaData::_squareFeetToSquareMeters },
{ "m^2", "ac", FactMetaData::UnitArea, UnitsSettings::AreaUnitsAcres, FactMetaData::_squareMetersToAcres, FactMetaData::_acresToSquareMeters },
{ "m^2", "mi^2", FactMetaData::UnitArea, UnitsSettings::AreaUnitsSquareMiles, FactMetaData::_squareMetersToSquareMiles, FactMetaData::_squareMilesToSquareMeters },
{ "m/s", "ft/s", FactMetaData::UnitSpeed, UnitsSettings::SpeedUnitsFeetPerSecond, FactMetaData::_metersToFeet, FactMetaData::_feetToMeters },
{ "m/s", "mph", FactMetaData::UnitSpeed, UnitsSettings::SpeedUnitsMilesPerHour, FactMetaData::_metersPerSecondToMilesPerHour, FactMetaData::_milesPerHourToMetersPerSecond },
{ "m/s", "km/h", FactMetaData::UnitSpeed, UnitsSettings::SpeedUnitsKilometersPerHour, FactMetaData::_metersPerSecondToKilometersPerHour, FactMetaData::_kilometersPerHourToMetersPerSecond },
{ "m/s", "kn", FactMetaData::UnitSpeed, UnitsSettings::SpeedUnitsKnots, FactMetaData::_metersPerSecondToKnots, FactMetaData::_knotsToMetersPerSecond },
{ "C", "F", FactMetaData::UnitTemperature, UnitsSettings::TemperatureUnitsFarenheit, FactMetaData::_celsiusToFarenheit, FactMetaData::_farenheitToCelsius },
const char* FactMetaData::_decimalPlacesJsonKey = "decimalPlaces";
const char* FactMetaData::_nameJsonKey = "name";
const char* FactMetaData::_typeJsonKey = "type";
const char* FactMetaData::_shortDescriptionJsonKey = "shortDescription";
const char* FactMetaData::_longDescriptionJsonKey = "longDescription";
const char* FactMetaData::_unitsJsonKey = "units";
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)
: QObject (parent)
, _type (valueTypeInt32)
, _decimalPlaces (unknownDecimalPlaces)
, _rawDefaultValue (0)
, _rawMax (_maxForType())
, _maxIsDefaultForType (true)
, _rawMin (_minForType())
, _minIsDefaultForType (true)
, _rawTranslator (_defaultTranslator)
, _cookedTranslator (_defaultTranslator)
, _rawIncrement (std::numeric_limits<double>::quiet_NaN())
, _hasControl (true)
, _readOnly (false)
_category = kDefaultCategory;
_group = kDefaultGroup;
FactMetaData::FactMetaData(ValueType_t type, QObject* parent)
: QObject (parent)
, _type (type)
, _decimalPlaces (unknownDecimalPlaces)
, _rawDefaultValue (0)
, _rawMax (_maxForType())
, _maxIsDefaultForType (true)
, _rawMin (_minForType())
, _minIsDefaultForType (true)
, _rawTranslator (_defaultTranslator)
, _cookedTranslator (_defaultTranslator)
, _rawIncrement (std::numeric_limits<double>::quiet_NaN())
, _hasControl (true)
, _readOnly (false)
_category = kDefaultCategory;
_group = kDefaultGroup;
FactMetaData::FactMetaData(const FactMetaData& other, QObject* parent)
: QObject(parent)
{
*this = other;
}
FactMetaData::FactMetaData(ValueType_t type, const QString name, QObject* parent)
: QObject (parent)
, _type (type)
, _decimalPlaces (unknownDecimalPlaces)
, _rawDefaultValue (0)
, _rawMax (_maxForType())
, _maxIsDefaultForType (true)
, _rawMin (_minForType())
, _minIsDefaultForType (true)
, _name (name)
, _rawTranslator (_defaultTranslator)
, _cookedTranslator (_defaultTranslator)
, _rawIncrement (std::numeric_limits<double>::quiet_NaN())
, _hasControl (true)
, _readOnly (false)
_category = kDefaultCategory;
_group = kDefaultGroup;
const FactMetaData& FactMetaData::operator=(const FactMetaData& other)
{
_rawDefaultValue = other._rawDefaultValue;
_defaultValueAvailable = other._defaultValueAvailable;
_bitmaskStrings = other._bitmaskStrings;
_bitmaskValues = other._bitmaskValues;
_enumStrings = other._enumStrings;
_enumValues = other._enumValues;
_category = other._category;
_group = other._group;
_longDescription = other._longDescription;
_minIsDefaultForType = other._minIsDefaultForType;
_name = other._name;
_shortDescription = other._shortDescription;
_type = other._type;
_rawUnits = other._rawUnits;
_cookedUnits = other._cookedUnits;
_rawTranslator = other._rawTranslator;
_cookedTranslator = other._cookedTranslator;
_vehicleRebootRequired = other._vehicleRebootRequired;
_qgcRebootRequired = other._qgcRebootRequired;
_rawIncrement = other._rawIncrement;
_writeOnly = other._writeOnly;
const QString FactMetaData::defaultCategory()
{
return QString(kDefaultCategory);
}
const QString FactMetaData::defaultGroup()
{
return QString(kDefaultGroup);
}
QVariant FactMetaData::rawDefaultValue(void) const
} else {
qWarning() << "Attempt to access unavailable default value";
return QVariant(0);
}
}
void FactMetaData::setRawDefaultValue(const QVariant& rawDefaultValue)
if (_type == valueTypeString || (_rawMin <= rawDefaultValue && rawDefaultValue <= _rawMax)) {
_rawDefaultValue = rawDefaultValue;
_defaultValueAvailable = true;
} else {
qWarning() << "Attempt to set default value which is outside min/max range";
}
}
void FactMetaData::setRawMin(const QVariant& rawMin)
qWarning() << "Attempt to set min below allowable value for fact: " << name()
<< ", value attempted: " << rawMin
<< ", type: " << type() << ", min for type: " << _minForType();
void FactMetaData::setRawMax(const QVariant& rawMax)
if (rawMax > _maxForType()) {
qWarning() << "Attempt to set max above allowable value";
QVariant FactMetaData::_minForType(void) const
case valueTypeUint8:
return QVariant(std::numeric_limits<unsigned char>::min());
case valueTypeInt8:
return QVariant(std::numeric_limits<signed char>::min());
case valueTypeUint16:
return QVariant(std::numeric_limits<unsigned short int>::min());
case valueTypeInt16:
return QVariant(std::numeric_limits<short int>::min());
case valueTypeUint32:
return QVariant(std::numeric_limits<uint32_t>::min());
return QVariant(std::numeric_limits<int32_t>::min());
case valueTypeUint64:
return QVariant((qulonglong)std::numeric_limits<uint64_t>::min());
return QVariant((qlonglong)std::numeric_limits<int64_t>::min());
case valueTypeFloat:
return QVariant(-std::numeric_limits<float>::max());
case valueTypeDouble:
return QVariant(-std::numeric_limits<double>::max());
case valueTypeElapsedTimeInSeconds:
return QVariant(0.0);
case valueTypeCustom:
return QVariant();
// Make windows compiler happy, even switch is full cased
return QVariant();
QVariant FactMetaData::_maxForType(void) const
case valueTypeUint8:
return QVariant(std::numeric_limits<unsigned char>::max());
case valueTypeInt8:
return QVariant(std::numeric_limits<signed char>::max());
case valueTypeUint16:
return QVariant(std::numeric_limits<unsigned short int>::max());
case valueTypeInt16:
return QVariant(std::numeric_limits<short int>::max());
case valueTypeUint32:
return QVariant(std::numeric_limits<uint32_t>::max());
return QVariant(std::numeric_limits<int32_t>::max());
case valueTypeUint64:
return QVariant((qulonglong)std::numeric_limits<uint64_t>::max());
return QVariant((qlonglong)std::numeric_limits<int64_t>::max());
case valueTypeFloat:
return QVariant(std::numeric_limits<float>::max());
case valueTypeElapsedTimeInSeconds:
case valueTypeDouble:
return QVariant(std::numeric_limits<double>::max());
case valueTypeCustom:
return QVariant();
// Make windows compiler happy, even switch is full cased
return QVariant();
bool FactMetaData::convertAndValidateRaw(const QVariant& rawValue, bool convertOnly, QVariant& typedValue, QString& errorString)
bool convertOk = false;
case FactMetaData::valueTypeInt8:
case FactMetaData::valueTypeInt16:
case FactMetaData::valueTypeInt32:
typedValue = QVariant(rawValue.toInt(&convertOk));
if (!convertOnly && convertOk) {
if (typedValue < rawMin() || typedValue > rawMax()) {
errorString = tr("Value must be within %1 and %2").arg(rawMin().toInt()).arg(rawMax().toInt());
case FactMetaData::valueTypeInt64:
typedValue = QVariant(rawValue.toLongLong(&convertOk));
if (!convertOnly && convertOk) {
if (typedValue < rawMin() || typedValue > rawMax()) {
errorString = tr("Value must be within %1 and %2").arg(rawMin().toInt()).arg(rawMax().toInt());
}
}
break;
case FactMetaData::valueTypeUint8:
case FactMetaData::valueTypeUint16:
case FactMetaData::valueTypeUint32:
typedValue = QVariant(rawValue.toUInt(&convertOk));
if (!convertOnly && convertOk) {
if (typedValue < rawMin() || typedValue > rawMax()) {
errorString = tr("Value must be within %1 and %2").arg(rawMin().toUInt()).arg(rawMax().toUInt());
case FactMetaData::valueTypeUint64:
typedValue = QVariant(rawValue.toULongLong(&convertOk));
if (!convertOnly && convertOk) {
if (typedValue < rawMin() || typedValue > rawMax()) {
errorString = tr("Value must be within %1 and %2").arg(rawMin().toUInt()).arg(rawMax().toUInt());
}
}
break;
case FactMetaData::valueTypeFloat:
typedValue = QVariant(rawValue.toFloat(&convertOk));
if (!convertOnly && convertOk) {
if (typedValue < rawMin() || typedValue > rawMax()) {
errorString = tr("Value must be within %1 and %2").arg(rawMin().toDouble()).arg(rawMax().toDouble());
case FactMetaData::valueTypeElapsedTimeInSeconds:
case FactMetaData::valueTypeDouble:
typedValue = QVariant(rawValue.toDouble(&convertOk));
if (!convertOnly && convertOk) {
if (typedValue < rawMin() || typedValue > rawMax()) {
errorString = tr("Value must be within %1 and %2").arg(rawMin().toDouble()).arg(rawMax().toDouble());
case FactMetaData::valueTypeString:
convertOk = true;
typedValue = QVariant(rawValue.toString());
break;
case FactMetaData::valueTypeBool:
convertOk = true;
typedValue = QVariant(rawValue.toBool());
break;
case FactMetaData::valueTypeCustom:
convertOk = true;
typedValue = QVariant(rawValue.toByteArray());
break;
return convertOk && errorString.isEmpty();
}
bool FactMetaData::convertAndValidateCooked(const QVariant& cookedValue, bool convertOnly, QVariant& typedValue, QString& errorString)
{
bool convertOk = false;
errorString.clear();
switch (type()) {
case FactMetaData::valueTypeInt8:
case FactMetaData::valueTypeInt16:
case FactMetaData::valueTypeInt32:
typedValue = QVariant(cookedValue.toInt(&convertOk));
if (!convertOnly && convertOk) {
if (cookedMin() > typedValue || typedValue > cookedMax()) {
errorString = tr("Value must be within %1 and %2").arg(cookedMin().toInt()).arg(cookedMax().toInt());
case FactMetaData::valueTypeInt64:
typedValue = QVariant(cookedValue.toLongLong(&convertOk));
if (!convertOnly && convertOk) {
if (cookedMin() > typedValue || typedValue > cookedMax()) {
errorString = tr("Value must be within %1 and %2").arg(cookedMin().toInt()).arg(cookedMax().toInt());
}
}
break;
case FactMetaData::valueTypeUint8:
case FactMetaData::valueTypeUint16:
case FactMetaData::valueTypeUint32:
typedValue = QVariant(cookedValue.toUInt(&convertOk));
if (!convertOnly && convertOk) {
if (cookedMin() > typedValue || typedValue > cookedMax()) {
errorString = tr("Value must be within %1 and %2").arg(cookedMin().toUInt()).arg(cookedMax().toUInt());
case FactMetaData::valueTypeUint64:
typedValue = QVariant(cookedValue.toULongLong(&convertOk));
if (!convertOnly && convertOk) {
if (cookedMin() > typedValue || typedValue > cookedMax()) {
errorString = tr("Value must be within %1 and %2").arg(cookedMin().toUInt()).arg(cookedMax().toUInt());
}
}
break;
case FactMetaData::valueTypeFloat:
typedValue = QVariant(cookedValue.toFloat(&convertOk));
if (!convertOnly && convertOk) {
if (cookedMin() > typedValue || typedValue > cookedMax()) {
errorString = tr("Value must be within %1 and %2").arg(cookedMin().toFloat()).arg(cookedMax().toFloat());
case FactMetaData::valueTypeElapsedTimeInSeconds:
case FactMetaData::valueTypeDouble:
typedValue = QVariant(cookedValue.toDouble(&convertOk));
if (!convertOnly && convertOk) {
if (cookedMin() > typedValue || typedValue > cookedMax()) {
errorString = tr("Value must be within %1 and %2").arg(cookedMin().toDouble()).arg(cookedMax().toDouble());
case FactMetaData::valueTypeString:
convertOk = true;
typedValue = QVariant(cookedValue.toString());
break;
case FactMetaData::valueTypeBool:
convertOk = true;
typedValue = QVariant(cookedValue.toBool());
break;
case FactMetaData::valueTypeCustom:
convertOk = true;
typedValue = QVariant(cookedValue.toByteArray());
break;
}
if (!convertOk) {
}
return convertOk && errorString.isEmpty();
}
bool FactMetaData::clampValue(const QVariant& cookedValue, QVariant& typedValue)
{
bool convertOk = false;
switch (type()) {
case FactMetaData::valueTypeInt8:
case FactMetaData::valueTypeInt16:
case FactMetaData::valueTypeInt32:
typedValue = QVariant(cookedValue.toInt(&convertOk));
if (convertOk) {
if (cookedMin() > typedValue) {
typedValue = cookedMin();
} else if(typedValue > cookedMax()) {
typedValue = cookedMax();
}
}
break;
case FactMetaData::valueTypeInt64:
typedValue = QVariant(cookedValue.toLongLong(&convertOk));
if (convertOk) {
if (cookedMin() > typedValue) {
typedValue = cookedMin();
} else if(typedValue > cookedMax()) {
typedValue = cookedMax();
}
}
break;
case FactMetaData::valueTypeUint8:
case FactMetaData::valueTypeUint16:
case FactMetaData::valueTypeUint32:
typedValue = QVariant(cookedValue.toUInt(&convertOk));
if (convertOk) {
if (cookedMin() > typedValue) {
typedValue = cookedMin();
} else if(typedValue > cookedMax()) {
typedValue = cookedMax();
}
}
break;
case FactMetaData::valueTypeUint64:
typedValue = QVariant(cookedValue.toULongLong(&convertOk));
if (convertOk) {
if (cookedMin() > typedValue) {
typedValue = cookedMin();
} else if(typedValue > cookedMax()) {
typedValue = cookedMax();
}
}
break;
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
case FactMetaData::valueTypeFloat:
typedValue = QVariant(cookedValue.toFloat(&convertOk));
if (convertOk) {
if (cookedMin() > typedValue) {
typedValue = cookedMin();
} else if(typedValue > cookedMax()) {
typedValue = cookedMax();
}
}
break;
case FactMetaData::valueTypeElapsedTimeInSeconds:
case FactMetaData::valueTypeDouble:
typedValue = QVariant(cookedValue.toDouble(&convertOk));
if (convertOk) {
if (cookedMin() > typedValue) {
typedValue = cookedMin();
} else if(typedValue > cookedMax()) {
typedValue = cookedMax();
}
}
break;
case FactMetaData::valueTypeString:
convertOk = true;
typedValue = QVariant(cookedValue.toString());
break;
case FactMetaData::valueTypeBool:
convertOk = true;
typedValue = QVariant(cookedValue.toBool());
break;
case FactMetaData::valueTypeCustom:
convertOk = true;
typedValue = QVariant(cookedValue.toByteArray());
break;
}
return convertOk;
}
void FactMetaData::setBitmaskInfo(const QStringList& strings, const QVariantList& values)
{
if (strings.count() != values.count()) {
qWarning() << "Count mismatch strings:values" << strings.count() << values.count();
return;
}
_bitmaskStrings = strings;
_bitmaskValues = values;
}
void FactMetaData::addBitmaskInfo(const QString& name, const QVariant& value)
{
_bitmaskStrings << name;
_bitmaskValues << value;
}
void FactMetaData::setEnumInfo(const QStringList& strings, const QVariantList& values)
{
if (strings.count() != values.count()) {
qWarning() << "Count mismatch strings:values" << strings.count() << values.count();
return;
}
_enumStrings = strings;
_enumValues = values;
void FactMetaData::addEnumInfo(const QString& name, const QVariant& value)
{
_enumStrings << name;
_enumValues << value;
}
void FactMetaData::setTranslators(Translator rawTranslator, Translator cookedTranslator)
{
_rawTranslator = rawTranslator;
_cookedTranslator = cookedTranslator;
}
void FactMetaData::setBuiltInTranslator(void)
{
if (_enumStrings.count()) {
// No translation if enum
setTranslators(_defaultTranslator, _defaultTranslator);
_cookedUnits = _rawUnits;
for (size_t i=0; i<sizeof(_rgBuiltInTranslations)/sizeof(_rgBuiltInTranslations[0]); i++) {
const BuiltInTranslation_s* pBuiltInTranslation = &_rgBuiltInTranslations[i];
if (pBuiltInTranslation->rawUnits.toLower() == _rawUnits.toLower()) {
_cookedUnits = pBuiltInTranslation->cookedUnits;
setTranslators(pBuiltInTranslation->rawTranslator, pBuiltInTranslation->cookedTranslator);
// Translator not yet set, try app settings translators
_setAppSettingsTranslators();
}
QVariant FactMetaData::_degreesToRadians(const QVariant& degrees)
{
return QVariant(qDegreesToRadians(degrees.toDouble()));
}
QVariant FactMetaData::_radiansToDegrees(const QVariant& radians)
{
return QVariant(qRadiansToDegrees(radians.toDouble()));
}
QVariant FactMetaData::_centiDegreesToDegrees(const QVariant& centiDegrees)
{
return QVariant(centiDegrees.toReal() / 100.0);
}
QVariant FactMetaData::_degreesToCentiDegrees(const QVariant& degrees)
{
return QVariant(qRound(degrees.toReal() * 100.0));
QVariant FactMetaData::_userGimbalDegreesToMavlinkGimbalDegrees(const QVariant& userGimbalDegrees)
{
// User facing gimbal degree values are from 0 (level) to 90 (straight down)
// Mavlink gimbal degree values are from 0 (level) to -90 (straight down)
return userGimbalDegrees.toDouble() * -1.0;
}
QVariant FactMetaData::_mavlinkGimbalDegreesToUserGimbalDegrees(const QVariant& mavlinkGimbalDegrees)
{
// User facing gimbal degree values are from 0 (level) to 90 (straight down)
// Mavlink gimbal degree values are from 0 (level) to -90 (straight down)
return mavlinkGimbalDegrees.toDouble() * -1.0;
}
QVariant FactMetaData::_metersToFeet(const QVariant& meters)
{
return QVariant(meters.toDouble() * 1.0/constants.feetToMeters);
}
QVariant FactMetaData::_feetToMeters(const QVariant& feet)
{
return QVariant(feet.toDouble() * constants.feetToMeters);
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
QVariant FactMetaData::_squareMetersToSquareKilometers(const QVariant& squareMeters)
{
return QVariant(squareMeters.toDouble() * 0.000001);
}
QVariant FactMetaData::_squareKilometersToSquareMeters(const QVariant& squareKilometers)
{
return QVariant(squareKilometers.toDouble() * 1000000.0);
}
QVariant FactMetaData::_squareMetersToHectares(const QVariant& squareMeters)
{
return QVariant(squareMeters.toDouble() * 0.0001);
}
QVariant FactMetaData::_hectaresToSquareMeters(const QVariant& hectares)
{
return QVariant(hectares.toDouble() * 1000.0);
}
QVariant FactMetaData::_squareMetersToSquareFeet(const QVariant& squareMeters)
{
return QVariant(squareMeters.toDouble() * 10.7639);
}
QVariant FactMetaData::_squareFeetToSquareMeters(const QVariant& squareFeet)
{
return QVariant(squareFeet.toDouble() * 0.0929);
}
QVariant FactMetaData::_squareMetersToAcres(const QVariant& squareMeters)
{
return QVariant(squareMeters.toDouble() * 0.000247105);
}
QVariant FactMetaData::_acresToSquareMeters(const QVariant& acres)
{
return QVariant(acres.toDouble() * 4046.86);
}
QVariant FactMetaData::_squareMetersToSquareMiles(const QVariant& squareMeters)
{
return QVariant(squareMeters.toDouble() * 3.86102e-7);
}
QVariant FactMetaData::_squareMilesToSquareMeters(const QVariant& squareMiles)
{
return QVariant(squareMiles.toDouble() * 258999039.98855);
}
QVariant FactMetaData::_metersPerSecondToMilesPerHour(const QVariant& metersPerSecond)
{
return QVariant((metersPerSecond.toDouble() * 1.0/constants.milesToMeters) * constants.secondsPerHour);
}
QVariant FactMetaData::_milesPerHourToMetersPerSecond(const QVariant& milesPerHour)
{
return QVariant((milesPerHour.toDouble() * constants.milesToMeters) / constants.secondsPerHour);
}
QVariant FactMetaData::_metersPerSecondToKilometersPerHour(const QVariant& metersPerSecond)
{
return QVariant((metersPerSecond.toDouble() / 1000.0) * constants.secondsPerHour);
}
QVariant FactMetaData::_kilometersPerHourToMetersPerSecond(const QVariant& kilometersPerHour)
{
return QVariant((kilometersPerHour.toDouble() * 1000.0) / constants.secondsPerHour);
}
QVariant FactMetaData::_metersPerSecondToKnots(const QVariant& metersPerSecond)
{
return QVariant(metersPerSecond.toDouble() * constants.secondsPerHour / (1000.0 * constants.knotsToKPH));
}
QVariant FactMetaData::_knotsToMetersPerSecond(const QVariant& knots)
{
return QVariant(knots.toDouble() * (1000.0 * constants.knotsToKPH / constants.secondsPerHour));
QVariant FactMetaData::_percentToNorm(const QVariant& percent)
{
return QVariant(percent.toDouble() / 100.0);
}
QVariant FactMetaData::_normToPercent(const QVariant& normalized)
{
return QVariant(normalized.toDouble() * 100.0);
}
QVariant FactMetaData::_centimetersToInches(const QVariant& centimeters)
{
return QVariant(centimeters.toDouble() * 1.0/constants.inchesToCentimeters);
}
QVariant FactMetaData::_inchesToCentimeters(const QVariant& inches)
{
return QVariant(inches.toDouble() * constants.inchesToCentimeters);
}
QVariant FactMetaData::_celsiusToFarenheit(const QVariant& celsius)
{
return QVariant(celsius.toDouble() * (9.0 / 5.0) + 32);
}
QVariant FactMetaData::_farenheitToCelsius(const QVariant& farenheit)
{
return QVariant((farenheit.toDouble() - 32) * (5.0 / 9.0));
}
void FactMetaData::setRawUnits(const QString& rawUnits)
{
_rawUnits = rawUnits;
_cookedUnits = rawUnits;
FactMetaData::ValueType_t FactMetaData::stringToType(const QString& typeString, bool& unknownType)
{
QStringList knownTypeStrings;
QList<ValueType_t> knownTypes;
unknownType = false;
knownTypeStrings << QStringLiteral("Uint8")
<< QStringLiteral("Int8")
<< QStringLiteral("Uint16")
<< QStringLiteral("Int16")
<< QStringLiteral("Uint32")
<< QStringLiteral("Int32")
<< QStringLiteral("Uint64")
<< QStringLiteral("Int64")
<< QStringLiteral("ElapsedSeconds")
<< QStringLiteral("Custom");
<< valueTypeInt8
<< valueTypeUint16
<< valueTypeInt16
<< valueTypeUint32
<< valueTypeInt32
<< valueTypeUint64
<< valueTypeInt64
<< valueTypeElapsedTimeInSeconds
<< valueTypeCustom;
for (int i=0; i<knownTypeStrings.count(); i++) {
if (knownTypeStrings[i].compare(typeString, Qt::CaseInsensitive) == 0) {
return knownTypes[i];
}
}
unknownType = true;
return valueTypeDouble;
}
size_t FactMetaData::typeToSize(ValueType_t type)
{
switch (type) {
case valueTypeUint8:
case valueTypeInt8:
return 1;
case valueTypeUint16:
case valueTypeInt16:
return 2;
case valueTypeUint32:
case valueTypeInt32:
case valueTypeFloat:
return 4;
case valueTypeUint64:
case valueTypeInt64:
case valueTypeCustom:
return MAVLINK_MSG_PARAM_EXT_SET_FIELD_PARAM_VALUE_LEN;
default:
qWarning() << "Unsupported fact value type" << type;
/// Set translators according to app settings
void FactMetaData::_setAppSettingsTranslators(void)
// We can only translate between real numbers
if (!_enumStrings.count() && (type() == valueTypeDouble || type() == valueTypeFloat)) {
for (size_t i=0; i<sizeof(_rgAppSettingsTranslations)/sizeof(_rgAppSettingsTranslations[0]); i++) {
const AppSettingsTranslation_s* pAppSettingsTranslation = &_rgAppSettingsTranslations[i];
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
if (_rawUnits.toLower() != pAppSettingsTranslation->rawUnits.toLower()) {
continue;
}
UnitsSettings* settings = qgcApp()->toolbox()->settingsManager()->unitsSettings();
uint settingsUnits = 0;
switch (pAppSettingsTranslation->unitType) {
case UnitDistance:
settingsUnits = settings->distanceUnits()->rawValue().toUInt();
break;
case UnitSpeed:
settingsUnits = settings->speedUnits()->rawValue().toUInt();
break;
case UnitArea:
settingsUnits = settings->areaUnits()->rawValue().toUInt();
break;
case UnitTemperature:
settingsUnits = settings->temperatureUnits()->rawValue().toUInt();
break;
default:
break;
}
if (settingsUnits == pAppSettingsTranslation->unitOption) {
_cookedUnits = pAppSettingsTranslation->cookedUnits;
setTranslators(pAppSettingsTranslation->rawTranslator, pAppSettingsTranslation->cookedTranslator);
return;
}
}
}
}
const FactMetaData::AppSettingsTranslation_s* FactMetaData::_findAppSettingsDistanceUnitsTranslation(const QString& rawUnits)
{
for (size_t i=0; i<sizeof(_rgAppSettingsTranslations)/sizeof(_rgAppSettingsTranslations[0]); i++) {
const AppSettingsTranslation_s* pAppSettingsTranslation = &_rgAppSettingsTranslations[i];
if (rawUnits.toLower() != pAppSettingsTranslation->rawUnits.toLower()) {
continue;
}
uint settingsUnits = qgcApp()->toolbox()->settingsManager()->unitsSettings()->distanceUnits()->rawValue().toUInt();
if (pAppSettingsTranslation->unitType == UnitDistance
&& pAppSettingsTranslation->unitOption == settingsUnits) {
return pAppSettingsTranslation;
}
}
const FactMetaData::AppSettingsTranslation_s* FactMetaData::_findAppSettingsAreaUnitsTranslation(const QString& rawUnits)
{
for (size_t i=0; i<sizeof(_rgAppSettingsTranslations)/sizeof(_rgAppSettingsTranslations[0]); i++) {
const AppSettingsTranslation_s* pAppSettingsTranslation = &_rgAppSettingsTranslations[i];
if (rawUnits.toLower() != pAppSettingsTranslation->rawUnits.toLower()) {
continue;
}
uint settingsUnits = qgcApp()->toolbox()->settingsManager()->unitsSettings()->areaUnits()->rawValue().toUInt();
if (pAppSettingsTranslation->unitType == UnitArea
&& pAppSettingsTranslation->unitOption == settingsUnits) {
return pAppSettingsTranslation;
}
}
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
QVariant FactMetaData::metersToAppSettingsDistanceUnits(const QVariant& meters)
{
const AppSettingsTranslation_s* pAppSettingsTranslation = _findAppSettingsDistanceUnitsTranslation("m");
if (pAppSettingsTranslation) {
return pAppSettingsTranslation->rawTranslator(meters);
} else {
return meters;
}
}
QVariant FactMetaData::appSettingsDistanceUnitsToMeters(const QVariant& distance)
{
const AppSettingsTranslation_s* pAppSettingsTranslation = _findAppSettingsDistanceUnitsTranslation("m");
if (pAppSettingsTranslation) {
return pAppSettingsTranslation->cookedTranslator(distance);
} else {
return distance;
}
}
QString FactMetaData::appSettingsDistanceUnitsString(void)
{
const AppSettingsTranslation_s* pAppSettingsTranslation = _findAppSettingsDistanceUnitsTranslation("m");
if (pAppSettingsTranslation) {
return pAppSettingsTranslation->cookedUnits;
} else {
return QStringLiteral("m");
}
}
QVariant FactMetaData::squareMetersToAppSettingsAreaUnits(const QVariant& squareMeters)
{
const AppSettingsTranslation_s* pAppSettingsTranslation = _findAppSettingsAreaUnitsTranslation("m^2");
if (pAppSettingsTranslation) {
return pAppSettingsTranslation->rawTranslator(squareMeters);
} else {
return squareMeters;
}
}
QVariant FactMetaData::appSettingsAreaUnitsToSquareMeters(const QVariant& area)
{