[Interest] Guide me through the Qt offerings for GUIs

Konstantin Shegunov kshegunov at gmail.com
Sun Apr 25 17:31:14 CEST 2021

On Sun, Apr 25, 2021 at 2:21 PM Giuseppe D'Angelo via Interest <
interest at qt-project.org> wrote:

> 22/04/21 20:38, Konstantin Shegunov:
> > Registering a struct/data class with the meta type system and/or
> > marshaling it over QVariant, just so it can be visible in QML isn't
> > that. Or things as natural (with C++) as having the UI raise some
> > encapsulated piece of data in a signal (say some struct, say QColor or
> > QVector3D) which the backend responds to isn't it either.
> I think I'm missing some context: when you say "isn't that" or "isn't
> it", what "that"/"it" are you referring to?

By that/it I specifically meant that I don't consider (re)wrapping already
encapsulated and self contained piece of data (e.g. one coming from the
backend to UI or vice versa) specifically for the purposes of it being used
only in the UI, a part of the business logic, a presentation layer or some
other sort of application design layer that's worth doing. This I consider
an adapter, so you tie two APIs/interfaces that are not compatible and
you're just stuck suffering with it ... which may be necessary sometimes,
no doubt, but in my opinion shouldn't be, if you're thinking about the Qt
codebase as a whole. Think of my statement like: "we are forcing the user
to write a middle man between the QAbstractItemView and QAbstractItemModel
just because we decided that's the right way ..."

"Controller" is an extremely overloaded word. Could you please clarify
> what design are you referring to?
> I don't understand some of your points, like "UI that's completely
> decoupled from the business logic". What does this mean -- shouldn't the
> business logic be the one decoupled from the UI? Are you talking about
> UI testing (via a mock business implementation)?

Right, I can see how this could've happened. No, I wasn't talking about
testing. I meant it in the sense of the MVC. I have UI, I have models
and/or possibly backend objects, so I have this entity whose main
responsibility is to possibly instantiate some objects, connect the two
mentioned layers, ideally keeping the coupling between them in one
manageable spot, and maybe implement at most some validation/simplistic
logic about the data transfer. Now, with QML you can't have this, because
the scene instantiation happens behind closed doors, so to speak, and you
don't have access to it after the fact (beside some nasty hacking with
findChildren<> and/or relying on the private API). This is my "technical"
beef with it, the idea I like. Currently, I have to expose said
"controller" object, or some other object I've designed specifically for
the purposes of routing the data to and fro without actually having to.
This obviously goes to the fact that the quick scene simply has no C++
interface, nor can you control the way it's instantiated. There's the
QComponent::createObject, sure but how do you "reach in" the scene to add
your newly created quick item?

Sure it is! I said it myself, it's typically not just one magic
> do-it-all layer, but multiple layers. In those layers you
> * adapt business logic datatypes into Qt datatypes;

My argument is that you adapt said datatypes even if they're very Qt-ish
and very much in line with what QML should eat easily. Instead we have this
superfluous re-wrapping just so it is possible to have them accessible.
Moreover, the UI couldn't possibly populate such a type directly, could it?
(going back to the factories for QVector3D, and the QColor being actually a
string in QML).

> * expose the relevant business logic in QObjects;

Yes, everything is QObject, even if it may not need to be necessarily,
which is one of my arguments. I mean, one could live with it, but in my
ideal world, I wouldn't want to.

> * write Qt models wrapping business logic datasets;

* create custom UI components;

This is perfectly fine and expected no matter if you're doing widgets, QML
or whatever else.

> * write state machines and what else is necessary to drive the UI based
> on the business logic state;

Most of the state machines that I'd seen in QML code were done in the UI
part, just sayin'. You could, obviously, do it from the C++ side, but many
people don't, as it's easier to define it in QML. Which is in conflict,
somewhat at least, with your comment that QML forces you to have the
separation between UI and business.

> The important message here is that such
> adaptation / UI logic layers do exist in any non trivial application,
> and the fact that from QML you just can't "just" reach into business
> logic, you need to jump through the language border, giving you a
> significant chance of making the integration more "clean".

Again, my "main complaint" is that you jump said border from the side of
the UI, not from the coupling code that you have in your C++ code. This
forces you to write additional code just so you can keep the UI "clean" of
the business logic, the middle man that does nothing but is an adapter - a
duplication of what your "glue code" already does on the C++ side for the
sole purpose of not polluting the UI with calls into it.

> ... I don't see how using JS magically allows you to call functions into
> your C++ business logic?

It doesn't, but it magically allows you to implement the business logic on
the side of the UI (as testified by a mail or two in this thread).  Which
leads us to my second "complain" about QML, which isn't technical and the
actual reason I started writing (I usually prefer to keep silent in these
epic threads): The word "declarative" has been thrown around like it's some
magic that makes code good, but as I wrote to Volker, there's nothing more
"declarative" in QML than in the widgets. It's become this sort of a
blanket term to explain everything and all about why QML is the greatest
thing since the sliced bread. Don't get me wrong, I do like many of the
ideas of the quick scene, and I like the syntax of QML, and many things
(with some appropriate tooling) can be made better with it, but the
QComponent class and the QQmlEngine are simply the reincarnation of the
QUiLoader; one could argue the latter is even better, as the QUiLoader just
doesn't allow me to inject random JS (or C++) code into the UI definition.
For what is worth removing this enforced and arbitrary barrier between the
quick scene and the C++ code is going to be a superb improvement to QML, I
think (also see André's email for some considerations about it, which I
mostly share).

"You can write FORTRAN in any language".

Amen, brother! This is so true it's not even funny (anymore). Seen a lot of
FORTRAN and suffered through some of it (being a physicist), so I vote we
just nuke that mentality altogether. I agree with the rest, so I'm not
going to quote it here.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20210425/fed25976/attachment.html>

More information about the Interest mailing list