[Development] Property bindings in Qt 6
Simon Hausmann
Simon.Hausmann at qt.io
Thu Sep 26 17:44:55 CEST 2019
Hi,
Yeah, custom setters are required.
One option would be to say that such properties are implemented using the traditional property system altogether — bridging will be necessary anyway.
Another option would be to implement what you described, perhaps in a more convenient way though.
Simon
> On 26. Sep 2019, at 17:38, Mitch Curtis <mitch.curtis at qt.io> wrote:
>
>
>>
>> -----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