—Resources for using QML and C++ models.
I recently experimented with Qt and QML in an effort to construct an application that relies upon a QML ListView and a C++ model. This is a collection of resources that I found helpful. Article relies upon Qt 5.12.
I wandered around in the dark on some of this. The best path forward for learning is item 2 and 3.
Item 1 was my reviewing the difference between Model-View-Controller and the Model Delegate used by Qt.
Item 4 looks at whether I need to implement insertRows()
when I found Qt’s documentation on subclassing QAbstractListModel
a little vague.
(I don’t.)
The winding path:
A terrific Model View Controller (MVC) diagram provides a simple explanation of the Model-View-Controller pattern. This includes a diagram and a set of rules that are well presented and straight forward to understand.
The nice part of this article is that it shows best practice and poor practice side-by-side.
Models and Views in Qt Quick provides an overview on models and views in Qt. Qt uses a variant of MVC that combines the view and controller into a single entity and introduces a delegate. Importantly, the delegate is not a controller.
There is some confusion regarding Qt’s implementation of MVC (see for example Why Qt is misusing model/view terminology?). That thread was useful to provide a contrast to a textbook MVC implementation.
For me the answer lies in whether you choose to separate the view and controller. (My favorite reference for Model View Controller.) Qt combines them to create a Model Delegate pattern. The model delegate pattern combines the view and controller into a UI delegate.
Using C++ Models with Qt Quick Views has a video showing how to create an application with QML and a C++ model.
Explanation on creating read-only view and extending them to C++ models (around 9:31).
The video shows how to connect the view and model together using a delegate in C++ (around 13:00 through to the end of the video).
Importantly, the view (a QML ListView
) is connected to the model in C++ (the TodoModel
class) using the QML model
keyword.
The model is connected to the data, also in C++ (the ToDoList
).
The creation of the TodoList
class starts at 20:30.
Address Book Example provides a look at using a QTableView
(my goal was a QListView
).
This example proved helpful in understanding whether the insertRows()
method needed to be implemented or not.
This example provided a look at what an implementation should look like.
By default, insertRows()
returns false
if it’s not overloaded in a subclass of QAbstractListModel
.
The guidance in QAbstractListModel
is you can overload this method (of course you can).
It was light on details as to when you had to overload it.
Thinking about the QML and C++ model in terms of a Model Delegate instead of Model-View-Controller permits better reasoning about the implementation.
A source of confusion for me was the relationship between the QML QListView
and the QAbstractListModel
as it relates to model updates.
Using C++ Models with Qt Quick Views puts the data in the backend, separate from the model (see video at 30:11).
It follows the guidance in Models and Views in Qt Quick.
Whereas, How to Use a QSqlQueryModel in QML puts data in the model’s constructor (see step 4 [implementation] and step 3 [use]).
The difference between the two approaches is unclear to me at this time.
It’s unclear because I view the database as a persistent data store similar in purpose to the TodoList
class in Using C++ Models with Qt Quick Views.
Not sure why the rules would change.
(To be fair, when I wrote this article How to Use a QSqlQueryModel in QML was tagged as needs improvement.)
Here’s a list of starting points in the video from Using C++ Models with Qt Quick Views:
Highlight | Time |
---|---|
Creating a read-only view | 0:00 |
Extending view to C++ models | 9:31 |
Creating the C++ backend class | 20:30 |
Adding data through the view | 45:30 |
The only confusing part of the video was the introduction of data into the constructor of the ToDoList
class at 45:30.
The ToDoList
class looks like it’s part of the control.
It’s a small point, especially in a tutorial, but adding data to ToDoList
gives that class multiple reasons to change.
In my opinion, a better approach is to extend ToDoItem
to include a container class and have ToDoList
use that container instead.