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 55 56 57 58 59 60 61 62
Fact::Fact(FactMetaData* metaData, QObject* parent)
    : QObject(parent)
    , _name                     (metaData->name())
    , _componentId              (0)
    , _rawValue                 (0)
    , _type                     (metaData->type())
    , _metaData                 (NULL)
    , _sendValueChangedSignals  (true)
    , _deferredValueChangeSignal(false)
63
    , _valueSliderModel         (NULL)
64 65 66 67 68 69
{
    // Allow core plugin a chance to override the default value
    qgcApp()->toolbox()->corePlugin()->adjustSettingMetaData(*metaData);
    setMetaData(metaData, true /* setDefaultFromMetaData */);
}

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

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

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

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

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

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

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

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

    // 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
173
}
174 175 176 177 178 179

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

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

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

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

    return QString();
}

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

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

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

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

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

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

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

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

    return valueString;
332 333
}

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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