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

Don Gagne's avatar
Don Gagne committed
10 11 12 13 14

/// @file
///     @author Don Gagne <don@thegagnes.com>

#include "Fact.h"
Don Gagne's avatar
Don Gagne committed
15
#include "QGCMAVLink.h"
Don Gagne's avatar
Don Gagne committed
16 17

#include <QtQml>
18
#include <QQmlEngine>
Don Gagne's avatar
Don Gagne committed
19

20 21
static const char* kMissingMetadata = "Meta data pointer missing";

Don Gagne's avatar
Don Gagne committed
22 23 24
Fact::Fact(QObject* parent)
    : QObject(parent)
    , _componentId(-1)
25
    , _rawValue(0)
Don Gagne's avatar
Don Gagne committed
26 27
    , _type(FactMetaData::valueTypeInt32)
    , _metaData(NULL)
Don Gagne's avatar
Don Gagne committed
28 29
    , _sendValueChangedSignals(true)
    , _deferredValueChangeSignal(false)
Don Gagne's avatar
Don Gagne committed
30 31 32
{    
    FactMetaData* metaData = new FactMetaData(_type, this);
    setMetaData(metaData);
33 34 35

    // Better sage than sorry on object ownership
    QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
Don Gagne's avatar
Don Gagne committed
36 37
}

Don Gagne's avatar
Don Gagne committed
38 39 40 41
Fact::Fact(int componentId, QString name, FactMetaData::ValueType_t type, QObject* parent)
    : QObject(parent)
    , _name(name)
    , _componentId(componentId)
42
    , _rawValue(0)
Don Gagne's avatar
Don Gagne committed
43 44
    , _type(type)
    , _metaData(NULL)
Don Gagne's avatar
Don Gagne committed
45 46
    , _sendValueChangedSignals(true)
    , _deferredValueChangeSignal(false)
Don Gagne's avatar
Don Gagne committed
47
{
Don Gagne's avatar
Don Gagne committed
48 49
    FactMetaData* metaData = new FactMetaData(_type, this);
    setMetaData(metaData);
50
    QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
Don Gagne's avatar
Don Gagne committed
51
}
Don Gagne's avatar
Don Gagne committed
52

Don Gagne's avatar
Don Gagne committed
53 54 55 56
Fact::Fact(const Fact& other, QObject* parent)
    : QObject(parent)
{
    *this = other;
57
    QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
Don Gagne's avatar
Don Gagne committed
58 59 60 61
}

const Fact& Fact::operator=(const Fact& other)
{
Don Gagne's avatar
Don Gagne committed
62 63 64 65 66 67 68
    _name                       = other._name;
    _componentId                = other._componentId;
    _rawValue                   = other._rawValue;
    _type                       = other._type;
    _sendValueChangedSignals    = other._sendValueChangedSignals;
    _deferredValueChangeSignal  = other._deferredValueChangeSignal;

Don Gagne's avatar
Don Gagne committed
69 70 71 72 73 74 75
    if (_metaData && other._metaData) {
        *_metaData = *other._metaData;
    } else {
        _metaData = NULL;
    }
    
    return *this;
Don Gagne's avatar
Don Gagne committed
76 77
}

Don Gagne's avatar
Don Gagne committed
78
void Fact::forceSetRawValue(const QVariant& value)
79 80 81 82 83
{
    if (_metaData) {
        QVariant    typedValue;
        QString     errorString;
        
84
        if (_metaData->convertAndValidateRaw(value, true /* convertOnly */, typedValue, errorString)) {
Don Gagne's avatar
Don Gagne committed
85
            _rawValue.setValue(typedValue);
Don Gagne's avatar
Don Gagne committed
86
            _sendValueChangedSignal(cookedValue());
Don Gagne's avatar
Don Gagne committed
87
            emit _containerRawValueChanged(rawValue());
88
            emit rawValueChanged(_rawValue);
89 90
        }
    } else {
91
        qWarning() << kMissingMetadata;
92 93 94
    }
}

