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();
|
||||
Q_ASSERT(existingBinding);
|
||||
if (existingBinding->isSticky()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto observer = existingBinding->takeObservers();
|
||||
d_ref() = 0;
|
||||
|
@ -184,6 +184,11 @@ private:
|
||||
bool hasBindingWrapper:1;
|
||||
// used to detect binding loops for eagerly evaluated properties
|
||||
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;
|
||||
|
||||
@ -234,11 +239,14 @@ public:
|
||||
size_t dependencyObserverCount = 0;
|
||||
|
||||
bool isUpdating() {return updating;}
|
||||
void setSticky(bool keep = true) {m_sticky = keep;}
|
||||
bool isSticky() {return m_sticky;}
|
||||
|
||||
QPropertyBindingPrivate(QMetaType metaType, const QtPrivate::BindingFunctionVTable *vtable,
|
||||
const QPropertyBindingSourceLocation &location, bool isQQmlPropertyBinding=false)
|
||||
: hasBindingWrapper(false)
|
||||
, isQQmlPropertyBinding(isQQmlPropertyBinding)
|
||||
, m_sticky(false)
|
||||
, vtable(vtable)
|
||||
, location(location)
|
||||
, metaType(metaType)
|
||||
|
@ -56,6 +56,7 @@ private slots:
|
||||
void avoidDependencyAllocationAfterFirstEval();
|
||||
void boolProperty();
|
||||
void takeBinding();
|
||||
void stickyBinding();
|
||||
void replaceBinding();
|
||||
void changeHandler();
|
||||
void propertyChangeHandlerApi();
|
||||
@ -307,6 +308,30 @@ void tst_QProperty::takeBinding()
|
||||
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()
|
||||
{
|
||||
QProperty<int> first(100);
|
||||
|
Loading…
x
Reference in New Issue
Block a user