FactMetaData.h 18.8 KB
Newer Older
1 2
/****************************************************************************
 *
3
 * (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
4 5 6 7 8 9
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

10
#pragma once
Don Gagne's avatar
Don Gagne committed
11 12 13 14

#include <QObject>
#include <QString>
#include <QVariant>
15
#include <QJsonObject>
16

Don Gagne's avatar
Don Gagne committed
17 18
/// Holds the meta data associated with a Fact.
///
Ricardo de Almeida Gonzaga's avatar
Ricardo de Almeida Gonzaga committed
19
/// Holds the meta data associated with a Fact. This is kept in a separate object from the Fact itself
Don Gagne's avatar
Don Gagne committed
20 21 22 23 24
/// since you may have multiple instances of the same Fact. But there is only ever one FactMetaData
/// instance or each Fact.
class FactMetaData : public QObject
{
    Q_OBJECT
25

Don Gagne's avatar
Don Gagne committed
26 27 28 29 30 31 32 33
public:
    typedef enum {
        valueTypeUint8,
        valueTypeInt8,
        valueTypeUint16,
        valueTypeInt16,
        valueTypeUint32,
        valueTypeInt32,
34 35
        valueTypeUint64,
        valueTypeInt64,
Don Gagne's avatar
Don Gagne committed
36
        valueTypeFloat,
Don Gagne's avatar
Don Gagne committed
37
        valueTypeDouble,
38
        valueTypeString,
39 40
        valueTypeBool,
        valueTypeElapsedTimeInSeconds,  // Internally stored as double, valueString displays as HH:MM:SS
41
        valueTypeCustom,                // Internally stored as a QByteArray
Don Gagne's avatar
Don Gagne committed
42
    } ValueType_t;
43 44

    typedef QVariant (*Translator)(const QVariant& from);
45

46 47 48 49 50 51
    // Custom function to validate a cooked value.
    //  @return Error string for failed validation explanation to user. Empty string indicates no error.
    typedef QString (*CustomCookedValidator)(const QVariant& cookedValue);

    typedef QMap<QString /* param Name */, FactMetaData*> NameToMetaDataMap_t;

Gus Grubba's avatar
Gus Grubba committed
52 53 54 55
    FactMetaData(QObject* parent = nullptr);
    FactMetaData(ValueType_t type, QObject* parent = nullptr);
    FactMetaData(ValueType_t type, const QString name, QObject* parent = nullptr);
    FactMetaData(const FactMetaData& other, QObject* parent = nullptr);
Don Gagne's avatar
Don Gagne committed
56

57 58
    typedef QMap<QString, QString> DefineMap_t;

59
    static QMap<QString, FactMetaData*> createMapFromJsonFile(const QString& jsonFilename, QObject* metaDataParent);
60
    static QMap<QString, FactMetaData*> createMapFromJsonArray(const QJsonArray jsonArray, DefineMap_t& defineMap, QObject* metaDataParent);
61

62
    static FactMetaData* createFromJsonObject(const QJsonObject& json, QMap<QString, QString>& defineMap, QObject* metaDataParent);
63

Don Gagne's avatar
Don Gagne committed
64
    const FactMetaData& operator=(const FactMetaData& other);
65

66 67
    /// Converts from meters to the user specified horizontal distance unit
    static QVariant metersToAppSettingsHorizontalDistanceUnits(const QVariant& meters);
68

69 70
    /// Converts from user specified horizontal distance unit to meters
    static QVariant appSettingsHorizontalDistanceUnitsToMeters(const QVariant& distance);
71

72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
    /// Returns the string for horizontal distance units which has configued by user
    static QString appSettingsHorizontalDistanceUnitsString(void);

    /// Converts from meters to the user specified vertical distance unit
    static QVariant metersToAppSettingsVerticalDistanceUnits(const QVariant& meters);

    /// Converts from user specified vertical distance unit to meters
    static QVariant appSettingsVerticalDistanceUnitsToMeters(const QVariant& distance);

    /// Returns the string for vertical distance units which has configued by user
    static QString appSettingsVerticalDistanceUnitsString(void);

    /// Converts from grams to the user specified weight unit
    static QVariant gramsToAppSettingsWeightUnits(const QVariant& grams);

    /// Converts from user specified weight unit to grams
    static QVariant appSettingsWeightUnitsToGrams(const QVariant& weight);

    /// Returns the string for weight units which has configued by user
    static QString appSettingsWeightUnitsString(void);
