Skip to content

Commit

Permalink
Simplify signature of untyped property bindings
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
tronical committed Apr 17, 2020
1 parent 4857f0e commit f395ced
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 29 deletions.
12 changes: 4 additions & 8 deletions src/corelib/kernel/qproperty.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,8 @@ class Q_CORE_EXPORT QPropertyBindingError
class Q_CORE_EXPORT QUntypedPropertyBinding
{
public:
// Returns either a boolean to indicate value change or an error.
using BindingEvaluationResult = std::variant<bool, QPropertyBindingError>;
// 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<BindingEvaluationResult(const QMetaType &metaType, void *dataPtr)>;

QUntypedPropertyBinding();
Expand Down Expand Up @@ -160,13 +158,11 @@ class QPropertyBinding : public QUntypedPropertyBinding

if (auto valuePtr = std::get_if<PropertyType>(&result)) {
PropertyType *propertyPtr = reinterpret_cast<PropertyType *>(dataPtr);
if (*propertyPtr == *valuePtr)
return false;
*propertyPtr = std::move(*valuePtr);
return true;
return {};
}

return false;
return {};
}
};

Expand Down
32 changes: 21 additions & 11 deletions src/corelib/kernel/qpropertybinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "qproperty_p.h"

#include <QScopedValueRollback>
#include <QVariant>

QT_BEGIN_NAMESPACE

Expand Down Expand Up @@ -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<QPropertyBase *>(propertyDataPtr);
bool temp = propertyPtr->extraBit();
result = evaluationFunction(metaType, &temp);
if (auto changedPtr = std::get_if<bool>(&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<bool>(&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<QPropertyBindingError>(&result))
error = std::move(*errorPtr);
if (evalError.type() != QPropertyBindingError::NoError)
error = evalError;

dirty = false;
return changed;
Expand Down
16 changes: 6 additions & 10 deletions tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -617,22 +617,20 @@ void tst_QProperty::genericPropertyBinding()

{
QUntypedPropertyBinding doubleBinding(QMetaType::fromType<double>(),
[](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<int>(),
[](const QMetaType &metaType, void *dataPtr) -> bool {
[](const QMetaType &metaType, void *dataPtr) -> QUntypedPropertyBinding::BindingEvaluationResult {
Q_ASSERT(metaType.id() == qMetaTypeId<int>());

int *intPtr = reinterpret_cast<int*>(dataPtr);
if (*intPtr == 100)
return false;
*intPtr = 100;
return true;
return QPropertyBindingError::NoError;
}, QPropertyBindingSourceLocation());

QVERIFY(property.setBinding(intBinding));
Expand All @@ -647,12 +645,10 @@ void tst_QProperty::genericPropertyBindingBool()
QVERIFY(!property.value());

QUntypedPropertyBinding boolBinding(QMetaType::fromType<bool>(),
[](const QMetaType &, void *dataPtr) -> bool {
[](const QMetaType &, void *dataPtr) -> QUntypedPropertyBinding::BindingEvaluationResult {
auto boolPtr = reinterpret_cast<bool *>(dataPtr);
if (*boolPtr)
return false;
*boolPtr = true;
return true;
return {};
}, QPropertyBindingSourceLocation());
QVERIFY(property.setBinding(boolBinding));

Expand Down

0 comments on commit f395ced

Please sign in to comment.