Re: [Interest] Guide me through the Qt offerings for GUIs

2021-04-25 Thread Ulf Hermann

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:

struct MyMediumSizeValueType
{
Q_GADGET
QML_ANONYMOUS

// 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)

QString oneThing;
QString secondThing;
QDir 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.


best,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Guide me through the Qt offerings for GUIs

2021-04-25 Thread Konstantin Shegunov
On Sun, Apr 25, 2021 at 2:21 PM Giuseppe D'Angelo via Interest <
interest@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 

Re: [Interest] Guide me through the Qt offerings for GUIs

2021-04-25 Thread Henry Skoglund



On 2021-04-25 13:56, André Pönitz wrote:

...
Hi Nuno.

This is an interesting statement.

My personal experience is exactly the opposite: By using Qt Quick one is
forced to use non-trivial amounts of glue code that is conceptually
unnecessary in the QWidget case.

As a concrete example: A while ago I converted Qt Creator's Welcome screen
(on the UI side essentially the thing that you see whe selecting the Welcome
mode plus a bit of helper code) from Qt Quick to QWidgets. The driving force
behind that change were re-occurring issues in setups with limited or
"broken" OpenGL support and the overall application startup time previously
dominated by this rather small plugin. Having to tell people to run with
"-noload Welcome" to mitigate these created a rather unwelcoming user
experience.

Besides solving the actually triggering problems this had the (not
completely, but surely at this level unexpected) side effect of reducing the
overall code side considerably: The original setup consisted some C++
"backend", the QML "frontend" and the "glue" to expose the backend to the
frontend (i.e. what Peppe calls "presentation" layer in Message-ID:
<421f4e26-dc6f-c06f-782f-72b67caf5...@kdab.com>). I do, btw, agree this is
indeed "best practice" for a Qt Quick application, so the original
implementation was ok, given the limits of the chosen technology.

For the replacement I had to do add some custom finger-painting code with
e.g. absolute pixel counts to mimic the original appearance closely (which
is, btw, quite unusual for a normal QWidget based setup), but even with that
the total LOC of backend + the complete frontend was less than previous LOC
of backend + glue. I.e. already the absolute number of LOC of the C++ bits
(with shifted functionality) overall decreased, and the QML bits were
completely gone.

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, ...


Anticipating some potential responses here: Of course, using QWidgets you
have at some point a _conceptually_ similar problem of having to associate
your QDir "data" with e.g. a QLineEdit, and your enum value with a QComboBox
or some QRadioButtons in a QButtonGroup. The concept of a "glue" layer
doesn't magicaly go away. However, in this case you have the choice to put
this glue code at a place were they make most sense (and also shift stance
easily once requirement changes), by e.g. putting the "necessary"
"three-line-lambda" in a place where your "logical" backend/frontend divide
actually is. With Qt Quick there is already some divide between .qml and
.cpp after you have prototype, and even when this turns out to be not the
the best place for the cut in the end, or when the requirements change
(a.k.a. "always"...) there is a high inertia to keep the divide as-is, even
if it doesn't fit the problem well anymore - simply because converting even
only a handfuls lines of code between C++ and QML is significantly more
effort then shifting these lines between different parts of a uniform C++
code base.

Please note that I am really not saying that there is no backend/frontend
glue in any QWidget based application. I surely have seen enough code piling
glue layer on glue layer for no traceable reason also for QWidget
applications so I know this generalization is not true. The point is really
that for a _reasonably_ developed QWidget application the amount of
_necessary_ glue is significantly(!) less than the _necessary_ glue of an
equally _reasonably_ developed Qt Quick application.  On top of that go
benefits like being the ability to use the same kind of tooling (debugger,
profiler, static analyzer, ...) for both parts in one go.

As you seem to have made different experiences I'd like to ask whether there
are concrete examples I may look at?

Andre'


Hi, re. backend/frontend glue i QWidget flavored apps:
you could also say that some "glue" will appear when you choose a 
QTableView instead of a QTableWidget in your Qt app.
IOW, most of the time (at least in my apps) working directly with a 
QTableWidget gets the job done easier/faster. Of course the QTableView 
model stuff is useful in some cases but I think the default design 
choice should be the plain widget.


Rgrds Henry
P.S. Reminds me of another, slightly similar 

Re: [Interest] Guide me through the Qt offerings for GUIs

2021-04-25 Thread Roland Hughes


On 4/24/21 5:00 AM, Frank Mertens wrote:

IMX6UL is just a marketing name. Look it up. "UL" stands for ultra-low. It has 
nothing in common with the IMX6 architecture. It is actually the first IMX7. It does not 
have a GPU and surely you can run it on a battery. Ask your hardware guys. They know.


No, no, no, no. *Never* ask hardware guys a question that could be taken 
as having an interest in hardware. Next you will find yourself assigned 
PIC coding and some bare metal coding and "Hey! Why don't you do these 
device drivers for us too?"


No.

Just listen to what they say in meetings and take notes. When it comes 
to the CPU and memory, my design and implementation shouldn't care what 
they put under the hood. Given most designs use some form of 
publish-subscribe message queue, I don't even care what else they put 
under the hood until I have to write one of those services.


--
Roland Hughes, President
Logikal Solutions
(630)-205-1593

http://www.theminimumyouneedtoknow.com
http://www.infiniteexposure.net
http://www.johnsmith-book.com
http://www.logikalblog.com
http://www.interestingauthors.com/blog

___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Guide me through the Qt offerings for GUIs

2021-04-25 Thread André Pönitz
On Wed, Apr 21, 2021 at 05:31:33PM +0100, Nuno Santos wrote:
>For me, the major benefit of Qml is speed. Before using Qml I’ve done a
>couple of years doing Qt Widgets. The glue code to make things work is a
>big pain.

Hi Nuno.

This is an interesting statement.

My personal experience is exactly the opposite: By using Qt Quick one is
forced to use non-trivial amounts of glue code that is conceptually
unnecessary in the QWidget case.

As a concrete example: A while ago I converted Qt Creator's Welcome screen
(on the UI side essentially the thing that you see whe selecting the Welcome
mode plus a bit of helper code) from Qt Quick to QWidgets. The driving force
behind that change were re-occurring issues in setups with limited or
"broken" OpenGL support and the overall application startup time previously
dominated by this rather small plugin. Having to tell people to run with
"-noload Welcome" to mitigate these created a rather unwelcoming user
experience.

Besides solving the actually triggering problems this had the (not
completely, but surely at this level unexpected) side effect of reducing the
overall code side considerably: The original setup consisted some C++
"backend", the QML "frontend" and the "glue" to expose the backend to the
frontend (i.e. what Peppe calls "presentation" layer in Message-ID:
<421f4e26-dc6f-c06f-782f-72b67caf5...@kdab.com>). I do, btw, agree this is
indeed "best practice" for a Qt Quick application, so the original
implementation was ok, given the limits of the chosen technology.

For the replacement I had to do add some custom finger-painting code with
e.g. absolute pixel counts to mimic the original appearance closely (which
is, btw, quite unusual for a normal QWidget based setup), but even with that
the total LOC of backend + the complete frontend was less than previous LOC
of backend + glue. I.e. already the absolute number of LOC of the C++ bits
(with shifted functionality) overall decreased, and the QML bits were
completely gone. 

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, ...


Anticipating some potential responses here: Of course, using QWidgets you
have at some point a _conceptually_ similar problem of having to associate
your QDir "data" with e.g. a QLineEdit, and your enum value with a QComboBox
or some QRadioButtons in a QButtonGroup. The concept of a "glue" layer
doesn't magicaly go away. However, in this case you have the choice to put
this glue code at a place were they make most sense (and also shift stance
easily once requirement changes), by e.g. putting the "necessary"
"three-line-lambda" in a place where your "logical" backend/frontend divide
actually is. With Qt Quick there is already some divide between .qml and
.cpp after you have prototype, and even when this turns out to be not the
the best place for the cut in the end, or when the requirements change
(a.k.a. "always"...) there is a high inertia to keep the divide as-is, even
if it doesn't fit the problem well anymore - simply because converting even
only a handfuls lines of code between C++ and QML is significantly more
effort then shifting these lines between different parts of a uniform C++
code base.

Please note that I am really not saying that there is no backend/frontend
glue in any QWidget based application. I surely have seen enough code piling
glue layer on glue layer for no traceable reason also for QWidget
applications so I know this generalization is not true. The point is really
that for a _reasonably_ developed QWidget application the amount of
_necessary_ glue is significantly(!) less than the _necessary_ glue of an
equally _reasonably_ developed Qt Quick application.  On top of that go
benefits like being the ability to use the same kind of tooling (debugger,
profiler, static analyzer, ...) for both parts in one go.

As you seem to have made different experiences I'd like to ask whether there
are concrete examples I may look at?

Andre'
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


[Interest] [SPAM] Re: Guide me through the Qt offerings for GUIs

2021-04-25 Thread Roland Hughes
Spam detection software, running on the system "mx.qt-project.org",
has identified this incoming email as possible spam.  The original
message has been attached to this so you can view it or label
similar future email.  If you have any questions, see
the administrator of that system for details.

Content preview:  >If you are *so* resouce constrained, use LVGL. 
You're probably not using 15MB Qt llibraries anyway, and they would 
take too long load anyway.
   Oh, we do. It's only the dynamic allocations. Initial allocation as 
determined
   by the loader, taking one big block, is fine or at least it always has been.
   

Content analysis details:   (4.8 points, 4.6 required)

