Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cppmodels.qdoc
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3
4/*!
5\page qtquick-modelviewsdata-cppmodels.html
6\title Using C++ Models with Qt Quick Views
7\brief using Qt Quick views with models defined in C++
8
9
10\section1 Data Provided In A Custom C++ Model
11
12Models can be defined in C++ and then made available to QML. This is useful
13for exposing existing C++ data models or otherwise complex datasets to QML.
14
15A C++ model class can be defined as a \l QStringList, a \l {QVariant::}{QVariantList}, a
16QObjectList or a \l QAbstractItemModel. The first three are useful for exposing
17simpler datasets, while QAbstractItemModel provides a more flexible solution for
18more complex models.
19
20\section2 QStringList-based Model
21
22A model may be a simple \l QStringList, which provides the contents of the list
23via the \e modelData role.
24
25Here is a ListView with a delegate that references its model item's
26value using the \c modelData role:
27
28\snippet models/stringlistmodel/view.qml 0
29
30A Qt application can load this QML document and set the value of \c myModel
31to a QStringList:
32
33\snippet models/stringlistmodel/main.cpp 0
34
35The complete source code for this example is available in
36\l {models/stringlistmodel}{examples/quick/models/stringlistmodel}
37within the Qt install directory.
38
39\note There is no way for the view to know that the contents of a QStringList
40have changed. If the QStringList changes, it will be necessary to reset
41the model by setting the view's \c model property again.
42
43\section2 QVariantList-based Model
44
45A model may be a single \l {QVariant::}{QVariantList}, which provides the contents
46of the list via the \e modelData role.
47
48The API works just like with \l QStringList, as shown in the previous section.
49
50\note There is no way for the view to know that the contents of a QVariantList
51have changed. If the QVariantList changes, it will be necessary to reset
52the model by setting the view's \c model property again.
53
54\section2 QObjectList-based Model
55
56A list of QObject* values can also be used as a model. A QList<QObject*> provides
57the properties of the objects in the list as roles.
58
59The following application creates a \c DataObject class with
60Q_PROPERTY values that will be accessible as named roles when a
61QList<DataObject*> is exposed to QML:
62
63\snippet models/objectlistmodel/dataobject.h 0
64\dots 4
65\snippet models/objectlistmodel/dataobject.h 1
66\codeline
67\snippet models/objectlistmodel/main.cpp 0
68\dots
69
70The QObject* is available as the \c modelData property. As a convenience,
71the properties of the object are also made available directly in the
72delegate's context. Here, \c view.qml references the \c DataModel properties in
73the ListView delegate:
74
75\snippet models/objectlistmodel/view.qml 0
76
77Note the use of the \c color property. You can require existing properties
78by declaring them as \c required in a derived type.
79
80The complete source code for this example is available in
81\l {models/objectlistmodel}{examples/quick/models/objectlistmodel}
82within the Qt install directory.
83
84\note There is no way for the view to know that the contents of a QObjectList
85have changed. If the QObjectList changes, it will be necessary to reset
86the model by setting the view's \c model property again.
87
88\section2 QAbstractItemModel Subclass
89
90A model can be defined by subclassing QAbstractItemModel. This is the
91best approach if you have a more complex model that cannot be supported
92by the other approaches. A QAbstractItemModel can also automatically
93notify a QML view when the model data changes.
94
95The roles of a QAbstractItemModel subclass can be exposed to QML by
96reimplementing QAbstractItemModel::roleNames().
97
98Here is an application with a QAbstractListModel subclass named \c AnimalModel,
99which exposes the \e type and \e sizes roles. It reimplements
100QAbstractItemModel::roleNames() to expose the role names, so that they can be
101accessed via QML:
102
103\snippet models/abstractitemmodel/model.h 0
104\dots
105\snippet models/abstractitemmodel/model.h 1
106\dots
107\snippet models/abstractitemmodel/model.h 2
108\codeline
109\snippet models/abstractitemmodel/model.cpp 0
110\codeline
111\snippet models/abstractitemmodel/main.cpp 0
112\dots
113
114This model is displayed by a ListView delegate that accesses the \e type and \e size
115roles:
116
117\snippet models/abstractitemmodel/view.qml 0
118
119QML views are automatically updated when the model changes. Remember the model
120must follow the standard rules for model changes and notify the view when
121the model has changed by using QAbstractItemModel::dataChanged(),
122QAbstractItemModel::beginInsertRows(), and so on. See the \l {Model subclassing reference} for
123more information.
124
125The complete source code for this example is available in
126\l {models/abstractitemmodel}{examples/quick/models/abstractitemmodel}
127within the Qt install directory.
128
129QAbstractItemModel presents a hierarchy of tables, but the views currently provided by QML
130can only display list data.
131In order to display the child lists of a hierarchical model,
132use the DelegateModel QML type, which provides the following properties and functions to be used
133with list models of QAbstractItemModel type:
134
135\list
136\li \e hasModelChildren role property to determine whether a node has child nodes.
137\li \l DelegateModel::rootIndex allows the root node to be specified
138\li \l DelegateModel::modelIndex() returns a QModelIndex which can be assigned to DelegateModel::rootIndex
139\li \l DelegateModel::parentModelIndex() returns a QModelIndex which can be assigned to DelegateModel::rootIndex
140\endlist
141
142\section2 Exposing C++ Data Models to QML
143
144The above examples use required properties on the view to set
145model values directly in QML components. An alternative to this is to
146register the C++ model class as a QML type (see
147\l{Defining QML Types from C++}). This allows the model classes to be
148created directly as types within QML:
149
150\table
151\row
152
153\li C++
154\li
155\code
156class MyModel : public QAbstractItemModel
157{
158 Q_OBJECT
159 QML_ELEMENT
160
161 // [...]
162}
163\endcode
164\row
165\li QML
166\li
167\qml
168MyModel {
169 id: myModel
170}
171\endqml
172
173\qml
174ListView {
175 width: 200; height: 250
176 model: myModel
177 delegate: Text {
178 required property string someProperty
179 text: someProperty
180 }
181}
182\endqml
183
184\endtable
185
186See \l {Writing QML Extensions with C++} for details on writing QML types
187in C++.
188
189\section2 Changing Model Data
190
191Besides the \c roleNames() and \c data(), editable models must reimplement
192the \l{QAbstractItemModel::}{setData} method to save changes to existing model data.
193The following version of the method checks if the given model index is valid
194and the \c role is equal to \l Qt::EditRole:
195
196\code
197bool EditableModel::setData(const QModelIndex &index, const QVariant &value, int role)
198{
199 if (index.isValid() && role == Qt::EditRole) {
200 // Set data in model here. It can also be a good idea to check whether
201 // the new value actually differs from the current value
202 if (m_entries[index.row()] != value.toString()) {
203 m_entries[index.row()] = value.toString();
204 emit dataChanged(index, index, { Qt::EditRole, Qt::DisplayRole });
205 return true;
206 }
207 }
208 return false;
209}
210\endcode
211
212\note It is important to emit the \l{QAbstractItemModel::}{dataChanged}()
213signal after saving the changes.
214
215Unlike the C++ item views such as QListView or QTableView, the \c setData()
216method must be explicitly invoked from QML delegates whenever appropriate. This is done
217by simply assigning a new value to the corresponding model property.
218
219\qml
220ListView {
221 anchors.fill: parent
222 model: EditableModel {}
223 delegate: TextField {
224 width: ListView.view.width
225 text: model.edit
226 onAccepted: model.edit = text
227 }
228}
229\endqml
230
231\note The \c edit role is equal to \l Qt::EditRole. See \l{QAbstractItemModel::}{roleNames}()
232for the built-in role names. However, real life models would usually register custom roles.
233
234*/