Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mobile and Embedded platforms support #138

Open
LateusBetelgeuse opened this issue Dec 27, 2020 · 8 comments
Open

Mobile and Embedded platforms support #138

LateusBetelgeuse opened this issue Dec 27, 2020 · 8 comments

Comments

@LateusBetelgeuse
Copy link

Qt officially supports Android and iOS. Also supports cross-compiling for some embedded platforms like Raspberri Pi.
Having this for mobile will be awesome for users that RNG in their consoles.

I was thinking that, in the long-term I could port this project but with a QtQuick-based UI, which is fluid and animated, looks very well on all platforms, new styles are very easy to implement, and in Qt 6 they also have native styles for desktop. Then I checked the code and... nice! This project is pretty well designed and refactored, so I think that I can contribute modernizing the UI with the latest Qt things (widgets are very outdated), if you are interested, of course. Also... check the new Qt 6's concurrent API.

I will not have time to work on this anytime soon, but I may have time in some months, or may not, but I think that this is a good idea. Right now, the UI do not fit for mobile purposes because of the several windows and it does not scale well (almost everything falls outside the screen).

@Admiral-Fish
Copy link
Owner

I have considered mobile support several times in the past. Gonna leave some thoughts and questions about this.

Android is gonna be much easier since you don't need to go through the play store by installing apk's manually(although it is a single $25 payment last I checked) and I actually have several Android devices that I could personally mess with. iOS is much more annoying since I don't know of a way to install without using the App Store (which is $100/yr last I checked) and I don't have any devices to test on. I can't think of anything immediately regarding embedded platforms.

