Details
-
Bug
-
Resolution: Unresolved
-
P2: Important
-
6.0
-
None
Description
Setting a bindable property to some value should remove the binding.
When using Q_OBJECT_COMPAT_PROPERTY it fails to do so if the setter is called inside of a signal handler of the signal emitted by the setter.
The problem is the following:
In QObjectCompatProperty there is logic to remove the binding when the setter is executed. But because QObjectCompatProperty calls the setter itself when evaluating the binding, this code is disabled during binding evaluation. When binding evaluation leads to a signal being emitted and that signal leads to user code calling the setter, it is still disabled.
So correct logic would be: Binding removal is disabled if the setter is called directly by QObjectCompatProperty.
Implemented logic is: Binding removal is disabled if the setter call is somewhere up the call stack.
This problem could be solved by the proposal I already made in QTBUG-89890 :
My proposal would be that any write to a bindable property just assigns the underlying QObjectCompatProperty. The old setters become private functions which are then, in turn, called by the QObjectCompatProperty.
Source code for reproduction:
#include <QObject> #include <QDebug> #include <private/qproperty_p.h> class Foo : public QObject { Q_OBJECT Q_PROPERTY(int a READ a WRITE setA NOTIFY aChanged BINDABLE bindableA) public: int a() const { return Adata; } void setA(int value) { int oldvalue = Adata; Adata = value; if (value != oldvalue) emit aChanged(value); } QBindable<int> bindableA() { return &Adata; } signals: void aChanged(int); private: Q_OBJECT_COMPAT_PROPERTY(Foo, int, Adata, &Foo::setA) }; int main(){ QProperty<int> refvalue(5); Foo myfoo; myfoo.bindableA().setBinding([&](){ return refvalue.value(); }); // once myfoo.a becomes 10 or greater, we want it to stop updating QObject::connect(&myfoo, &Foo::aChanged, [&](int value){ if (value >= 10){ myfoo.setA(value); } }); // change refvalue, myfoo.a follows refvalue = 6; assert(myfoo.a() == 6); refvalue = 8; assert(myfoo.a() == 8); refvalue = 10; assert(myfoo.a() == 10); refvalue = 12; assert(myfoo.a() == 10); } #include "main.moc"
Attachments
Gerrit Reviews
For Gerrit Dashboard: QTBUG-89914 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
330521,1 | WIP: Proposal for safer Q_OBJECT_COMPAT_PROPERTY | dev | qt/qtbase | Status: ABANDONED | -2 | 0 |