Fact.cc 17.4 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
#include "Fact.h"
11
#include "FactValueSliderListModel.h"
Don Gagne's avatar
Don Gagne committed
12
#include "QGCMAVLink.h"
13 14
#include "QGCApplication.h"
#include "QGCCorePlugin.h"
Don Gagne's avatar
Don Gagne committed
15 16

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

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

Don Gagne's avatar
Don Gagne committed
21
Fact::Fact(QObject* parent)
22 23 24 25 26 27
    : QObject                   (parent)
    , _componentId              (-1)
    , _rawValue                 (0)
    , _type                     (FactMetaData::valueTypeInt32)
    , _metaData                 (NULL)
    , _sendValueChangedSignals  (true)
Don Gagne's avatar
Don Gagne committed
28
    , _deferredValueChangeSignal(false)
29
    , _valueSliderModel         (NULL)
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
Fact::Fact(int componentId, QString name, FactMetaData::ValueType_t type, QObject* parent)
39 40 41 42 43 44 45
    : QObject                   (parent)
    , _name                     (name)
    , _componentId              (componentId)
    , _rawValue                 (0)
    , _type                     (type)
    , _metaData                 (NULL)
    , _sendValueChangedSignals  (true)
Don Gagne's avatar
Don Gagne committed
46
    , _deferredValueChangeSignal(false)
47
    , _valueSliderModel         (NULL)
Don Gagne's avatar
Don Gagne committed
48
{
Don Gagne's avatar
Don Gagne committed
49 50
    FactMetaData* metaData = new FactMetaData(_type, this);
    setMetaData(metaData);
51
    QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
Don Gagne's avatar
Don Gagne committed
52
}
Don Gagne's avatar
Don Gagne committed
53

54
Fact::Fact(const QString& settingsGroup, FactMetaData* metaData, QObject* parent)
55 56 57 58 59 60 61 62
    : QObject(parent)
    , _name                     (metaData->name())
    , _componentId              (0)
    , _rawValue                 (0)
    , _type                     (metaData->type())
    , _metaData                 (NULL)
    , _sendValueChangedSignals  (true)
    , _deferredValueChangeSignal(false)
63
    , _valueSliderModel         (NULL)
64
{
65
    qgcApp()->toolbox()->corePlugin()->adjustSettingMetaData(settingsGroup, *metaData);
66 67 68
    setMetaData(metaData, true /* setDefaultFromMetaData */);
}

Don Gagne's avatar
Don Gagne committed
69 70 71 72
Fact::Fact(const Fact& other, QObject* parent)
    : QObject(parent)
{
    *this = other;
73
    QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
Don Gagne's avatar
Don Gagne committed
74 75 76 77
}

const Fact& Fact::operator=(const Fact& other)
{
Don Gagne's avatar
Don Gagne committed
78 79 80 81 82 83
    _name                       = other._name;
    _componentId                = other._componentId;
    _rawValue                   = other._rawValue;
    _type                       = other._type;
    _sendValueChangedSignals    = other._sendValueChangedSignals;
    _deferredValueChangeSignal  = other._deferredValueChangeSignal;
84
    _valueSliderModel       = NULL;
Don Gagne's avatar
Don Gagne committed
85 86 87 88 89 90 91
    if (_metaData && other._metaData) {
        *_metaData = *other._metaData;
    } else {
        _metaData = NULL;
    }
    
    return *this;
Don Gagne's avatar
Don Gagne committed
92 93
}

Don Gagne's avatar
Don Gagne committed
94
void Fact::forceSetRawValue(const QVariant& value)
95 96 97 98 99
{
    if (_metaData) {
        QVariant    typedValue;
        QString     errorString;
        
100
        if (_metaData->convertAndValidateRaw(value, true /* convertOnly */, typedValue, errorString)) {
Don Gagne's avatar
Don Gagne committed
101
            _rawValue.setValue(typedValue);
Don Gagne's avatar
Don Gagne committed
102
            _sendValueChangedSignal(cookedValue());
103 104
            //-- Must be in this order
            emit _containerRawValueChanged(rawValue());
105
            emit rawValueChanged(_rawValue);
106 107
        }
    } else {
108
        qWarning() << kMissingMetadata << name();
109 110 111
    }
}