I have messed with QtQuick/QML several times in the times. Every time I have been extremely disappointed and always just gone back to using Widgets (which personally makes a lot more sense to me, though maybe that's because I started Qt using Widgets and not Quick). I used Flutter once to mess around with a mobile app and found the experience much more pleasant with how both UI and backend are Dart. I never liked/understood making C++ and QML play nice together.

I know the UI is not good for mobile devices since it was designed on/for computers. You mentioned Widgets are outdated, but I have not found anything online about Quick being a replacement to Widgets. If anything everything I find online suggests using Quick for mobile and Widgets for desktop. Is the Quick experience on desktop as good as Widgets? Is your vision to have a single UI in Quick work for mobile/desktop and replace the current Widgets UI?

I am not strictly for or against this. Just want to lay out my thoughts on the matter.

@LateusBetelgeuse
Copy link
Author

Thanks for answering, and sorry for the delay (this is my last year in the University and I am currently very busy). This may be long, so reading this will take you a few minutes from your time. Let's start with mobile platforms.
I have made many apps for Android in Qt, eighter for personal use and/or for a friend needs, and it's pretty straightforward. I was working in a more complete Pokémon database with data from PokéAPI (it's still a private repo). With iOS (even with macOS) I have zero experience. About the Play Store... well I currently live in Cuba, so such things are blocked here. Luckily you are right and APKs can be installed manually.
About embedded platforms, I have messed around with ARM devices like Raspberry Pi, and it's really fun. You can install Linux on it, then cross-compile Qt for ARM and build an AppImage just like you do on a regular Linux. It's really fun to have a Raspberry for dedicated things like RNG, for example. I used to have mine for creating hotspots to play local games and other game-related things. Also, I know that one can make a Raspberry to boot directly to a Qt app instead to booting to an operating system (though I haven't done it yet).

Let's talk about Qt Quick.
I started coding when I entered the University, and started GUI programming with Qt on my second year, with widgets, just like you, I liked it a lot and sticked with it for two semesters. That summer I discovered Qt Quick and I started messing around with it. By then the latest Qt release was 5.9, and Qt Quick 2 was just released in 5.7, so it was very immature by then, and the documentation insufficient. I just hated Qt Quick 1 (it is now gone in Qt 6), but Qt Quick 2 (now just Qt Quick) was awesome, and I saw it evolved in the next three years until now Qt 6, while widgets are just the same. They even announced a QSwitch and a QCircularProgress indicator three years ago, I'm still waiting for it. I know that you can customize widgets with style sheets (I think that you are using that), but you have no animations nor transitions, and there's a limited number of aspects that you can customize of each control.

Check this, for example, this Work-In-Progress app that uses my PokéM library to generate Wonder Mails for Mystery Dungeon games. You can't do this with widgets. Qt Quick allows you to have really fluid animated UIs.

Wonder.Mail.Generator.mp4

And it is also ready for mobile, just see what happens when you stretch it:

Mobile Layout

I agree that after working with widgets, using QQ2 can be weird, since it's a completelly different philosophy. I think it was easy for me because it was in my early coding years, don't know for sure. What I know, it's that I have not used widgets since then (with a very few exceptions). Why?

  • Because it forces you to take on good programming practices, since you export C++ objects to QML, but you cannot (shouldn't) directly mix C++ and QML, so the backend is completely unaware of the existence of QML, which leads to great refactoring.
  • Because it looks so much better. You can create custom components very easy in QQ2 (it was a pain in QQ1, that's why I hated it), and make animations really easily, and the performance is not any worse compared to widgets (in my experience is even better, mainly for animations and transitions), the memory footprint is very low. So basically, if you want that something look in some way, you can be 100% that you can achieve it with Qt Quick easily.
  • You can get exactly the same look'n'feel in all platforms if you want, just as you can do with style sheets, but you can customize anything, and also have transitions. Also, if you want native styles, Qt 6 unified the style model, so you can actually have a native style in Qt Quick.

You mentioned Widgets are outdated, but I have not found anything online about Quick being a replacement to Widgets

Not sure what you meant. Widgets and Qt Quick are both valid approaches, and Qt Quick was not released to drop widgets away. I started with widgets and used them for almost a year in all my school projects, then I switched to Qt Quick, and so far, there's nothing you can do in widgets that you cannot do with Qt Quick, and there's a lot of visual stuffs that you can do with Qt Quick and cannot be done with widgets. Oh! Just realized what you meant. When I said "outdated", I meant that in my opinion they look outdated. And it's very hard to make them look modern.

Is the Quick experience on desktop as good as Widgets?

Yes. In my humble opinion, even better, because you can easily make custom controls for specific purposes, and call for user attention very easily too. For example, did you saw the filter field in the pokémon ComboBox above? Very easy to do with QQ2, hard to do with widgets without making the QComboBox editable, and even so, making the completer look like that can be very hard, if not impossible. This is what I meant: even little details like that can be twisted very easily without compromising any functionality. If you want to do something, just do it because it will not be hard to make it in the exact way you want.

Is your vision to have a single UI in Quick work for mobile/desktop and replace the current Widgets UI?

Yes. However, loading a QML interface it's more or less the same thing as loading a widgets one. So you can have both. If you want that, fine for me, I just find that unnecessary, but it's your call.

Migrate from widgets to QML can be often difficult, since you can interact directly with widgets from the backend, so Qt widgets applications are usually not refactored, unless the programmer wants to refactor it. But your project is very well designed and refactored. If you want even more independence, you can encapsulate the different functionalities in separate plugins or libraries, one for 3rd gen, one for 4th gen etc, one for utilities, etc.

I never liked/understood making C++ and QML play nice together

  • Create a C++ class.
  • Any private variable that you want to expose to QML, declare it as a Q_PROPERTY.
  • Any function that you want to expose to QML, declare it as a public slot.
  • Add the macro QML_ELEMENT in the private section (under Q_OBJECT for example).
  • Done, create the object in QML:
MyRng {
    id: myRng

    seed: 0x0A // property declared in C++
}

The declarative way of QML actually feels much more natural. Any property that you change in C++/QML is updated in the other side. And property bindings are the best part: you can create a math expressions arbitrarily complex and its value is updated every time one of its dependencies changes. That part was so popular that in Qt 6 was included in C++ QProperty.

Just yesterday I made a simple interface for a HMI device for a school project. This is the UI using the Material style, that comes with Qt Quick.

Material.mp4

And then they requested an UI that saves energy, so I made this one, which is a modified version of the Basic style:

Basic.Modified.mp4

You may say... well I can do that with style sheets. True, but once you want to add transitions to color changes, well... you can't. There's the code for the styled button:

component OutlineButton: Button {
    id: control

    property color color: "white"
    property color secondaryColor: "black"

    icon.color: down || hovered ? secondaryColor : color

    background: Rectangle {
        implicitWidth: 100
        implicitHeight: 40
        opacity: enabled ? 1 : 0.3
        color: control.down ? Qt.darker(control.color, 1.1) : control.hovered ? control.color : "transparent"
        border.color: control.down ? Qt.darker(control.color, 1.1) : control.color
        border.width: 2
        radius: control.width/10
    }
}

Then just use it anywere:

OutlineButton {
    id: buttonPlay

    icon.source: "play.svg"
    icon.width: 48
    icon.height: 48
    color: "#41CD52"
    secondaryColor: "#09102B"
}

@Admiral-Fish
Copy link
Owner

So I have a few follow up thoughts.

You mentioned how Qt Quick has advanced and widgets hasn't much in the past 3 years. While I haven't followed new changes to either very closely Widgets has always been enough to satisfy my needs for this project. Is there anything Widgets has that Quick doesn't? You also mentioned Quick having animations/transitions, but I don't really see a need for them in this project currently.

In your example for the wonder mail generator, what exactly is not achievable using Widgets?

My biggest concern with C++/QML integeration is having to add back Qt specific stuff to the backend. I spent a decent amount of time a while back making the backend of this project completely independent of Qt so it can be used with anything and not locked into Qt. From what you are saying it seems like you have to make parts of the backend aware to the Qt Meta system. What kind of performance impact does the meta system impose and is it necessary? What I like about Widgets is the fact that I can make my backend completely unaware of the existence of Qt.

@LateusBetelgeuse
Copy link
Author

LateusBetelgeuse commented Jan 4, 2021

Widgets has always been enough to satisfy my needs for this project

It's like I said. Both Widgets and Qt Quick are valid approaches. When I worked with widgets, they also satisfied all my needs, but that's because I don't used to have many needs to fit. Only when I entered the world of modern and fluent UIs, my needs increased, because I realized that the quality of the final product is a lot bigger with less effort. In my experience, developing widgets-based apps it's a lot slower than developing qml-based apps.

Is there anything Widgets has that Quick doesn't?

Check this.

In your example for the wonder mail generator, what exactly is not achievable using Widgets?

Strictly speaking, there's nothing that you cannot do with widgets, but strictly speaking, it is possible that the clothes come out of the washing machine perfectly folded and arranged. The problem is the amount of time and effort that you must invest with one approach or another. I haven't used widgets anymore because I save an incredible amount of time making UIs, and the final result looks much better.

You also mentioned Quick having animations/transitions, but I don't really see a need for them in this project currently.

There's no need. Making things look nicer is never a need, but if you can make your app look a lot better, and your users will feel the impact of an improved UX with even less effort, why not? Most applications that I've done with widgets, remains in widgets because I have not interest on maintaining them, but with any new application or any old application in progress, I use Qt Quick without a second thought.

My biggest concern with C++/QML integeration is having to add back Qt specific stuff to the backend.

Following the example of the Wonder Mail Generator, the backend is written in pure C. I don't know why you must add specific Qt stuff to the backend.

From what you are saying it seems like you have to make parts of the backend aware to the Qt Meta system. What kind of performance impact does the meta system impose and is it necessary? What I like about Widgets is the fact that I can make my backend completely unaware of the existence of Qt.

I see. Don't worry, let me elaborate more what I said before, part by part.

What you call the "backend" must not be aware of Qt, that's cool, and it's one of the best things of this (and any) project. What you expose to QML is a wrapper around that backend. You also do it with widgets, but the wrapper is less refactored. A MainWindow class, that inherits from QMainWindow, contains both UI code, and the logic that you use to interact with the so-called "backend", and validate it's data before finally exposing it to the view. With QML, these two things are separated: the UI in QML, and the logic that extracts and validates the data before exposing it to the view, in C++.

I mean, in widgets apps, you have a Model-View pattern, because the "Controller" is part of the View (you extract data and make validations in the same class in which your UI is). In QML, you can effectively and intuitively separate the Controller and the View. It's actually very hard to not do it because QML is not meant for logic programming. You can write imperative code in some places in QML (like event handlers), but QML is not for that, C++ is. Once the data is perfectly validated and in the appropriate format, you expose it from C++ to QML. That's why I said that writing Qt Quick apps forces you into good programming practices.

About the performance... there's zero impact compared to widgets. Widgets uses the Qt's Meta Object System all along the UI classes (which also contains imperative logic). So what you do is basically separating a big class that contains the UI (that uses the Meta Object System) and the logic that extracts and validates data (that also uses the Meta Object System) into two components (one for UI and the other for the logic) that uses the Meta Object System.

In widgets, two different UIs require two different big classes to manage the logic, even if they access the same data. In QML, you can have multiple UI files, and a single C++ logic class that expose data, no matter who wanted it, C++ doesn't care. If only a QML file requires data, for the C++ class it's fine, if a million requires data, for the C++ class it's fine as well. C++ only cares about exposing the data that some UI may or not need (it doesn't know nor care about that). It's in QML where you decide wich UI file will require which data.

@Admiral-Fish
Copy link
Owner

Is the UI part of your Wonder Mail Generator on github?

@LateusBetelgeuse
Copy link
Author

Still a private repo, but you should be able to access it now. Anyway, these are the UI files:
qml.tar.gz

@LateusBetelgeuse
Copy link
Author

LateusBetelgeuse commented Jan 16, 2021

Anyway, the main purpose of this issue is pave the way to support mobile and embedded platforms, not to replace the current widgets UI. I think that we should make an UI for mobile in Qt Quick. We can have both UIs, although having just one can simplify the maintenance.

Since mobile devices have less space available in screen, I usually make new application in a mobile-oriented layout, because it's easier to later join two or more of those UIs for desktop than having desktop UIs and figure out how to split them.

For example:
1
2
3
4
5
6

In desktop, I don't need to show pokémon details in a separate UI. I can join the pokédex UI and the pokémon details UI to have a list in one side of the screen, and the pokémon info in the other side. Doing this can be pretty straightforward, doing the opposite may not. Also, in desktop, I can have the UI in one way or another depending of how much space I have available.

@XLR8thetrue
Copy link

I need help

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants