Fact.cc 14.8 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
    if (_metaData) {
194 195 196 197 198
        //-- Only enums have an index
        if(_metaData->enumValues().count()) {
            int index = 0;
            foreach (QVariant enumValue, _metaData->enumValues()) {
                if (enumValue == rawValue()) {
199 200
                    return index;
                }
201 202 203 204 205 206 207 208
                //-- 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;
                    }
                }
                index ++;
209
            }
210
            // Current value is not in list, add it manually
211
            _metaData->addEnumInfo(tr("Unknown: %1").arg(rawValue().toString()), rawValue());
212 213
            emit enumsChanged();
            return index;
214 215
        }
    } else {
216
        qWarning() << kMissingMetadata;
217 218 219 220 221 222 223 224 225
    }
    return -1;
}

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

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

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

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

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

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

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

    return valueString;
313 314
}

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557
QVariant Fact::clamp(const QString& cookedValue)
{
    if (_metaData) {
        QVariant typedValue;
        if(_metaData->clampValue(cookedValue, typedValue)) {
            return typedValue;
        } else {
            //-- If conversion failed, return current value
            return rawValue();
        }
    } else {
        qWarning() << kMissingMetadata;
    }
    return QVariant();
}

558 559 560 561 562
bool Fact::rebootRequired(void) const
{
    if (_metaData) {
        return _metaData->rebootRequired();
    } else {
563
        qWarning() << kMissingMetadata;
564 565 566
        return false;
    }
}
Don Gagne's avatar
Don Gagne committed
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592

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());
    }
}
593 594 595 596 597 598 599 600 601 602

QString Fact::enumOrValueString(void)
{
    if (_metaData) {
        if (_metaData->enumStrings().count()) {
            return enumStringValue();
        } else {
            return cookedValueString();
        }
    } else {
603
        qWarning() << kMissingMetadata;
604 605 606
    }
    return QString();
}
Don Gagne's avatar
Don Gagne committed
607 608 609 610 611 612

double Fact::increment(void) const
{
    if (_metaData) {
        return _metaData->increment();
    } else {
613
        qWarning() << kMissingMetadata;
Don Gagne's avatar
Don Gagne committed
614 615 616
    }
    return std::numeric_limits<double>::quiet_NaN();
}
617 618 619 620 621 622 623 624 625 626

bool Fact::hasControl(void) const
{
    if (_metaData) {
        return _metaData->hasControl();
    } else {
        qWarning() << kMissingMetadata;
        return false;
    }
}
627 628 629 630 631 632 633 634 635 636

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