March 8, 2021

A Look at ListView and C++ Models in Qt

  —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:

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

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

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

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

comments powered by Disqus