|
|
|
@ -15,9 +15,12 @@
@@ -15,9 +15,12 @@
|
|
|
|
|
|
|
|
|
|
#include "FactMetaData.h" |
|
|
|
|
#include "QGroundControlQmlGlobal.h" |
|
|
|
|
#include "JsonHelper.h" |
|
|
|
|
|
|
|
|
|
#include <QDebug> |
|
|
|
|
#include <QtMath> |
|
|
|
|
#include <QJsonParseError> |
|
|
|
|
#include <QJsonArray> |
|
|
|
|
|
|
|
|
|
#include <limits> |
|
|
|
|
#include <cmath> |
|
|
|
@ -59,6 +62,16 @@ const FactMetaData::AppSettingsTranslation_s FactMetaData::_rgAppSettingsTransla
@@ -59,6 +62,16 @@ const FactMetaData::AppSettingsTranslation_s FactMetaData::_rgAppSettingsTransla
|
|
|
|
|
{ "m/s", "kn", true, QGroundControlQmlGlobal::SpeedUnitsKnots, FactMetaData::_metersPerSecondToKnots, FactMetaData::_knotsToMetersPerSecond }, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
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::_minJsonKey = "min"; |
|
|
|
|
const char* FactMetaData::_maxJsonKey = "max"; |
|
|
|
|
|
|
|
|
|
FactMetaData::FactMetaData(QObject* parent) |
|
|
|
|
: QObject(parent) |
|
|
|
|
, _type(valueTypeInt32) |
|
|
|
@ -178,22 +191,22 @@ void FactMetaData::setRawMax(const QVariant& rawMax)
@@ -178,22 +191,22 @@ void FactMetaData::setRawMax(const QVariant& rawMax)
|
|
|
|
|
QVariant FactMetaData::_minForType(void) const |
|
|
|
|
{ |
|
|
|
|
switch (_type) { |
|
|
|
|
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<unsigned int>::min()); |
|
|
|
|
case valueTypeInt32: |
|
|
|
|
return QVariant(std::numeric_limits<int>::min()); |
|
|
|
|
case valueTypeFloat: |
|
|
|
|
return QVariant(-std::numeric_limits<float>::max()); |
|
|
|
|
case valueTypeDouble: |
|
|
|
|
return QVariant(-std::numeric_limits<double>::max()); |
|
|
|
|
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<unsigned int>::min()); |
|
|
|
|
case valueTypeInt32: |
|
|
|
|
return QVariant(std::numeric_limits<int>::min()); |
|
|
|
|
case valueTypeFloat: |
|
|
|
|
return QVariant(-std::numeric_limits<float>::max()); |
|
|
|
|
case valueTypeDouble: |
|
|
|
|
return QVariant(-std::numeric_limits<double>::max()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Make windows compiler happy, even switch is full cased
|
|
|
|
@ -203,22 +216,22 @@ QVariant FactMetaData::_minForType(void) const
@@ -203,22 +216,22 @@ QVariant FactMetaData::_minForType(void) const
|
|
|
|
|
QVariant FactMetaData::_maxForType(void) const |
|
|
|
|
{ |
|
|
|
|
switch (_type) { |
|
|
|
|
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<unsigned int>::max()); |
|
|
|
|
case valueTypeInt32: |
|
|
|
|
return QVariant(std::numeric_limits<int>::max()); |
|
|
|
|
case valueTypeFloat: |
|
|
|
|
return QVariant(std::numeric_limits<float>::max()); |
|
|
|
|
case valueTypeDouble: |
|
|
|
|
return QVariant(std::numeric_limits<double>::max()); |
|
|
|
|
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<unsigned int>::max()); |
|
|
|
|
case valueTypeInt32: |
|
|
|
|
return QVariant(std::numeric_limits<int>::max()); |
|
|
|
|
case valueTypeFloat: |
|
|
|
|
return QVariant(std::numeric_limits<float>::max()); |
|
|
|
|
case valueTypeDouble: |
|
|
|
|
return QVariant(std::numeric_limits<double>::max()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Make windows compiler happy, even switch is full cased
|
|
|
|
@ -232,45 +245,45 @@ bool FactMetaData::convertAndValidateRaw(const QVariant& rawValue, bool convertO
@@ -232,45 +245,45 @@ bool FactMetaData::convertAndValidateRaw(const QVariant& rawValue, bool convertO
|
|
|
|
|
errorString.clear(); |
|
|
|
|
|
|
|
|
|
switch (type()) { |
|
|
|
|
case FactMetaData::valueTypeInt8: |
|
|
|
|
case FactMetaData::valueTypeInt16: |
|
|
|
|
case FactMetaData::valueTypeInt32: |
|
|
|
|
typedValue = QVariant(rawValue.toInt(&convertOk)); |
|
|
|
|
if (!convertOnly && convertOk) { |
|
|
|
|
if (rawMin() > typedValue || typedValue > rawMax()) { |
|
|
|
|
errorString = QString("Value must be within %1 and %2").arg(cookedMin().toInt()).arg(cookedMax().toInt()); |
|
|
|
|
} |
|
|
|
|
case FactMetaData::valueTypeInt8: |
|
|
|
|
case FactMetaData::valueTypeInt16: |
|
|
|
|
case FactMetaData::valueTypeInt32: |
|
|
|
|
typedValue = QVariant(rawValue.toInt(&convertOk)); |
|
|
|
|
if (!convertOnly && convertOk) { |
|
|
|
|
if (rawMin() > typedValue || typedValue > rawMax()) { |
|
|
|
|
errorString = QString("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(rawValue.toUInt(&convertOk)); |
|
|
|
|
if (!convertOnly && convertOk) { |
|
|
|
|
if (rawMin() > typedValue || typedValue > rawMax()) { |
|
|
|
|
errorString = QString("Value must be within %1 and %2").arg(cookedMin().toUInt()).arg(cookedMax().toUInt()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case FactMetaData::valueTypeUint8: |
|
|
|
|
case FactMetaData::valueTypeUint16: |
|
|
|
|
case FactMetaData::valueTypeUint32: |
|
|
|
|
typedValue = QVariant(rawValue.toUInt(&convertOk)); |
|
|
|
|
if (!convertOnly && convertOk) { |
|
|
|
|
if (rawMin() > typedValue || typedValue > rawMax()) { |
|
|
|
|
errorString = QString("Value must be within %1 and %2").arg(cookedMin().toUInt()).arg(cookedMax().toUInt()); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case FactMetaData::valueTypeFloat: |
|
|
|
|
typedValue = QVariant(rawValue.toFloat(&convertOk)); |
|
|
|
|
if (!convertOnly && convertOk) { |
|
|
|
|
if (rawMin() > typedValue || typedValue > rawMax()) { |
|
|
|
|
errorString = QString("Value must be within %1 and %2").arg(cookedMin().toFloat()).arg(cookedMax().toFloat()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case FactMetaData::valueTypeFloat: |
|
|
|
|
typedValue = QVariant(rawValue.toFloat(&convertOk)); |
|
|
|
|
if (!convertOnly && convertOk) { |
|
|
|
|
if (rawMin() > typedValue || typedValue > rawMax()) { |
|
|
|
|
errorString = QString("Value must be within %1 and %2").arg(cookedMin().toFloat()).arg(cookedMax().toFloat()); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case FactMetaData::valueTypeDouble: |
|
|
|
|
typedValue = QVariant(rawValue.toDouble(&convertOk)); |
|
|
|
|
if (!convertOnly && convertOk) { |
|
|
|
|
if (rawMin() > typedValue || typedValue > rawMax()) { |
|
|
|
|
errorString = QString("Value must be within %1 and %2").arg(cookedMin().toDouble()).arg(cookedMax().toDouble()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case FactMetaData::valueTypeDouble: |
|
|
|
|
typedValue = QVariant(rawValue.toDouble(&convertOk)); |
|
|
|
|
if (!convertOnly && convertOk) { |
|
|
|
|
if (rawMin() > typedValue || typedValue > rawMax()) { |
|
|
|
|
errorString = QString("Value must be within %1 and %2").arg(cookedMin().toDouble()).arg(cookedMax().toDouble()); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!convertOk) { |
|
|
|
@ -287,45 +300,45 @@ bool FactMetaData::convertAndValidateCooked(const QVariant& cookedValue, bool co
@@ -287,45 +300,45 @@ bool FactMetaData::convertAndValidateCooked(const QVariant& cookedValue, bool co
|
|
|
|
|
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 = QString("Value must be within %1 and %2").arg(cookedMin().toInt()).arg(cookedMax().toInt()); |
|
|
|
|
} |
|
|
|
|
case FactMetaData::valueTypeInt8: |
|
|
|
|
case FactMetaData::valueTypeInt16: |
|
|
|
|
case FactMetaData::valueTypeInt32: |
|
|
|
|
typedValue = QVariant(cookedValue.toInt(&convertOk)); |
|
|
|
|
if (!convertOnly && convertOk) { |
|
|
|
|
if (cookedMin() > typedValue || typedValue > cookedMax()) { |
|
|
|
|
errorString = QString("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 = QString("Value must be within %1 and %2").arg(cookedMin().toUInt()).arg(cookedMax().toUInt()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case FactMetaData::valueTypeUint8: |
|
|
|
|
case FactMetaData::valueTypeUint16: |
|
|
|
|
case FactMetaData::valueTypeUint32: |
|
|
|
|
typedValue = QVariant(cookedValue.toUInt(&convertOk)); |
|
|
|
|
if (!convertOnly && convertOk) { |
|
|
|
|
if (cookedMin() > typedValue || typedValue > cookedMax()) { |
|
|
|
|
errorString = QString("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 = QString("Value must be within %1 and %2").arg(cookedMin().toFloat()).arg(cookedMax().toFloat()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case FactMetaData::valueTypeFloat: |
|
|
|
|
typedValue = QVariant(cookedValue.toFloat(&convertOk)); |
|
|
|
|
if (!convertOnly && convertOk) { |
|
|
|
|
if (cookedMin() > typedValue || typedValue > cookedMax()) { |
|
|
|
|
errorString = QString("Value must be within %1 and %2").arg(cookedMin().toFloat()).arg(cookedMax().toFloat()); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case FactMetaData::valueTypeDouble: |
|
|
|
|
typedValue = QVariant(cookedValue.toDouble(&convertOk)); |
|
|
|
|
if (!convertOnly && convertOk) { |
|
|
|
|
if (cookedMin() > typedValue || typedValue > cookedMax()) { |
|
|
|
|
errorString = QString("Value must be within %1 and %2").arg(cookedMin().toDouble()).arg(cookedMax().toDouble()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case FactMetaData::valueTypeDouble: |
|
|
|
|
typedValue = QVariant(cookedValue.toDouble(&convertOk)); |
|
|
|
|
if (!convertOnly && convertOk) { |
|
|
|
|
if (cookedMin() > typedValue || typedValue > cookedMax()) { |
|
|
|
|
errorString = QString("Value must be within %1 and %2").arg(cookedMin().toDouble()).arg(cookedMax().toDouble()); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!convertOk) { |
|
|
|
@ -536,22 +549,22 @@ FactMetaData::ValueType_t FactMetaData::stringToType(const QString& typeString,
@@ -536,22 +549,22 @@ FactMetaData::ValueType_t FactMetaData::stringToType(const QString& typeString,
|
|
|
|
|
unknownType = false; |
|
|
|
|
|
|
|
|
|
knownTypeStrings << QStringLiteral("Uint8") |
|
|
|
|
<< QStringLiteral("Int8") |
|
|
|
|
<< QStringLiteral("Uint16") |
|
|
|
|
<< QStringLiteral("Int16") |
|
|
|
|
<< QStringLiteral("Uint32") |
|
|
|
|
<< QStringLiteral("Int32") |
|
|
|
|
<< QStringLiteral("Float") |
|
|
|
|
<< QStringLiteral("Double"); |
|
|
|
|
<< QStringLiteral("Int8") |
|
|
|
|
<< QStringLiteral("Uint16") |
|
|
|
|
<< QStringLiteral("Int16") |
|
|
|
|
<< QStringLiteral("Uint32") |
|
|
|
|
<< QStringLiteral("Int32") |
|
|
|
|
<< QStringLiteral("Float") |
|
|
|
|
<< QStringLiteral("Double"); |
|
|
|
|
|
|
|
|
|
knownTypes << valueTypeUint8 |
|
|
|
|
<< valueTypeInt8 |
|
|
|
|
<< valueTypeUint16 |
|
|
|
|
<< valueTypeInt16 |
|
|
|
|
<< valueTypeUint32 |
|
|
|
|
<< valueTypeInt32 |
|
|
|
|
<< valueTypeFloat |
|
|
|
|
<< valueTypeDouble; |
|
|
|
|
<< valueTypeInt8 |
|
|
|
|
<< valueTypeUint16 |
|
|
|
|
<< valueTypeInt16 |
|
|
|
|
<< valueTypeUint32 |
|
|
|
|
<< valueTypeInt32 |
|
|
|
|
<< valueTypeFloat |
|
|
|
|
<< valueTypeDouble; |
|
|
|
|
|
|
|
|
|
for (int i=0; i<knownTypeStrings.count(); i++) { |
|
|
|
|
if (knownTypeStrings[i].compare(typeString, Qt::CaseInsensitive) == 0) { |
|
|
|
@ -567,25 +580,25 @@ FactMetaData::ValueType_t FactMetaData::stringToType(const QString& typeString,
@@ -567,25 +580,25 @@ FactMetaData::ValueType_t FactMetaData::stringToType(const QString& typeString,
|
|
|
|
|
size_t FactMetaData::typeToSize(ValueType_t type) |
|
|
|
|
{ |
|
|
|
|
switch (type) { |
|
|
|
|
case valueTypeUint8: |
|
|
|
|
case valueTypeInt8: |
|
|
|
|
return 1; |
|
|
|
|
case valueTypeUint8: |
|
|
|
|
case valueTypeInt8: |
|
|
|
|
return 1; |
|
|
|
|
|
|
|
|
|
case valueTypeUint16: |
|
|
|
|
case valueTypeInt16: |
|
|
|
|
return 2; |
|
|
|
|
case valueTypeUint16: |
|
|
|
|
case valueTypeInt16: |
|
|
|
|
return 2; |
|
|
|
|
|
|
|
|
|
case valueTypeUint32: |
|
|
|
|
case valueTypeInt32: |
|
|
|
|
case valueTypeFloat: |
|
|
|
|
return 4; |
|
|
|
|
case valueTypeUint32: |
|
|
|
|
case valueTypeInt32: |
|
|
|
|
case valueTypeFloat: |
|
|
|
|
return 4; |
|
|
|
|
|
|
|
|
|
case valueTypeDouble: |
|
|
|
|
return 8; |
|
|
|
|
case valueTypeDouble: |
|
|
|
|
return 8; |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
qWarning() << "Unsupported fact value type" << type; |
|
|
|
|
return 4; |
|
|
|
|
default: |
|
|
|
|
qWarning() << "Unsupported fact value type" << type; |
|
|
|
|
return 4; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -615,7 +628,7 @@ const FactMetaData::AppSettingsTranslation_s* FactMetaData::_findAppSettingsDist
@@ -615,7 +628,7 @@ const FactMetaData::AppSettingsTranslation_s* FactMetaData::_findAppSettingsDist
|
|
|
|
|
const AppSettingsTranslation_s* pAppSettingsTranslation = &_rgAppSettingsTranslations[i]; |
|
|
|
|
|
|
|
|
|
if (pAppSettingsTranslation->rawUnits == rawUnits && |
|
|
|
|
(!pAppSettingsTranslation->speed && pAppSettingsTranslation->speedOrDistanceUnits == QGroundControlQmlGlobal::distanceUnits()->rawValue().toUInt())) { |
|
|
|
|
(!pAppSettingsTranslation->speed && pAppSettingsTranslation->speedOrDistanceUnits == QGroundControlQmlGlobal::distanceUnits()->rawValue().toUInt())) { |
|
|
|
|
return pAppSettingsTranslation; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -629,7 +642,7 @@ const FactMetaData::AppSettingsTranslation_s* FactMetaData::_findAppSettingsArea
@@ -629,7 +642,7 @@ const FactMetaData::AppSettingsTranslation_s* FactMetaData::_findAppSettingsArea
|
|
|
|
|
const AppSettingsTranslation_s* pAppSettingsTranslation = &_rgAppSettingsTranslations[i]; |
|
|
|
|
|
|
|
|
|
if (pAppSettingsTranslation->rawUnits == rawUnits && |
|
|
|
|
(!pAppSettingsTranslation->speed && pAppSettingsTranslation->speedOrDistanceUnits == QGroundControlQmlGlobal::areaUnits()->rawValue().toUInt()) |
|
|
|
|
(!pAppSettingsTranslation->speed && pAppSettingsTranslation->speedOrDistanceUnits == QGroundControlQmlGlobal::areaUnits()->rawValue().toUInt()) |
|
|
|
|
) { |
|
|
|
|
return pAppSettingsTranslation; |
|
|
|
|
} |
|
|
|
@ -736,3 +749,120 @@ int FactMetaData::decimalPlaces(void) const
@@ -736,3 +749,120 @@ int FactMetaData::decimalPlaces(void) const
|
|
|
|
|
|
|
|
|
|
return actualDecimalPlaces; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
FactMetaData* FactMetaData::_createFromJsonObject(const QJsonObject& json, QObject* metaDataParent) |
|
|
|
|
{ |
|
|
|
|
QString errorString; |
|
|
|
|
|
|
|
|
|
// Make sure we have the required keys
|
|
|
|
|
QStringList requiredKeys; |
|
|
|
|
requiredKeys << _nameJsonKey << _typeJsonKey; |
|
|
|
|
if (!JsonHelper::validateRequiredKeys(json, requiredKeys, errorString)) { |
|
|
|
|
qWarning() << errorString; |
|
|
|
|
return new FactMetaData(valueTypeUint32, metaDataParent); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Validate key types
|
|
|
|
|
QStringList keys; |
|
|
|
|
QList<QJsonValue::Type> types; |
|
|
|
|
keys << _nameJsonKey << _decimalPlacesJsonKey << _typeJsonKey << _shortDescriptionJsonKey << _longDescriptionJsonKey << _unitsJsonKey << _defaultValueJsonKey << _minJsonKey << _maxJsonKey; |
|
|
|
|
types << QJsonValue::String << QJsonValue::Double << QJsonValue::String << QJsonValue::String << QJsonValue::String << QJsonValue::String << QJsonValue::Double << QJsonValue::Double << QJsonValue::Double; |
|
|
|
|
if (!JsonHelper::validateKeyTypes(json, keys, types, errorString)) { |
|
|
|
|
qWarning() << errorString; |
|
|
|
|
return new FactMetaData(valueTypeUint32, metaDataParent); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool unknownType; |
|
|
|
|
FactMetaData::ValueType_t type = FactMetaData::stringToType(json[_typeJsonKey].toString(), unknownType); |
|
|
|
|
if (unknownType) { |
|
|
|
|
qWarning() << "Unknown type" << json[_typeJsonKey].toString(); |
|
|
|
|
return new FactMetaData(valueTypeUint32, metaDataParent); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
FactMetaData* metaData = new FactMetaData(type, metaDataParent); |
|
|
|
|
|
|
|
|
|
metaData->_name = json[_nameJsonKey].toString(); |
|
|
|
|
|
|
|
|
|
QStringList enumValues, enumStrings; |
|
|
|
|
if (JsonHelper::parseEnum(json, enumStrings, enumValues, errorString)) { |
|
|
|
|
for (int i=0; i<enumValues.count(); i++) { |
|
|
|
|
QVariant enumVariant; |
|
|
|
|
QString errorString; |
|
|
|
|
|
|
|
|
|
if (metaData->convertAndValidateRaw(enumValues[i], false /* validate */, enumVariant, errorString)) { |
|
|
|
|
metaData->addEnumInfo(enumStrings[i], enumVariant); |
|
|
|
|
} else { |
|
|
|
|
qWarning() << "Invalid enum value, name:" << metaData->name() |
|
|
|
|
<< " type:" << metaData->type() |
|
|
|
|
<< " value:" << enumValues[i] |
|
|
|
|
<< " error:" << errorString; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
qWarning() << errorString; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
metaData->setDecimalPlaces(json[_decimalPlacesJsonKey].toInt(0)); |
|
|
|
|
metaData->setShortDescription(json[_shortDescriptionJsonKey].toString()); |
|
|
|
|
metaData->setLongDescription(json[_longDescriptionJsonKey].toString()); |
|
|
|
|
|
|
|
|
|
if (json.contains(_unitsJsonKey)) { |
|
|
|
|
metaData->setRawUnits(json[_unitsJsonKey].toString()); |
|
|
|
|
} |
|
|
|
|
if (json.contains(_defaultValueJsonKey)) { |
|
|
|
|
metaData->setRawDefaultValue(json[_defaultValueJsonKey].toDouble()); |
|
|
|
|
} |
|
|
|
|
if (json.contains(_minJsonKey)) { |
|
|
|
|
metaData->setRawMin(json[_minJsonKey].toDouble()); |
|
|
|
|
} |
|
|
|
|
if (json.contains(_maxJsonKey)) { |
|
|
|
|
metaData->setRawMax(json[_maxJsonKey].toDouble()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return metaData; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QMap<QString, FactMetaData*> FactMetaData::createMapFromJsonFile(const QString& jsonFilename, QObject* metaDataParent) |
|
|
|
|
{ |
|
|
|
|
QMap<QString, FactMetaData*> metaDataMap; |
|
|
|
|
|
|
|
|
|
QFile jsonFile(jsonFilename); |
|
|
|
|
if (!jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) { |
|
|
|
|
qWarning() << "Unable to open file" << jsonFilename << jsonFile.errorString(); |
|
|
|
|
return metaDataMap; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QByteArray bytes = jsonFile.readAll(); |
|
|
|
|
jsonFile.close(); |
|
|
|
|
QJsonParseError jsonParseError; |
|
|
|
|
QJsonDocument doc = QJsonDocument::fromJson(bytes, &jsonParseError); |
|
|
|
|
if (jsonParseError.error != QJsonParseError::NoError) { |
|
|
|
|
qWarning() << "Unable to parse json document" << jsonFilename << jsonParseError.errorString(); |
|
|
|
|
return metaDataMap; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!doc.isArray()) { |
|
|
|
|
qWarning() << "json document is not array"; |
|
|
|
|
return metaDataMap; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QJsonArray jsonArray = doc.array(); |
|
|
|
|
for (int i=0; i<jsonArray.count(); i++) { |
|
|
|
|
QJsonValueRef jsonValue = jsonArray[i]; |
|
|
|
|
|
|
|
|
|
if (!jsonValue.isObject()) { |
|
|
|
|
qWarning() << QStringLiteral("JsonValue at index %1 not an object").arg(i); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
QJsonObject jsonObject = jsonValue.toObject(); |
|
|
|
|
FactMetaData* metaData = _createFromJsonObject(jsonObject, metaDataParent); |
|
|
|
|
|
|
|
|
|
if (metaDataMap.contains(metaData->name())) { |
|
|
|
|
qWarning() << QStringLiteral("Duplicate fact name:") << metaData->name(); |
|
|
|
|
} else { |
|
|
|
|
metaDataMap[metaData->name()] = metaData; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return metaDataMap; |
|
|
|
|
} |
|
|
|
|