[Development] The future of QProperty and QBindable

Schimkowitsch Robert Robert.Schimkowitsch at andritz.com
Fri Mar 7 10:48:39 CET 2025


Hi,

I can only summarize your message in four letters: ARGH!
We widely use BINDABLE in Q_PROPERTY (>500 places) because it removes a lot of boilerplate from our C++ classes.

Compare code with BINDABLE:

// ***
Q_PROPERTY(qreal x BINDABLE getX READ default)

QBindable<qreal> getX() const
{
   return m_X; // Which is a QProperty<qreal>
}

// Code setting the property
m_X = newX;
// ***

Code without BINDABLE:
//***
Q_PROPERTY(qreal x READ getX WRITE setX NOTIFY notifyXChanged)

qreal getX() const
{
   return m_X;
}

void setX(const qreal& arg)
{
   if (m_X == arg)
   {
      return;
   }
   m_X = arg;
   emit notifyXChanged();
}

// Code setting the property
setX(newX);
//***

I have never had any issues using BINDABLE. I have avoided using them in complex situations, true, but for the simple use case I outlined, they were just a major improvement over READ/WRITE/NOTIFY.

Please don't deprecate that!

Kind regards

Robert


> -----Original Message-----
> From: Development <development-bounces at qt-project.org> On Behalf Of
> Ulf Hermann via Development
> Sent: Friday, 7 March 2025 10:15
> To: development at qt-project.org
> Subject: [Development] The future of QProperty and QBindable
>
> CAUTION: External email. Do not click on links or open attachments unless
> you know the sender and that the content is safe.
>
>
> Hi,
>
> We've had a discussion [1] about QProperty and QBindable during the last
> contributors' summit, but unfortunately didn't reach any conclusion.
> I'll summarize the most important part of the discussion here:
>
> "There is functionality to retrofit Q_PROPERTY with synthetic bindables."
>
> This may be surprising but bear with me. First, (belated) big thanks to Patrick
> Stewart for making this happen. The relevant API are the constructors for
> QBindable [2][3].
>
>
> Without integration with moc, Q_PROPERTY and QML, QProperty and
> QBindable would be fairly simple and self-contained pieces of code. They
> could be moved to a separate library, e.g. QtBindable and live there without
> hurting anyone.
>
> Conversely, the deep integration with moc, Q_PROPERTY and QML gives us a
> lot of headaches. If you use a QProperty to back a Q_PROPERTY you need to
> be extremely careful when writing getters and setter, so that you don't
> accidentally produce spurious dependencies. A classic example is a setter first
> comparing the value before setting it. You can't just do "if
> (someQProperty.value() == newValue)". You have to do
> "someProperty.valueBypassingBindings()". Furthermore, you need to call
> removeBindingUnlessInWrapper() at the right place so that any bindings to
> the property are broken when setting a new value (even if the value is the
> same). The complexity grows if you have properties that depend on each
> other or otherwise interact. In general, this is not something we can ask users
> to get right. We ourselves have produced a lot of bugs [4][5] when introducing
> bindables into the few places in Qt where we have them now. And we're not
> done fixing them [6]. Finally, the QBindingStorage member in QObjectData
> that makes all this possible, increases the size of every QObject by two
> pointers, no matter if it uses bindables or not.
>
>
> Let's take a step back here, though. The original idea of introducing QProperty
> and QBindable was twofold:
>
> 1. Offer a convenient C++ API for bindings.
> 2. Enable the Qt Quick Compiler to generate better C++ code for bindings.
>
> 1 can be achieved without deep integration into moc and Q_PROPERTY. An
> external adapter for Q_PROPERTY is generally enough to connect
> Q_PROPERTY with bindables. Granted, the result will probably be slower than
> a deeply integrated bindable, However, given the amount of optimization we
> needed to put in to get any visible performance edge for
> QProperty/QBindable over classic signal/slot connections at all, I expect the
> difference to be small.
>
> 2 turned out to be chimera. qmlsc can generate rather performant code for a
> binding using QProperty directly, but there are preconditions:
> a, The binding needs to be compilable in the first place.
> b, You need to use direct mode [7], which implies private API and accessible
> headers.
> c, The property written to has to be bindable.
> d, The properties read from have to be bindable.
> In practice, this rarely materializes. On the flip side, when not used directly
> like this, but rather through dynamically typed lookups inside QQmlEngine, or
> in the adaptor methods for AOT-compiled non-direct code, QProperty and
> QBindable do not offer a clear performance benefit over regular
> READ/WRITE/NOTIFY properties. They do, however, produce a lot of
> complexity. I'm currently working on the property-to-property binding we use
> to implement the interaction between models and delegates via required
> properties [8]. This thing requires four different implementations to cover all
> the permutations. And this is just one example.
>
>
> So here is my suggestion:
>
> 1, Deprecate the BINDABLE attribute to Q_PROPERTY. We probably can't have
> moc produce a warning about it right away, but we can already adapt the
> documentation.
> 2, Deprecate QObjectBindableProperty and friends.
> 3, Revert our own bindable Q_PROPERTYs to be backed by simple data
> members rather than QProperty again. Implement the public fooBindable()
> methods in terms of the Q_PROPERTY adaptors for QBindable and deprecate
> them. Drop all the BINDABLEs in private API.
> 4, Remove the integration with QProperty and QBindable in QML. QML will
> always use the READ/WRITE/NOTIFY methods again and ignore any
> BINDABLE.
> 5, In Qt7, move the remaining QProperty and QBindable code into a separate
> library.
>
> This sounds easy, but there is a slight caveat: You can omit the change signal if
> you have a BINDABLE, and QML will currently still be able to listen to the
> property. I guess some projects are doing this. If QML were to completely
> ignore all bindables, it would not be able to get notified about those
> properties anymore. Therefore, both moc and the QML engine should warn
> about BINDABLEs without NOTIFY. Ideally, as a porting helper, moc could
> temporarily accept "NOTIFY default" to generate a notification signal from a
> bindable, but I don't know if we can pull this off. Only afterwards, maybe after
> two minor versions of Qt, we can remove bindable support from QML.
>
>
> I'm registering another session for the upcoming contributors' summit in May
> [9], but I would appreciate opinions already before.
>
> best regards,
> Ulf
>
> [1] https://ddec1-0-en-
> ctp.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2fwiki.qt.i
> o%2fQtCS2024%5fQProperty&umid=35d287fd-0e81-445e-ac6b-
> b30fbfebfbf4&rct=1741339018&auth=c40ca16f35916d8a02f8c25adf579f293a
> 3f6a33-6261c88704c195a0c68cef2269fc03e2267eccb3
> [2] https://ddec1-0-en-
> ctp.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2fdoc.qt.i
> o%2fqt%2d6%2fqbindable.html%23QBindable&umid=35d287fd-0e81-445e-
> ac6b-
> b30fbfebfbf4&rct=1741339018&auth=c40ca16f35916d8a02f8c25adf579f293a
> 3f6a33-dc18a678cc0efc8bbdc3346b437989df05d2cda8
> [3] https://ddec1-0-en-
> ctp.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2fdoc.qt.i
> o%2fqt%2d6%2fqbindable.html%23QBindable%2d1&umid=35d287fd-0e81-
> 445e-ac6b-
> b30fbfebfbf4&rct=1741339018&auth=c40ca16f35916d8a02f8c25adf579f293a
> 3f6a33-8754b18e4b022ca867b1d4cf68d79cd18dfc4e4d
> [4] https://ddec1-0-en-
> ctp.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2fbugrepo
> rts.qt.io%2fbrowse%2fQTBUG%2d116211&umid=35d287fd-0e81-445e-ac6b-
> b30fbfebfbf4&rct=1741339018&auth=c40ca16f35916d8a02f8c25adf579f293a
> 3f6a33-e4396153f73799684c504b6e7fdb0e398b649373
> [5] https://ddec1-0-en-
> ctp.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2fbugrepo
> rts.qt.io%2fbrowse%2fQTBUG%2d116345&umid=35d287fd-0e81-445e-ac6b-
> b30fbfebfbf4&rct=1741339018&auth=c40ca16f35916d8a02f8c25adf579f293a
> 3f6a33-39d69e213944d803c057df4839a800e7e98e54c8 and its sub-tasks [6]
> https://ddec1-0-en-
> ctp.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2fcoderevi
> ew.qt%2dproject.org%2fc%2fqt%2fqtbase%2f%2b%2f611485&umid=35d287f
> d-0e81-445e-ac6b-
> b30fbfebfbf4&rct=1741339018&auth=c40ca16f35916d8a02f8c25adf579f293a
> 3f6a33-1b4de4276f5c1bb169b77f18eaddc95d84575194
> [7] https://ddec1-0-en-
> ctp.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2fdoc.qt.i
> o%2fQt%2d6%2fqtqml%2dqml%2dscript%2dcompiler.html%23direct%2dmod
> e&umid=35d287fd-0e81-445e-ac6b-
> b30fbfebfbf4&rct=1741339018&auth=c40ca16f35916d8a02f8c25adf579f293a
> 3f6a33-b644331af91dda5de6015d0fd669e36eb00ebd62
> [8]
> https://ddec1-0-en-
> ctp.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2fcode.qt.
> io%2fcgit%2fqt%2fqtdeclarative.git%2ftree%2fsrc%2fqml%2fqml%2fqqmlprop
> ertytopropertybinding.cpp&umid=35d287fd-0e81-445e-ac6b-
> b30fbfebfbf4&rct=1741339018&auth=c40ca16f35916d8a02f8c25adf579f293a
> 3f6a33-7a3dab56d6346285219eebef4e5439f5a6f9fe60
> [9] https://ddec1-0-en-
> ctp.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2fwiki.qt.i
> o%2fQt%5fContributor%5fSummit%5f2025%5f%2d%5fProgram&umid=35d28
> 7fd-0e81-445e-ac6b-
> b30fbfebfbf4&rct=1741339018&auth=c40ca16f35916d8a02f8c25adf579f293a
> 3f6a33-57e28a5c89de14afd6413832caa7a18de7706702
> --
> Development mailing list
> Development at qt-project.org
> https://ddec1-0-en-
> ctp.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2flists.qt%
> 2dproject.org%2flistinfo%2fdevelopment&umid=35d287fd-0e81-445e-ac6b-
> b30fbfebfbf4&rct=1741339018&auth=c40ca16f35916d8a02f8c25adf579f293a
> 3f6a33-03261dd67bb78e46426db1bb6aa525538b910dce

________________________________

This message and any attachments are solely for the use of the intended recipients. They may contain privileged and/or confidential information or other information protected from disclosure. If you are not an intended recipient, you are hereby notified that you received this email in error and that any review, dissemination, distribution or copying of this email and any attachment is strictly prohibited. If you have received this email in error, please contact the sender and delete the message and any attachment from your system.

ANDRITZ HYDRO GmbH


Rechtsform/ Legal form: Gesellschaft mit beschränkter Haftung / Corporation

Firmensitz/ Registered seat: Wien

Firmenbuchgericht/ Court of registry: Handelsgericht Wien

Firmenbuchnummer/ Company registration: FN 61833 g

DVR: 0605077

UID-Nr.: ATU14756806


Thank You
________________________________


More information about the Development mailing list