Gus Grubba's avatar
Gus Grubba committed
112
void Fact::setRawValue(const QVariant& value)
Don Gagne's avatar
Don Gagne committed
113
{
Don Gagne's avatar
Don Gagne committed
114 115 116 117
    if (_metaData) {
        QVariant    typedValue;
        QString     errorString;
        
118
        if (_metaData->convertAndValidateRaw(value, true /* convertOnly */, typedValue, errorString)) {
119 120
            if (typedValue != _rawValue) {
                _rawValue.setValue(typedValue);
Don Gagne's avatar
Don Gagne committed
121
                _sendValueChangedSignal(cookedValue());
122 123
                //-- Must be in this order
                emit _containerRawValueChanged(rawValue());
124
                emit rawValueChanged(_rawValue);
Don Gagne's avatar
Don Gagne committed
125 126 127
            }
        }
    } else {
128
        qWarning() << kMissingMetadata << name();
129
    }
Don Gagne's avatar
Don Gagne committed
130 131
}

Don Gagne's avatar
Don Gagne committed
132
void Fact::setCookedValue(const QVariant& value)
133 134 135 136
{
    if (_metaData) {
        setRawValue(_metaData->cookedTranslator()(value));
    } else {
137
        qWarning() << kMissingMetadata << name();
138 139 140 141 142 143 144 145
    }
}

void Fact::setEnumStringValue(const QString& value)
{
    if (_metaData) {
        int index = _metaData->enumStrings().indexOf(value);
        if (index != -1) {
Don Gagne's avatar
Don Gagne committed
146
            setCookedValue(_metaData->enumValues()[index]);
147 148
        }
    } else {
149
        qWarning() << kMissingMetadata << name();
150 151 152 153 154 155
    }
}

void Fact::setEnumIndex(int index)
{
    if (_metaData) {
Don Gagne's avatar
Don Gagne committed
156
        setCookedValue(_metaData->enumValues()[index]);
157
    } else {
158
        qWarning() << kMissingMetadata << name();
159 160 161
    }
}

Don Gagne's avatar
Don Gagne committed
162
void Fact::_containerSetRawValue(const QVariant& value)
Don Gagne's avatar
Don Gagne committed
163
{
164 165 166 167 168
    if(_rawValue != value) {
        _rawValue = value;
        _sendValueChangedSignal(cookedValue());
        emit rawValueChanged(_rawValue);
    }
169 170 171

    // This always need to be signalled in order to support forceSetRawValue usage and waiting for vehicleUpdated signal
    emit vehicleUpdated(_rawValue);
Don Gagne's avatar
Don Gagne committed
172
}
173 174 175 176 177 178

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

179 180 181 182 183
int Fact::componentId(void) const
{
    return _componentId;
}

Don Gagne's avatar
Don Gagne committed
184
QVariant Fact::cookedValue(void) const
185
{
186 187 188
    if (_metaData) {
        return _metaData->rawTranslator()(_rawValue);
    } else {
189
        qWarning() << kMissingMetadata << name();
190 191 192 193
        return _rawValue;
    }
}

194
QString Fact::enumStringValue(void)
195 196 197
{
    if (_metaData) {
        int enumIndex = this->enumIndex();
Don Gagne's avatar
Don Gagne committed
198
        if (enumIndex >= 0 && enumIndex < _metaData->enumStrings().count()) {
199 200 201
            return _metaData->enumStrings()[enumIndex];
        }
    } else {
202
        qWarning() << kMissingMetadata << name();
203 204 205 206 207
    }

    return QString();
}

