Simplify signature of untyped property bindings
Instead of requiring the implementation to do the compare dance, let's do this in the library. This reduces the amount of duplicated code slightly and makes it easier to generate binding code from qml files. Change-Id: Ia3b16cf9769e74d076b669efe4119ab84af3cdf0 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
4857f0ebd7
commit
f395cedc5b
@ -117,10 +117,8 @@ private:
|
|||||||
class Q_CORE_EXPORT QUntypedPropertyBinding
|
class Q_CORE_EXPORT QUntypedPropertyBinding
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Returns either a boolean to indicate value change or an error.
|
using BindingEvaluationResult = QPropertyBindingError;
|
||||||
using BindingEvaluationResult = std::variant<bool, QPropertyBindingError>;
|
// writes binding result into dataPtr
|
||||||
// returns true if value changed, false if the binding evaluation lead to the same value as the property
|
|
||||||
// already has.
|
|
||||||
using BindingEvaluationFunction = std::function<BindingEvaluationResult(const QMetaType &metaType, void *dataPtr)>;
|
using BindingEvaluationFunction = std::function<BindingEvaluationResult(const QMetaType &metaType, void *dataPtr)>;
|
||||||
|
|
||||||
QUntypedPropertyBinding();
|
QUntypedPropertyBinding();
|
||||||
@ -160,13 +158,11 @@ class QPropertyBinding : public QUntypedPropertyBinding
|
|||||||
|
|
||||||
if (auto valuePtr = std::get_if<PropertyType>(&result)) {
|
if (auto valuePtr = std::get_if<PropertyType>(&result)) {
|
||||||
PropertyType *propertyPtr = reinterpret_cast<PropertyType *>(dataPtr);
|
PropertyType *propertyPtr = reinterpret_cast<PropertyType *>(dataPtr);
|
||||||
if (*propertyPtr == *valuePtr)
|
|
||||||
return false;
|
|
||||||
*propertyPtr = std::move(*valuePtr);
|
*propertyPtr = std::move(*valuePtr);
|
||||||
return true;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return {};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "qproperty_p.h"
|
#include "qproperty_p.h"
|
||||||
|
|
||||||
#include <QScopedValueRollback>
|
#include <QScopedValueRollback>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
@ -80,25 +81,34 @@ bool QPropertyBindingPrivate::evaluateIfDirtyAndReturnTrueIfValueChanged()
|
|||||||
|
|
||||||
BindingEvaluationState evaluationFrame(this);
|
BindingEvaluationState evaluationFrame(this);
|
||||||
|
|
||||||
|
QPropertyBindingError evalError;
|
||||||
QUntypedPropertyBinding::BindingEvaluationResult result;
|
QUntypedPropertyBinding::BindingEvaluationResult result;
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
if (metaType.id() == QMetaType::Bool) {
|
if (metaType.id() == QMetaType::Bool) {
|
||||||
auto propertyPtr = reinterpret_cast<QPropertyBase *>(propertyDataPtr);
|
auto propertyPtr = reinterpret_cast<QPropertyBase *>(propertyDataPtr);
|
||||||
bool temp = propertyPtr->extraBit();
|
bool newValue = false;
|
||||||
result = evaluationFunction(metaType, &temp);
|
evalError = evaluationFunction(metaType, &newValue);
|
||||||
if (auto changedPtr = std::get_if<bool>(&result)) {
|
if (evalError.type() == QPropertyBindingError::NoError) {
|
||||||
changed = *changedPtr;
|
if (propertyPtr->extraBit() != newValue) {
|
||||||
if (changed)
|
propertyPtr->setExtraBit(newValue);
|
||||||
propertyPtr->setExtraBit(temp);
|
changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result = evaluationFunction(metaType, propertyDataPtr);
|
QVariant resultVariant(metaType.id(), nullptr);
|
||||||
if (auto changedPtr = std::get_if<bool>(&result))
|
evalError = evaluationFunction(metaType, resultVariant.data());
|
||||||
changed = *changedPtr;
|
if (evalError.type() == QPropertyBindingError::NoError) {
|
||||||
|
int compareResult = 0;
|
||||||
|
if (!QMetaType::compare(propertyDataPtr, resultVariant.constData(), metaType.id(), &compareResult) || compareResult != 0) {
|
||||||
|
changed = true;
|
||||||
|
metaType.destruct(propertyDataPtr);
|
||||||
|
metaType.construct(propertyDataPtr, resultVariant.constData());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto errorPtr = std::get_if<QPropertyBindingError>(&result))
|
if (evalError.type() != QPropertyBindingError::NoError)
|
||||||
error = std::move(*errorPtr);
|
error = evalError;
|
||||||
|
|
||||||
dirty = false;
|
dirty = false;
|
||||||
return changed;
|
return changed;
|
||||||
|
@ -617,22 +617,20 @@ void tst_QProperty::genericPropertyBinding()
|
|||||||
|
|
||||||
{
|
{
|
||||||
QUntypedPropertyBinding doubleBinding(QMetaType::fromType<double>(),
|
QUntypedPropertyBinding doubleBinding(QMetaType::fromType<double>(),
|
||||||
[](const QMetaType &, void *) -> bool {
|
[](const QMetaType &, void *) -> QUntypedPropertyBinding::BindingEvaluationResult {
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
return false;
|
return QPropertyBindingError::NoError;
|
||||||
}, QPropertyBindingSourceLocation());
|
}, QPropertyBindingSourceLocation());
|
||||||
QVERIFY(!property.setBinding(doubleBinding));
|
QVERIFY(!property.setBinding(doubleBinding));
|
||||||
}
|
}
|
||||||
|
|
||||||
QUntypedPropertyBinding intBinding(QMetaType::fromType<int>(),
|
QUntypedPropertyBinding intBinding(QMetaType::fromType<int>(),
|
||||||
[](const QMetaType &metaType, void *dataPtr) -> bool {
|
[](const QMetaType &metaType, void *dataPtr) -> QUntypedPropertyBinding::BindingEvaluationResult {
|
||||||
Q_ASSERT(metaType.id() == qMetaTypeId<int>());
|
Q_ASSERT(metaType.id() == qMetaTypeId<int>());
|
||||||
|
|
||||||
int *intPtr = reinterpret_cast<int*>(dataPtr);
|
int *intPtr = reinterpret_cast<int*>(dataPtr);
|
||||||
if (*intPtr == 100)
|
|
||||||
return false;
|
|
||||||
*intPtr = 100;
|
*intPtr = 100;
|
||||||
return true;
|
return QPropertyBindingError::NoError;
|
||||||
}, QPropertyBindingSourceLocation());
|
}, QPropertyBindingSourceLocation());
|
||||||
|
|
||||||
QVERIFY(property.setBinding(intBinding));
|
QVERIFY(property.setBinding(intBinding));
|
||||||
@ -647,12 +645,10 @@ void tst_QProperty::genericPropertyBindingBool()
|
|||||||
QVERIFY(!property.value());
|
QVERIFY(!property.value());
|
||||||
|
|
||||||
QUntypedPropertyBinding boolBinding(QMetaType::fromType<bool>(),
|
QUntypedPropertyBinding boolBinding(QMetaType::fromType<bool>(),
|
||||||
[](const QMetaType &, void *dataPtr) -> bool {
|
[](const QMetaType &, void *dataPtr) -> QUntypedPropertyBinding::BindingEvaluationResult {
|
||||||
auto boolPtr = reinterpret_cast<bool *>(dataPtr);
|
auto boolPtr = reinterpret_cast<bool *>(dataPtr);
|
||||||
if (*boolPtr)
|
|
||||||
return false;
|
|
||||||
*boolPtr = true;
|
*boolPtr = true;
|
||||||
return true;
|
return {};
|
||||||
}, QPropertyBindingSourceLocation());
|
}, QPropertyBindingSourceLocation());
|
||||||
QVERIFY(property.setBinding(boolBinding));
|
QVERIFY(property.setBinding(boolBinding));
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user