92

93 94 95 96 97 98 99 100 101
    /// Converts from meters to the user specified distance unit
    static QVariant squareMetersToAppSettingsAreaUnits(const QVariant& squareMeters);

    /// Converts from user specified distance unit to meters
    static QVariant appSettingsAreaUnitsToSquareMeters(const QVariant& area);

    /// Returns the string for distance units which has configued by user
    static QString appSettingsAreaUnitsString(void);

102 103 104
    /// Returns the string for speed units which has configued by user
    static QString appSettingsSpeedUnitsString();

105 106 107
    static const QString defaultCategory    ();
    static const QString defaultGroup       ();

108
    int             decimalPlaces           (void) const;
109 110
    QVariant        rawDefaultValue         (void) const;
    QVariant        cookedDefaultValue      (void) const { return _rawTranslator(rawDefaultValue()); }
111
    bool            defaultValueAvailable   (void) const { return _defaultValueAvailable; }
112 113
    QStringList     bitmaskStrings          (void) const { return _bitmaskStrings; }
    QVariantList    bitmaskValues           (void) const { return _bitmaskValues; }
114 115
    QStringList     enumStrings             (void) const { return _enumStrings; }
    QVariantList    enumValues              (void) const { return _enumValues; }
116
    QString         category                (void) const { return _category; }
117 118
    QString         group                   (void) const { return _group; }
    QString         longDescription         (void) const { return _longDescription;}
119
    QVariant        rawMax                  (void) const { return _rawMax; }
120
    QVariant        cookedMax               (void) const;
121
    bool            maxIsDefaultForType     (void) const { return _maxIsDefaultForType; }
122
    QVariant        rawMin                  (void) const { return _rawMin; }
123
    QVariant        cookedMin               (void) const;
124 125 126 127
    bool            minIsDefaultForType     (void) const { return _minIsDefaultForType; }
    QString         name                    (void) const { return _name; }
    QString         shortDescription        (void) const { return _shortDescription; }
    ValueType_t     type                    (void) const { return _type; }
128 129
    QString         rawUnits                (void) const { return _rawUnits; }
    QString         cookedUnits             (void) const { return _cookedUnits; }
130 131
    bool            vehicleRebootRequired   (void) const { return _vehicleRebootRequired; }
    bool            qgcRebootRequired       (void) const { return _qgcRebootRequired; }
132
    bool            hasControl              (void) const { return _hasControl; }
133
    bool            readOnly                (void) const { return _readOnly; }
134
    bool            writeOnly               (void) const { return _writeOnly; }
135
    bool            volatileValue           (void) const { return _volatile; }
136

Don Gagne's avatar
Don Gagne committed
137 138
    /// Amount to increment value when used in controls such as spin button or slider with detents.
    /// NaN for no increment available.
139
    double          rawIncrement            (void) const { return _rawIncrement; }
140
    double          cookedIncrement         (void) const;
Don Gagne's avatar
Don Gagne committed
141

142 143
    Translator      rawTranslator           (void) const { return _rawTranslator; }
    Translator      cookedTranslator        (void) const { return _cookedTranslator; }
144

145 146 147
    /// Used to add new values to the bitmask lists after the meta data has been loaded
    void addBitmaskInfo(const QString& name, const QVariant& value);

148 149 150
    /// Used to add new values to the enum lists after the meta data has been loaded
    void addEnumInfo(const QString& name, const QVariant& value);