208
int Fact::enumIndex(void)
209
{
210
    static const double accuracy = 1.0 / 1000000.0;
211
    if (_metaData) {
212 213 214 215 216
        //-- Only enums have an index
        if(_metaData->enumValues().count()) {
            int index = 0;
            foreach (QVariant enumValue, _metaData->enumValues()) {
                if (enumValue == rawValue()) {
217 218
                    return index;
                }
219 220 221 222 223 224 225 226
                //-- 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 ++;
227
            }
228
            // Current value is not in list, add it manually
229
            _metaData->addEnumInfo(tr("Unknown: %1").arg(rawValue().toString()), rawValue());
230 231
            emit enumsChanged();
            return index;
232 233
        }
    } else {
234
        qWarning() << kMissingMetadata << name();
235 236 237 238 239 240 241 242 243
    }
    return -1;
}

QStringList Fact::enumStrings(void) const
{
    if (_metaData) {
        return _metaData->enumStrings();
    } else {
244
        qWarning() << kMissingMetadata << name();
245 246 247 248 249 250 251 252 253
        return QStringList();
    }
}

QVariantList Fact::enumValues(void) const
{
    if (_metaData) {
        return _metaData->enumValues();
    } else {
254
        qWarning() << kMissingMetadata << name();
255 256
        return QVariantList();
    }
257 258
}

259 260 261
void Fact::setEnumInfo(const QStringList& strings, const QVariantList& values)
{
    if (_metaData) {
262
        _metaData->setEnumInfo(strings, values);
263
    } else {
264
        qWarning() << kMissingMetadata << name();
265 266 267
    }
}

268 269 270 271 272
QStringList Fact::bitmaskStrings(void) const
{
    if (_metaData) {
        return _metaData->bitmaskStrings();
    } else {
273
        qWarning() << kMissingMetadata << name();
274 275 276 277 278 279 280 281 282
        return QStringList();
    }
}

QVariantList Fact::bitmaskValues(void) const
{
    if (_metaData) {
        return _metaData->bitmaskValues();
    } else {
283
        qWarning() << kMissingMetadata << name();
284 285 286 287
        return QVariantList();
    }
}

288
QString Fact::_variantToString(const QVariant& variant, int decimalPlaces) const
289
{
290 291 292
    QString valueString;

    switch (type()) {
Don Gagne's avatar
Don Gagne committed
293 294 295 296 297 298
    case FactMetaData::valueTypeFloat:
    {
        float fValue = variant.toFloat();
        if (qIsNaN(fValue)) {
            valueString = QStringLiteral("--.--");
        } else {
299
            valueString = QString("%1").arg(fValue, 0, 'f', decimalPlaces);
Don Gagne's avatar
Don Gagne committed
300 301 302 303 304 305 306 307 308
        }
    }
        break;
    case FactMetaData::valueTypeDouble:
    {
        double dValue = variant.toDouble();
        if (qIsNaN(dValue)) {
            valueString = QStringLiteral("--.--");
        } else {
309
            valueString = QString("%1").arg(dValue, 0, 'f', decimalPlaces);
Don Gagne's avatar
Don Gagne committed
310 311 312
        }
    }
        break;
Don Gagne's avatar
Don Gagne committed
313 314 315
    case FactMetaData::valueTypeBool:
        valueString = variant.toBool() ? tr("true") : tr("false");
        break;
316 317 318 319 320 321 322 323 324 325 326 327
    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
328 329 330
    default:
        valueString = variant.toString();
        break;
331 332 333
    }

    return valueString;
334 335
}

336 337 338 339 340 341
QString Fact::rawValueStringFullPrecision(void) const
{
    return _variantToString(rawValue(), 18);
}


342 343
QString Fact::rawValueString(void) const
{
344
    return _variantToString(rawValue(), decimalPlaces());
345 346 347
}

QString Fact::cookedValueString(void) const
348
{
349
    return _variantToString(cookedValue(), decimalPlaces());
350 351
}

352 353 354 355 356 357 358 359
QVariant Fact::rawDefaultValue(void) const
{
    if (_metaData) {
        if (!_metaData->defaultValueAvailable()) {
            qDebug() << "Access to unavailable default value";
        }
        return _metaData->rawDefaultValue();
    } else {
360
        qWarning() << kMissingMetadata << name();
361 362 363 364 365
        return QVariant(0);
    }
}

