Fact.cc 14.2 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
    // Better safe than sorry on object ownership
35
    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());
87 88
            //-- Must be in this order
            emit _containerRawValueChanged(rawValue());
89
            emit rawValueChanged(_rawValue);
90 91
        }
    } else {
92
        qWarning() << kMissingMetadata;
93 94 95
    }
}

Gus Grubba's avatar
Gus Grubba committed
96
void Fact::setRawValue(const QVariant& value)
Don Gagne's avatar
Don Gagne committed
97
{
Don Gagne's avatar
Don Gagne committed
98 99 100 101
    if (_metaData) {
        QVariant    typedValue;
        QString     errorString;
        
102
        if (_metaData->convertAndValidateRaw(value, true /* convertOnly */, typedValue, errorString)) {
103 104
            if (typedValue != _rawValue) {
                _rawValue.setValue(typedValue);
Don Gagne's avatar
Don Gagne committed
105
                _sendValueChangedSignal(cookedValue());
106 107
                //-- Must be in this order
                emit _containerRawValueChanged(rawValue());
108
                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 149 150 151 152 153
    if(_rawValue != value) {
        _rawValue = value;
        _sendValueChangedSignal(cookedValue());
        emit vehicleUpdated(_rawValue);
        emit rawValueChanged(_rawValue);
    }
Don Gagne's avatar
Don Gagne committed
154
}
155 156 157 158 159 160

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

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

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

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

    return QString();
}

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

    return -1;
}

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

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

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

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

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

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

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

    return valueString;
311 312
}

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

bool Fact::rebootRequired(void) const
{
    if (_metaData) {
        return _metaData->rebootRequired();
    } else {
545
        qWarning() << kMissingMetadata;
546 547 548
        return false;
    }
}
Don Gagne's avatar
Don Gagne committed
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 574

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());
    }
}
575 576 577 578 579 580 581 582 583 584

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

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

bool Fact::hasControl(void) const
{
    if (_metaData) {
        return _metaData->hasControl();
    } else {
        qWarning() << kMissingMetadata;
        return false;
    }
}
609 610 611 612 613 614 615 616 617 618

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