95
void Fact::setRawValue(const QVariant& value, bool skipSignal)
Don Gagne's avatar
Don Gagne committed
96
{
Don Gagne's avatar
Don Gagne committed
97 98 99 100
    if (_metaData) {
        QVariant    typedValue;
        QString     errorString;
        
101
        if (_metaData->convertAndValidateRaw(value, true /* convertOnly */, typedValue, errorString)) {
102 103
            if (typedValue != _rawValue) {
                _rawValue.setValue(typedValue);
Don Gagne's avatar
Don Gagne committed
104
                _sendValueChangedSignal(cookedValue());
105 106 107 108
                if(!skipSignal) {
                    emit _containerRawValueChanged(rawValue());
                    emit rawValueChanged(_rawValue);
                }
Don Gagne's avatar
Don Gagne committed
109 110 111
            }
        }
    } else {
112
        qWarning() << kMissingMetadata;
113
    }
Don Gagne's avatar
Don Gagne committed
114 115
}

Don Gagne's avatar
Don Gagne committed
116
void Fact::setCookedValue(const QVariant& value)
117 118 119 120
{
    if (_metaData) {
        setRawValue(_metaData->cookedTranslator()(value));
    } else {
121
        qWarning() << kMissingMetadata;
122 123 124 125 126 127 128 129
    }
}

void Fact::setEnumStringValue(const QString& value)
{
    if (_metaData) {
        int index = _metaData->enumStrings().indexOf(value);
        if (index != -1) {
Don Gagne's avatar
Don Gagne committed
130
            setCookedValue(_metaData->enumValues()[index]);
131 132
        }
    } else {
133
        qWarning() << kMissingMetadata;
134 135 136 137 138 139
    }
}

void Fact::setEnumIndex(int index)
{
    if (_metaData) {
Don Gagne's avatar
Don Gagne committed
140
        setCookedValue(_metaData->enumValues()[index]);
141
    } else {
142
        qWarning() << kMissingMetadata;
143 144 145
    }
}

Don Gagne's avatar
Don Gagne committed
146
void Fact::_containerSetRawValue(const QVariant& value)
Don Gagne's avatar
Don Gagne committed
147
{
148
    _rawValue = value;
Don Gagne's avatar
Don Gagne committed
149
    _sendValueChangedSignal(cookedValue());
150
    emit vehicleUpdated(_rawValue);
151
    emit rawValueChanged(_rawValue);
Don Gagne's avatar
Don Gagne committed
152
}
153 154 155 156 157 158

QString Fact::name(void) const
{
    return _name;
}

159 160 161 162 163
int Fact::componentId(void) const
{
    return _componentId;
}

Don Gagne's avatar
Don Gagne committed
164
QVariant Fact::cookedValue(void) const
165
{
166 167 168
    if (_metaData) {
        return _metaData->rawTranslator()(_rawValue);
    } else {
169
        qWarning() << kMissingMetadata;
170 171 172 173
        return _rawValue;
    }
}

174
QString Fact::enumStringValue(void)
175 176 177
{
    if (_metaData) {
        int enumIndex = this->enumIndex();
Don Gagne's avatar
Don Gagne committed
178
        if (enumIndex >= 0 && enumIndex < _metaData->enumStrings().count()) {
179 180 181
            return _metaData->enumStrings()[enumIndex];
        }
    } else {
182
        qWarning() << kMissingMetadata;
183 184 185 186 187
    }

    return QString();
}

188
int Fact::enumIndex(void)
189
{
190
    static const double accuracy = 1.0 / 1000000.0;
191 192 193
    if (_metaData) {
        int index = 0;
        foreach (QVariant enumValue, _metaData->enumValues()) {
Don Gagne's avatar
Don Gagne committed
194
            if (enumValue == rawValue()) {
195 196
                return index;
            }
197 198 199 200 201 202 203
            //-- Float comparissons don't always work
            if(type() == FactMetaData::valueTypeFloat || type() == FactMetaData::valueTypeDouble) {
                double diff = fabs(enumValue.toDouble() - rawValue().toDouble());
                if(diff < accuracy) {
                    return index;
                }
            }
204 205
            index ++;
        }
206 207 208 209 210
        // Current value is not in list, add it manually
        _metaData->addEnumInfo(QString("Unknown: %1").arg(rawValue().toString()), rawValue());
        emit enumStringsChanged();
        emit enumValuesChanged();
        return index;
211
    } else {
212
        qWarning() << kMissingMetadata;
213 214 215 216 217 218 219 220 221 222
    }

    return -1;
}