 pts rule name  description
 -- --
-1.9 BAYES_00   BODY: Bayes spam probability is 0 to 1%
[score: 0.]
-0.0 RCVD_IN_MSPIKE_H2  RBL: Average reputation (+2)
[209.182.201.150 listed in wl.mailspike.net]
 0.0 URIBL_BLOCKED  ADMINISTRATOR NOTICE: The query to URIBL was
blocked.  See

http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block
 for more information.
[URIs: logikalsolutions.com]
 0.0 SPF_HELO_NONE  SPF: HELO does not publish an SPF Record
 3.3 RCVD_IN_SBL_CSSRBL: Received via a relay in Spamhaus SBL-CSS
[50.201.197.204 listed in zen.spamhaus.org]
 0.8 RDNS_NONE  Delivered to internal network by a host with no rDNS
 2.5 FAKE_REPLY_A1  No description available.


--- Begin Message ---


>If you are *so* resouce constrained, use LVGL. You're probably not using 15MB 
Qt llibraries anyway, and they would take too long load anyway.

Oh, we do. It's only the dynamic allocations. Initial allocation as 
determined by the loader, taking one big block, is fine or at least it 
always has been.


Putting it in perspective for you.

The UI artists were providing one SVG file per screen. That file had all 
of the images for said screen. We had to pull each image out. Initially, 
because it was there, the section pre-loading images for BLITting just 
cached all of them from the file before moving on. One of the developers 
changed this early on to load alphabetically. We started getting more 
and more images. On the desktop things loaded in under 3 seconds so 
nobody cared. Cold boot on target was 40-45 minutes.


Changing the code to load all images from an SVG file before moving on 
dropped cold boot to under 5 minutes. (I want to say 3.) Still too long, 
but night and day different.


On the desktop we didn't notice any real difference.

Creating objects for all of the XML inside of the SVG was a lot of 
dynamic memory allocation in tiny units.


--
Roland Hughes, President
Logikal Solutions
(630)-205-1593

http://www.theminimumyouneedtoknow.com
http://www.infiniteexposure.net
http://www.johnsmith-book.com
http://www.logikalblog.com
http://www.interestingauthors.com/blog

--- End Message ---
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Guide me through the Qt offerings for GUIs

2021-04-25 Thread Giuseppe D'Angelo via Interest

22/04/21 20:38, Konstantin Shegunov:
On Thu, Apr 22, 2021 at 7:19 PM Giuseppe D'Angelo via Interest 
mailto:interest@qt-project.org>> wrote:


You should create a C++ layer (call it a "presentation" layer) that
sits
between your (possibly non-Qt) business logic and the UI. That layer
contains stuff like item models, QObjects that expose the relevant
business logic APIs, type wrappers, and so on.


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?



