[Interest] Guide me through the Qt offerings for GUIs
ulf.hermann at qt.io
Sun Apr 25 18:41:17 CEST 2021
> One thing I noticed contributing to this effect is that it is apparently
> difficult to pass objects of "medium" complexity through the glue layer > Simple stuff like integers and strings are fine (enums already get
> interesting...), really complex stuff like QAbstractItemModels can be fine,
> but for "two strings, an enum and an optional QDir" you already have to make
> up your mind whether this is more like "three strings and an int" or more
> like "something that needs moc". This contributes to an effect that I
> consider self-censorship when it comes to selecting appropriate data
> structures for the backend: If I know I can only expose certain types to the
> frontend, I am tempted to used these types in the backend, not necessarily
> the ones best suited one for the task. If the only tool is a hammer, ...
There is a difference between value types and object types in QML and
that difference is closely related to the difference between types you
would pass as pointer vs types you would pass as value in C++. For all
of this you do need moc. Basically, any QObject derived class is an
object type, and any Q_GADGET is a value type. The choice between those
is about as difficult as it is in C++.
You can use any Q_GADGET as value type in QML these days:
// I'm not sure whether plain MEMBER actually works.
// Maybe you need a WRITE (and that would be a bug in QML).
Q_PROPERTY(QString oneThing MEMBER oneThing)
Q_PROPERTY(QString secondThing MEMBER secondThing)
Q_PROPERTY(QDir thirdThing MEMBER thirdThing)
Enums in value types are not supported because of naming requirements.
Enums need to be part of uppercase-named types, and only object types
and namespaces are uppercase-named. However, you can either expose an
existing Q_GADGET as namespace using QML_FOREIGN_NAMESPACE (potentially
in addition to exposing the same struct as value type) or you can move
the enum to a suitable place if you're designing the whole thing from
scratch for QML.
Named value types are still somewhat black magic, but we'll get to that
soon-ish. You can use QML_ANONYMOUS and the QML "var" type for now. You
can also have a QML_ANONYMOUS type as Q_PROPERTY of a C++ class, under
its C++ name.
QDir is problematic because it does not expose any of its members as
Q_INVOKABLE or Q_PROPERTY, and it's not a Q_GADGET. Your best bet is
creating a wrapper type that does all these things. In that wrapper type
you can also encode the "optional" nature of it. A pre-defined value
type for QDir would be a candidate for our new QtCore QML module.
So, yes, QML is designed to use the metatype system. If you want to pass
data to QML, you have to declare the types. Once, you have done so, it
can be very easy to pass data back and forth in a structured way. The
type declarations can live in their own headers, and they can be purely
declarative, such as the example given above. While such declarations
add some lines of code, they do not add a lot of complexity.
Granted, we have promoted other, worse ways of connecting QML and C++ in
the past. In particular context properties. And, despite my recent
efforts to clean this up, there are still some holes in the type system.
For example named value types or (civilized) construction of value types
in QML. However, on the plus side, you do not need to call
qmlRegisterFooBar and figure out all the parameters to that anymore.
More information about the Interest