FactMetaData.h 18.2 KB
Newer Older
1 2
/****************************************************************************
 *
Gus Grubba's avatar
Gus Grubba committed
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
    // 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);

Gus Grubba's avatar
Gus Grubba committed
50 51 52 53
    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
54

55
    static QMap<QString, FactMetaData*> createMapFromJsonFile(const QString& jsonFilename, QObject* metaDataParent);
56
    static QMap<QString, FactMetaData*> createMapFromJsonArray(const QJsonArray jsonArray, QMap<QString, QString>& defineMap, QObject* metaDataParent);
57

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

Don Gagne's avatar
Don Gagne committed
60
    const FactMetaData& operator=(const FactMetaData& other);
61

Remek Zajac's avatar
Remek Zajac committed
62 63
    /// Converts from meters to the user specified horizontal distance unit
    static QVariant metersToAppSettingsHorizontalDistanceUnits(const QVariant& meters);
64

Remek Zajac's avatar
Remek Zajac committed
65 66
    /// Converts from user specified horizontal distance unit to meters
    static QVariant appSettingsHorizontalDistanceUnitsToMeters(const QVariant& distance);
67

Remek Zajac's avatar
Remek Zajac committed
68 69
    /// Returns the string for horizontal distance units which has configued by user
    static QString appSettingsHorizontalDistanceUnitsString(void);
70

Remek Zajac's avatar
Remek Zajac committed
71 72
    /// Converts from meters to the user specified vertical distance unit
    static QVariant metersToAppSettingsVerticalDistanceUnits(const QVariant& meters);
73

Remek Zajac's avatar
Remek Zajac committed
74 75
    /// Converts from user specified vertical distance unit to meters
    static QVariant appSettingsVerticalDistanceUnitsToMeters(const QVariant& distance);
76

Remek Zajac's avatar
Remek Zajac committed
77 78
    /// Returns the string for vertical distance units which has configued by user
    static QString appSettingsVerticalDistanceUnitsString(void);
79 80

    /// Converts from grams to the user specified weight unit
Remek Zajac's avatar
Remek Zajac committed
81
    static QVariant gramsToAppSettingsWeightUnits(const QVariant& grams);
82 83

    /// Converts from user specified weight unit to grams
Remek Zajac's avatar
Remek Zajac committed
84
    static QVariant appSettingsWeightUnitsToGrams(const QVariant& weight);
85 86 87 88

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

89 90 91 92 93 94 95 96 97
    /// 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);

98 99 100
    static const QString defaultCategory    ();
    static const QString defaultGroup       ();

101
    int             decimalPlaces           (void) const;
102 103
    QVariant        rawDefaultValue         (void) const;
    QVariant        cookedDefaultValue      (void) const { return _rawTranslator(rawDefaultValue()); }
104
    bool            defaultValueAvailable   (void) const { return _defaultValueAvailable; }
105 106
    QStringList     bitmaskStrings          (void) const { return _bitmaskStrings; }
    QVariantList    bitmaskValues           (void) const { return _bitmaskValues; }
107 108
    QStringList     enumStrings             (void) const { return _enumStrings; }
    QVariantList    enumValues              (void) const { return _enumValues; }
109
    QString         category                (void) const { return _category; }
110 111
    QString         group                   (void) const { return _group; }
    QString         longDescription         (void) const { return _longDescription;}
112
    QVariant        rawMax                  (void) const { return _rawMax; }
113
    QVariant        cookedMax               (void) const;
114
    bool            maxIsDefaultForType     (void) const { return _maxIsDefaultForType; }
115
    QVariant        rawMin                  (void) const { return _rawMin; }
116
    QVariant        cookedMin               (void) const;
117 118 119 120
    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; }
121 122
    QString         rawUnits                (void) const { return _rawUnits; }
    QString         cookedUnits             (void) const { return _cookedUnits; }
123 124
    bool            vehicleRebootRequired   (void) const { return _vehicleRebootRequired; }
    bool            qgcRebootRequired       (void) const { return _qgcRebootRequired; }
125
    bool            hasControl              (void) const { return _hasControl; }
126
    bool            readOnly                (void) const { return _readOnly; }
127
    bool            writeOnly               (void) const { return _writeOnly; }
128
    bool            volatileValue           (void) const { return _volatile; }
129

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

135 136
    Translator      rawTranslator           (void) const { return _rawTranslator; }
    Translator      cookedTranslator        (void) const { return _cookedTranslator; }
137

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

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

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
    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);
163 164 165

    void setTranslators(Translator rawTranslator, Translator cookedTranslator);

166 167 168
    /// Set the translators to the standard built in versions
    void setBuiltInTranslator(void);

169
    /// Converts the specified raw value, validating against meta data
Gus Grubba's avatar
Gus Grubba committed
170 171 172 173
    ///     @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
174
    /// @returns false: Convert failed, errorString set
175 176 177 178
    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
179

180
    /// Converts the specified cooked value and clamps it (max/min)
Gus Grubba's avatar
Gus Grubba committed
181 182
    ///     @param cookedValue: Value to convert, can be string
    ///     @param typeValue: Converted value, correctly typed and clamped
183 184 185
    /// @returns false: Convertion failed
    bool clampValue(const QVariant& cookedValue, QVariant& typedValue);

186 187 188 189
    /// 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; }

190 191
    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
192

Don Gagne's avatar
Don Gagne committed
193
    static ValueType_t stringToType(const QString& typeString, bool& unknownType);
194
    static size_t typeToSize(ValueType_t type);
Don Gagne's avatar
Don Gagne committed
195

196 197
    static const char* qgcFileType;

198
private:
199 200
    QVariant _minForType(void) const;
    QVariant _maxForType(void) const;
201
    void _setAppSettingsTranslators(void);
202

203 204 205 206 207 208 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 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258

    /**
     * @brief Clamp a value based in the cookedMin and CookedMax values
     *
     * @tparam T
     * @param variantValue
     */
    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();
        }
    }

    /**
     * @brief Check if value is inside cooked limits
     *
     * @tparam T
     * @param variantValue
     */
    template<class T>
    bool isInCookedLimit(const QVariant& variantValue) const {
        return cookedMin().value<T>() < variantValue.value<T>() && variantValue.value<T>() < cookedMax().value<T>();
    }

    /**
     * @brief Check if value is inside raw limits
     *
     * @tparam T
     * @param variantValue
     */
    template<class T>
    bool isInRawLimit(const QVariant& variantValue) const {
        return rawMin().value<T>() <= variantValue.value<T>() && variantValue.value<T>() < rawMax().value<T>();
    }

    /**
     * @brief Check if value if over min limit
     *
     * @param variantValue
     * @return true
     * @return false
     */
    bool isInRawMinLimit(const QVariant& variantValue) const;

    /**
     * @brief Check if value is lower than upper limit
     *
     * @param variantValue
     * @return true
     * @return false
     */
    bool isInRawMaxLimit(const QVariant& variantValue) const;