QVariant Fact::cookedDefaultValue(void) const
366
{
Don Gagne's avatar
Don Gagne committed
367 368 369 370
    if (_metaData) {
        if (!_metaData->defaultValueAvailable()) {
            qDebug() << "Access to unavailable default value";
        }
371
        return _metaData->cookedDefaultValue();
Don Gagne's avatar
Don Gagne committed
372
    } else {
373
        qWarning() << kMissingMetadata << name();
Don Gagne's avatar
Don Gagne committed
374
        return QVariant(0);
375
    }
376 377
}

378
QString Fact::cookedDefaultValueString(void) const
379
{
380
    return _variantToString(cookedDefaultValue(), decimalPlaces());
381 382
}

383
FactMetaData::ValueType_t Fact::type(void) const
384
{
385
    return _type;
386 387
}

388
QString Fact::shortDescription(void) const
389
{
Don Gagne's avatar
Don Gagne committed
390 391 392
    if (_metaData) {
        return _metaData->shortDescription();
    } else {
393
        qWarning() << kMissingMetadata << name();
Don Gagne's avatar
Don Gagne committed
394 395
        return QString();
    }
396 397
}

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

408 409 410 411 412
QString Fact::rawUnits(void) const
{
    if (_metaData) {
        return _metaData->rawUnits();
    } else {
413
        qWarning() << kMissingMetadata << name();
414 415 416 417 418
        return QString();
    }
}

QString Fact::cookedUnits(void) const
419
{
Don Gagne's avatar
Don Gagne committed
420
    if (_metaData) {
421
        return _metaData->cookedUnits();
Don Gagne's avatar
Don Gagne committed
422
    } else {
423
        qWarning() << kMissingMetadata << name();
Don Gagne's avatar
Don Gagne committed
424 425
        return QString();
    }
426 427
}

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

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

448 449
QString Fact::cookedMinString(void) const
{
450
    return _variantToString(cookedMin(), decimalPlaces());
451 452 453
}

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

463
QVariant Fact::cookedMax(void) const
464
{
465 466 467
    if (_metaData) {
        return _metaData->cookedMax();
    } else {
468
        qWarning() << kMissingMetadata << name();
469 470 471 472 473 474
        return QVariant(0);
    }
}

QString Fact::cookedMaxString(void) const
{
475
    return _variantToString(cookedMax(), decimalPlaces());
476 477
}

478
bool Fact::minIsDefaultForType(void) const
Don Gagne's avatar
Don Gagne committed
479 480 481 482
{
    if (_metaData) {
        return _metaData->minIsDefaultForType();
    } else {
483
        qWarning() << kMissingMetadata << name();
Don Gagne's avatar
Don Gagne committed
484 485 486 487
        return false;
    }
}

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

498 499 500 501 502
int Fact::decimalPlaces(void) const
{
    if (_metaData) {
        return _metaData->decimalPlaces();
    } else {
503
        qWarning() << kMissingMetadata << name();
504 505 506 507
        return FactMetaData::defaultDecimalPlaces;
    }
}

508 509 510 511 512 513 514 515 516 517
QString Fact::category(void) const
{
    if (_metaData) {
        return _metaData->category();
    } else {
        qWarning() << kMissingMetadata << name();
        return QString();
    }
}

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

528
void Fact::setMetaData(FactMetaData* metaData, bool setDefaultFromMetaData)
529 530
{
    _metaData = metaData;
531 532 533
    if (setDefaultFromMetaData) {
        setRawValue(rawDefaultValue());
    }
Don Gagne's avatar
Don Gagne committed
534
    emit valueChanged(cookedValue());
535
}
536

537
bool Fact::valueEqualsDefault(void) const
538
{
Don Gagne's avatar
Don Gagne committed
539 540
    if (_metaData) {
        if (_metaData->defaultValueAvailable()) {
541
            return _metaData->rawDefaultValue() == rawValue();
Don Gagne's avatar
Don Gagne committed
542 543 544
        } else {
            return false;
        }
545
    } else {
546
        qWarning() << kMissingMetadata << name();
547 548 549 550
        return false;
    }
}

