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 <lars.knoll@qt.io>
This commit is contained in:
Fabian Kosmale 2021-01-22 11:06:52 +01:00
parent f07c6f52ac
commit 0f4d512dc4
3 changed files with 60 additions and 1 deletions

View File

@ -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<T>::isValid(), hasBinding
*/
/*!
\fn template <typename T> QPropertyBinding<T> QBindable<T>::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<T> will be invalid.
\sa setBinding, getBinding, QPropertyBinding<T>::isValid(), hasBinding
*/
/*!
\fn template <typename T> void QBindable<T>::setBinding(const QPropertyBinding<T> &binding)

View File

@ -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<QPropertyBinding<T> &&>(QUntypedBindable::binding());
}
QPropertyBinding<T> takeBinding()
{
return static_cast<QPropertyBinding<T> &&>(QUntypedBindable::takeBinding());
}
using QUntypedBindable::setBinding;
QPropertyBinding<T> setBinding(const QPropertyBinding<T> &binding)
{

View File

@ -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<int> 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