Fact.cc 18.5 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.
 *
 ****************************************************************************/

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
    : QObject                   (parent)
    , _componentId              (-1)
    , _rawValue                 (0)
    , _type                     (FactMetaData::valueTypeInt32)
Gus Grubba's avatar
Gus Grubba committed
26
    , _metaData                 (nullptr)
27
    , _sendValueChangedSignals  (true)
Don Gagne's avatar
Don Gagne committed
28
    , _deferredValueChangeSignal(false)
Gus Grubba's avatar
Gus Grubba committed
29
    , _valueSliderModel         (nullptr)
30
    , _ignoreQGCRebootRequired  (false)
Don Gagne's avatar
Don Gagne committed
31 32 33
{    
    FactMetaData* metaData = new FactMetaData(_type, this);
    setMetaData(metaData);
34

35
    _init();
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
    : QObject                   (parent)
    , _name                     (name)
    , _componentId              (componentId)
    , _rawValue                 (0)
    , _type                     (type)
Gus Grubba's avatar
Gus Grubba committed
44
    , _metaData                 (nullptr)
45
    , _sendValueChangedSignals  (true)
Don Gagne's avatar
Don Gagne committed
46
    , _deferredValueChangeSignal(false)
Gus Grubba's avatar
Gus Grubba committed
47
    , _valueSliderModel         (nullptr)
48
    , _ignoreQGCRebootRequired  (false)
Don Gagne's avatar
Don Gagne committed
49
{
Don Gagne's avatar
Don Gagne committed
50 51
    FactMetaData* metaData = new FactMetaData(_type, this);
    setMetaData(metaData);
52 53

    _init();
Don Gagne's avatar
Don Gagne committed
54
}
Don Gagne's avatar
Don Gagne committed
55

56
Fact::Fact(const QString& settingsGroup, FactMetaData* metaData, QObject* parent)
57 58 59 60 61
    : QObject(parent)
    , _name                     (metaData->name())
    , _componentId              (0)
    , _rawValue                 (0)
    , _type                     (metaData->type())
Gus Grubba's avatar
Gus Grubba committed
62
    , _metaData                 (nullptr)
63 64
    , _sendValueChangedSignals  (true)
    , _deferredValueChangeSignal(false)
Gus Grubba's avatar
Gus Grubba committed
65
    , _valueSliderModel         (nullptr)
66
    , _ignoreQGCRebootRequired  (false)
67
{
68
    qgcApp()->toolbox()->corePlugin()->adjustSettingMetaData(settingsGroup, *metaData);
69
    setMetaData(metaData, true /* setDefaultFromMetaData */);
70 71

    _init();
72 73
}

Don Gagne's avatar
Don Gagne committed
74 75 76 77
Fact::Fact(const Fact& other, QObject* parent)
    : QObject(parent)
{
    *this = other;
78 79 80 81 82 83

    _init();
}

void Fact::_init(void)
{
84
    QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
85
    connect(this, &Fact::_containerRawValueChanged, this, &Fact::_checkForRebootMessaging);
Don Gagne's avatar
Don Gagne committed
86 87 88 89
}

const Fact& Fact::operator=(const Fact& other)
{
Don Gagne's avatar
Don Gagne committed
90 91 92 93 94 95
    _name                       = other._name;
    _componentId                = other._componentId;
    _rawValue                   = other._rawValue;
    _type                       = other._type;
    _sendValueChangedSignals    = other._sendValueChangedSignals;
    _deferredValueChangeSignal  = other._deferredValueChangeSignal;
96 97
    _valueSliderModel           = nullptr;
    _ignoreQGCRebootRequired    = other._ignoreQGCRebootRequired;
Don Gagne's avatar
Don Gagne committed
98 99 100
    if (_metaData && other._metaData) {
        *_metaData = *other._metaData;
    } else {
Gus Grubba's avatar
Gus Grubba committed
101
        _metaData = nullptr;
Don Gagne's avatar
Don Gagne committed
102 103 104
    }
    
    return *this;
Don Gagne's avatar
Don Gagne committed
105 106
}

Don Gagne's avatar
Don Gagne committed
107
void Fact::forceSetRawValue(const QVariant& value)
108 109 110 111 112
{
    if (_metaData) {
        QVariant    typedValue;
        QString     errorString;
        
113
        if (_metaData->convertAndValidateRaw(value, true /* convertOnly */, typedValue, errorString)) {
Don Gagne's avatar
Don Gagne committed
114
            _rawValue.setValue(typedValue);
Don Gagne's avatar
Don Gagne committed
115
            _sendValueChangedSignal(cookedValue());
116 117
            //-- Must be in this order
            emit _containerRawValueChanged(rawValue());
118
            emit rawValueChanged(_rawValue);
119 120
        }
    } else {
121
        qWarning() << kMissingMetadata << name();
122 123 124
    }
}

Gus Grubba's avatar
Gus Grubba committed
125
void Fact::setRawValue(const QVariant& value)
Don Gagne's avatar
Don Gagne committed
126
{
Don Gagne's avatar
Don Gagne committed
127 128 129 130
    if (_metaData) {
        QVariant    typedValue;
        QString     errorString;
        
131
        if (_metaData->convertAndValidateRaw(value, true /* convertOnly */, typedValue, errorString)) {
132 133
            if (typedValue != _rawValue) {
                _rawValue.setValue(typedValue);
Don Gagne's avatar
Don Gagne committed
134
                _sendValueChangedSignal(cookedValue());
135 136
                //-- Must be in this order
                emit _containerRawValueChanged(rawValue());
137
                emit rawValueChanged(_rawValue);
Don Gagne's avatar
Don Gagne committed
138 139 140
            }
        }
    } else {
141
        qWarning() << kMissingMetadata << name();
142
    }
Don Gagne's avatar
Don Gagne committed
143 144
}

Don Gagne's avatar
Don Gagne committed
145
void Fact::setCookedValue(const QVariant& value)
146 147 148 149
{
    if (_metaData) {
        setRawValue(_metaData->cookedTranslator()(value));
    } else {
150
        qWarning() << kMissingMetadata << name();
151 152 153
    }
}

Gus Grubba's avatar
Gus Grubba committed
154
int Fact::valueIndex(const QString& value)
155 156
{
    if (_metaData) {
Gus Grubba's avatar
Gus Grubba committed
157 158 159 160 161 162 163 164 165 166 167
        return _metaData->enumStrings().indexOf(value);
    }
    qWarning() << kMissingMetadata << name();
    return -1;
}

void Fact::setEnumStringValue(const QString& value)
{
    int index = valueIndex(value);
    if (index != -1) {
        setCookedValue(_metaData->enumValues()[index]);
168 169 170 171 172 173
    }
}

void Fact::setEnumIndex(int index)
{
    if (_metaData) {
Don Gagne's avatar
Don Gagne committed
174
        setCookedValue(_metaData->enumValues()[index]);
175
    } else {
176
        qWarning() << kMissingMetadata << name();
177 178 179
    }
}

Don Gagne's avatar
Don Gagne committed
180
void Fact::_containerSetRawValue(const QVariant& value)
Don Gagne's avatar
Don Gagne committed
181
{
182 183 184 185 186
    if(_rawValue != value) {
        _rawValue = value;
        _sendValueChangedSignal(cookedValue());
        emit rawValueChanged(_rawValue);
    }
187 188 189

    // 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
190
}
191 192 193 194 195 196

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

197 198 199 200 201
int Fact::componentId(void) const
{
    return _componentId;
}

Don Gagne's avatar
Don Gagne committed
202
QVariant Fact::cookedValue(void) const
203
{
204 205 206
    if (_metaData) {
        return _metaData->rawTranslator()(_rawValue);
    } else {
207
        qWarning() << kMissingMetadata << name();
208 209 210 211
        return _rawValue;
    }
}

212
QString Fact::enumStringValue(void)
213 214 215
{
    if (_metaData) {
        int enumIndex = this->enumIndex();
Don Gagne's avatar
Don Gagne committed
216
        if (enumIndex >= 0 && enumIndex < _metaData->enumStrings().count()) {
217 218 219
            return _metaData->enumStrings()[enumIndex];
        }
    } else {
220
        qWarning() << kMissingMetadata << name();
221 222 223 224 225
    }

    return QString();
}

226
int Fact::enumIndex(void)
227
{
228
    static const double accuracy = 1.0 / 1000000.0;
229
    if (_metaData) {
230 231 232
        //-- Only enums have an index
        if(_metaData->enumValues().count()) {
            int index = 0;
233
            for (QVariant enumValue: _metaData->enumValues()) {
234
                if (enumValue == rawValue()) {
235 236
                    return index;
                }
237 238 239 240 241 242 243 244
                //-- 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 ++;
245
            }
246
            // Current value is not in list, add it manually
247
            _metaData->addEnumInfo(tr("Unknown: %1").arg(rawValue().toString()), rawValue());
248 249
            emit enumsChanged();
            return index;
250 251
        }
    } else {
252
        qWarning() << kMissingMetadata << name();
253 254 255 256 257 258 259 260 261
    }
    return -1;
}

QStringList Fact::enumStrings(void) const
{
    if (_metaData) {
        return _metaData->enumStrings();
    } else {
262
        qWarning() << kMissingMetadata << name();
263 264 265 266 267 268 269 270 271
        return QStringList();
    }
}

QVariantList Fact::enumValues(void) const
{
    if (_metaData) {
        return _metaData->enumValues();
    } else {
272
        qWarning() << kMissingMetadata << name();
273 274
        return QVariantList();
    }
275 276
}

277 278 279
void Fact::setEnumInfo(const QStringList& strings, const QVariantList& values)
{
    if (_metaData) {
280
        _metaData->setEnumInfo(strings, values);
281
    } else {
282
        qWarning() << kMissingMetadata << name();
283 284 285
    }
}

286 287 288 289 290
QStringList Fact::bitmaskStrings(void) const
{
    if (_metaData) {
        return _metaData->bitmaskStrings();
    } else {
291
        qWarning() << kMissingMetadata << name();
292 293 294 295 296 297 298 299 300
        return QStringList();
    }
}

QVariantList Fact::bitmaskValues(void) const
{
    if (_metaData) {
        return _metaData->bitmaskValues();
    } else {
301
        qWarning() << kMissingMetadata << name();
302 303 304 305
        return QVariantList();
    }
}

306
QString Fact::_variantToString(const QVariant& variant, int decimalPlaces) const
307
{
308 309 310
    QString valueString;

    switch (type()) {
Don Gagne's avatar
Don Gagne committed
311 312 313 314 315 316
    case FactMetaData::valueTypeFloat:
    {
        float fValue = variant.toFloat();
        if (qIsNaN(fValue)) {
            valueString = QStringLiteral("--.--");
        } else {
317
            valueString = QString("%1").arg(fValue, 0, 'f', decimalPlaces);
Don Gagne's avatar
Don Gagne committed
318 319 320 321 322 323 324 325 326
        }
    }
        break;
    case FactMetaData::valueTypeDouble:
    {
        double dValue = variant.toDouble();
        if (qIsNaN(dValue)) {
            valueString = QStringLiteral("--.--");
        } else {
327
            valueString = QString("%1").arg(dValue, 0, 'f', decimalPlaces);
Don Gagne's avatar
Don Gagne committed
328 329 330
        }
    }
        break;
Don Gagne's avatar
Don Gagne committed
331 332 333
    case FactMetaData::valueTypeBool:
        valueString = variant.toBool() ? tr("true") : tr("false");
        break;
334 335 336 337 338 339 340 341 342 343 344 345
    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
346 347 348
    default:
        valueString = variant.toString();
        break;
349 350 351
    }

    return valueString;
352 353
}

354 355 356 357 358 359
QString Fact::rawValueStringFullPrecision(void) const
{
    return _variantToString(rawValue(), 18);
}


360 361
QString Fact::rawValueString(void) const
{
362
    return _variantToString(rawValue(), decimalPlaces());
363 364 365
}

QString Fact::cookedValueString(void) const
366
{
367
    return _variantToString(cookedValue(), decimalPlaces());
368 369
}

370 371 372 373 374 375 376 377
QVariant Fact::rawDefaultValue(void) const
{
    if (_metaData) {
        if (!_metaData->defaultValueAvailable()) {
            qDebug() << "Access to unavailable default value";
        }
        return _metaData->rawDefaultValue();
    } else {
378
        qWarning() << kMissingMetadata << name();
379 380 381 382 383
        return QVariant(0);
    }
}

QVariant Fact::cookedDefaultValue(void) const
384
{
Don Gagne's avatar
Don Gagne committed
385 386 387 388
    if (_metaData) {
        if (!_metaData->defaultValueAvailable()) {
            qDebug() << "Access to unavailable default value";
        }
389
        return _metaData->cookedDefaultValue();
Don Gagne's avatar
Don Gagne committed
390
    } else {
391
        qWarning() << kMissingMetadata << name();
Don Gagne's avatar
Don Gagne committed
392
        return QVariant(0);
393
    }
394 395
}

396
QString Fact::cookedDefaultValueString(void) const
397
{
398
    return _variantToString(cookedDefaultValue(), decimalPlaces());
399 400
}

401
FactMetaData::ValueType_t Fact::type(void) const
402
{
403
    return _type;
404 405
}

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

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

426 427 428 429 430
QString Fact::rawUnits(void) const
{
    if (_metaData) {
        return _metaData->rawUnits();
    } else {
431
        qWarning() << kMissingMetadata << name();
432 433 434 435 436
        return QString();
    }
}

QString Fact::cookedUnits(void) const
437
{
Don Gagne's avatar
Don Gagne committed
438
    if (_metaData) {
439
        return _metaData->cookedUnits();
Don Gagne's avatar
Don Gagne committed
440
    } else {
441
        qWarning() << kMissingMetadata << name();
Don Gagne's avatar
Don Gagne committed
442 443
        return QString();
    }
444 445
}

446
QVariant Fact::rawMin(void) const
447
{
Don Gagne's avatar
Don Gagne committed
448
    if (_metaData) {
449
        return _metaData->rawMin();
Don Gagne's avatar
Don Gagne committed
450
    } else {
451
        qWarning() << kMissingMetadata << name();
Don Gagne's avatar
Don Gagne committed
452 453
        return QVariant(0);
    }
454 455
}

456
QVariant Fact::cookedMin(void) const
457
{
458 459 460
    if (_metaData) {
        return _metaData->cookedMin();
    } else {
461
        qWarning() << kMissingMetadata << name();
462 463
        return QVariant(0);
    }
464 465
}

466 467
QString Fact::cookedMinString(void) const
{
468
    return _variantToString(cookedMin(), decimalPlaces());
469 470 471
}

QVariant Fact::rawMax(void) const
472
{
Don Gagne's avatar
Don Gagne committed
473
    if (_metaData) {
474
        return _metaData->rawMax();
Don Gagne's avatar
Don Gagne committed
475
    } else {
476
        qWarning() << kMissingMetadata << name();
Don Gagne's avatar
Don Gagne committed
477 478 479 480
        return QVariant(0);
    }
}

481
QVariant Fact::cookedMax(void) const
482
{
483 484 485
    if (_metaData) {
        return _metaData->cookedMax();
    } else {
486
        qWarning() << kMissingMetadata << name();
487 488 489 490 491 492
        return QVariant(0);
    }
}

QString Fact::cookedMaxString(void) const
{
493
    return _variantToString(cookedMax(), decimalPlaces());
494 495
}

496
bool Fact::minIsDefaultForType(void) const
Don Gagne's avatar
Don Gagne committed
497 498 499 500
{
    if (_metaData) {
        return _metaData->minIsDefaultForType();
    } else {
501
        qWarning() << kMissingMetadata << name();
Don Gagne's avatar
Don Gagne committed
502 503 504 505
        return false;
    }
}

506
bool Fact::maxIsDefaultForType(void) const
Don Gagne's avatar
Don Gagne committed
507 508 509 510
{
    if (_metaData) {
        return _metaData->maxIsDefaultForType();
    } else {
511
        qWarning() << kMissingMetadata << name();
Don Gagne's avatar
Don Gagne committed
512 513
        return false;
    }
514 515
}

516 517 518 519 520
int Fact::decimalPlaces(void) const
{
    if (_metaData) {
        return _metaData->decimalPlaces();
    } else {
521
        qWarning() << kMissingMetadata << name();
522
        return FactMetaData::kDefaultDecimalPlaces;
523 524 525
    }
}

526 527 528 529 530 531 532 533 534 535
QString Fact::category(void) const
{
    if (_metaData) {
        return _metaData->category();
    } else {
        qWarning() << kMissingMetadata << name();
        return QString();
    }
}

536
QString Fact::group(void) const
537
{
Don Gagne's avatar
Don Gagne committed
538 539 540
    if (_metaData) {
        return _metaData->group();
    } else {
541
        qWarning() << kMissingMetadata << name();
Don Gagne's avatar
Don Gagne committed
542 543
        return QString();
    }
544 545
}

546
void Fact::setMetaData(FactMetaData* metaData, bool setDefaultFromMetaData)
547 548
{
    _metaData = metaData;
549 550 551
    if (setDefaultFromMetaData) {
        setRawValue(rawDefaultValue());
    }
Don Gagne's avatar
Don Gagne committed
552
    emit valueChanged(cookedValue());
553
}
554

555
bool Fact::valueEqualsDefault(void) const
556
{
Don Gagne's avatar
Don Gagne committed
557 558
    if (_metaData) {
        if (_metaData->defaultValueAvailable()) {
559
            return _metaData->rawDefaultValue() == rawValue();
Don Gagne's avatar
Don Gagne committed
560 561 562
        } else {
            return false;
        }
563
    } else {
564
        qWarning() << kMissingMetadata << name();
565 566 567 568
        return false;
    }
}

569
bool Fact::defaultValueAvailable(void) const
570
{
Don Gagne's avatar
Don Gagne committed
571 572 573
    if (_metaData) {
        return _metaData->defaultValueAvailable();
    } else {
574
        qWarning() << kMissingMetadata << name();
Don Gagne's avatar
Don Gagne committed
575 576 577 578
        return false;
    }
}

579
QString Fact::validate(const QString& cookedValue, bool convertOnly)
Don Gagne's avatar
Don Gagne committed
580 581 582 583 584
{
    if (_metaData) {
        QVariant    typedValue;
        QString     errorString;
        
585
        _metaData->convertAndValidateCooked(cookedValue, convertOnly, typedValue, errorString);
Don Gagne's avatar
Don Gagne committed
586 587 588
        
        return errorString;
    } else {
589
        qWarning() << kMissingMetadata << name();
Don Gagne's avatar
Don Gagne committed
590 591 592
        return QString("Internal error: Meta data pointer missing");
    }
}
593

594 595 596 597 598 599 600 601 602 603 604
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 {
605
        qWarning() << kMissingMetadata << name();
606 607 608 609
    }
    return QVariant();
}

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

