[Development] Property bindings in Qt 6

Mitch Curtis mitch.curtis at qt.io
Thu Sep 26 17:38:40 CEST 2019


> -----Original Message-----
> From: Development <development-bounces at qt-project.org> On Behalf Of
> Simon Hausmann
> Sent: Thursday, 26 September 2019 5:03 PM
> To: development at qt-project.org
> Subject: [Development] Property bindings in Qt 6
> 
> Hi,
> 
> Earlier this year, Olivier, Samuel, Auri and I worked on a project to re-
> evaluate how we could bring the declarative Qt Quick approach of doing user
> interfaces closer to C++, in order to allow building and running user interfaces
> in very memory and processor-power constrained environments. There
> were many different outcomes of this. One of them was that we figured out
> a way to compile QML binding expressions down to full C++, without any run-
> time interpretation. This required building a new way of defining properties
> and their relationships, a new property binding system. The results were so
> convincing that the plan was born to productize this for Qt 6 in multiple layers
> and steps. I'd like to initiate a first step in that direction by proposing API and
> functionality for Qt 6 and briefly outline how we see the building blocks apply
> to QML and Qt Quick:
> 
> In QML, today, properties consist of a type, a setter function and a getter
> function, and the functions are implemented by the developer. There is also
> a change signal that needs to be emitted when the value changes.
> 
> Binding expressions declared in .qml files are created behind the scenes and
> the QML engine makes sure to call the getter functions during the evaluation
> and the setter function to write the result. Through a connection to the
> change signal, bindings are automatically re-evaluated when properties
> change and the new values are passed to the setter functions. It's pretty
> magic and it works, but it requires a fair amount of indirection and side-
> loading of data structures.
> 
> I would like to propose an API that replaces the setter and getter functions
> on objects with a new property template class that encapsulates the
> property value instead, and the ability to tie binding expressions to these
> properties for automatic updates. In short, it looks like this:
> 
>     QProperty<QString> surname("John");
> 
>     QProperty<QString> lastname("Smith");
> 
> 
>     QProperty<QString> fullname;
> 
>     fullname.setBinding([&]() { return surname() + " " + lastname(); });
> 
> 
>     qDebug() << fullname(); // Prints "John Smith"
> 
> 
>     surname = "Emma"; // Marks binding expression as dirty
> 
> 
>     qDebug() << fullname(); // Re-evaluates the binding expression and prints
> "Emma Smith"
> 
> 
> 
> 
> 
> You can see a work-in-progress patch for this in Gerrit at
> 
>     https://codereview.qt-project.org/c/qt/qtbase/+/275352
> 
> 
> The basic data structure behind this is the property value itself as well as
> doubly linked lists to track dependencies between properties and binding
> expressions. Due to the encapsulation of the data itself in a class, it is
> possible to do a lazy evaluation of bindings. (Credit goes in particular to
> Olivier for the idea and first implementation in our project)
> 
> 
> Once this class and its documentation is complete, the next step is to build a
> bridge to the QML engine and the moc, so that it's possible to associate
> binding expressions in .qml files with properties declared this way. Similarly,
> it needs to be possible to access such properties through the meta-call, if
> they are placed inside Q_OBJECT classes.
> 
> The next step is to begin applying this to the implementation of Qt Quick.
> Some of which may require shims for the public Qt Quick API (to keep it
> Q_PROPERTY based), and for the private Qt Quick types the idea would be to
> start using QProperty.
> 
> Finally, once all the pieces are in place, we hope to extend the qml tooling to
> compile the binding expressions in .qml files to C++ that uses this more light-
> weight property system whenever possible. Ulf has been working towards
> this from the QML engine direction (see the recent email about moc and
> meta-type extraction) and Fabian has been working on the QML linter as a
> starting point towards a compilation model for QML.
> 
> 
> This is our rough plan of how we'd like to address one aspect of QML and Qt
> Quick today. We are looking forward to any feedback and questions to help
> us review and refine this design.

I think you guys did an awesome job with it from what I've seen. :)

In my experience with a similar system, one drawback is the lack of ability to implement custom setters. For example, I often find that I need to validate some input to a setter:

https://code.qt.io/cgit/qt/qtquickcontrols2.git/tree/src/quicktemplates2/qquickslider.cpp#n355

In the end the solution was to use "dirty events" (i.e. derive from a certain type, implement operator() and pass a pointer the property in its constructor) as a way of reacting to the changes after they were made, but this is not ideal.

Will custom setters be possible?

> 
> Simon



More information about the Development mailing list