259 260 261 262 263 264
    // 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);
265 266
    static QVariant _userGimbalDegreesToMavlinkGimbalDegrees(const QVariant& userGimbalDegrees);
    static QVariant _mavlinkGimbalDegreesToUserGimbalDegrees(const QVariant& mavlinkGimbalDegrees);
267 268
    static QVariant _metersToFeet(const QVariant& meters);
    static QVariant _feetToMeters(const QVariant& feet);
269 270 271 272 273 274 275 276 277 278
    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);
279 280 281 282 283 284
    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);
285 286
    static QVariant _percentToNorm(const QVariant& percent);
    static QVariant _normToPercent(const QVariant& normalized);
287 288
    static QVariant _centimetersToInches(const QVariant& centimeters);
    static QVariant _inchesToCentimeters(const QVariant& inches);
289 290
    static QVariant _celsiusToFarenheit(const QVariant& celsius);
    static QVariant _farenheitToCelsius(const QVariant& farenheit);
291 292 293 294 295 296 297
    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);

298

Gus Grubba's avatar
Gus Grubba committed
299
    enum UnitTypes {
Remek Zajac's avatar
Remek Zajac committed
300 301
        UnitHorizontalDistance = 0,
        UnitVerticalDistance,
Gus Grubba's avatar
Gus Grubba committed
302 303
        UnitArea,
        UnitSpeed,
304 305
        UnitTemperature,
        UnitWeight
Gus Grubba's avatar
Gus Grubba committed
306
    };