151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
    void setDecimalPlaces           (int decimalPlaces)                 { _decimalPlaces = decimalPlaces; }
    void setRawDefaultValue         (const QVariant& rawDefaultValue);
    void setBitmaskInfo             (const QStringList& strings, const QVariantList& values);
    void setEnumInfo                (const QStringList& strings, const QVariantList& values);
    void setCategory                (const QString& category)           { _category = category; }
    void setGroup                   (const QString& group)              { _group = group; }
    void setLongDescription         (const QString& longDescription)    { _longDescription = longDescription;}
    void setRawMax                  (const QVariant& rawMax);
    void setRawMin                  (const QVariant& rawMin);
    void setName                    (const QString& name)               { _name = name; }
    void setShortDescription        (const QString& shortDescription)   { _shortDescription = shortDescription; }
    void setRawUnits                (const QString& rawUnits);
    void setVehicleRebootRequired   (bool rebootRequired)               { _vehicleRebootRequired = rebootRequired; }
    void setQGCRebootRequired       (bool rebootRequired)               { _qgcRebootRequired = rebootRequired; }
    void setRawIncrement            (double increment)                  { _rawIncrement = increment; }
    void setHasControl              (bool bValue)                       { _hasControl = bValue; }
    void setReadOnly                (bool bValue)                       { _readOnly = bValue; }
    void setWriteOnly               (bool bValue)                       { _writeOnly = bValue; }
    void setVolatileValue           (bool bValue);
170 171 172

    void setTranslators(Translator rawTranslator, Translator cookedTranslator);

173 174 175
    /// Set the translators to the standard built in versions
    void setBuiltInTranslator(void);

176
    /// Converts the specified raw value, validating against meta data
177 178 179 180
    ///     @param rawValue: Value to convert, can be string
    ///     @param convertOnly: true: convert to correct type only, do not validate against meta data
    ///     @param typeValue: Converted value, correctly typed
    ///     @param errorString: Error string if convert fails, values are cooked values since user visible
Don Gagne's avatar
Don Gagne committed
181
    /// @returns false: Convert failed, errorString set
182 183 184 185
    bool convertAndValidateRaw(const QVariant& rawValue, bool convertOnly, QVariant& typedValue, QString& errorString);

    /// Same as convertAndValidateRaw except for cookedValue input
    bool convertAndValidateCooked(const QVariant& cookedValue, bool convertOnly, QVariant& typedValue, QString& errorString);
Don Gagne's avatar
Don Gagne committed
186

187
    /// Converts the specified cooked value and clamps it (max/min)
188 189
    ///     @param cookedValue: Value to convert, can be string
    ///     @param typeValue: Converted value, correctly typed and clamped
190 191 192
    /// @returns false: Convertion failed
    bool clampValue(const QVariant& cookedValue, QVariant& typedValue);

193 194 195 196 197 198 199 200
    /// Sets a custom cooked validator function for this metadata. The custom validator will be called
    /// prior to the standard validator when convertAndValidateCooked is called.
    void setCustomCookedValidator(CustomCookedValidator customValidator) { _customCookedValidator = customValidator; }

    static const int kDefaultDecimalPlaces = 3;  ///< Default value for decimal places if not specified/known
    static const int kUnknownDecimalPlaces = -1; ///< Number of decimal places to specify is not known
    static const char* kDefaultCategory;
    static const char* kDefaultGroup;
201

Don Gagne's avatar
Don Gagne committed
202
    static ValueType_t stringToType(const QString& typeString, bool& unknownType);
203
    static QString typeToString(ValueType_t type);
204
    static size_t typeToSize(ValueType_t type);
Don Gagne's avatar
Don Gagne committed
205

206 207
    static const char* qgcFileType;

208
private:
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
    QVariant _minForType                (void) const;
    QVariant _maxForType                (void) const;
    void    _setAppSettingsTranslators  (void);

    /// Clamp a value to be within cookedMin and cookedMax
    template<class T>
    void clamp(QVariant& variantValue) const {
        if (cookedMin().value<T>() > variantValue.value<T>()) {
            variantValue = cookedMin();
        } else if(variantValue.value<T>() > cookedMax().value<T>()) {
            variantValue = cookedMax();
        }
    }

    template<class T>
    bool isInCookedLimit(const QVariant& variantValue) const {
        return cookedMin().value<T>() <= variantValue.value<T>() && variantValue.value<T>() <= cookedMax().value<T>();
    }

    template<class T>
    bool isInRawLimit(const QVariant& variantValue) const {
        return rawMin().value<T>() <= variantValue.value<T>() && variantValue.value<T>() <= rawMax().value<T>();
    }

    bool isInRawMinLimit(const QVariant& variantValue) const;
    bool isInRawMaxLimit(const QVariant& variantValue) const;

    static bool _parseEnum          (const QJsonObject& jsonObject, DefineMap_t defineMap, QStringList& rgDescriptions, QStringList& rgValues, QString& errorString);
    static bool _parseValuesArray   (const QJsonObject& jsonObject, QStringList& rgDescriptions, QList<double>& rgValues, QString& errorString);
    static bool _parseBitmaskArray  (const QJsonObject& jsonObject, QStringList& rgDescriptions, QList<double>& rgValues, QString& errorString);
