From 0f4d512dc46cb9d24b58083efdc1fa4631bdbec4 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Fri, 22 Jan 2021 11:06:52 +0100 Subject: [PATCH] Q(Untyped)Bindable: add takeBinding method We missed takeBinding as a supported operation on Q(Untyped)Bindable. To avoid adding version checks to code dealing with QBindableInterface, we simply synthesize takeBinding as a combination of binding to retrieve the binding and setBinding with a default-constructed QUntypedPropertyBinding. Change-Id: I43803a0dfe210353d0235f0373d2257f75ffe534 Reviewed-by: Lars Knoll --- src/corelib/kernel/qproperty.cpp | 21 +++++++++++++++++- src/corelib/kernel/qproperty.h | 22 +++++++++++++++++++ .../kernel/qproperty/tst_qproperty.cpp | 18 +++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index 342a3d34eb..90df159e88 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -787,11 +787,20 @@ QString QPropertyBindingError::description() const \sa hasBinding() */ +/*! + \fn QUntypedPropertyBinding QUntypedBindable::takeBinding() + + Removes the currently set binding from the property and returns it. + Returns a default-constructed QUntypedPropertyBinding if no binding is set. + + \since 6.1 +*/ + /*! \fn bool QUntypedBindable::setBinding(const QUntypedPropertyBinding &binding) Sets the underlying property's binding to \a binding. This does not have any effect - if the QUntypedBindable is read-only, invalid or if \a binding's type does match the + if the QUntypedBindable is read-only, null or if \a binding's type does match the underlying property's type. \sa QUntypedPropertyBinding::valueMetaType() @@ -841,6 +850,16 @@ QString QPropertyBindingError::description() const \sa setBinding, QPropertyBinding::isValid(), hasBinding */ +/*! + \fn template QPropertyBinding QBindable::takeBinding() + + Removes the currently set binding of the underlying property and returns it. + If the property does not have a binding, the returned \c QPropertyBinding will be invalid. + + \sa setBinding, getBinding, QPropertyBinding::isValid(), hasBinding +*/ + + /*! \fn template void QBindable::setBinding(const QPropertyBinding &binding) diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h index f853eb8634..750d75c4a7 100644 --- a/src/corelib/kernel/qproperty.h +++ b/src/corelib/kernel/qproperty.h @@ -581,6 +581,22 @@ public: { return iface ? iface->makeBinding(data, location) : QUntypedPropertyBinding(); } + + QUntypedPropertyBinding takeBinding() + { + if (!iface) + return QUntypedPropertyBinding {}; + // We do not have a dedicated takeBinding function pointer in the interface + // therefore we synthesize takeBinding by retrieving the binding with binding + // and calling setBinding with a default constructed QUntypedPropertyBinding + // afterwards. + if (!(iface->getBinding && iface->setBinding)) + return QUntypedPropertyBinding {}; + QUntypedPropertyBinding binding = iface->getBinding(data); + iface->setBinding(data, QUntypedPropertyBinding{}); + return binding; + } + void observe(QPropertyObserver *observer) { if (iface) @@ -650,6 +666,12 @@ public: { return static_cast &&>(QUntypedBindable::binding()); } + + QPropertyBinding takeBinding() + { + return static_cast &&>(QUntypedBindable::takeBinding()); + } + using QUntypedBindable::setBinding; QPropertyBinding setBinding(const QPropertyBinding &binding) { diff --git a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp index 3b656dae25..31ed610b09 100644 --- a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp +++ b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp @@ -78,6 +78,7 @@ private slots: void notifiedProperty(); void typeNoOperatorEqual(); void bindingValueReplacement(); + void quntypedBindableApi(); void testNewStuff(); void qobjectObservers(); @@ -1008,6 +1009,23 @@ void tst_QProperty::bindingValueReplacement() // QCOMPARE(test.iconText.value(), 42); } +void tst_QProperty::quntypedBindableApi() +{ + QProperty iprop; + QUntypedBindable bindable(&iprop); + QVERIFY(!bindable.hasBinding()); + QVERIFY(bindable.binding().isNull()); + bindable.setBinding(Qt::makePropertyBinding([]() -> int {return 42;})); + QVERIFY(bindable.hasBinding()); + QVERIFY(!bindable.binding().isNull()); + QUntypedPropertyBinding binding = bindable.takeBinding(); + QVERIFY(!bindable.hasBinding()); + bindable.setBinding(binding); + QCOMPARE(iprop.value(), 42); + QUntypedBindable propLess; + QVERIFY(propLess.takeBinding().isNull()); +} + class MyQObject : public QObject { Q_OBJECT