-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add QuantityObject and QuantityObjectModel
QuantityObject provides QObject-based access to a quantity value. QuantityObjectModel provides a model of QuantityObject values; it filters out objects without valid values. This allows ListQuantityGroup and its derived types to specify their models without creating a JavaScript array that directly refers each quantity value. Otherwise, whenever a quantity value is updated, the entire array is rebuilt, which in turn causes the QuantityRow repeater to rebuild its delegates. Part of #1338
- Loading branch information
Showing
9 changed files
with
713 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
/* | ||
** Copyright (C) 2025 Victron Energy B.V. | ||
** See LICENSE.txt for license information. | ||
*/ | ||
|
||
#include "quantityobject.h" | ||
|
||
#include <QQmlInfo> | ||
|
||
using namespace Victron::VenusOS; | ||
|
||
QuantityObject::QuantityObject(QObject *parent) | ||
: QObject(parent) | ||
{ | ||
} | ||
|
||
QObject* QuantityObject::object() const | ||
{ | ||
return m_object; | ||
} | ||
|
||
void QuantityObject::setObject(QObject* object) | ||
{ | ||
if (m_object != object) { | ||
m_object = object; | ||
connectNotifySignal(); | ||
emit objectChanged(); | ||
} | ||
} | ||
|
||
QString QuantityObject::key() const | ||
{ | ||
return m_key; | ||
} | ||
|
||
void QuantityObject::setKey(const QString &key) | ||
{ | ||
if (m_key != key) { | ||
m_key = key; | ||
connectNotifySignal(); | ||
emit keyChanged(); | ||
} | ||
} | ||
|
||
Victron::VenusOS::Enums::Units_Type QuantityObject::unit() const | ||
{ | ||
return m_unit; | ||
} | ||
|
||
void QuantityObject::setUnit(Victron::VenusOS::Enums::Units_Type unit) | ||
{ | ||
if (m_unit != unit) { | ||
m_unit = unit; | ||
emit unitChanged(); | ||
} | ||
} | ||
|
||
int QuantityObject::precision() const | ||
{ | ||
return m_precision; | ||
} | ||
|
||
void QuantityObject::setPrecision(int precision) | ||
{ | ||
if (m_precision != precision) { | ||
m_precision = precision; | ||
emit precisionChanged(); | ||
} | ||
} | ||
|
||
qreal QuantityObject::numberValue() const | ||
{ | ||
return m_value.value<qreal>(); | ||
} | ||
|
||
QString QuantityObject::textValue() const | ||
{ | ||
return m_value.metaType() == QMetaType(QMetaType::QString) ? m_value.toString() : QString(); | ||
} | ||
|
||
bool QuantityObject::hasValue() const | ||
{ | ||
// Return true if the value is not NaN or the text is not empty. | ||
return m_object && m_key.length() && m_value.isValid() | ||
&& (!qIsNaN(numberValue()) || textValue().length() > 0); | ||
} | ||
|
||
void QuantityObject::connectNotifySignal() | ||
{ | ||
if (m_notifySignalConnection) { | ||
QObject::disconnect(m_notifySignalConnection); | ||
} | ||
|
||
static const QMetaMethod updateValueMethod = | ||
staticMetaObject.method(staticMetaObject.indexOfMethod("updateValue()")); | ||
if (!updateValueMethod.isValid()) { | ||
qmlInfo(this) << "Failed to find updateValue() method!"; | ||
return; | ||
} | ||
|
||
if (m_object && m_key.length()) { | ||
const QMetaObject *metaObject = m_object->metaObject(); | ||
m_property = metaObject->property(metaObject->indexOfProperty(m_key.toLatin1())); | ||
if (m_property.isValid()) { | ||
m_notifySignalConnection = QObject::connect(m_object.data(), m_property.notifySignal(), this, updateValueMethod); | ||
if (!m_notifySignalConnection) { | ||
qmlInfo(this) << "Failed to connect to notify signal for: " << m_key; | ||
} | ||
updateValue(); | ||
} else { | ||
qmlInfo(this) << "Cannot find property: " << m_key; | ||
} | ||
} | ||
} | ||
|
||
void QuantityObject::updateValue() | ||
{ | ||
const qreal prevNumberValue = numberValue(); | ||
const QString prevTextValue = textValue(); | ||
const bool prevHasValue = hasValue(); | ||
|
||
if (m_object && m_property.isValid()) { | ||
m_value = m_property.read(m_object); | ||
} else { | ||
m_value.clear(); | ||
} | ||
|
||
if (prevNumberValue != numberValue()) { | ||
emit numberValueChanged(); | ||
} | ||
if (prevTextValue != textValue()) { | ||
emit textValueChanged(); | ||
} | ||
if (prevHasValue != hasValue()) { | ||
emit hasValueChanged(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* | ||
** Copyright (C) 2025 Victron Energy B.V. | ||
** See LICENSE.txt for license information. | ||
*/ | ||
|
||
#ifndef QUANTITYMODEL_H | ||
#define QUANTITYMODEL_H | ||
|
||
#include <qqmlintegration.h> | ||
#include <QMetaObject> | ||
#include <QMetaProperty> | ||
|
||
#include "enums.h" | ||
|
||
namespace Victron { | ||
namespace VenusOS { | ||
|
||
/* | ||
Provides QObject-based access to a quantity value. | ||
Example usage: | ||
QtObject { | ||
id: dataObject | ||
property real voltage: 0.14 | ||
property real power: 536 | ||
} | ||
QuantityObject { object: dataObject; key: "voltage"; unit: VenusOS.Units_Volt_DC } | ||
QuantityObject { object: dataObject; key: "power"; unit: VenusOS.Units_Watt } | ||
*/ | ||
class QuantityObject : public QObject | ||
{ | ||
Q_OBJECT | ||
QML_ELEMENT | ||
Q_PROPERTY(QObject* object READ object WRITE setObject NOTIFY objectChanged FINAL) | ||
Q_PROPERTY(QString key READ key WRITE setKey NOTIFY keyChanged FINAL) | ||
Q_PROPERTY(Victron::VenusOS::Enums::Units_Type unit READ unit WRITE setUnit NOTIFY unitChanged FINAL) | ||
Q_PROPERTY(int precision READ precision WRITE setPrecision NOTIFY precisionChanged FINAL) | ||
Q_PROPERTY(qreal numberValue READ numberValue NOTIFY numberValueChanged FINAL) | ||
Q_PROPERTY(QString textValue READ textValue NOTIFY textValueChanged FINAL) | ||
Q_PROPERTY(bool hasValue READ hasValue NOTIFY hasValueChanged FINAL) | ||
|
||
public: | ||
explicit QuantityObject(QObject *parent = nullptr); | ||
|
||
QObject* object() const; | ||
void setObject(QObject* object); | ||
|
||
QString key() const; | ||
void setKey(const QString &key); | ||
|
||
Victron::VenusOS::Enums::Units_Type unit() const; | ||
void setUnit(Victron::VenusOS::Enums::Units_Type unit); | ||
|
||
int precision() const; | ||
void setPrecision(int precision); | ||
|
||
qreal numberValue() const; | ||
QString textValue() const; // if the value has a string type | ||
bool hasValue() const; | ||
|
||
Q_SIGNALS: | ||
void objectChanged(); | ||
void keyChanged(); | ||
void unitChanged(); | ||
void precisionChanged(); | ||
void numberValueChanged(); | ||
void textValueChanged(); | ||
void hasValueChanged(); | ||
|
||
private Q_SLOTS: | ||
void updateValue(); | ||
|
||
private: | ||
void connectNotifySignal(); | ||
|
||
QPointer<QObject> m_object; | ||
QString m_key = QStringLiteral("value"); | ||
QVariant m_value; | ||
QMetaProperty m_property; | ||
QMetaObject::Connection m_notifySignalConnection; | ||
Victron::VenusOS::Enums::Units_Type m_unit = Victron::VenusOS::Enums::Units_None; | ||
int m_precision = Victron::VenusOS::Enums::Units_Precision_Default; | ||
}; | ||
|
||
} /* VenusOS */ | ||
} /* Victron */ | ||
|
||
#endif // QUANTITYMODEL_H |
Oops, something went wrong.