Newer
Older
const AppSettingsTranslation_s* pAppSettingsTranslation = _findAppSettingsAreaUnitsTranslation("m^2");
if (pAppSettingsTranslation) {
return pAppSettingsTranslation->cookedTranslator(area);
} else {
return area;
}
}
QString FactMetaData::appSettingsAreaUnitsString(void)
{
const AppSettingsTranslation_s* pAppSettingsTranslation = _findAppSettingsAreaUnitsTranslation("m^2");
if (pAppSettingsTranslation) {
return pAppSettingsTranslation->cookedUnits;
} else {
return QStringLiteral("m^2");
}
}
double FactMetaData::cookedIncrement(void) const
{
return _rawTranslator(this->rawIncrement()).toDouble();
int FactMetaData::decimalPlaces(void) const
{
int actualDecimalPlaces = defaultDecimalPlaces;
int incrementDecimalPlaces = unknownDecimalPlaces;
// First determine decimal places from increment
double increment = _rawTranslator(this->rawIncrement()).toDouble();
if (!qIsNaN(increment)) {
double integralPart;
// Get the fractional part only
increment = fabs(modf(increment, &integralPart));
if (increment == 0.0) {
// No fractional part, so no decimal places
incrementDecimalPlaces = 0;
} else {
incrementDecimalPlaces = -ceil(log10(increment));
}
}
// Correct decimal places is the larger of the two, increment or meta data value
if (incrementDecimalPlaces != unknownDecimalPlaces && _decimalPlaces == unknownDecimalPlaces) {
actualDecimalPlaces = incrementDecimalPlaces;
} else {
// Adjust decimal places for cooked translation
int settingsDecimalPlaces = _decimalPlaces == unknownDecimalPlaces ? defaultDecimalPlaces : _decimalPlaces;
double ctest = _rawTranslator(1.0).toDouble();
settingsDecimalPlaces += -log10(ctest);
settingsDecimalPlaces = qMin(25, settingsDecimalPlaces);
settingsDecimalPlaces = qMax(0, settingsDecimalPlaces);
actualDecimalPlaces = qMax(settingsDecimalPlaces, incrementDecimalPlaces);
}
return actualDecimalPlaces;
}
FactMetaData* FactMetaData::createFromJsonObject(const QJsonObject& json, QMap<QString, QString>& defineMap, 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);
}
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 },
{ _qgcRebootRequiredJsonKey, QJsonValue::Bool, false },
};
if (!JsonHelper::validateKeys(json, keyInfoList, 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, defineMap, enumStrings, enumValues, errorString, metaData->name())) {
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
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());
}
QString defaultValueJsonKey;
#ifdef __mobile__
if (json.contains(_mobileDefaultValueJsonKey)) {
if (defaultValueJsonKey.isEmpty() && json.contains(_defaultValueJsonKey)) {
defaultValueJsonKey = _defaultValueJsonKey;
}
if (!defaultValueJsonKey.isEmpty()) {
QVariant typedValue;
QString errorString;
QVariant initialValue = json[defaultValueJsonKey].toVariant();
if (metaData->convertAndValidateRaw(initialValue, true /* convertOnly */, typedValue, errorString)) {
metaData->setRawDefaultValue(typedValue);
} else {
qWarning() << "Invalid default value, name:" << metaData->name()
<< " type:" << metaData->type()
<< " value:" << initialValue
<< " error:" << errorString;
}
}
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;
}
}
QVariant typedValue;
QString errorString;
QVariant initialValue = json[_minJsonKey].toVariant();
if (metaData->convertAndValidateRaw(initialValue, true /* convertOnly */, typedValue, errorString)) {
metaData->setRawMin(typedValue);
} else {
qWarning() << "Invalid min value, name:" << metaData->name()
<< " type:" << metaData->type()
<< " value:" << initialValue
<< " error:" << errorString;
}
QVariant typedValue;
QString errorString;
QVariant initialValue = json[_maxJsonKey].toVariant();
if (metaData->convertAndValidateRaw(initialValue, true /* convertOnly */, typedValue, errorString)) {
metaData->setRawMax(typedValue);
} else {
qWarning() << "Invalid max value, name:" << metaData->name()
<< " type:" << metaData->type()
<< " value:" << initialValue
<< " error:" << errorString;
}
if (json.contains(_hasControlJsonKey)) {
metaData->setHasControl(json[_hasControlJsonKey].toBool());
} else {
metaData->setHasControl(true);
}
if (json.contains(_qgcRebootRequiredJsonKey)) {
metaData->setQGCRebootRequired(json[_qgcRebootRequiredJsonKey].toBool());
} else {
metaData->setQGCRebootRequired(false);
}
void FactMetaData::_loadJsonDefines(const QJsonObject& jsonDefinesObject, QMap<QString, QString>& defineMap)
{
for (const QString& defineName: jsonDefinesObject.keys()) {
QString mapKey = _jsonMetaDataDefinesName + QString(".") + defineName;
defineMap[mapKey] = jsonDefinesObject[defineName].toString();
}
}
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 filename:error:offset" << jsonFilename << jsonParseError.errorString() << jsonParseError.offset;
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
QJsonArray factArray;
QMap<QString /* define name */, QString /* define value */> defineMap;
if (doc.isObject()) {
// Check for Defines/Facts format
QString errorString;
QList<JsonHelper::KeyValidateInfo> keyInfoList = {
{ FactMetaData::_jsonMetaDataDefinesName, QJsonValue::Object, true },
{ FactMetaData::_jsonMetaDataFactsName, QJsonValue::Array, true },
};
if (!JsonHelper::validateKeys(doc.object(), keyInfoList, errorString)) {
qWarning() << "Json document incorrect format:" << errorString;
return metaDataMap;
}
_loadJsonDefines(doc.object()[FactMetaData::_jsonMetaDataDefinesName].toObject(), defineMap);
factArray = doc.object()[FactMetaData::_jsonMetaDataFactsName].toArray();
} else if (doc.isArray()) {
factArray = doc.array();
} else {
qWarning() << "Json document is neither array nor object";
QMap<QString, FactMetaData*> FactMetaData::createMapFromJsonArray(const QJsonArray jsonArray, QMap<QString, QString>& defineMap, QObject* metaDataParent)
{
QMap<QString, FactMetaData*> metaDataMap;
for (int i=0; i<jsonArray.count(); i++) {
QJsonValue jsonValue = jsonArray.at(i);
if (!jsonValue.isObject()) {
qWarning() << QStringLiteral("JsonValue at index %1 not an object").arg(i);
continue;
}
QJsonObject jsonObject = jsonValue.toObject();
FactMetaData* metaData = createFromJsonObject(jsonObject, defineMap, metaDataParent);
if (metaDataMap.contains(metaData->name())) {
qWarning() << QStringLiteral("Duplicate fact name:") << metaData->name();
} else {
metaDataMap[metaData->name()] = metaData;
}
}
return metaDataMap;
}
QVariant FactMetaData::cookedMax(void) const
{
// We have to be careful with cooked min/max. Running the raw values through the translator could flip min and max.
return qMax(_rawTranslator(_rawMax), _rawTranslator(_rawMin));
}
QVariant FactMetaData::cookedMin(void) const
{
// We have to be careful with cooked min/max. Running the raw values through the translator could flip min and max.
return qMin(_rawTranslator(_rawMax), _rawTranslator(_rawMin));
void FactMetaData::setVolatileValue(bool bValue)
{
_volatile = bValue;
if (_volatile) {
_readOnly = true;
}
}