bool Fact::qgcRebootRequired(void) const
{
622 623 624
    if (_ignoreQGCRebootRequired) {
        return false;
    } else if (_metaData) {
625
        return _metaData->qgcRebootRequired();
626
    } else {
627
        qWarning() << kMissingMetadata << name();
628 629 630
        return false;
    }
}
Don Gagne's avatar
Don Gagne committed
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656

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());
    }
}
657 658 659 660 661 662 663 664 665 666

QString Fact::enumOrValueString(void)
{
    if (_metaData) {
        if (_metaData->enumStrings().count()) {
            return enumStringValue();
        } else {
            return cookedValueString();
        }
    } else {
667
        qWarning() << kMissingMetadata << name();
668 669 670
    }
    return QString();
}
Don Gagne's avatar
Don Gagne committed
671

672
double Fact::rawIncrement(void) const
Don Gagne's avatar
Don Gagne committed
673 674
{
    if (_metaData) {
675
        return _metaData->rawIncrement();
Don Gagne's avatar
Don Gagne committed
676
    } else {
677
        qWarning() << kMissingMetadata << name();
Don Gagne's avatar
Don Gagne committed
678 679 680
    }
    return std::numeric_limits<double>::quiet_NaN();
}
681

682 683 684 685 686 687 688 689 690 691
double Fact::cookedIncrement(void) const
{
    if (_metaData) {
        return _metaData->cookedIncrement();
    } else {
        qWarning() << kMissingMetadata << name();
    }
    return std::numeric_limits<double>::quiet_NaN();
}

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

