QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
Fact.cc
Go to the documentation of this file.
1#include <cmath>
2#include <cstdio>
3#include <cstdlib>
4#include <cstring>
5#include <limits>
6
7#include "Fact.h"
8#include "AppMessages.h"
9#include "QGCApplication.h"
10#include "QGCCorePlugin.h"
11#include "QGCLoggingCategory.h"
12#include "SettingsManager.h"
13
14QGC_LOGGING_CATEGORY(FactLog, "FactSystem.Fact")
15
16Fact::Fact(QObject *parent)
17 : QObject(parent)
18{
19 // qCDebug(FactLog) << Q_FUNC_INFO << this;
20
21 FactMetaData *const metaData = new FactMetaData(_type, this);
22 setMetaData(metaData);
23
24 _init();
25}
26
27Fact::Fact(int componentId, const QString &name, FactMetaData::ValueType_t type, QObject *parent)
28 : QObject(parent)
29 , _name(name)
30 , _componentId(componentId)
31 , _type(type)
32{
33 // qCDebug(FactLog) << Q_FUNC_INFO << this;
34
35 FactMetaData *const metaData = new FactMetaData(_type, this);
37
38 _init();
39}
40
41Fact::Fact(const QString& settingsGroup, FactMetaData *metaData, QObject *parent)
42 : QObject(parent)
43 , _name(metaData->name())
44 , _componentId(0)
45 , _type(metaData->type())
46{
47 // qCDebug(FactLog) << Q_FUNC_INFO << this;
48
49 bool visible = true;
50 SettingsManager::adjustSettingMetaData(settingsGroup, *metaData, visible);
51 setMetaData(metaData, true /* setDefaultFromMetaData */);
52
53 if (!QGC::runningUnitTests()) {
54 if (metaData->defaultValueAvailable() && !visible) {
55 // If setting is not visible, we force to default value
56 const QVariant defaultValue = metaData->rawDefaultValue();
57 QMutexLocker<QRecursiveMutex> locker(&_rawValueMutex);
58 _rawValue = defaultValue;
59 }
60 }
61
62 _init();
63}
64
65Fact::Fact(const Fact &other, QObject *parent)
66 : QObject(parent)
67{
68 // qCDebug(FactLog) << Q_FUNC_INFO << this;
69
70 *this = other;
71
72 _init();
73}
74
76{
77 // qCDebug(FactLog) << Q_FUNC_INFO << this;
78}
79
80void Fact::_init()
81{
82 (void) connect(this, &Fact::containerRawValueChanged, this, &Fact::_checkForRebootMessaging);
83}
84
85const Fact &Fact::operator=(const Fact& other)
86{
87 if (this == &other) {
88 return *this;
89 }
90
91 QMutexLocker<QRecursiveMutex> otherLocker(&other._rawValueMutex);
92 QMutexLocker<QRecursiveMutex> locker(&_rawValueMutex);
93
94 _name = other._name;
96 _rawValue = other._rawValue;
97 _type = other._type;
100 if (_metaData && other._metaData) {
101 *_metaData = *other._metaData;
102 } else {
103 if (_metaData) {
104 (void) disconnect(_metaData, &FactMetaData::appSettingsUnitsChanged, this, &Fact::_appSettingsUnitsChanged);
105 }
106 _metaData = nullptr;
107 }
108
109 return *this;
110}
111
112void Fact::forceSetRawValue(const QVariant &value)
113{
114 if (_metaData) {
115 QVariant typedValue;
116 QString errorString;
117
118 if (_metaData->convertAndValidateRaw(value, true /* convertOnly */, typedValue, errorString)) {
119 {
120 QMutexLocker<QRecursiveMutex> locker(&_rawValueMutex);
121 _rawValue = typedValue;
122 }
123
124 const QVariant cooked = _metaData->rawTranslator()(typedValue);
126 //-- Must be in this order
127 emit containerRawValueChanged(typedValue);
128 emit rawValueChanged(typedValue);
129 }
130 } else {
131 qCWarning(FactLog) << kMissingMetadata << name();
132 }
133}
134
135void Fact::setRawValue(const QVariant &value)
136{
137 if (_metaData) {
138 QVariant typedValue;
139 QString errorString;
140
141 if (_metaData->convertAndValidateRaw(value, true /* convertOnly */, typedValue, errorString)) {
142 bool changed = false;
143 {
144 QMutexLocker<QRecursiveMutex> locker(&_rawValueMutex);
145 if (typedValue != _rawValue) {
146 _rawValue = typedValue;
147 changed = true;
148 }
149 }
150
151 if (changed) {
152 const QVariant cooked = _metaData->rawTranslator()(typedValue);
154 //-- Must be in this order
155 emit containerRawValueChanged(typedValue);
156 emit rawValueChanged(typedValue);
157 }
158 }
159 } else {
160 qCWarning(FactLog) << kMissingMetadata << name();
161 }
162}
163
164void Fact::setCookedValue(const QVariant& value)
165{
166 if (_metaData) {
168 } else {
169 qCWarning(FactLog) << kMissingMetadata << name();
170 }
171}
172
173int Fact::valueIndex(const QString &value) const
174{
175 if (_metaData) {
176 return _metaData->enumStrings().indexOf(value);
177 }
178 qCWarning(FactLog) << kMissingMetadata << name();
179 return -1;
180}
181
182void Fact::setEnumStringValue(const QString &value)
183{
184 const int index = valueIndex(value);
185 if (index != -1) {
187 }
188}
189
190void Fact::setEnumIndex(int index)
191{
192 if (_metaData) {
194 } else {
195 qCWarning(FactLog) << kMissingMetadata << name();
196 }
197}
198
199void Fact::containerSetRawValue(const QVariant &value)
200{
201 QVariant cooked;
202 QVariant currentRaw = value;
203 bool changed = false;
204 {
205 QMutexLocker<QRecursiveMutex> locker(&_rawValueMutex);
206 if (_rawValue != value) {
207 _rawValue = value;
208 changed = true;
209 }
210 currentRaw = _rawValue;
211 if (_metaData) {
212 cooked = _metaData->rawTranslator()(_rawValue);
213 } else {
214 cooked = _rawValue;
215 }
216 }
217
218 if (changed) {
220 emit rawValueChanged(currentRaw);
221 }
222
223 // This always need to be signalled in order to support forceSetRawValue usage and waiting for vehicleUpdated signal
224 emit vehicleUpdated(currentRaw);
225}
226
227QVariant Fact::cookedValue() const
228{
229 QMutexLocker<QRecursiveMutex> locker(&_rawValueMutex);
230 if (_metaData) {
232 }
233
234 qCWarning(FactLog) << kMissingMetadata << name();
235 return _rawValue;
236}
237
238QVariant Fact::rawToCooked(const QVariant &rawValue) const
239{
240 if (_metaData) {
242 }
243
244 qCWarning(FactLog) << kMissingMetadata << name();
245 return rawValue;
246}
247
249{
250 if (_metaData) {
251 const int enumIndex = this->enumIndex();
252 if ((enumIndex >= 0) && (enumIndex < _metaData->enumStrings().count())) {
254 }
255 } else {
256 qCWarning(FactLog) << kMissingMetadata << name();
257 }
258
259 return QString();
260}
261
263{
264 if (_metaData) {
265 //-- Only enums have an index
266 if (!_metaData->enumValues().isEmpty()) {
267 int index = 0;
268 for (const QVariant &enumValue: _metaData->enumValues()) {
269 if (enumValue == rawValue()) {
270 return index;
271 }
272 //-- Float comparisons don't always work
274 const double diff = fabs(enumValue.toDouble() - rawValue().toDouble());
275 static constexpr double accuracy = 1.0 / 1000000.0;
276 if (diff < accuracy) {
277 return index;
278 }
279 }
280 index++;
281 }
282 // Current value is not in list, add it manually. Defer the signal since this can
283 // be called from within a QML binding read and a synchronous emit causes binding loops.
284 _metaData->addEnumInfo(tr("Unknown: %1").arg(rawValue().toString()), rawValue());
285 QMetaObject::invokeMethod(this, &Fact::enumsChanged, Qt::QueuedConnection);
286 return index;
287 }
288 } else {
289 qCWarning(FactLog) << kMissingMetadata << name();
290 }
291 return -1;
292}
293
294QStringList Fact::enumStrings() const
295{
296 if (_metaData) {
297 return _metaData->enumStrings();
298 } else {
299 qCWarning(FactLog) << kMissingMetadata << name();
300 return QStringList();
301 }
302}
303
304QVariantList Fact::enumValues() const
305{
306 if (_metaData) {
307 return _metaData->enumValues();
308 } else {
309 qCWarning(FactLog) << kMissingMetadata << name();
310 return QVariantList();
311 }
312}
313
314void Fact::setEnumInfo(const QStringList &strings, const QVariantList &values)
315{
316 if (_metaData) {
317 _metaData->setEnumInfo(strings, values);
318 emit enumsChanged();
319 } else {
320 qCWarning(FactLog) << kMissingMetadata << name();
321 }
322}
323
324QStringList Fact::bitmaskStrings() const
325{
326 if (_metaData) {
327 return _metaData->bitmaskStrings();
328 } else {
329 qCWarning(FactLog) << kMissingMetadata << name();
330 return QStringList();
331 }
332}
333
334QVariantList Fact::bitmaskValues() const
335{
336 if (_metaData) {
337 return _metaData->bitmaskValues();
338 } else {
339 qCWarning(FactLog) << kMissingMetadata << name();
340 return QVariantList();
341 }
342}
343
345{
346 if (_metaData) {
347 const auto values = _metaData->bitmaskValues();
348 const auto strings = _metaData->bitmaskStrings();
349 if (values.size() != strings.size()) {
350 qCWarning(FactLog) << "Size of bitmask value and string is different." << name();
351 return {};
352 }
353
354 QStringList selected;
355 for (qsizetype i = 0; i < values.size(); i++) {
356 if (rawValue().toInt() & values[i].toInt()) {
357 selected += strings[i];
358 }
359 }
360
361 if (selected.isEmpty()) {
362 selected += "Not value selected";
363 }
364
365 return selected;
366 } else {
367 qCWarning(FactLog) << kMissingMetadata << name();
368 return {};
369 }
370}
371
372QString Fact::_variantToString(const QVariant &variant, int decimalPlaces) const
373{
374 QString valueString;
375
376 const auto stripNegativeZero = [](QString &candidate) {
377 static const QRegularExpression reNegativeZero(QStringLiteral("^-0\\.0+$"));
378 const auto match = reNegativeZero.match(candidate);
379 if (match.hasMatch() || candidate == QStringLiteral("-0")) {
380 candidate = candidate.mid(1);
381 }
382 };
383
384 switch (type()) {
386 {
387 const float fValue = variant.toFloat();
388 if (qIsNaN(fValue)) {
389 valueString = invalidValueString(decimalPlaces);
390 } else {
391 valueString = QStringLiteral("%1").arg(fValue, 0, 'f', decimalPlaces);
392 stripNegativeZero(valueString);
393 }
394 }
395 break;
397 {
398 const double dValue = variant.toDouble();
399 if (qIsNaN(dValue)) {
400 valueString = invalidValueString(decimalPlaces);
401 } else {
402 valueString = QStringLiteral("%1").arg(dValue, 0, 'f', decimalPlaces);
403 stripNegativeZero(valueString);
404 }
405 break;
406 }
408 valueString = variant.toBool() ? tr("true") : tr("false");
409 break;
411 {
412 const double dValue = variant.toDouble();
413 if (qIsNaN(dValue)) {
414 valueString = invalidValueString(decimalPlaces);
415 } else {
416 QTime time(0, 0, 0, 0);
417 time = time.addSecs(dValue);
418 valueString = time.toString(QStringLiteral("hh:mm:ss"));
419 }
420 break;
421 }
422 default:
423 valueString = variant.toString();
424 break;
425 }
426
427 return valueString;
428}
429
430QString Fact::invalidValueString(int decimalPlaces) const {
431 switch (type()) {
434 if (decimalPlaces <= 0) {
435 return QStringLiteral("–");
436 }
437 return QStringLiteral("–.") +
438 QString(decimalPlaces, QChar(u'–'));
440 return QStringLiteral("––:––:––");
441 default:
442 return QStringLiteral("–");
443 }
444}
445
447{
449 const float fValue = rawValue().toFloat();
450 if (std::isnan(fValue)) {
451 return invalidValueString(0);
452 }
453 // Find the shortest decimal string that round-trips back to the same float bits.
454 // snprintf with "%.*g" formats to p significant digits; strtof checks the round-trip.
455 // TODO: replace with std::to_chars once macOS min target >= 13.3
456 char buf[32];
457 for (int p = 1; p <= std::numeric_limits<float>::max_digits10; ++p) {
458 std::snprintf(buf, sizeof(buf), "%.*g", p, static_cast<double>(fValue));
459 if (std::strtof(buf, nullptr) == fValue) {
460 break;
461 }
462 }
463 if (std::strcmp(buf, "-0") == 0) {
464 buf[0] = '0';
465 buf[1] = '\0';
466 }
467 return QString::fromLatin1(buf);
468 } else if (type() == FactMetaData::valueTypeDouble) {
469 const double dValue = rawValue().toDouble();
470 if (std::isnan(dValue)) {
471 return invalidValueString(0);
472 }
473 // TODO: replace with std::to_chars once macOS min target >= 13.3
474 QString result = QString::number(dValue, 'g', QLocale::FloatingPointShortest);
475 if (result == QStringLiteral("-0")) {
476 result = QStringLiteral("0");
477 }
478 return result;
479 } else {
480 return _variantToString(rawValue(), 0);
481 }
482}
483
484QString Fact::rawValueString() const
485{
487}
488
490{
492}
493
494QVariant Fact::rawDefaultValue() const
495{
496 if (_metaData) {
498 qCDebug(FactLog) << "Access to unavailable default value";
499 }
500 return _metaData->rawDefaultValue();
501 } else {
502 qCWarning(FactLog) << kMissingMetadata << name();
503 return QVariant(0);
504 }
505}
506
508{
509 if (_metaData) {
511 qCDebug(FactLog) << "Access to unavailable default value";
512 }
514 } else {
515 qCWarning(FactLog) << kMissingMetadata << name();
516 return QVariant(0);
517 }
518}
519
524
526{
527 if (_metaData) {
528 return _metaData->shortDescription();
529 } else {
530 qCWarning(FactLog) << kMissingMetadata << name();
531 return QString();
532 }
533}
534
535QString Fact::label() const
536{
537 if (_metaData) {
538 // Fall back for older metadata which is missing a label
539 if (!_metaData->label().isEmpty()) {
540 return _metaData->label();
541 }
542 if (!_metaData->shortDescription().isEmpty()) {
543 return _metaData->shortDescription();
544 }
545 return name();
546 } else {
547 qCWarning(FactLog) << kMissingMetadata << name();
548 return QString();
549 }
550}
551
553{
554 if (_metaData) {
555 return _metaData->longDescription();
556 } else {
557 qCWarning(FactLog) << kMissingMetadata << name();
558 return QString();
559 }
560}
561
562QString Fact::rawUnits() const
563{
564 if (_metaData) {
565 return _metaData->rawUnits();
566 } else {
567 qCWarning(FactLog) << kMissingMetadata << name();
568 return QString();
569 }
570}
571
572QString Fact::cookedUnits() const
573{
574 if (_metaData) {
575 return _metaData->cookedUnits();
576 } else {
577 qCWarning(FactLog) << kMissingMetadata << name();
578 return QString();
579 }
580}
581
582QVariant Fact::rawMin() const
583{
584 if (_metaData) {
585 return _metaData->rawMin();
586 } else {
587 qCWarning(FactLog) << kMissingMetadata << name();
588 return QVariant(0);
589 }
590}
591
592QVariant Fact::cookedMin() const
593{
594 if (_metaData) {
595 return _metaData->cookedMin();
596 } else {
597 qCWarning(FactLog) << kMissingMetadata << name();
598 return QVariant(0);
599 }
600}
601
602QVariant Fact::rawUserMin() const
603{
604 if (_metaData) {
605 return _metaData->rawUserMin();
606 }
607
608 qCWarning(FactLog) << kMissingMetadata << name();
609 return QVariant(0);
610}
611
612QVariant Fact::cookedUserMin() const
613{
614 if (_metaData) {
615 return _metaData->cookedUserMin();
616 }
617
618 qCWarning(FactLog) << kMissingMetadata << name();
619 return QVariant(0);
620}
621
623{
625}
626
628{
630}
631
632QVariant Fact::rawMax() const
633{
634 if (_metaData) {
635 return _metaData->rawMax();
636 } else {
637 qCWarning(FactLog) << kMissingMetadata << name();
638 return QVariant(0);
639 }
640}
641
642QVariant Fact::cookedMax() const
643{
644 if (_metaData) {
645 return _metaData->cookedMax();
646 } else {
647 qCWarning(FactLog) << kMissingMetadata << name();
648 return QVariant(0);
649 }
650}
651
652QVariant Fact::rawUserMax() const
653{
654 if (_metaData) {
655 return _metaData->rawUserMax();
656 }
657
658 qCWarning(FactLog) << kMissingMetadata << name();
659 return QVariant(0);
660}
661
662QVariant Fact::cookedUserMax() const
663{
664 if (_metaData) {
665 return _metaData->cookedUserMax();
666 }
667
668 qCWarning(FactLog) << kMissingMetadata << name();
669 return QVariant(0);
670}
671
673{
675}
676
678{
680}
681
683{
684 if (_metaData) {
686 } else {
687 qCWarning(FactLog) << kMissingMetadata << name();
688 return false;
689 }
690}
691
693{
694 if (_metaData) {
696 } else {
697 qCWarning(FactLog) << kMissingMetadata << name();
698 return false;
699 }
700}
701
703{
704 if (_metaData) {
705 return _metaData->decimalPlaces();
706 } else {
707 qCWarning(FactLog) << kMissingMetadata << name();
709 }
710}
711
713{
714 if (_metaData) {
715 return _metaData->maxStringLength();
716 } else {
717 qCWarning(FactLog) << kMissingMetadata << name();
718 return 0;
719 }
720}
721
722QString Fact::category() const
723{
724 if (_metaData) {
725 return _metaData->category();
726 } else {
727 qCWarning(FactLog) << kMissingMetadata << name();
728 return QString();
729 }
730}
731
732QString Fact::group() const
733{
734 if (_metaData) {
735 return _metaData->group();
736 } else {
737 qCWarning(FactLog) << kMissingMetadata << name();
738 return QString();
739 }
740}
741
742void Fact::setMetaData(FactMetaData *metaData, bool setDefaultFromMetaData)
743{
744 if (_metaData) {
745 (void) disconnect(_metaData, &FactMetaData::appSettingsUnitsChanged, this, &Fact::_appSettingsUnitsChanged);
746 }
748 if (_metaData) {
749 (void) connect(_metaData, &FactMetaData::appSettingsUnitsChanged, this, &Fact::_appSettingsUnitsChanged);
750 }
751 if (setDefaultFromMetaData && metaData->defaultValueAvailable()) {
753 }
754 emit cookedValuesChanged();
756}
757
758void Fact::_appSettingsUnitsChanged()
759{
760 emit cookedValuesChanged();
762}
763
765{
766 if (_metaData) {
768 return _metaData->rawDefaultValue() == rawValue();
769 } else {
770 return false;
771 }
772 } else {
773 qCWarning(FactLog) << kMissingMetadata << name();
774 return false;
775 }
776}
777
779{
780 if (_metaData) {
782 } else {
783 qCWarning(FactLog) << kMissingMetadata << name();
784 return false;
785 }
786}
787
788QString Fact::validate(const QString &cookedValue, bool convertOnly)
789{
790 if (_metaData) {
791 QVariant typedValue;
792 QString errorString;
793
794 _metaData->convertAndValidateCooked(cookedValue, convertOnly, typedValue, errorString);
795
796 return errorString;
797 } else {
798 qCWarning(FactLog) << kMissingMetadata << name();
799 return QStringLiteral("Internal error: Meta data pointer missing");
800 }
801}
802
803QVariant Fact::clamp(const QString &cookedValue)
804{
805 if (_metaData) {
806 QVariant typedValue;
807 if (_metaData->clampValue(cookedValue, typedValue)) {
808 return typedValue;
809 } else {
810 //-- If conversion failed, return current value
811 return rawValue();
812 }
813 } else {
814 qCWarning(FactLog) << kMissingMetadata << name();
815 }
816 return QVariant();
817}
818
820{
821 if (_metaData) {
823 } else {
824 qCWarning(FactLog) << kMissingMetadata << name();
825 return false;
826 }
827}
828
830{
831 if (_metaData) {
833 } else {
834 qCWarning(FactLog) << kMissingMetadata << name();
835 return false;
836 }
837}
838
846
847void Fact::_sendValueChangedSignal(const QVariant &value)
848{
850 emit valueChanged(value);
852 } else {
854 }
855}
856
864
866{
867 if (_metaData) {
868 if (_metaData->enumStrings().count()) {
869 return enumStringValue();
870 } else {
871 return cookedValueString();
872 }
873 } else {
874 qCWarning(FactLog) << kMissingMetadata << name();
875 }
876 return QString();
877}
878
879double Fact::rawIncrement() const
880{
881 if (_metaData) {
882 return _metaData->rawIncrement();
883 } else {
884 qCWarning(FactLog) << kMissingMetadata << name();
885 }
886 return std::numeric_limits<double>::quiet_NaN();
887}
888
890{
891 if (_metaData) {
892 return _metaData->cookedIncrement();
893 } else {
894 qCWarning(FactLog) << kMissingMetadata << name();
895 }
896 return std::numeric_limits<double>::quiet_NaN();
897}
898
900{
901 if (_metaData) {
902 return _metaData->hasControl();
903 } else {
904 qCWarning(FactLog) << kMissingMetadata << name();
905 return false;
906 }
907}
908
909bool Fact::readOnly() const
910{
911 if (_metaData) {
912 return _metaData->readOnly();
913 } else {
914 qCWarning(FactLog) << kMissingMetadata << name();
915 return false;
916 }
917}
918
919bool Fact::writeOnly() const
920{
921 if (_metaData) {
922 return _metaData->writeOnly();
923 } else {
924 qCWarning(FactLog) << kMissingMetadata << name();
925 return false;
926 }
927}
928
930{
931 if (_metaData) {
932 return _metaData->volatileValue();
933 } else {
934 qCWarning(FactLog) << kMissingMetadata << name();
935 return false;
936 }
937}
938
939void Fact::_checkForRebootMessaging()
940{
941 if (qgcApp()) {
942 // showAppMessage() logs during unit tests (and additionally shows the real
943 // dialog in UI test mode), so tests assert this messaging via expectAppMessage()
944 if (qgcRebootRequired()) {
945 QGC::showRebootAppMessage(tr("Restart application for changes to take effect."));
946 }
947 }
948}
#define qgcApp()
QString errorString
#define QGC_LOGGING_CATEGORY(name, categoryStr)
Holds the meta data associated with a Fact.
QString label() const
QStringList enumStrings() const
QVariant cookedDefaultValue() const
bool hasControl() const
QVariant cookedMin() const
QStringList bitmaskStrings() const
void appSettingsUnitsChanged()
Translators and cooked units were updated to a new app units setting.
bool clampValue(const QVariant &cookedValue, QVariant &typedValue) const
bool qgcRebootRequired() const
bool convertAndValidateCooked(const QVariant &cookedValue, bool convertOnly, QVariant &typedValue, QString &errorString) const
Same as convertAndValidateRaw except for cookedValue input.
QVariant cookedUserMax() const
Translator cookedTranslator() const
QVariant cookedMax() const
QString group() const
QVariant rawMin() const
@ valueTypeElapsedTimeInSeconds
QVariantList enumValues() const
QString cookedUnits() const
QString shortDescription() const
bool maxIsDefaultForType() const
int decimalPlaces() const
static constexpr int kDefaultDecimalPlaces
Default value for decimal places if not specified/known.
QVariant cookedUserMin() const
QVariant rawUserMin() const
bool convertAndValidateRaw(const QVariant &rawValue, bool convertOnly, QVariant &typedValue, QString &errorString) const
QString rawUnits() const
QVariant rawUserMax() const
double rawIncrement() const
int maxStringLength() const
Maximum string length for valueTypeString facts. 0 means no limit.
void setEnumInfo(const QStringList &strings, const QVariantList &values)
bool readOnly() const
QString category() const
QString longDescription() const
bool minIsDefaultForType() const
bool writeOnly() const
void addEnumInfo(const QString &name, const QVariant &value)
Used to add new values to the enum lists after the meta data has been loaded.
QVariantList bitmaskValues() const
QVariant rawDefaultValue() const
bool vehicleRebootRequired() const
bool volatileValue() const
QVariant rawMax() const
bool defaultValueAvailable() const
double cookedIncrement() const
Translator rawTranslator() const
A Fact is used to hold a single value within the system.
Definition Fact.h:15
bool _sendValueChangedSignals
Definition Fact.h:211
QString _name
Definition Fact.h:205
QStringList bitmaskStrings() const
Definition Fact.cc:324
bool writeOnly() const
Definition Fact.cc:919
int valueIndex(const QString &value) const
Definition Fact.cc:173
int enumIndex()
Definition Fact.cc:262
QString enumOrValueString()
Definition Fact.cc:865
void setMetaData(FactMetaData *metaData, bool setDefaultFromMetaData=false)
Definition Fact.cc:742
QStringList selectedBitmaskStrings() const
Provide a list of selected strings based on the fact value with the bitmaskString/bitmaskValues map.
Definition Fact.cc:344
QString cookedUnits() const
Definition Fact.cc:572
bool qgcRebootRequired() const
Definition Fact.cc:829
QString longDescription() const
Definition Fact.cc:552
Fact(QObject *parent=nullptr)
Definition Fact.cc:16
virtual ~Fact()
Definition Fact.cc:75
bool _deferredValueChangeSignal
Definition Fact.h:212
Q_INVOKABLE QVariant rawToCooked(const QVariant &rawValue) const
Definition Fact.cc:238
QVariant cookedValue() const
Definition Fact.cc:227
void sendValueChangedSignalsChanged(bool sendValueChangedSignals)
QString shortDescription() const
Definition Fact.cc:525
void containerSetRawValue(const QVariant &value)
Value coming from Vehicle. This does NOT send a _containerRawValueChanged signal.
Definition Fact.cc:199
FactMetaData * _metaData
Definition Fact.h:210
QVariantList enumValues() const
Definition Fact.cc:304
QString cookedMaxString() const
Definition Fact.cc:672
FactMetaData * metaData()
Definition Fact.h:172
QVariant rawDefaultValue() const
Definition Fact.cc:494
bool valueEqualsDefault() const
Definition Fact.cc:764
FactMetaData::ValueType_t _type
Definition Fact.h:209
double rawIncrement() const
Definition Fact.cc:879
bool maxIsDefaultForType() const
Definition Fact.cc:692
bool readOnly() const
Definition Fact.cc:909
QString cookedMinString() const
Definition Fact.cc:622
QString cookedUserMinString() const
Definition Fact.cc:627
void setEnumInfo(const QStringList &strings, const QVariantList &values)
Generally this is done during parsing. But if you know what you are doing, you can.
Definition Fact.cc:314
void sendDeferredValueChangedSignal()
Definition Fact.cc:857
QVariant cookedUserMax() const
Definition Fact.cc:662
QString invalidValueString() const
Definition Fact.h:131
void rawValueChanged(const QVariant &value)
QRecursiveMutex _rawValueMutex
Definition Fact.h:208
QString cookedUserMaxString() const
Definition Fact.cc:677
static constexpr const char * kMissingMetadata
Definition Fact.h:214
QString group() const
Definition Fact.cc:732
FactMetaData::ValueType_t type() const
Definition Fact.h:127
void setSendValueChangedSignals(bool sendValueChangedSignals)
Definition Fact.cc:839
QVariant cookedUserMin() const
Definition Fact.cc:612
QString cookedDefaultValueString() const
Definition Fact.cc:520
const Fact & operator=(const Fact &other)
Definition Fact.cc:85
QVariant cookedMin() const
Definition Fact.cc:592
double cookedIncrement() const
Definition Fact.cc:889
void setRawValue(const QVariant &value)
Definition Fact.cc:135
QString rawValueString() const
Definition Fact.cc:484
void setEnumIndex(int index)
Definition Fact.cc:190
bool sendValueChangedSignals() const
Definition Fact.h:159
bool defaultValueAvailable() const
Definition Fact.cc:778
QVariant rawUserMax() const
Definition Fact.cc:652
bool volatileValue() const
Definition Fact.cc:929
QVariant rawMax() const
Definition Fact.cc:632
void forceSetRawValue(const QVariant &value)
Sets and sends new value to vehicle even if value is the same.
Definition Fact.cc:112
int decimalPlaces() const
Definition Fact.cc:702
QStringList enumStrings() const
Definition Fact.cc:294
QString cookedValueString() const
Definition Fact.cc:489
QString name() const
Definition Fact.h:124
void containerRawValueChanged(const QVariant &value)
This signal is meant for use by Fact container implementations. Used to send changed values to vehicl...
void cookedValuesChanged()
Cooked units, ranges, defaults, increment or precision changed without a raw value change.
QString rawValueStringFullPrecision() const
Returns the values as a string with full 18 digit precision if float/double.
Definition Fact.cc:446
QVariantList bitmaskValues() const
Definition Fact.cc:334
QVariant cookedMax() const
Definition Fact.cc:642
QVariant rawMin() const
Definition Fact.cc:582
Q_INVOKABLE QString validate(const QString &cookedValue, bool convertOnly)
Definition Fact.cc:788
void setEnumStringValue(const QString &value)
Definition Fact.cc:182
int _componentId
Definition Fact.h:206
QString rawUnits() const
Definition Fact.cc:562
Q_INVOKABLE QVariant clamp(const QString &cookedValue)
Convert and clamp value.
Definition Fact.cc:803
QString _variantToString(const QVariant &variant, int decimalPlaces) const
Definition Fact.cc:372
QVariant cookedDefaultValue() const
Definition Fact.cc:507
QString category() const
Definition Fact.cc:722
bool minIsDefaultForType() const
Definition Fact.cc:682
QVariant _rawValue
Definition Fact.h:207
void _sendValueChangedSignal(const QVariant &value)
Definition Fact.cc:847
int maxStringLength() const
Definition Fact.cc:712
void setCookedValue(const QVariant &value)
Definition Fact.cc:164
QVariant rawUserMin() const
Definition Fact.cc:602
void enumsChanged()
QString enumStringValue()
Definition Fact.cc:248
QString label() const
Definition Fact.cc:535
void vehicleUpdated(const QVariant &value)
Signalled when the param write ack comes back from the vehicle.
bool hasControl() const
Definition Fact.cc:899
bool vehicleRebootRequired() const
Definition Fact.cc:819
QVariant rawValue() const
Definition Fact.h:87
void valueChanged(const QVariant &value)
This signal is only meant for use by the QT property system. It should not be connected to by client ...
static void adjustSettingMetaData(const QString &settingsGroup, FactMetaData &metaData, bool &userVisible)
bool runningUnitTests()
void showRebootAppMessage(const QString &message, const QString &title)
Modal reboot-required message. Debounced within 2 minutes.