QStringList Fact::enumStrings(void) const
{
    if (_metaData) {
        return _metaData->enumStrings();
    } else {
223
        qWarning() << kMissingMetadata;
224 225 226 227 228 229 230 231 232
        return QStringList();
    }
}

QVariantList Fact::enumValues(void) const
{
    if (_metaData) {
        return _metaData->enumValues();
    } else {
233
        qWarning() << kMissingMetadata;
234 235
        return QVariantList();
    }
236 237
}

238 239 240 241 242 243 244 245 246
void Fact::setEnumInfo(const QStringList& strings, const QVariantList& values)
{
    if (_metaData) {
        return _metaData->setEnumInfo(strings, values);
    } else {
        qWarning() << kMissingMetadata;
    }
}

247 248 249 250 251
QStringList Fact::bitmaskStrings(void) const
{
    if (_metaData) {
        return _metaData->bitmaskStrings();
    } else {
252
        qWarning() << kMissingMetadata;
253 254 255 256 257 258 259 260 261
        return QStringList();
    }
}

QVariantList Fact::bitmaskValues(void) const
{
    if (_metaData) {
        return _metaData->bitmaskValues();
    } else {
262
        qWarning() << kMissingMetadata;
263 264 265 266
        return QVariantList();
    }
}

267
QString Fact::_variantToString(const QVariant& variant, int decimalPlaces) const
268
{
269 270 271
    QString valueString;

    switch (type()) {
Don Gagne's avatar
Don Gagne committed
272 273 274 275 276 277
    case FactMetaData::valueTypeFloat:
    {
        float fValue = variant.toFloat();
        if (qIsNaN(fValue)) {
            valueString = QStringLiteral("--.--");
        } else {
278
            valueString = QString("%1").arg(fValue, 0, 'f', decimalPlaces);
Don Gagne's avatar
Don Gagne committed
279 280 281 282 283 284 285 286 287
        }
    }
        break;
    case FactMetaData::valueTypeDouble:
    {
        double dValue = variant.toDouble();
        if (qIsNaN(dValue)) {
            valueString = QStringLiteral("--.--");
        } else {
288
            valueString = QString("%1").arg(dValue, 0, 'f', decimalPlaces);
Don Gagne's avatar
Don Gagne committed
289 290 291
        }
    }
        break;
292 293 294 295 296 297 298 299 300 301 302 303
    case FactMetaData::valueTypeElapsedTimeInSeconds:
    {
        double dValue = variant.toDouble();
        if (qIsNaN(dValue)) {
            valueString = QStringLiteral("--:--:--");
        } else {
            QTime time(0, 0, 0, 0);
            time = time.addSecs(dValue);
            valueString = time.toString(QStringLiteral("hh:mm:ss"));
        }
    }
        break;
Don Gagne's avatar
Don Gagne committed
304 305 306
    default:
        valueString = variant.toString();
        break;
307 308 309
    }

    return valueString;
310 311
}

312 313 314 315 316 317
QString Fact::rawValueStringFullPrecision(void) const
{
    return _variantToString(rawValue(), 18);
}


318 319
QString Fact::rawValueString(void) const
{
320
    return _variantToString(rawValue(), decimalPlaces());
321 322 323
}

QString Fact::cookedValueString(void) const
324
{
325
    return _variantToString(cookedValue(), decimalPlaces());
326 327
}

328 329 330 331 332 333 334 335
QVariant Fact::rawDefaultValue(void) const
{
    if (_metaData) {
        if (!_metaData->defaultValueAvailable()) {
            qDebug() << "Access to unavailable default value";
        }
        return _metaData->rawDefaultValue();
    } else {
336
        qWarning() << kMissingMetadata;
337 338 339 340 341
        return QVariant(0);
    }
}

QVariant Fact::cookedDefaultValue(void) const
342
{
Don Gagne's avatar
Don Gagne committed
343 344 345 346
    if (_metaData) {
        if (!_metaData->defaultValueAvailable()) {
            qDebug() << "Access to unavailable default value";
        }
347
        return _metaData->cookedDefaultValue();
Don Gagne's avatar
Don Gagne committed
348
    } else {
349
        qWarning() << kMissingMetadata;
Don Gagne's avatar
Don Gagne committed
350
        return QVariant(0);
351
    }
352 353
}