551
bool Fact::defaultValueAvailable(void) const
552
{
Don Gagne's avatar
Don Gagne committed
553 554 555
    if (_metaData) {
        return _metaData->defaultValueAvailable();
    } else {
556
        qWarning() << kMissingMetadata << name();
Don Gagne's avatar
Don Gagne committed
557 558 559 560
        return false;
    }
}

561
QString Fact::validate(const QString& cookedValue, bool convertOnly)
Don Gagne's avatar
Don Gagne committed
562 563 564 565 566
{
    if (_metaData) {
        QVariant    typedValue;
        QString     errorString;
        
567
        _metaData->convertAndValidateCooked(cookedValue, convertOnly, typedValue, errorString);
Don Gagne's avatar
Don Gagne committed
568 569 570
        
        return errorString;
    } else {
571
        qWarning() << kMissingMetadata << name();
Don Gagne's avatar
Don Gagne committed
572 573 574
        return QString("Internal error: Meta data pointer missing");
    }
}
575

576 577 578 579 580 581 582 583 584 585 586
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 {
587
        qWarning() << kMissingMetadata << name();
588 589 590 591
    }
    return QVariant();
}

592 593 594 595 596
bool Fact::rebootRequired(void) const
{
    if (_metaData) {
        return _metaData->rebootRequired();
    } else {
597
        qWarning() << kMissingMetadata << name();
598 599 600
        return false;
    }
}
Don Gagne's avatar
Don Gagne committed
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626

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());
    }
}
627 628 629 630 631 632 633 634 635 636

QString Fact::enumOrValueString(void)
{
    if (_metaData) {
        if (_metaData->enumStrings().count()) {
            return enumStringValue();
        } else {
            return cookedValueString();
        }
    } else {
637
        qWarning() << kMissingMetadata << name();
638 639 640
    }
    return QString();
}
Don Gagne's avatar
Don Gagne committed
641

642
double Fact::rawIncrement(void) const
Don Gagne's avatar
Don Gagne committed
643 644
{
    if (_metaData) {
645
        return _metaData->rawIncrement();
Don Gagne's avatar
Don Gagne committed
646
    } else {
647
        qWarning() << kMissingMetadata << name();
Don Gagne's avatar
Don Gagne committed
648 649 650
    }
    return std::numeric_limits<double>::quiet_NaN();
}
651

652 653 654 655 656 657 658 659 660 661
double Fact::cookedIncrement(void) const
{
    if (_metaData) {
        return _metaData->cookedIncrement();
    } else {
        qWarning() << kMissingMetadata << name();
    }
    return std::numeric_limits<double>::quiet_NaN();
}

662 663 664 665 666
bool Fact::hasControl(void) const
{
    if (_metaData) {
        return _metaData->hasControl();
    } else {
667
        qWarning() << kMissingMetadata << name();
668 669 670
        return false;
    }
}
671 672 673 674 675 676

bool Fact::readOnly(void) const
{
    if (_metaData) {
        return _metaData->readOnly();
    } else {
677
        qWarning() << kMissingMetadata << name();
678 679 680
        return false;
    }
}
681

682 683 684 685 686 687 688 689 690 691
bool Fact::writeOnly(void) const
{
    if (_metaData) {
        return _metaData->writeOnly();
    } else {
        qWarning() << kMissingMetadata << name();
        return false;
    }
}

692 693 694 695 696 697 698 699 700
bool Fact::volatileValue(void) const
{
    if (_metaData) {
        return _metaData->volatileValue();
    } else {
        qWarning() << kMissingMetadata << name();
        return false;
    }
}
701 702 703 704 705 706 707 708

FactValueSliderListModel* Fact::valueSliderModel(void)
{
    if (!_valueSliderModel) {
        _valueSliderModel = new FactValueSliderListModel(*this);
    }
    return _valueSliderModel;
}