 As a matter of 
fact, how do you tie your existing backend to QML? Say we have this nice 
encapsulated UI that's completely decoupled from the business logic, how 
do I tie a specific object from the Quick scene and connect the 
notifications back to C++? I can't do it from the business logic (i.e. 
controller side), I have to expose the backend to the QML engine and do 
it from there, am I wrong? Basically you say it's fine that the UI 
drives the controller (incl. object creation)?


"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)?





We can agree on the principles, gladly, but this is really a gross 
oversimplification of the problem.


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;
* write Qt models wrapping business logic datasets;
* expose the relevant business logic in QObjects;
* create custom UI components;
* write state machines and what else is necessary to drive the UI based 
on the business logic state;


and so on. All/most of this gets done in C++. Some other bits may be 
done in QML, if it makes sense. 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".






While building this layering may be super tedious (YMMV), in the long
run, it makes your application more robust, not less. The fact that QML
_forces_ you to have this stuff becomes somehow a good thing.


Forces you? Do you mean, perhaps, that JS is somehow not supported, or 
maybe that Component.createObject is somehow hidden and/or inaccessible?


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





On widgets, well, raise your hand if you didn't at least once connect a
QPushButton to a slot declared in the widget that contains the button,
and perform some business logic from there (yay business logic in
the UI!).


Yes, it is done, and not without an honorable mention of the 
documentation, where the view-controller idiom is used extensively.  But 
then, raise your hand if you at least once didn't use an `if` (or some 
other JS piece of code) in a QML file. I can pull out for you numerous 
cases of it being done, probably too numerous to count even in the 
examples. Shooting yourself in the foot is not restricted to one 
language or another, nor to the technological solution in use is my 
point.


"You can write FORTRAN in any language".

The point I was trying to make is this: you need to write some degree of 
QML/C++ integration code to make the two worlds communicate. This, at 
least, gives you an excellent chance of clearly separating UI from 
business logic. That chance doesn't guarantee not doing a complete mess, 
but at least it's there.


(Then, as I said, you should also write most of your _UI logic_ itself 
in C++ as well. And now we have at least two layers. And so on an so forth.)


Now, am I saying that the C++/QML integration is absolutely perfect and 
you'll never write cleaner UI code? Of course not, there's still tons of 
shortcomings and annoyances that will make you say "sigh" and take 
shortcuts here and there.


My 2 c,
--
Giuseppe D'Angelo | giuseppe.dang...@kdab.com | Senior Software Engineer
KDAB (France) S.A.S., a KDAB Group company
Tel. France +33 (0)4 90 84 08 53, http://www.kdab.com
KDAB - The Qt, C++ and OpenGL Experts



smime.p7s
Description: Firma crittografica S/MIME
___
Interest mailing list
Interest@qt-project.org