8#include <QtCore/QJsonArray>
9#include <QtCore/QJsonObject>
10#include <QtCore/QtMath>
16 {
"centi-degrees",
"deg", FactMetaData::_centiDegreesToDegrees, FactMetaData::_degreesToCentiDegrees },
17 {
"radians",
"deg", FactMetaData::_radiansToDegrees, FactMetaData::_degreesToRadians },
18 {
"rad",
"deg", FactMetaData::_radiansToDegrees, FactMetaData::_degreesToRadians },
19 {
"gimbal-degrees",
"deg", FactMetaData::_mavlinkGimbalDegreesToUserGimbalDegrees, FactMetaData::_userGimbalDegreesToMavlinkGimbalDegrees },
20 {
"norm",
"%", FactMetaData::_normToPercent, FactMetaData::_percentToNorm },
21 {
"centi-celsius",
"C", FactMetaData::_centiCelsiusToCelsius, FactMetaData::_celsiusToCentiCelsius },
25const FactMetaData::AppSettingsTranslation_s FactMetaData::_rgAppSettingsTranslations[] = {
43 {
"m^2",
"ac", FactMetaData::UnitArea,
UnitsSettings::AreaUnitsAcres, FactMetaData::_squareMetersToAcres, FactMetaData::_acresToSquareMeters },
48 {
"m/s",
"kn", FactMetaData::UnitSpeed,
UnitsSettings::SpeedUnitsKnots, FactMetaData::_metersPerSecondToKnots, FactMetaData::_knotsToMetersPerSecond },
91 _decimalPlaces = other._decimalPlaces;
92 _rawDefaultValue = other._rawDefaultValue;
93 _defaultValueAvailable = other._defaultValueAvailable;
94 _bitmaskStrings = other._bitmaskStrings;
95 _bitmaskValues = other._bitmaskValues;
96 _enumStrings = other._enumStrings;
97 _enumValues = other._enumValues;
98 _category = other._category;
99 _group = other._group;
100 _longDescription = other._longDescription;
101 _rawMax = other._rawMax;
102 _rawMin = other._rawMin;
103 _rawUserMin = other._rawUserMin;
104 _rawUserMax = other._rawUserMax;
106 _shortDescription = other._shortDescription;
108 _rawUnits = other._rawUnits;
109 _cookedUnits = other._cookedUnits;
110 _rawTranslator = other._rawTranslator;
111 _cookedTranslator = other._cookedTranslator;
112 _vehicleRebootRequired = other._vehicleRebootRequired;
113 _qgcRebootRequired = other._qgcRebootRequired;
114 _rawIncrement = other._rawIncrement;
115 _hasControl = other._hasControl;
116 _readOnly = other._readOnly;
117 _writeOnly = other._writeOnly;
118 _volatile = other._volatile;
125 if (_defaultValueAvailable) {
126 return _rawDefaultValue;
128 qWarning(FactMetaDataLog) <<
"Attempt to access unavailable default value";
137 _defaultValueAvailable =
true;
139 qWarning(FactMetaDataLog) <<
"Attempt to set default value which is outside min/max range. Name:" <<
name()
141 <<
", type:" <<
type()
142 <<
", min:" << _rawMin
143 <<
", max:" << _rawMax;
150 _defaultValueAvailable =
true;
155 if (isInRawMinLimit(
rawMin)) {
157 if (_rawUserMin.isValid() && !isInRawMinLimit(_rawUserMin)) {
158 _rawUserMin = _rawMin;
161 qWarning(FactMetaDataLog) <<
"Attempt to set min below allowable value for fact:" <<
name()
162 <<
", attempted value:" <<
rawMin
163 <<
", type:" <<
type()
164 <<
", min for type:" << _minForType();
165 _rawMin = _minForType();
166 _rawUserMin = _rawMin;
172 if (isInRawMaxLimit(
rawMax)) {
174 if (_rawUserMax.isValid() && !isInRawMaxLimit(_rawUserMax)) {
175 _rawUserMax = _rawMax;
178 qWarning(FactMetaDataLog) <<
"Attempt to set max above allowable value for fact:" <<
name()
179 <<
", attempted value:" <<
rawMax
180 <<
", type:" <<
type()
181 <<
", max for type:" << _maxForType();
182 _rawMax = _maxForType();
183 _rawUserMax = _rawMax;
192 qWarning(FactMetaDataLog) <<
"Attempt to set user min below allowable value for fact:" <<
name()
194 <<
", type:" <<
type()
195 <<
", min:" << _rawMin;
196 _rawUserMin = _rawMin;
205 qWarning(FactMetaDataLog) <<
"Attempt to set user max above allowable value for fact:" <<
name()
207 <<
", type:" <<
type()
208 <<
", max:" << _rawMax;
209 _rawUserMax = _rawMax;
213bool FactMetaData::isInRawMinLimit(
const QVariant &variantValue)
const
217 return (_rawMin.value<
unsigned char>() <= variantValue.value<
unsigned char>());
219 return (_rawMin.value<
signed char>() <= variantValue.value<
signed char>());
221 return (_rawMin.value<
unsigned short int>() <= variantValue.value<
unsigned short int>());
223 return (_rawMin.value<
short int>() <= variantValue.value<
short int>());
225 return (_rawMin.value<uint32_t>() <= variantValue.value<uint32_t>());
227 return (_rawMin.value<int32_t>() <= variantValue.value<int32_t>());
229 return (_rawMin.value<uint64_t>() <= variantValue.value<uint64_t>());
231 return (_rawMin.value<int64_t>() <= variantValue.value<int64_t>());
233 return ((qIsNaN(variantValue.toFloat())) || (_rawMin.value<
float>() <= variantValue.value<
float>()));
235 return ((qIsNaN(variantValue.toDouble())) || (_rawMin.value<
double>() <= variantValue.value<
double>()));
241bool FactMetaData::isInRawMaxLimit(
const QVariant &variantValue)
const
245 return (_rawMax.value<
unsigned char>() >= variantValue.value<
unsigned char>());
247 return (_rawMax.value<
signed char>() >= variantValue.value<
signed char>());
249 return (_rawMax.value<
unsigned short int>() >= variantValue.value<
unsigned short int>());
251 return (_rawMax.value<
short int>() >= variantValue.value<
short int>());
253 return (_rawMax.value<uint32_t>() >= variantValue.value<uint32_t>());
255 return (_rawMax.value<int32_t>() >= variantValue.value<int32_t>());
257 return (_rawMax.value<uint64_t>() >= variantValue.value<uint64_t>());
259 return (_rawMax.value<int64_t>() >= variantValue.value<int64_t>());
261 return (qIsNaN(variantValue.toFloat()) || (_rawMax.value<
float>() >= variantValue.value<
float>()));
263 return (qIsNaN(variantValue.toDouble()) || (_rawMax.value<
double>() >= variantValue.value<
double>()));
273 return QVariant(std::numeric_limits<unsigned char>::min());
275 return QVariant(std::numeric_limits<signed char>::min());
277 return QVariant(std::numeric_limits<unsigned short int>::min());
279 return QVariant(std::numeric_limits<short int>::min());
281 return QVariant(std::numeric_limits<uint32_t>::min());
283 return QVariant(std::numeric_limits<int32_t>::min());
285 return QVariant((qulonglong)std::numeric_limits<uint64_t>::min());
287 return QVariant((qlonglong)std::numeric_limits<int64_t>::min());
289 return QVariant(-std::numeric_limits<float>::max());
291 return QVariant(-std::numeric_limits<double>::max());
297 return QVariant(0.0);
308 return QVariant(std::numeric_limits<unsigned char>::max());
310 return QVariant(std::numeric_limits<signed char>::max());
312 return QVariant(std::numeric_limits<unsigned short int>::max());
314 return QVariant(std::numeric_limits<short int>::max());
316 return QVariant(std::numeric_limits<uint32_t>::max());
318 return QVariant(std::numeric_limits<int32_t>::max());
320 return QVariant((qulonglong)std::numeric_limits<uint64_t>::max());
322 return QVariant((qlonglong)std::numeric_limits<int64_t>::max());
324 return QVariant(std::numeric_limits<float>::max());
327 return QVariant(std::numeric_limits<double>::max());
340 bool convertOk =
false;
348 typedValue = QVariant(rawValue.toInt(&convertOk));
349 if (!convertOnly && convertOk) {
350 if (!isInRawLimit<int32_t>(typedValue)) {
356 typedValue = QVariant(rawValue.toLongLong(&convertOk));
357 if (!convertOnly && convertOk) {
358 if (!isInRawLimit<int64_t>(typedValue)) {
366 typedValue = QVariant(rawValue.toUInt(&convertOk));
367 if (!convertOnly && convertOk) {
368 if (!isInRawLimit<uint32_t>(typedValue)) {
374 typedValue = QVariant(rawValue.toULongLong(&convertOk));
375 if (!convertOnly && convertOk) {
376 if (!isInRawLimit<uint64_t>(typedValue)) {
382 typedValue = QVariant(rawValue.toFloat(&convertOk));
383 if (!convertOnly && convertOk) {
384 if (!isInRawLimit<float>(typedValue)) {
391 typedValue = QVariant(rawValue.toDouble(&convertOk));
392 if (!convertOnly && convertOk) {
393 if (!isInRawLimit<double>(typedValue)) {
400 typedValue = QVariant(rawValue.toString());
404 typedValue = QVariant(rawValue.toBool());
408 typedValue = QVariant(rawValue.toByteArray());
421 bool convertOk =
false;
425 if (!convertOnly && _customCookedValidator) {
436 typedValue = QVariant(cookedValue.toInt(&convertOk));
437 if (!convertOnly && convertOk) {
438 if (!isInCookedLimit<int32_t>(typedValue)) {
444 typedValue = QVariant(cookedValue.toLongLong(&convertOk));
445 if (!convertOnly && convertOk) {
446 if (!isInCookedLimit<int64_t>(typedValue)) {
454 typedValue = QVariant(cookedValue.toUInt(&convertOk));
455 if (!convertOnly && convertOk) {
456 if (!isInCookedLimit<uint32_t>(typedValue)) {
462 typedValue = QVariant(cookedValue.toULongLong(&convertOk));
463 if (!convertOnly && convertOk) {
464 if (!isInCookedLimit<uint64_t>(typedValue)) {
470 typedValue = QVariant(cookedValue.toFloat(&convertOk));
471 if (!convertOnly && convertOk) {
472 if (!isInCookedLimit<float>(typedValue)) {
479 typedValue = QVariant(cookedValue.toDouble(&convertOk));
480 if (!convertOnly && convertOk) {
481 if (!isInCookedLimit<double>(typedValue)) {
488 typedValue = QVariant(cookedValue.toString());
492 typedValue = QVariant(cookedValue.toBool());
496 typedValue = QVariant(cookedValue.toByteArray());
509 bool convertOk =
false;
515 typedValue = QVariant(cookedValue.toInt(&convertOk));
517 clamp<int32_t>(typedValue);
521 typedValue = QVariant(cookedValue.toLongLong(&convertOk));
523 clamp<int64_t>(typedValue);
529 typedValue = QVariant(cookedValue.toUInt(&convertOk));
531 clamp<uint32_t>(typedValue);
535 typedValue = QVariant(cookedValue.toULongLong(&convertOk));
537 clamp<uint64_t>(typedValue);
541 typedValue = QVariant(cookedValue.toFloat(&convertOk));
543 clamp<float>(typedValue);
548 typedValue = QVariant(cookedValue.toDouble(&convertOk));
550 clamp<double>(typedValue);
555 typedValue = QVariant(cookedValue.toString());
559 typedValue = QVariant(cookedValue.toBool());
563 typedValue = QVariant(cookedValue.toByteArray());
572 if (strings.count() != values.count()) {
573 qWarning(FactMetaDataLog) <<
"Count mismatch strings:values" << strings.count() << values.count();
577 _bitmaskStrings = strings;
578 _bitmaskValues = values;
584 _bitmaskStrings <<
name;
585 _bitmaskValues << value;
590 if (strings.count() != values.count()) {
591 qWarning(FactMetaDataLog) <<
"Count mismatch strings:values" << strings.count() << values.count();
595 _enumStrings = strings;
596 _enumValues = values;
602 _enumStrings <<
name;
603 _enumValues << value;
608 const int index = _enumValues.indexOf(value);
610 qWarning(FactMetaDataLog) <<
"Value does not exist in fact:" << value;
614 _enumValues.removeAt(index);
615 _enumStrings.removeAt(index);
620 _rawTranslator = rawTranslator_;
621 _cookedTranslator = cookedTranslator_;
626 if (_enumStrings.count() || _bitmaskStrings.count()) {
629 _cookedUnits = _rawUnits;
632 for (
size_t i = 0; i < std::size(_rgBuiltInTranslations); i++) {
633 const BuiltInTranslation_s *pBuiltInTranslation = &_rgBuiltInTranslations[i];
635 if (pBuiltInTranslation->rawUnits.toLower() == _rawUnits.toLower()) {
636 _cookedUnits = pBuiltInTranslation->cookedUnits;
637 setTranslators(pBuiltInTranslation->rawTranslator, pBuiltInTranslation->cookedTranslator);
644 _setAppSettingsTranslators();
647QVariant FactMetaData::_degreesToRadians(
const QVariant °rees)
649 return QVariant(qDegreesToRadians(degrees.toDouble()));
652QVariant FactMetaData::_radiansToDegrees(
const QVariant &radians)
654 return QVariant(qRadiansToDegrees(radians.toDouble()));
657QVariant FactMetaData::_centiDegreesToDegrees(
const QVariant ¢iDegrees)
659 return QVariant(centiDegrees.toReal() / 100.0);
662QVariant FactMetaData::_degreesToCentiDegrees(
const QVariant °rees)
664 return QVariant(qRound(degrees.toReal() * 100.0));
667QVariant FactMetaData::_centiCelsiusToCelsius(
const QVariant ¢iCelsius)
669 return QVariant(centiCelsius.toReal() / 100.0);
672QVariant FactMetaData::_celsiusToCentiCelsius(
const QVariant &celsius)
674 return QVariant(qRound(celsius.toReal() * 100.0));
677QVariant FactMetaData::_userGimbalDegreesToMavlinkGimbalDegrees(
const QVariant &userGimbalDegrees)
681 return (userGimbalDegrees.toDouble() * -1.0);
684QVariant FactMetaData::_mavlinkGimbalDegreesToUserGimbalDegrees(
const QVariant& mavlinkGimbalDegrees)
688 return (mavlinkGimbalDegrees.toDouble() * -1.0);
691QVariant FactMetaData::_metersToFeet(
const QVariant &meters)
693 return QVariant((meters.toDouble() * 1.0) / constants.feetToMeters);
696QVariant FactMetaData::_feetToMeters(
const QVariant &feet)
698 return QVariant(feet.toDouble() * constants.feetToMeters);
701QVariant FactMetaData::_squareMetersToSquareKilometers(
const QVariant &squareMeters)
703 return QVariant(squareMeters.toDouble() * 0.000001);
706QVariant FactMetaData::_squareKilometersToSquareMeters(
const QVariant &squareKilometers)
708 return QVariant(squareKilometers.toDouble() * 1000000.0);
711QVariant FactMetaData::_squareMetersToHectares(
const QVariant &squareMeters)
713 return QVariant(squareMeters.toDouble() * 0.0001);
716QVariant FactMetaData::_hectaresToSquareMeters(
const QVariant &hectares)
718 return QVariant(hectares.toDouble() * 1000.0);
721QVariant FactMetaData::_squareMetersToSquareFeet(
const QVariant &squareMeters)
723 return QVariant(squareMeters.toDouble() * constants.squareMetersToSquareFeet);
726QVariant FactMetaData::_squareFeetToSquareMeters(
const QVariant &squareFeet)
728 return QVariant(squareFeet.toDouble() * constants.feetToSquareMeters);
731QVariant FactMetaData::_squareMetersToAcres(
const QVariant &squareMeters)
733 return QVariant(squareMeters.toDouble() * constants.squareMetersToAcres);
736QVariant FactMetaData::_acresToSquareMeters(
const QVariant &acres)
738 return QVariant(acres.toDouble() * constants.acresToSquareMeters);
741QVariant FactMetaData::_squareMetersToSquareMiles(
const QVariant &squareMeters)
743 return QVariant(squareMeters.toDouble() * constants.squareMetersToSquareMiles);
746QVariant FactMetaData::_squareMilesToSquareMeters(
const QVariant &squareMiles)
748 return QVariant(squareMiles.toDouble() * constants.squareMilesToSquareMeters);
751QVariant FactMetaData::_metersPerSecondToMilesPerHour(
const QVariant &metersPerSecond)
753 return QVariant(((metersPerSecond.toDouble() * 1.0) / constants.milesToMeters) * constants.secondsPerHour);
756QVariant FactMetaData::_milesPerHourToMetersPerSecond(
const QVariant &milesPerHour)
758 return QVariant((milesPerHour.toDouble() * constants.milesToMeters) / constants.secondsPerHour);
761QVariant FactMetaData::_metersPerSecondToKilometersPerHour(
const QVariant &metersPerSecond)
763 return QVariant((metersPerSecond.toDouble() / 1000.0) * constants.secondsPerHour);
766QVariant FactMetaData::_kilometersPerHourToMetersPerSecond(
const QVariant &kilometersPerHour)
768 return QVariant((kilometersPerHour.toDouble() * 1000.0) / constants.secondsPerHour);
771QVariant FactMetaData::_metersPerSecondToKnots(
const QVariant &metersPerSecond)
773 return QVariant((metersPerSecond.toDouble() * constants.secondsPerHour) / (1000.0 * constants.knotsToKPH));
776QVariant FactMetaData::_knotsToMetersPerSecond(
const QVariant& knots)
778 return QVariant(knots.toDouble() * (1000.0 * constants.knotsToKPH / constants.secondsPerHour));
781QVariant FactMetaData::_percentToNorm(
const QVariant &percent)
783 return QVariant(percent.toDouble() / 100.0);
786QVariant FactMetaData::_normToPercent(
const QVariant &normalized)
788 return QVariant(normalized.toDouble() * 100.0);
791QVariant FactMetaData::_centimetersToInches(
const QVariant ¢imeters)
793 return QVariant((centimeters.toDouble() * 1.0) / constants.inchesToCentimeters);
796QVariant FactMetaData::_inchesToCentimeters(
const QVariant &inches)
798 return QVariant(inches.toDouble() * constants.inchesToCentimeters);
801QVariant FactMetaData::_celsiusToFarenheit(
const QVariant &celsius)
803 return QVariant((celsius.toDouble() * (9.0 / 5.0)) + 32);
806QVariant FactMetaData::_farenheitToCelsius(
const QVariant &farenheit)
808 return QVariant((farenheit.toDouble() - 32) * (5.0 / 9.0));
811QVariant FactMetaData::_kilogramsToGrams(
const QVariant &kg)
813 return QVariant(kg.toDouble() * 1000);
816QVariant FactMetaData::_ouncesToGrams(
const QVariant &oz)
818 return QVariant(oz.toDouble() * constants.ouncesToGrams);
821QVariant FactMetaData::_poundsToGrams(
const QVariant &lbs)
823 return QVariant(lbs.toDouble() * constants.poundsToGrams);
826QVariant FactMetaData::_gramsToKilograms(
const QVariant &g)
828 return QVariant(g.toDouble() / 1000);
831QVariant FactMetaData::_gramsToOunces(
const QVariant &g)
833 return QVariant(g.toDouble() / constants.ouncesToGrams);
836QVariant FactMetaData::_gramsToPunds(
const QVariant &g)
838 return QVariant(g.toDouble() / constants.poundsToGrams);
853 for (
size_t i = 0; i < std::size(_rgKnownTypeStrings); i++) {
854 if (typeString.compare(_rgKnownTypeStrings[i], Qt::CaseInsensitive) == 0) {
855 return _rgKnownValueTypes[i];
866 for (
size_t i = 0; i < std::size(_rgKnownTypeStrings); i++) {
867 if (
type == _rgKnownValueTypes[i]) {
868 return _rgKnownTypeStrings[i];
872 return QStringLiteral(
"UnknownType%1").arg(
type);
895 qWarning(FactMetaDataLog) <<
"Unsupported fact value type" <<
type;
900void FactMetaData::_setAppSettingsTranslators()
904 for (
size_t i = 0; i < std::size(_rgAppSettingsTranslations); i++) {
905 const AppSettingsTranslation_s *pAppSettingsTranslation = &_rgAppSettingsTranslations[i];
907 if (_rawUnits.toLower() != pAppSettingsTranslation->rawUnits.toLower()) {
912 uint settingsUnits = 0;
914 switch (pAppSettingsTranslation->unitType) {
915 case UnitHorizontalDistance:
916 settingsUnits = settings->horizontalDistanceUnits()->rawValue().toUInt();
918 case UnitVerticalDistance:
919 settingsUnits = settings->verticalDistanceUnits()->rawValue().toUInt();
922 settingsUnits = settings->speedUnits()->rawValue().toUInt();
925 settingsUnits = settings->areaUnits()->rawValue().toUInt();
927 case UnitTemperature:
928 settingsUnits = settings->temperatureUnits()->rawValue().toUInt();
931 settingsUnits = settings->weightUnits()->rawValue().toUInt();
937 if (settingsUnits == pAppSettingsTranslation->unitOption) {
938 _cookedUnits = pAppSettingsTranslation->cookedUnits;
939 setTranslators(pAppSettingsTranslation->rawTranslator, pAppSettingsTranslation->cookedTranslator);
946const FactMetaData::AppSettingsTranslation_s* FactMetaData::_findAppSettingsUnitsTranslation(
const QString &rawUnits, UnitTypes type)
948 for (
size_t i = 0; i < std::size(_rgAppSettingsTranslations); i++) {
949 const AppSettingsTranslation_s *
const pAppSettingsTranslation = &_rgAppSettingsTranslations[i];
951 if (
rawUnits.toLower() != pAppSettingsTranslation->rawUnits.toLower()) {
958 case UnitHorizontalDistance:
959 unitOption = unitsSettings->horizontalDistanceUnits()->rawValue().toUInt();
961 case UnitVerticalDistance:
962 unitOption = unitsSettings->verticalDistanceUnits()->rawValue().toUInt();
965 unitOption = unitsSettings->areaUnits()->rawValue().toUInt();
968 unitOption = unitsSettings->speedUnits()->rawValue().toUInt();
970 case UnitTemperature:
971 unitOption = unitsSettings->temperatureUnits()->rawValue().toUInt();
974 unitOption = unitsSettings->weightUnits()->rawValue().toUInt();
978 if ((pAppSettingsTranslation->unitType ==
type) && (pAppSettingsTranslation->unitOption == unitOption)) {
979 return pAppSettingsTranslation;
988 const AppSettingsTranslation_s *
const pAppSettingsTranslation = _findAppSettingsUnitsTranslation(
"m", UnitHorizontalDistance);
989 if (pAppSettingsTranslation) {
990 return pAppSettingsTranslation->rawTranslator(meters);
998 const AppSettingsTranslation_s *
const pAppSettingsTranslation = _findAppSettingsUnitsTranslation(
"vertical m", UnitVerticalDistance);
999 if (pAppSettingsTranslation) {
1000 return pAppSettingsTranslation->rawTranslator(meters);
1008 const AppSettingsTranslation_s *
const pAppSettingsTranslation = _findAppSettingsUnitsTranslation(
"m", UnitHorizontalDistance);
1009 if (pAppSettingsTranslation) {
1010 return pAppSettingsTranslation->cookedTranslator(distance);
1018 const AppSettingsTranslation_s *
const pAppSettingsTranslation = _findAppSettingsUnitsTranslation(
"vertical m", UnitVerticalDistance);
1019 if (pAppSettingsTranslation) {
1020 return pAppSettingsTranslation->cookedTranslator(distance);
1028 const AppSettingsTranslation_s *
const pAppSettingsTranslation = _findAppSettingsUnitsTranslation(
"m", UnitHorizontalDistance);
1029 if (pAppSettingsTranslation) {
1030 return pAppSettingsTranslation->cookedUnits;
1032 return QStringLiteral(
"m");
1038 const AppSettingsTranslation_s *
const pAppSettingsTranslation = _findAppSettingsUnitsTranslation(
"vertical m", UnitVerticalDistance);
1039 if (pAppSettingsTranslation) {
1040 return pAppSettingsTranslation->cookedUnits;
1042 return QStringLiteral(
"m");
1048 const AppSettingsTranslation_s *
const pAppSettingsTranslation = _findAppSettingsUnitsTranslation(
"g", UnitWeight);
1049 if (pAppSettingsTranslation) {
1050 return pAppSettingsTranslation->cookedUnits;
1052 return QStringLiteral(
"g");
1058 const AppSettingsTranslation_s *
const pAppSettingsTranslation = _findAppSettingsUnitsTranslation(
"m^2", UnitArea);
1059 if (pAppSettingsTranslation) {
1060 return pAppSettingsTranslation->rawTranslator(squareMeters);
1062 return squareMeters;
1068 const AppSettingsTranslation_s *
const pAppSettingsTranslation = _findAppSettingsUnitsTranslation(
"m^2", UnitArea);
1069 if (pAppSettingsTranslation) {
1070 return pAppSettingsTranslation->cookedTranslator(area);
1078 const AppSettingsTranslation_s *
const pAppSettingsTranslation = _findAppSettingsUnitsTranslation(
"m^2", UnitArea);
1079 if (pAppSettingsTranslation) {
1080 return pAppSettingsTranslation->cookedUnits;
1082 return QStringLiteral(
"m^2");
1087 const AppSettingsTranslation_s *
const pAppSettingsTranslation = _findAppSettingsUnitsTranslation(
"g", UnitWeight);
1088 if (pAppSettingsTranslation) {
1089 return pAppSettingsTranslation->rawTranslator(grams);
1096 const AppSettingsTranslation_s *
const pAppSettingsTranslation = _findAppSettingsUnitsTranslation(
"g", UnitWeight);
1097 if (pAppSettingsTranslation) {
1098 return pAppSettingsTranslation->cookedTranslator(weight);
1106 const AppSettingsTranslation_s *
const pAppSettingsTranslation = _findAppSettingsUnitsTranslation(
"m/s", UnitSpeed);
1107 if (pAppSettingsTranslation) {
1108 return pAppSettingsTranslation->rawTranslator(metersSecond);
1110 return metersSecond;
1116 const AppSettingsTranslation_s *
const pAppSettingsTranslation = _findAppSettingsUnitsTranslation(
"m/s", UnitSpeed);
1117 if (pAppSettingsTranslation) {
1118 return pAppSettingsTranslation->cookedTranslator(speed);
1126 const AppSettingsTranslation_s *
const pAppSettingsTranslation = _findAppSettingsUnitsTranslation(
"m/s", UnitSpeed);
1127 if (pAppSettingsTranslation) {
1128 return pAppSettingsTranslation->cookedUnits;
1130 return QStringLiteral(
"m/s");
1136 return _rawTranslator(this->
rawIncrement()).toDouble();
1145 double increment = _rawTranslator(this->
rawIncrement()).toDouble();
1146 if (!qIsNaN(increment)) {
1147 double integralPart;
1150 increment = fabs(modf(increment, &integralPart));
1151 if (increment == 0.0) {
1153 incrementDecimalPlaces = 0;
1155 incrementDecimalPlaces = -ceil(log10(increment));
1161 actualDecimalPlaces = incrementDecimalPlaces;
1165 const double ctest = _rawTranslator(1.0).toDouble();
1167 settingsDecimalPlaces += -log10(ctest);
1169 settingsDecimalPlaces = qMin(25, settingsDecimalPlaces);
1170 settingsDecimalPlaces = qMax(0, settingsDecimalPlaces);
1172 actualDecimalPlaces = settingsDecimalPlaces;
1175 actualDecimalPlaces = _decimalPlaces;
1178 return actualDecimalPlaces;
1185 static const QList<JsonParsing::KeyValidateInfo> keyInfoList = {
1186 { _nameJsonKey, QJsonValue::String,
true },
1187 { _labelJsonKey, QJsonValue::String,
false },
1188 { _typeJsonKey, QJsonValue::String,
true },
1189 { _shortDescriptionJsonKey, QJsonValue::String,
false },
1190 { _longDescriptionJsonKey, QJsonValue::String,
false },
1191 { _unitsJsonKey, QJsonValue::String,
false },
1192 { _decimalPlacesJsonKey, QJsonValue::Double,
false },
1193 { _minJsonKey, QJsonValue::Double,
false },
1194 { _maxJsonKey, QJsonValue::Double,
false },
1195 { _userMinJsonKey, QJsonValue::Double,
false },
1196 { _userMaxJsonKey, QJsonValue::Double,
false },
1197 { _hasControlJsonKey, QJsonValue::Bool,
false },
1198 { _qgcRebootRequiredJsonKey, QJsonValue::Bool,
false },
1199 { _rebootRequiredJsonKey, QJsonValue::Bool,
false },
1200 { _categoryJsonKey, QJsonValue::String,
false },
1201 { _groupJsonKey, QJsonValue::String,
false },
1202 { _volatileJsonKey, QJsonValue::Bool,
false },
1203 { _readOnlyJsonKey, QJsonValue::Bool,
false },
1204 { _enumBitmaskArrayJsonKey, QJsonValue::Array,
false },
1205 { _enumValuesArrayJsonKey, QJsonValue::Array,
false },
1206 { _enumValuesJsonKey, QJsonValue::String,
false },
1207 { _enumStringsJsonKey, QJsonValue::String,
false },
1218 qWarning(FactMetaDataLog) <<
"Unknown type" << json[_typeJsonKey].toString();
1224 metaData->_name = json[_nameJsonKey].toString();
1226 QStringList rgDescriptions;
1227 QList<double> rgDoubleValues;
1228 QList<int> rgIntValues;
1229 QStringList rgStringValues;
1231 bool foundBitmask =
false;
1232 if (!_parseValuesArray(json, rgDescriptions, rgDoubleValues,
errorString)) {
1233 qWarning(FactMetaDataLog) << QStringLiteral(
"FactMetaData::createFromJsonObject _parseValueDescriptionArray for '%1' failed. %2").arg(metaData->
name(),
errorString);
1235 if (rgDescriptions.isEmpty()) {
1236 if (!_parseBitmaskArray(json, rgDescriptions, rgIntValues,
errorString)) {
1237 qWarning(FactMetaDataLog) << QStringLiteral(
"FactMetaData::createFromJsonObject _parseBitmaskArray for '%1' failed. %2").arg(metaData->
name(),
errorString);
1239 foundBitmask = rgDescriptions.count() != 0;
1241 if (rgDescriptions.isEmpty()) {
1242 if (!_parseEnum(metaData->_name, json, defineMap, rgDescriptions, rgStringValues,
errorString)) {
1243 qWarning(FactMetaDataLog) << QStringLiteral(
"FactMetaData::createFromJsonObject _parseEnum for '%1' failed. %2").arg(metaData->
name(),
errorString);
1247 if (
errorString.isEmpty() && !rgDescriptions.isEmpty()) {
1248 for (qsizetype i = 0; i < rgDescriptions.count(); i++) {
1250 metaData->
addBitmaskInfo(rgDescriptions[i], 1 << rgIntValues[i]);
1252 const QVariant rawValueVariant = !rgDoubleValues.isEmpty() ? QVariant(rgDoubleValues[i]) : QVariant(rgStringValues[i]);
1253 QVariant convertedValueVariant;
1254 QString enumErrorString;
1255 if (metaData->
convertAndValidateRaw(rawValueVariant,
false , convertedValueVariant, enumErrorString)) {
1256 metaData->
addEnumInfo(rgDescriptions[i], convertedValueVariant);
1258 qWarning(FactMetaDataLog) << QStringLiteral(
"FactMetaData::createFromJsonObject convertAndValidateRaw on enum value for %1 failed.").arg(metaData->
name())
1259 <<
"type:" << metaData->
type()
1260 <<
"value:" << rawValueVariant
1261 <<
"error:" << enumErrorString;
1269 metaData->
setLabel(json[_labelJsonKey].toString());
1272 if (json.contains(_unitsJsonKey)) {
1273 metaData->
setRawUnits(json[_unitsJsonKey].toString());
1276 QString defaultValueJsonKey = _defaultValueJsonKey;
1277#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
1278 if (json.contains(_mobileDefaultValueJsonKey)) {
1279 defaultValueJsonKey = _mobileDefaultValueJsonKey;
1283 if (json.contains(defaultValueJsonKey)) {
1284 const QJsonValue jsonValue = json[defaultValueJsonKey];
1289 QVariant typedValue;
1290 QString defaultValueErrorString;
1291 const QVariant initialValue = jsonValue.toVariant();
1296 qWarning(FactMetaDataLog) <<
"Invalid default value,"
1297 <<
"name:" << metaData->
name()
1298 <<
"type:" << metaData->
type()
1299 <<
"value:" << initialValue
1300 <<
"error:" << defaultValueErrorString;
1305 if (json.contains(_incrementJsonKey)) {
1306 QVariant typedValue;
1307 QString incrementErrorString;
1308 const QVariant initialValue = json[_incrementJsonKey].toVariant();
1312 qWarning(FactMetaDataLog) <<
"Invalid increment value,"
1313 <<
"name:" << metaData->
name()
1314 <<
"type:" << metaData->
type()
1315 <<
"value:" << initialValue
1316 <<
"error:" << incrementErrorString;
1320 if (json.contains(_minJsonKey)) {
1321 QVariant typedValue;
1322 QString minErrorString;
1323 const QVariant initialValue = json[_minJsonKey].toVariant();
1327 qWarning(FactMetaDataLog) <<
"Invalid min value,"
1328 <<
"name:" << metaData->
name()
1329 <<
"type:" << metaData->
type()
1330 <<
"value:" << initialValue
1331 <<
"error:" << minErrorString;
1335 if (json.contains(_maxJsonKey)) {
1336 QVariant typedValue;
1337 QString maxErrorString;
1338 const QVariant initialValue = json[_maxJsonKey].toVariant();
1342 qWarning(FactMetaDataLog) <<
"Invalid max value,"
1343 <<
"name:" << metaData->
name()
1344 <<
"type:" << metaData->
type()
1345 <<
"value:" << initialValue
1346 <<
"error:" << maxErrorString;
1352 if (json.contains(_userMinJsonKey)) {
1353 QVariant typedValue;
1354 QString userMinErrorString;
1355 const QVariant initialValue = json[_userMinJsonKey].toVariant();
1359 qWarning(FactMetaDataLog) <<
"Invalid userMin value,"
1360 <<
"name:" << metaData->
name()
1361 <<
"type:" << metaData->
type()
1362 <<
"value:" << initialValue
1363 <<
"error:" << userMinErrorString;
1367 if (json.contains(_userMaxJsonKey)) {
1368 QVariant typedValue;
1369 QString userMaxErrorString;
1370 const QVariant initialValue = json[_userMaxJsonKey].toVariant();
1374 qWarning(FactMetaDataLog) <<
"Invalid userMax value,"
1375 <<
"name:" << metaData->
name()
1376 <<
"type:" << metaData->
type()
1377 <<
"value:" << initialValue
1378 <<
"error:" << userMaxErrorString;
1382 bool hasControlJsonKey =
true;
1383 if (json.contains(_hasControlJsonKey)) {
1384 hasControlJsonKey = json[_hasControlJsonKey].toBool();
1389 if (json.contains(_qgcRebootRequiredJsonKey)) {
1394 bool rebootRequired =
false;
1395 if (json.contains(_rebootRequiredJsonKey)) {
1396 rebootRequired = json[_rebootRequiredJsonKey].toBool();
1401 if (json.contains(_readOnlyJsonKey)) {
1402 readOnly = json[_readOnlyJsonKey].toBool();
1407 if (json.contains(_volatileJsonKey)) {
1411 if (json.contains(_groupJsonKey)) {
1412 metaData->
setGroup(json[_groupJsonKey].toString());
1415 if (json.contains(_categoryJsonKey)) {
1416 metaData->
setCategory(json[_categoryJsonKey].toString());
1422void FactMetaData::_loadJsonDefines(
const QJsonObject &jsonDefinesObject, QMap<QString, QString> &defineMap)
1424 for (
const QString &defineName: jsonDefinesObject.keys()) {
1425 const QString mapKey = _jsonMetaDataDefinesName + QStringLiteral(
".") + defineName;
1426 defineMap[mapKey] = jsonDefinesObject[defineName].toString();
1432 QMap<QString, FactMetaData*> metaDataMap;
1438 QStringList{
"label",
"shortDesc",
"longDesc",
"enumStrings"},
1439 QStringList{
"name"});
1441 qWarning(FactMetaDataLog) <<
"Internal Error:" <<
errorString;
1445 static const QList<JsonParsing::KeyValidateInfo> keyInfoList = {
1446 { FactMetaData::_jsonMetaDataDefinesName, QJsonValue::Object,
false },
1447 { FactMetaData::_jsonMetaDataFactsName, QJsonValue::Array,
true },
1450 qWarning(FactMetaDataLog) <<
"Json document incorrect format:" <<
errorString;
1454 QMap<QString , QString > defineMap;
1455 _loadJsonDefines(jsonObject[FactMetaData::_jsonMetaDataDefinesName].toObject(), defineMap);
1456 const QJsonArray factArray = jsonObject[FactMetaData::_jsonMetaDataFactsName].toArray();
1463 QMap<QString, FactMetaData*> metaDataMap;
1464 for (
const QJsonValue &jsonValue : jsonArray) {
1465 if (!jsonValue.isObject()) {
1466 qWarning(FactMetaDataLog) <<
"JsonValue is not an object";
1470 const QJsonObject jsonObject = jsonValue.toObject();
1472 if (metaDataMap.contains(metaData->
name())) {
1473 qWarning(FactMetaDataLog) <<
"Duplicate fact name:" << metaData->
name();
1476 metaDataMap[metaData->
name()] = metaData;
1486 return qMax(_rawTranslator(_rawMax).toDouble(), _rawTranslator(_rawMin).toDouble());
1492 return qMin(_rawTranslator(_rawMax).toDouble(), _rawTranslator(_rawMin).toDouble());
1502 const QRegularExpression splitRegex(
"[,,、]");
1503 QStringList valueList = translatedList.split(splitRegex, Qt::SkipEmptyParts);
1504 for (QString &value: valueList) {
1505 value = value.trimmed();
1510bool FactMetaData::_parseEnum(
const QString& name,
const QJsonObject &jsonObject,
const DefineMap_t &defineMap, QStringList &rgDescriptions, QStringList &rgValues, QString &
errorString)
1512 rgDescriptions.clear();
1516 if (!jsonObject.contains(_enumStringsJsonKey)) {
1520 const QString jsonStrings = jsonObject.value(_enumStringsJsonKey).toString();
1521 const QString defineMapStrings = defineMap.value(jsonStrings, jsonStrings);
1524 const QString jsonValues = jsonObject.value(_enumValuesJsonKey).toString();
1525 const QString defineMapValues = defineMap.value(jsonValues, jsonValues);
1528 if (rgDescriptions.count() != rgValues.count()) {
1529 errorString = QStringLiteral(
"Enum strings/values count mismatch - name: '%1' strings: '%2'[%3] values: '%4'[%5]").arg(
name).arg(defineMapStrings).arg(rgDescriptions.count()).arg(defineMapValues).arg(rgValues.count());
1536bool FactMetaData::_parseValuesArray(
const QJsonObject &jsonObject, QStringList &rgDescriptions, QList<double> &rgValues, QString &
errorString)
1538 rgDescriptions.clear();
1542 if (!jsonObject.contains(_enumValuesArrayJsonKey)) {
1546 static const QList<JsonParsing::KeyValidateInfo> keyInfoList = {
1547 { _enumValuesArrayDescriptionJsonKey, QJsonValue::String,
true },
1548 { _enumValuesArrayValueJsonKey, QJsonValue::Double,
true },
1551 const QJsonArray &rgValueDescription = jsonObject[_enumValuesArrayJsonKey].toArray();
1552 for (
const QJsonValue& jsonValue : rgValueDescription) {
1553 if (jsonValue.type() != QJsonValue::Object) {
1554 errorString = QStringLiteral(
"Value in \"values\" array is not an object.");
1558 const QJsonObject &valueDescriptionObject = jsonValue.toObject();
1564 rgDescriptions.append(valueDescriptionObject[_enumValuesArrayDescriptionJsonKey].toString());
1565 rgValues.append(valueDescriptionObject[_enumValuesArrayValueJsonKey].toDouble());
1571bool FactMetaData::_parseBitmaskArray(
const QJsonObject &jsonObject, QStringList &rgDescriptions, QList<int> &rgValues, QString &
errorString)
1573 rgDescriptions.clear();
1577 if (!jsonObject.contains(_enumBitmaskArrayJsonKey)) {
1581 static const QList<JsonParsing::KeyValidateInfo> keyInfoList = {
1582 { _enumBitmaskArrayDescriptionJsonKey, QJsonValue::String,
true },
1583 { _enumBitmaskArrayIndexJsonKey, QJsonValue::Double,
true },
1586 const QJsonArray &rgValueDescription = jsonObject[_enumBitmaskArrayJsonKey].toArray();
1587 for (
const QJsonValue &jsonValue : rgValueDescription) {
1588 if (jsonValue.type() != QJsonValue::Object) {
1589 errorString = QStringLiteral(
"Value in \"values\" array is not an object.");
1593 const QJsonObject &valueDescriptionObject = jsonValue.toObject();
1599 rgDescriptions.append(valueDescriptionObject[_enumBitmaskArrayDescriptionJsonKey].toString());
1600 rgValues.append(valueDescriptionObject[_enumBitmaskArrayIndexJsonKey].toInt());
1608 if (!_rawUserMin.isValid()) {
1612 return _rawTranslator(_rawUserMin);
1617 if (!_rawUserMax.isValid()) {
1621 return _rawTranslator(_rawUserMax);
#define QGC_LOGGING_CATEGORY(name, categoryStr)
#define MAVLINK_MSG_PARAM_EXT_SET_FIELD_PARAM_VALUE_LEN
UnitsSettings * unitsSettings() const
static SettingsManager * instance()
@ TemperatureUnitsCelsius
@ TemperatureUnitsFarenheit
@ VerticalDistanceUnitsFeet
@ VerticalDistanceUnitsMeters
@ SpeedUnitsKilometersPerHour
@ SpeedUnitsFeetPerSecond
@ SpeedUnitsMetersPerSecond
@ AreaUnitsSquareKilometers
@ HorizontalDistanceUnitsFeet
@ HorizontalDistanceUnitsMeters
bool validateKeys(const QJsonObject &jsonObject, const QList< KeyValidateInfo > &keyInfo, QString &errorString)
Validates that all required keys are present and that listed keys have the expected type.
QJsonObject openInternalQGCJsonFile(const QString &jsonFilename, const QString &expectedFileType, int minSupportedVersion, int maxSupportedVersion, int &version, QString &errorString, const QStringList &defaultTranslateKeys, const QStringList &defaultArrayIDKeys)