354
QString Fact::cookedDefaultValueString(void) const
355
{
356
    return _variantToString(cookedDefaultValue(), decimalPlaces());
357 358
}

359
FactMetaData::ValueType_t Fact::type(void) const
360
{
361
    return _type;
362 363
}

364
QString Fact::shortDescription(void) const
365
{
Don Gagne's avatar
Don Gagne committed
366 367 368
    if (_metaData) {
        return _metaData->shortDescription();
    } else {
369
        qWarning() << kMissingMetadata;
Don Gagne's avatar
Don Gagne committed
370 371
        return QString();
    }
372 373
}

374
QString Fact::longDescription(void) const
375
{
Don Gagne's avatar
Don Gagne committed
376 377 378
    if (_metaData) {
        return _metaData->longDescription();
    } else {
379
        qWarning() << kMissingMetadata;
Don Gagne's avatar
Don Gagne committed
380 381
        return QString();
    }
382 383
}

384 385 386 387 388
QString Fact::rawUnits(void) const
{
    if (_metaData) {
        return _metaData->rawUnits();
    } else {
389
        qWarning() << kMissingMetadata;
390 391 392 393 394
        return QString();
    }
}

QString Fact::cookedUnits(void) const
395
{
Don Gagne's avatar
Don Gagne committed
396
    if (_metaData) {
397
        return _metaData->cookedUnits();
Don Gagne's avatar
Don Gagne committed
398
    } else {
399
        qWarning() << kMissingMetadata;
Don Gagne's avatar
Don Gagne committed
400 401
        return QString();
    }
402 403
}

404
QVariant Fact::rawMin(void) const
405
{
Don Gagne's avatar
Don Gagne committed
406
    if (_metaData) {
407
        return _metaData->rawMin();
Don Gagne's avatar
Don Gagne committed
408
    } else {
409
        qWarning() << kMissingMetadata;
Don Gagne's avatar
Don Gagne committed
410 411
        return QVariant(0);
    }
412 413
}

414
QVariant Fact::cookedMin(void) const
415
{
416 417 418
    if (_metaData) {
        return _metaData->cookedMin();
    } else {
419
        qWarning() << kMissingMetadata;
420 421
        return QVariant(0);
    }
422 423
}

424 425
QString Fact::cookedMinString(void) const
{
426
    return _variantToString(cookedMin(), decimalPlaces());
427 428 429
}

QVariant Fact::rawMax(void) const
430
{
Don Gagne's avatar
Don Gagne committed
431
    if (_metaData) {
432
        return _metaData->rawMax();
Don Gagne's avatar
Don Gagne committed
433
    } else {
434
        qWarning() << kMissingMetadata;
Don Gagne's avatar
Don Gagne committed
435 436 437 438
        return QVariant(0);
    }
}

439
QVariant Fact::cookedMax(void) const
440
{
441 442 443
    if (_metaData) {
        return _metaData->cookedMax();
    } else {
444
        qWarning() << kMissingMetadata;
445 446 447 448 449 450
        return QVariant(0);
    }
}

QString Fact::cookedMaxString(void) const
{
451
    return _variantToString(cookedMax(), decimalPlaces());
452 453
}

454
bool Fact::minIsDefaultForType(void) const
Don Gagne's avatar
Don Gagne committed
455 456 457 458
{
    if (_metaData) {
        return _metaData->minIsDefaultForType();
    } else {
459
        qWarning() << kMissingMetadata;
Don Gagne's avatar
Don Gagne committed
460 461 462 463
        return false;
    }
}

464
bool Fact::maxIsDefaultForType(void) const
Don Gagne's avatar
Don Gagne committed
465 466 467 468
{
    if (_metaData) {
        return _metaData->maxIsDefaultForType();
    } else {
469
        qWarning() << kMissingMetadata;
Don Gagne's avatar
Don Gagne committed
470 471
        return false;
    }
472 473
}

