How to architect a Qt/C++ Application
cleanqt.io
cleanqt.io
The bindgen that seems to show up on google search is very un-intuitive to use (or maybe that's because I'm a rust newbie)
https://www.vandenoever.info/blog/2017/02/17/a-simple-rust-g...
I've tried most QT Rust projects and none were all that usable. I'm afraid your plans are not likely to succeed.
https://www.vandenoever.info/blog/2018/10/30/building_qt_app...
If it fails to build on Mac OS, I'd like to see why and help. The latest version uses Cargo for building, so e.g. `cargo qrep && qrep` should give you a working Rust + Qt example application.
Personally, I like Qt a lot more than GTK (both as a programmer and a user), but to each their own. QtQuick/QML is really great way of quickly whipping together complex UI’s. I’ve never used Qt on Rust though.
The documentation isn't perfect but its _really_ easy to map the documentation of the bindings to the original C documentation. From quick glance the situation seems to be more or less (maybe a bit less) the same with python bindings for Gtk.
I personally have enjoyed the gtk-rs bindings.
It is pretty trivial if you want to build an almost purely QML app. As soon as you want to do some C++ stuff (e.g. registering new C++ classes, using QtWidgets), however, things go south very quickly. The main problem is that Qt has its own ideas about ownership (QObject-parent-stuff), and Rust really does not like that. You end of working a lot with raw pointers and boxes. It feels like you’re writing C++ but in Rust (if that makes sense).
Rust-qt is really nice IMO, and I would extremely encourage anyone interested to take a look, and provide more feedbacks and contributions to the maintainers (I am not one of them). Some non-trivial examples would help a lot. But expect sharp edges.
Keen to see more on the QtQuick/QML stuff. I keep reading things about how great it is but never had the time to get into it.
For your "good-to-know topics" perhaps a brief direction for deploying applications? Bonus points for mobile deployment.
The distinction between these two parts is that the view is just a display of the data (model) whereas the controller is a way for the user to edit it. This was more relevant back in the 1970s where these things were more often separate. For a modern(ish) example, think of Vim's separation between the main display of your text file (the view) and its command line at the bottom (the controller). In most modern GUIs this distinction is meaningless, so you would group controller and view into the view and have a simple overall model-view separation.
Now I'm not saying that all of the classes you've called (something)Controller should be moved to the UI, I'm just saying that they're misnamed (at least by the traditional definitions). I think that your interpretation of model vs controller is raw model data vs non-graphical operations that act on them. But operations on the data are just as much part of the model as the data itself. For example, if I have a word processor then my model is a document, including operations on it. If I want to update the document programmatically (bypassing the GUI), for example to add a word, then I expect to call a method of the model. This should do everything to keep the model consistent, such as returning an updated word count. But that still doesn't need anything called a controller.
I just said that I'm not telling you to move your controller classes to the UI (view) layer. But that's a general comment about the meaning of "model view controller". The specific example you present on that page is "MenuModel" and "MenuController". These sound like things that both belong in the UI layer. Going back to the word processor example, your model might have a SaveToFile() method (although it would expect a file name parameter - popping up a save file dialogue box is the UI's job). But it won't know whether that came from a File->Save menu item or the user hitting ctrl+S. It's the UI's (view's) job to create a menu, choose what commands go on it, and map the OnClick events to actions on the model.
No doubt others will disagree with my understanding of the definition of "controller". This is the one thing you can be really sure about with that term! And it's another good reason to avoid it. Everyone agrees with "model" and "view" mean, so if you use those terms then people will know what you mean, but if you describe something as a "controller" then it just causes confusion.
> ...
> But operations on the data are just as much part of the model as the data itself.
So you want to move controller into the view or to the model? I can't tell. :)
I understand the term "model" to include non-graphical operations on model data. For example, SaveToFile() or InsertTextAtPosition() methods. These should definitely NOT be merged with the view!
--> I believe that the linked article called these non-graphical operations "controllers", but I disagree.
----------------
I understand the term "controller" to be graphical controls that allow manipulation of the data. For example, a the QMenuItem "save" along with its associated signal (which of course will just call a method on the model), or the OnKeyPress handler on an edit control.
--> I believe that the linked article just considers these to be part of the "view". I'm actually OK with this, because I the distinction between controller (in this sense) and view is not very useful.
There's some really good ideas in it, and you definitely make valid points. But this ^ happens too much for "MVC" to be a valuable term.
Over the years I've extracted many components from my controllers to the point where they're finally getting pretty slim. At first I let the controller fetch the model - e.g. update a model from the network, but later extracted this into a manager/provider object so multiple controllers and views can easily share this. Then I removed anything resembling business logic from the controller as I realised that was part of the model too, and moved this into service objects or utility functions (and not on the model-objects themselves, as I try to keep these focused just on data storage and serialization/deserialization). This might also include some form of dispatch if the business logic is triggered by a command. Similarly I moved all kinds of formatting code into presenter objects. Then I added viewmodels as an adapter layer on top of the actual model - both to insulate the controller from the actual model (didn't seem that important at first, but I finally 'got it' later) and to have a place to store local state such as current selection, scroll position, etc. And finally, I recently went all the way with the viewmodel after I extracted the logic of which view leads to which view out of the controller and into a flow coordinator object. This way, a given controller doesn't know what view is shown when you click the 'Next' button - instead it asks its viewmodel. That way the controller doesn't know anything about what needs to happen next or how the next view is shown. And that way all the logic about which view leads to which view resides in the flow coordinator which injects this into the controllers via the viewmodel. That way a view-controller pair becomes a completely reusable component that can be shown in multiple ways from multiple locations as part of different flows, and even using different models.
I don't always bother with all of the above, but it goes to show just how many separate concerns can actually end up in a controller, or instead be extracted to its own object: Fetching the model (provider), formatting the data (presenters), mutating the model (service/dispatch objects), wrapping the model (viewmodel), local ui state (viewmodel) and navigation between views (flow coordinator). It really goes to show that MVC isn't so much an architecture as it's the foundation for one; You've separated your view and model - great, now what about the rest of the application?
While outlining the post, I was uncertain what to call the particular group of classes (or concern) now called the Controllers. If you look through the GitHub project, you'll find that at one point they were called Routers. I agree with you that this design is not a MVC by the traditional definition (i.e. Smalltalk's), however there are many variants out there, see for example Apple's https://developer.apple.com/library/archive/documentation/Ge..., that I didn't think it would hurt 'to add' another. As long as it's clearly defined what it is. But perhaps it is not clear.
In this design, the 'traditional controller' is already part of the front-end. One of the goals of this design is to keep the front-end only concerned with styling and the layout of the application, and not the logic or the flow. So from the front-end, the user-interactions will be forwarded down to the 'back-end' Controllers. Those controllers are responsible for the flow of the application. The back-end includes logic and models in the traditional sense, see for example the DocumentsModel (https://github.com/Fagrell/clean-editor/blob/master/lib/publ...), however there are also models that correspond to specific Components. Those "Model Components" contain logic and a state, e.g. the MenuModel referred to in the post.
Perhaps an even better separation would be to add another layer?
- UI front-end - View/Component layer -> includes the 'view and controller by the traditional definition'.
- Router/Controller layer -> includes Models for specific components and Routers (as Controllers are defined in the post). Defines the flow.
- Back-end layer -> includes models by the traditional definition.
Thoughts?
Personally, I hate the name controller because its really unclear to me what they actually do. What do they control? The actual update logic is part of the domain knowledge, so that should live in the model itself, as quietbritishjim said. Router is a better name imho (even if itself not a perfect name).
For example, the logic of inserting text when insertion mode is active, removing the selected text when the delete key is pressed etc is all part of the controller, not the view.
By splitting the view and the controller, a different view, for example a console one, or a remote one, can be done with the exact same editing capabilities, since they are to use the same controller.
https://github.com/qmlnet/qmlnet
Disclaimer: I'm the author.
* Could this be mixed into an existing C# WinForms applications? I'm just talking about using a mix of different window types; I don't want/expect a mix within individual windows.
* Do you know if QT Quick has significantly better performance than WinForms for 2D graphics? I know that WinForms is not hardware accelerated (because it's based on GDI+ which was abandoned by Microsoft before they added hardware acceleration support). But I find documentation about QT Quick's hardware acceleration vague and confusing e.g. [1].
I work on an old WinForms application that makes heavy use of traditional 2D graphics APIs (i.e. Pen and Brush objects used during OnPaint events) but performance is a significant practical problem, and I'd like to find a way to move to something faster somewhat incrementally. My current thinking is to use WPM for new windows, but QT might be a bit nicer.
[1] http://doc.qt.io/QtQuick2DRenderer/qtquick2drenderer-perform...
Actual rendering overview (rather technical): http://doc.qt.io/qt-5/qtquick-visualcanvas-scenegraph.html
Cool blog post about performance improvement through draw call batching: http://blog.qt.io/blog/2013/09/02/new-scene-graph-renderer/
I ask because this same tutorial has an explanation on how to use CMake with Qt. Arguably Qbs is a lot "cleaner" than CMake scripting... but it doesn't appear to be a popular choice.
How do you follow blogs in general these days. My twitter is too full of things, so I'd probably miss the posts sometimes.
Today we've a superior technology like Electron. Why should we use old technology like Qt?
VSCode is built in Electron.
> VSCode is built in Electron.
So is slack, which (from what I've heard, I have no personal experience) eats RAM like a maniac. Neither of these example applications tips the scale between Qt or Electron on being superior.
Again, based on what I've heard/read, Qt being less recourse hungry and written in C++ allows it to be (for example) embedded (to cars or iot devices, for example).
The "new" js desktop technology is new only in the sense that js is new to the desktop (so it still doesn't really know about all the desktop requirements). Same for servers: there are better tools for the job from the purely technical point of view.
If there is anything superior to Qt, Electron clearly aint it.
And it takes up 3GB of RAM on my 8GB machine.