bool Fact::readOnly(void) const
{
    if (_metaData) {
        return _metaData->readOnly();
    } else {
707
        qWarning() << kMissingMetadata << name();
708 709 710
        return false;
    }
}
711

712 713 714 715 716 717 718 719 720 721
bool Fact::writeOnly(void) const
{
    if (_metaData) {
        return _metaData->writeOnly();
    } else {
        qWarning() << kMissingMetadata << name();
        return false;
    }
}

722 723 724 725 726 727 728 729 730
bool Fact::volatileValue(void) const
{
    if (_metaData) {
        return _metaData->volatileValue();
    } else {
        qWarning() << kMissingMetadata << name();
        return false;
    }
}
731 732 733 734 735 736 737 738

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

void Fact::_checkForRebootMessaging(void)
{
742 743 744
    if(qgcApp()) {
        if (!qgcApp()->runningUnitTests()) {
            if (vehicleRebootRequired()) {
745
                qgcApp()->showAppMessage(tr("Change of parameter %1 requires a Vehicle reboot to take effect.").arg(name()));
746
            } else if (qgcRebootRequired()) {
747
                qgcApp()->showAppMessage(tr("Change of '%1' value requires restart of %2 to take effect.").arg(shortDescription()).arg(qgcApp()->applicationName()));
748
            }
749 750 751
        }
    }
}
752 753 754 755 756

void Fact::_setIgnoreQGCRebootRequired(bool ignore)
{
    _ignoreQGCRebootRequired = ignore;
}