QPropertyBinding: Add sticky mode
A sticky QPropertyBinding is a binding that does not get removed when a write occurs. This is used in the QML engine to implement support for the QQmlPropertyData::DontRemoveBinding flag. Task-number: QTBUG-91689 Change-Id: Ib575b49abe634215318ccc7ba46212cc21eb4dad Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
parent
a794c5e287
commit
e835bccb1e
@ -508,6 +508,9 @@ void QPropertyBindingData::removeBinding_helper()
|
|||||||
|
|
||||||
auto *existingBinding = d.binding();
|
auto *existingBinding = d.binding();
|
||||||
Q_ASSERT(existingBinding);
|
Q_ASSERT(existingBinding);
|
||||||
|
if (existingBinding->isSticky()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto observer = existingBinding->takeObservers();
|
auto observer = existingBinding->takeObservers();
|
||||||
d_ref() = 0;
|
d_ref() = 0;
|
||||||
|
@ -184,6 +184,11 @@ private:
|
|||||||
bool hasBindingWrapper:1;
|
bool hasBindingWrapper:1;
|
||||||
// used to detect binding loops for eagerly evaluated properties
|
// used to detect binding loops for eagerly evaluated properties
|
||||||
bool isQQmlPropertyBinding:1;
|
bool isQQmlPropertyBinding:1;
|
||||||
|
/* a sticky binding does not get removed in removeBinding
|
||||||
|
this is used to support QQmlPropertyData::DontRemoveBinding
|
||||||
|
in qtdeclarative
|
||||||
|
*/
|
||||||
|
bool m_sticky:1;
|
||||||
|
|
||||||
const QtPrivate::BindingFunctionVTable *vtable;
|
const QtPrivate::BindingFunctionVTable *vtable;
|
||||||
|
|
||||||
@ -234,11 +239,14 @@ public:
|
|||||||
size_t dependencyObserverCount = 0;
|
size_t dependencyObserverCount = 0;
|
||||||
|
|
||||||
bool isUpdating() {return updating;}
|
bool isUpdating() {return updating;}
|
||||||
|
void setSticky(bool keep = true) {m_sticky = keep;}
|
||||||
|
bool isSticky() {return m_sticky;}
|
||||||
|
|
||||||
QPropertyBindingPrivate(QMetaType metaType, const QtPrivate::BindingFunctionVTable *vtable,
|
QPropertyBindingPrivate(QMetaType metaType, const QtPrivate::BindingFunctionVTable *vtable,
|
||||||
const QPropertyBindingSourceLocation &location, bool isQQmlPropertyBinding=false)
|
const QPropertyBindingSourceLocation &location, bool isQQmlPropertyBinding=false)
|
||||||
: hasBindingWrapper(false)
|
: hasBindingWrapper(false)
|
||||||
, isQQmlPropertyBinding(isQQmlPropertyBinding)
|
, isQQmlPropertyBinding(isQQmlPropertyBinding)
|
||||||
|
, m_sticky(false)
|
||||||
, vtable(vtable)
|
, vtable(vtable)
|
||||||
, location(location)
|
, location(location)
|
||||||
, metaType(metaType)
|
, metaType(metaType)
|
||||||
|
@ -56,6 +56,7 @@ private slots:
|
|||||||
void avoidDependencyAllocationAfterFirstEval();
|
void avoidDependencyAllocationAfterFirstEval();
|
||||||
void boolProperty();
|
void boolProperty();
|
||||||
void takeBinding();
|
void takeBinding();
|
||||||
|
void stickyBinding();
|
||||||
void replaceBinding();
|
void replaceBinding();
|
||||||
void changeHandler();
|
void changeHandler();
|
||||||
void propertyChangeHandlerApi();
|
void propertyChangeHandlerApi();
|
||||||
@ -307,6 +308,30 @@ void tst_QProperty::takeBinding()
|
|||||||
QVERIFY(!existingBinding.isNull());
|
QVERIFY(!existingBinding.isNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QProperty::stickyBinding()
|
||||||
|
{
|
||||||
|
QProperty<int> prop;
|
||||||
|
QProperty<int> prop2 {2};
|
||||||
|
prop.setBinding([&](){ return prop2.value(); });
|
||||||
|
QCOMPARE(prop.value(), 2);
|
||||||
|
auto privBinding = QPropertyBindingPrivate::get(prop.binding());
|
||||||
|
// If we make a binding sticky,
|
||||||
|
privBinding->setSticky();
|
||||||
|
// then writing to the property does not remove it
|
||||||
|
prop = 1;
|
||||||
|
QVERIFY(prop.hasBinding());
|
||||||
|
// but the value still changes.
|
||||||
|
QCOMPARE(prop.value(), 1);
|
||||||
|
// The binding continues to work normally.
|
||||||
|
prop2 = 3;
|
||||||
|
QCOMPARE(prop.value(), 3);
|
||||||
|
// If we remove the stickiness
|
||||||
|
privBinding->setSticky(false);
|
||||||
|
// the binding goes away on the next write
|
||||||
|
prop = 42;
|
||||||
|
QVERIFY(!prop.hasBinding());
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QProperty::replaceBinding()
|
void tst_QProperty::replaceBinding()
|
||||||
{
|
{
|
||||||
QProperty<int> first(100);
|
QProperty<int> first(100);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user