239 240 241 242 243 244 245

    // Built in translators
    static QVariant _defaultTranslator(const QVariant& from) { return from; }
    static QVariant _degreesToRadians(const QVariant& degrees);
    static QVariant _radiansToDegrees(const QVariant& radians);
    static QVariant _centiDegreesToDegrees(const QVariant& centiDegrees);
    static QVariant _degreesToCentiDegrees(const QVariant& degrees);
246 247
    static QVariant _userGimbalDegreesToMavlinkGimbalDegrees(const QVariant& userGimbalDegrees);
    static QVariant _mavlinkGimbalDegreesToUserGimbalDegrees(const QVariant& mavlinkGimbalDegrees);
248 249
    static QVariant _metersToFeet(const QVariant& meters);
    static QVariant _feetToMeters(const QVariant& feet);
250 251 252 253 254 255 256 257 258 259
    static QVariant _squareMetersToSquareKilometers(const QVariant& squareMeters);
    static QVariant _squareKilometersToSquareMeters(const QVariant& squareKilometers);
    static QVariant _squareMetersToHectares(const QVariant& squareMeters);
    static QVariant _hectaresToSquareMeters(const QVariant& hectares);
    static QVariant _squareMetersToSquareFeet(const QVariant& squareMeters);
    static QVariant _squareFeetToSquareMeters(const QVariant& squareFeet);
    static QVariant _squareMetersToAcres(const QVariant& squareMeters);
    static QVariant _acresToSquareMeters(const QVariant& acres);
    static QVariant _squareMetersToSquareMiles(const QVariant& squareMeters);
    static QVariant _squareMilesToSquareMeters(const QVariant& squareMiles);
260 261 262 263 264 265
    static QVariant _metersPerSecondToMilesPerHour(const QVariant& metersPerSecond);
    static QVariant _milesPerHourToMetersPerSecond(const QVariant& milesPerHour);
    static QVariant _metersPerSecondToKilometersPerHour(const QVariant& metersPerSecond);
    static QVariant _kilometersPerHourToMetersPerSecond(const QVariant& kilometersPerHour);
    static QVariant _metersPerSecondToKnots(const QVariant& metersPerSecond);
    static QVariant _knotsToMetersPerSecond(const QVariant& knots);
266 267
    static QVariant _percentToNorm(const QVariant& percent);
    static QVariant _normToPercent(const QVariant& normalized);
268 269
    static QVariant _centimetersToInches(const QVariant& centimeters);
    static QVariant _inchesToCentimeters(const QVariant& inches);
270 271
    static QVariant _celsiusToFarenheit(const QVariant& celsius);
    static QVariant _farenheitToCelsius(const QVariant& farenheit);
272 273 274 275 276 277 278
    static QVariant _kilogramsToGrams(const QVariant& kg);
    static QVariant _ouncesToGrams(const QVariant& oz);
    static QVariant _poundsToGrams(const QVariant& lbs);
    static QVariant _gramsToKilograms(const QVariant& g);
    static QVariant _gramsToOunces(const QVariant& g);
    static QVariant _gramsToPunds(const QVariant& g);

279

Gus Grubba's avatar
Gus Grubba committed
280
    enum UnitTypes {
281 282
        UnitHorizontalDistance = 0,
        UnitVerticalDistance,
Gus Grubba's avatar
Gus Grubba committed
283 284
        UnitArea,
        UnitSpeed,
285 286
        UnitTemperature,
        UnitWeight
Gus Grubba's avatar
Gus Grubba committed
287
    };
288