474 475 476 477 478
int Fact::decimalPlaces(void) const
{
    if (_metaData) {
        return _metaData->decimalPlaces();
    } else {
479
        qWarning() << kMissingMetadata;
480 481 482 483
        return FactMetaData::defaultDecimalPlaces;
    }
}

484
QString Fact::group(void) const
485
{
Don Gagne's avatar
Don Gagne committed
486 487 488
    if (_metaData) {
        return _metaData->group();
    } else {
489
        qWarning() << kMissingMetadata;
Don Gagne's avatar
Don Gagne committed
490 491
        return QString();
    }
492 493
}

494 495 496
void Fact::setMetaData(FactMetaData* metaData)
{
    _metaData = metaData;
Don Gagne's avatar
Don Gagne committed
497
    emit valueChanged(cookedValue());
498
}
499

500
bool Fact::valueEqualsDefault(void) const
501
{
Don Gagne's avatar
Don Gagne committed
502 503
    if (_metaData) {
        if (_metaData->defaultValueAvailable()) {
504
            return _metaData->rawDefaultValue() == rawValue();
Don Gagne's avatar
Don Gagne committed
505 506 507
        } else {
            return false;
        }
508
    } else {
509
        qWarning() << kMissingMetadata;
510 511 512 513
        return false;
    }
}

514
bool Fact::defaultValueAvailable(void) const
515
{
Don Gagne's avatar
Don Gagne committed
516 517 518
    if (_metaData) {
        return _metaData->defaultValueAvailable();
    } else {
519
        qWarning() << kMissingMetadata;
Don Gagne's avatar
Don Gagne committed
520 521 522 523
        return false;
    }
}

524
QString Fact::validate(const QString& cookedValue, bool convertOnly)
Don Gagne's avatar
Don Gagne committed
525 526 527 528 529
{
    if (_metaData) {
        QVariant    typedValue;
        QString     errorString;
        
530
        _metaData->convertAndValidateCooked(cookedValue, convertOnly, typedValue, errorString);
Don Gagne's avatar
Don Gagne committed
531 532 533
        
        return errorString;
    } else {
534
        qWarning() << kMissingMetadata;
Don Gagne's avatar
Don Gagne committed
535 536 537
        return QString("Internal error: Meta data pointer missing");
    }
}
538 539 540 541 542 543

bool Fact::rebootRequired(void) const
{
    if (_metaData) {
        return _metaData->rebootRequired();
    } else {
544
        qWarning() << kMissingMetadata;
545 546 547
        return false;
    }
}
Don Gagne's avatar
Don Gagne committed
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573

void Fact::setSendValueChangedSignals (bool sendValueChangedSignals)
{
    if (sendValueChangedSignals != _sendValueChangedSignals) {
        _sendValueChangedSignals = sendValueChangedSignals;
        emit sendValueChangedSignalsChanged(_sendValueChangedSignals);
    }
}

void Fact::_sendValueChangedSignal(QVariant value)
{
    if (_sendValueChangedSignals) {
        emit valueChanged(value);
        _deferredValueChangeSignal = false;
    } else {
        _deferredValueChangeSignal = true;
    }
}

void Fact::sendDeferredValueChangedSignal(void)
{
    if (_deferredValueChangeSignal) {
        _deferredValueChangeSignal = false;
        emit valueChanged(cookedValue());
    }
}
574 575 576 577 578 579 580 581 582 583

QString Fact::enumOrValueString(void)
{
    if (_metaData) {
        if (_metaData->enumStrings().count()) {
            return enumStringValue();
        } else {
            return cookedValueString();
        }
    } else {
584
        qWarning() << kMissingMetadata;
585 586 587
    }
    return QString();
}
Don Gagne's avatar
Don Gagne committed
588 589 590 591 592 593

double Fact::increment(void) const
{
    if (_metaData) {
        return _metaData->increment();
    } else {
594
        qWarning() << kMissingMetadata;
Don Gagne's avatar
Don Gagne committed
595 596 597
    }
    return std::numeric_limits<double>::quiet_NaN();
}
598 599 600 601 602 603 604 605 606 607

bool Fact::hasControl(void) const
{
    if (_metaData) {
        return _metaData->hasControl();
    } else {
        qWarning() << kMissingMetadata;
        return false;
    }
}