307

Gus Grubba's avatar
Gus Grubba committed
308
    struct AppSettingsTranslation_s {
Remek Zajac's avatar
Remek Zajac committed
309 310 311 312 313 314
        QString       rawUnits;
        const char*   cookedUnits;
        UnitTypes     unitType;
        uint32_t      unitOption;
        Translator    rawTranslator;
        Translator    cookedTranslator;
315 316
    };

Remek Zajac's avatar
Remek Zajac committed
317 318
    static const AppSettingsTranslation_s* _findAppSettingsHorizontalDistanceUnitsTranslation(const QString& rawUnits);
    static const AppSettingsTranslation_s* _findAppSettingsVerticalDistanceUnitsTranslation(const QString& rawUnits);
319
    static const AppSettingsTranslation_s* _findAppSettingsAreaUnitsTranslation(const QString& rawUnits);
320
    static const AppSettingsTranslation_s* _findAppSettingsWeightUnitsTranslation(const QString& rawUnits);
321

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

324 325
    ValueType_t     _type;                  // must be first for correct constructor init
    int             _decimalPlaces;
326
    QVariant        _rawDefaultValue;
327
    bool            _defaultValueAvailable;
328 329
    QStringList     _bitmaskStrings;
    QVariantList    _bitmaskValues;
330 331
    QStringList     _enumStrings;
    QVariantList    _enumValues;
332
    QString         _category;
333 334
    QString         _group;
    QString         _longDescription;
335
    QVariant        _rawMax;
336
    bool            _maxIsDefaultForType;
337
    QVariant        _rawMin;
338 339 340
    bool            _minIsDefaultForType;
    QString         _name;
    QString         _shortDescription;
341 342
    QString         _rawUnits;
    QString         _cookedUnits;
343 344
    Translator      _rawTranslator;
    Translator      _cookedTranslator;
345 346
    bool            _vehicleRebootRequired;
    bool            _qgcRebootRequired;
347
    double          _rawIncrement;
348
    bool            _hasControl;
349
    bool            _readOnly;
350
    bool            _writeOnly;
351
    bool            _volatile;
352
    CustomCookedValidator _customCookedValidator = nullptr;
353

354 355 356 357 358 359
    // Exact conversion constants
    static const struct UnitConsts_s {
        static const qreal secondsPerHour;
        static const qreal knotsToKPH;
        static const qreal milesToMeters;
        static const qreal feetToMeters;
360
        static const qreal inchesToCentimeters;
361 362
        static const qreal ouncesToGrams;
        static const qreal poundsToGrams;
363 364
    } constants;

365
    struct BuiltInTranslation_s {
366
        QString rawUnits;
367 368 369 370 371
        const char* cookedUnits;
        Translator  rawTranslator;
        Translator  cookedTranslator;

    };
372

373
    static const BuiltInTranslation_s _rgBuiltInTranslations[];
374

375
    static const AppSettingsTranslation_s _rgAppSettingsTranslations[];
376

377 378 379 380 381 382 383 384 385 386 387
    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;
388
    static const char* _hasControlJsonKey;
389
    static const char* _qgcRebootRequiredJsonKey;
390 391 392

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