Gus Grubba's avatar
Gus Grubba committed
289
    struct AppSettingsTranslation_s {
290 291 292 293 294 295
        QString       rawUnits;
        const char*   cookedUnits;
        UnitTypes     unitType;
        uint32_t      unitOption;
        Translator    rawTranslator;
        Translator    cookedTranslator;
296 297
    };

298
    static const AppSettingsTranslation_s* _findAppSettingsUnitsTranslation(const QString& rawUnits, UnitTypes type);
299

300 301
    static void _loadJsonDefines(const QJsonObject& jsonDefinesObject, QMap<QString, QString>& defineMap);

302 303
    ValueType_t     _type;                  // must be first for correct constructor init
    int             _decimalPlaces;
304
    QVariant        _rawDefaultValue;
305
    bool            _defaultValueAvailable;
306 307
    QStringList     _bitmaskStrings;
    QVariantList    _bitmaskValues;
308 309
    QStringList     _enumStrings;
    QVariantList    _enumValues;
310
    QString         _category;
311 312
    QString         _group;
    QString         _longDescription;
313
    QVariant        _rawMax;
314
    bool            _maxIsDefaultForType;
315
    QVariant        _rawMin;
316 317 318
    bool            _minIsDefaultForType;
    QString         _name;
    QString         _shortDescription;
319 320
    QString         _rawUnits;
    QString         _cookedUnits;
321 322
    Translator      _rawTranslator;
    Translator      _cookedTranslator;
323 324
    bool            _vehicleRebootRequired;
    bool            _qgcRebootRequired;
325
    double          _rawIncrement;
326
    bool            _hasControl;
327
    bool            _readOnly;
328
    bool            _writeOnly;
329
    bool            _volatile;
330
    CustomCookedValidator _customCookedValidator = nullptr;
331

332 333 334 335 336 337
    // Exact conversion constants
    static const struct UnitConsts_s {
        static const qreal secondsPerHour;
        static const qreal knotsToKPH;
        static const qreal milesToMeters;
        static const qreal feetToMeters;
338
        static const qreal inchesToCentimeters;
339 340
        static const qreal ouncesToGrams;
        static const qreal poundsToGrams;
341 342
    } constants;

343
    struct BuiltInTranslation_s {
344
        QString rawUnits;
345 346 347 348 349
        const char* cookedUnits;
        Translator  rawTranslator;
        Translator  cookedTranslator;

    };
350

351
    static const BuiltInTranslation_s _rgBuiltInTranslations[];
352

353
    static const AppSettingsTranslation_s _rgAppSettingsTranslations[];
354

355 356 357
    static const char*          _rgKnownTypeStrings[];
    static const ValueType_t    _rgKnownValueTypes[];

358 359 360 361 362 363 364 365 366 367 368
    static const char* _nameJsonKey;
    static const char* _decimalPlacesJsonKey;
    static const char* _typeJsonKey;
    static const char* _shortDescriptionJsonKey;
    static const char* _longDescriptionJsonKey;
    static const char* _unitsJsonKey;
    static const char* _defaultValueJsonKey;
    static const char* _mobileDefaultValueJsonKey;
    static const char* _minJsonKey;
    static const char* _maxJsonKey;
    static const char* _incrementJsonKey;
369
    static const char* _hasControlJsonKey;
370
    static const char* _qgcRebootRequiredJsonKey;
371 372 373 374 375 376 377 378 379 380 381
    static const char* _categoryJsonKey;
    static const char* _groupJsonKey;
    static const char* _volatileJsonKey;
    static const char* _enumStringsJsonKey;
    static const char* _enumValuesJsonKey;
    static const char* _enumValuesArrayJsonKey;
    static const char* _enumBitmaskArrayJsonKey;
    static const char* _enumValuesArrayValueJsonKey;
    static const char* _enumValuesArrayDescriptionJsonKey;
    static const char* _enumBitmaskArrayIndexJsonKey;
    static const char* _enumBitmaskArrayDescriptionJsonKey;
382 383 384

    static const char* _jsonMetaDataDefinesName;
    static const char* _jsonMetaDataFactsName;
Don Gagne's avatar
Don Gagne committed
385
};