Compiling QML to C++: Avoiding duck typing
Warning: CategoryLabel.qml:36:41: Property "displayName" not found on type "QObject" property string text: model ? model.displayName : ""
We know that this particular QObject has a property displayName, because we know that it is in fact a TimelineModel as declared in src/libs/tracing/timelinemodel.h. However, qmlsc does not know. And it doesn't trust us. We could assign some object without a displayName to the "model" property tomorrow, after all.
Let's check how expensive this binding was. Profile Qt Creator again, and have it open our example trace. You can click the label on line 36 in CategoryLabel.qml to see how long it took. On my machine, the binding was evaluated 24 times, with a cumulative duration of 53.3µs. Click the label again a few times and notice that the table in the profiler jumps between a different lines. If you take a look at the two subtables at the bottom, you will see that one of the lines in the "Callee" table refers to the same file and line has the line in the main table:
Here we have 40.4µs total time. How come? To clarify this, you can select the timeline view and zoom in using Ctrl and the mouse scroll wheel on the point you're interested in. As we are dealing with a very short time span you may need to scroll for while. Eventually you'll arrive at something like this:
TimelineModel so far is an anonymous type. We can see that from the QML_ANONYMOUS macro in its declaration. In order to show the compiler that there is a displayName to the "model" property, we can give TimelineModel a QML name, and use that as type of the property. Replace the QML_ANONYMOUS with QML_ELEMENT to use the "TimelineModel" name also in QML, and declare the model property in CategoryLabel.qml as follows:
property TimelineModel model
This makes it find the property, but now we get another warning:
Warning: CategoryLabel.qml:36:41: Could not compile binding for text: Member displayName of Timeline::TimelineModel of ??::model with type Timeline::TimelineModel can be shadowed property string text: model ? model.displayName : ""
What is this? Shadowing of a property is the practice of declaring the same property, potentially with a different type in a derived class in C++. The QML engine will pick the most derived class when resolving the type of a property. We could therefore go and declare a type EvilTimelineModel that provides a displayName property, but not as a QString, but rather as an EvilFoozle. The compiler will not generate any code to deal with such things as that would slow down the very, very common case where this is not done. Instead, it forces you to declare that you won't do it. This is what the "FINAL" attribute to Q_PROPERTY is for. A FINAL property cannot be shadowed. The QML engine rejects types that shadow FINAL properties. So, add FINAL to the displayName property as follows:
Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName NOTIFY displayNameChanged FINAL)
We depend on declarative QML type registration for the QML_ELEMENT macro. Declarative type registration has been around since Qt 5.15. The FINAL attribute to Q_PROPERTY has been around since Qt 4.6.
Subscribe to our newsletter
Try Qt 6.6 Now!
Download the latest release here: www.qt.io/download.
Qt 6.6. is a feature release with focus on improving UX capabilities including responsive UI technology and the Qt Graph module.
Check out all our open positions here and follow us on Instagram to see what it's like to be #QtPeople.