How do you persist and update your models?
-
Being more familiar with web applications, I'm trying to get more comfortable with the Qt way of doing things.
Let's say you implement the software of a cash register where you can add products before checkout. In the web world you would probably have some model classes like Product and ShoppingCart, but instead of exposing these directly to the UI there would be DTOs or ViewModels or whatever. Two or more DTOs could be backed by the same "backend model".
When moving this case to C++ and Qt I'm not sure how this is best handled. I'm thinking that the backend models can live in C++ only and then create AbstractItem(List)Models as "DTOs". I've seen something similar in the Qt examples (animal), but they only show how to create AbstractItemModel from a "plain" class. No example of updating from UI or persisting.
How would you add a product to a ShoppingCartModel? Consider also that the ShoppingCartModel should be persisted at all time so that you can reload it if for instance power is lost.
Enter some data in a QML view and click a button. What happens next?
- Call an add method on the model? Will the model delegate to a repository in order to persist the change?
- Call a method on some other object that handles persisting and then adds the new product to the shoppingcart model? If so, how does it get hold of the model?
Any advice, examples, resources will be very helpful!
-
In Qt, there's usually the model (based on QAbstractItemModel and friends), then the delegate and the view. There's no notion of persisting a change. If you want your change to be saved, save it in your model. Depending on how you write the model, it will either store that info in RAM, or save it into some database, or send over network, or save in a file. Or wait for app closing signal. All depends on your use case and requirements, and on how you implement it, really.
Consider the shopping app you mentioned. The shop will most probably reside on some server. Your Qt application, however, will likely be installed on some desktop or mobile device. If your user adds an item to the cart, you'll likely just send a REST call to the server. Your app does not need to care about persistence. So, "if for instance power is lost" argument hardly applies (besides the fact that mobile devices will very rarely loose power spontaneously).
With that in mind, here is what I think about your question:
Enter some data in a QML view and click a button. What happens next?
Call an add method on the model? Will the model delegate to a repository in order to persist the change?Yes, handle the new item/ change in setData() or in addRow() of your model. Whether the model delegates anything anywhere depends solely on how you implement the model. Perhaps the name "ItemModel" is a bit misleading for you - focus on "Abstract" word first. These classes in Qt are only a kind of scaffolding, helping organize handling of models and data transfer between GUI and backend. They do not implement any actual data storage themselves.
-
I know that this is not a concept in Qt (unless you use the SQL based model base classes).
But say that you wanted to implement the backend in the GUI application. You perform some actions in the GUI and the result is stored in a database. Without using Qt SQL models, how would you solve it?
In my experiment I've done something like this.
class Item {}; class ShoppingCart { std::vector<Item> items; }; class ShoppingCartRepository {}; // Qt side /* alt 1: */ class ShoppingCartModel : QAbstractListModel { void addItem(); } /* alt 2: */ class QmlFacade { void addItemToCart(); } // in main ctx->setContextProperty("shoppingCart", &shoppingCartModel); ctx->setContextProperty("facade", &qmlFacade); // in QML onAddClicked: { shoppingCart.addItem(...) // or facade.addItem(...) }
I'm thinking that the goal is having "plain" models that are not QObjects. These can implement domain logic, and constraints and invariants lives in the backend. The only use of the QAbastractListModel is to keep the UI in sync and notify about changes made by the backend. Also, by not using the SQL model classes, I don't have a hard connection between the database and the model classes.
-
@tskardal said in How do you persist and update your models?:
I'm thinking that the goal is having "plain" models that are not QObjects.
That's a quite normal thing to do. Let the Qt model be just an intermediary between actual data model/tree and the GUI.
If your implementation works, then it's OK I guess. I'm not sure if there any actual question to answer here :-)