From f395cedc5b7c5f0aa55387e906e4ad420f887533 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 14 Apr 2020 11:03:11 +0200 Subject: 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 --- src/corelib/kernel/qproperty.h | 12 +++----- src/corelib/kernel/qpropertybinding.cpp | 32 ++++++++++++++-------- .../corelib/kernel/qproperty/tst_qproperty.cpp | 16 ++++------- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h index 8f050327d5..e43f59053d 100644 --- a/src/corelib/kernel/qproperty.h +++ b/src/corelib/kernel/qproperty.h @@ -117,10 +117,8 @@ private: class Q_CORE_EXPORT QUntypedPropertyBinding { public: - // Returns either a boolean to indicate value change or an error. - using BindingEvaluationResult = std::variant; - // returns true if value changed, false if the binding evaluation lead to the same value as the property - // already has. + using BindingEvaluationResult = QPropertyBindingError; + // writes binding result into dataPtr using BindingEvaluationFunction = std::function; QUntypedPropertyBinding(); @@ -160,13 +158,11 @@ class QPropertyBinding : public QUntypedPropertyBinding if (auto valuePtr = std::get_if(&result)) { PropertyType *propertyPtr = reinterpret_cast(dataPtr); - if (*propertyPtr == *valuePtr) - return false; *propertyPtr = std::move(*valuePtr); - return true; + return {}; } - return false; + return {}; } }; diff --git a/src/corelib/kernel/qpropertybinding.cpp b/src/corelib/kernel/qpropertybinding.cpp index 358977e63e..29b1a4a69a 100644 --- a/src/corelib/kernel/qpropertybinding.cpp +++ b/src/corelib/kernel/qpropertybinding.cpp @@ -41,6 +41,7 @@ #include "qproperty_p.h" #include +#include QT_BEGIN_NAMESPACE @@ -80,25 +81,34 @@ bool QPropertyBindingPrivate::evaluateIfDirtyAndReturnTrueIfValueChanged() BindingEvaluationState evaluationFrame(this); + QPropertyBindingError evalError; QUntypedPropertyBinding::BindingEvaluationResult result; bool changed = false; if (metaType.id() == QMetaType::Bool) { auto propertyPtr = reinterpret_cast(propertyDataPtr); - bool temp = propertyPtr->extraBit(); - result = evaluationFunction(metaType, &temp); - if (auto changedPtr = std::get_if(&result)) { - changed = *changedPtr; - if (changed) - propertyPtr->setExtraBit(temp); + bool newValue = false; + evalError = evaluationFunction(metaType, &newValue); + if (evalError.type() == QPropertyBindingError::NoError) { + if (propertyPtr->extraBit() != newValue) { + propertyPtr->setExtraBit(newValue); + changed = true; + } } } else { - result = evaluationFunction(metaType, propertyDataPtr); - if (auto changedPtr = std::get_if(&result)) - changed = *changedPtr; + QVariant resultVariant(metaType.id(), nullptr); + evalError = evaluationFunction(metaType, resultVariant.data()); + 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(&result)) - error = std::move(*errorPtr); + if (evalError.type() != QPropertyBindingError::NoError) + error = evalError; dirty = false; return changed; diff --git a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp index cc04c2f1b5..488ecacb8d 100644 --- a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp +++ b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp @@ -617,22 +617,20 @@ void tst_QProperty::genericPropertyBinding() { QUntypedPropertyBinding doubleBinding(QMetaType::fromType(), - [](const QMetaType &, void *) -> bool { + [](const QMetaType &, void *) -> QUntypedPropertyBinding::BindingEvaluationResult { Q_ASSERT(false); - return false; + return QPropertyBindingError::NoError; }, QPropertyBindingSourceLocation()); QVERIFY(!property.setBinding(doubleBinding)); } QUntypedPropertyBinding intBinding(QMetaType::fromType(), - [](const QMetaType &metaType, void *dataPtr) -> bool { + [](const QMetaType &metaType, void *dataPtr) -> QUntypedPropertyBinding::BindingEvaluationResult { Q_ASSERT(metaType.id() == qMetaTypeId()); int *intPtr = reinterpret_cast(dataPtr); - if (*intPtr == 100) - return false; *intPtr = 100; - return true; + return QPropertyBindingError::NoError; }, QPropertyBindingSourceLocation()); QVERIFY(property.setBinding(intBinding)); @@ -647,12 +645,10 @@ void tst_QProperty::genericPropertyBindingBool() QVERIFY(!property.value()); QUntypedPropertyBinding boolBinding(QMetaType::fromType(), - [](const QMetaType &, void *dataPtr) -> bool { + [](const QMetaType &, void *dataPtr) -> QUntypedPropertyBinding::BindingEvaluationResult { auto boolPtr = reinterpret_cast(dataPtr); - if (*boolPtr) - return false; *boolPtr = true; - return true; + return {}; }, QPropertyBindingSourceLocation()); QVERIFY(property.setBinding(boolBinding)); -- cgit v1.2.3