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
modelview.qdoc
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3
4/*!
5 \page modelview.html
6 \ingroup tutorials
7 \startpage {index.html}{Qt Reference Documentation}
8
9 \title Model/View Tutorial
10 \brief An introduction to ModelView programming
11
12 Every UI developer should know about ModelView programming and the goal of
13 this tutorial is to provide you with an easily understandable introduction
14 to this topic.
15
16 Table, list and tree widgets are components frequently used in GUIs. There
17 are 2 different ways how these widgets can access their data. The
18 traditional way involves widgets which include internal containers for
19 storing data. This approach is very intuitive, however, in many non-trivial
20 applications, it leads to data synchronization issues.
21 The second approach is model/view programming, in
22 which widgets do not maintain internal data containers. They access external
23 data through a standardized interface and therefore avoid data duplication.
24 This may seem complicated at first, but once you take a closer look, it is
25 not only easy to grasp, but the many benefits of model/view programming also
26 become clearer.
27
28 \image treeview.png {Directory and its contents in a tree view}
29
30 In the process, we will learn about some basic technologies provided by Qt,
31 such as:
32
33 \list
34 \li The difference between standard and model/view widgets
35 \li Adapters between forms and models
36 \li Developing a simple model/view application
37 \li Predefined models
38 \li Intermediate topics such as:
39 \list
40 \li Tree views
41 \li Selection
42 \li Delegates
43 \li Debugging with model test
44 \endlist
45 \endlist
46
47 You will also learn whether your new application can be written easier with
48 model/view programming or if classic widgets will work just as well.
49
50 This tutorial includes example code for you to edit and integrate into your
51 project. The tutorial's source code is located in Qt's
52 \e examples/widgets/tutorials/modelview directory.
53
54 For more detailed information you may also want to look at the
55 \l{model-view-programming.html}{reference documentation}
56
57
58 \section1 1. Introduction
59
60 Model/View is a technology used to separate data from views in widgets that
61 handle data sets. Standard widgets are not designed for separating data
62 from views and this is why Qt has two different types of widgets. Both
63 types of widgets look the same, but they interact with data differently.
64
65 \table
66 \row
67 \li Standard widgets use data that is part of the widget.
68 \li \image standardwidget.png
69 {Structure where the "view" is separate from the "data"}
70 \row
71 \li View classes operate on external data (the model)
72 \li \image modelview.png
73 {Structure that uses a "view" and a "model" for the data }
74 \endtable
75
76 \section2 1.1 Standard Widgets
77
78 Let's have a closer look at a standard table widget. A table widget is a 2D
79 array of the data elements that the user can change. The table widget can be
80 integrated into a program flow by reading and writing the data elements that
81 the table widget provides.
82 This method is very intuitive and useful in many applications, but displaying
83 and editing a database table with a standard table widget can be problematic.
84 Two copies of the data have to be coordinated: one outside the
85 widget; one inside the widget. The developer is responsible for
86 synchronizing both versions. Besides this, the tight coupling of presentation and data
87 makes it harder to write unit tests.
88
89 \section2 1.2 Model/View to the Rescue
90
91 Model/view stepped up to provide a solution that uses a more versatile
92 architecture. Model/view eliminates the data consistency problems that may
93 occur with standard widgets. Model/view also makes it easier to use more
94 than one view of the same data because one model can be passed on to many
95 views. The most important difference is that model/view widgets do not store
96 data behind the table cells. In fact, they operate directly from your data.
97 Since view classes do not know your data's structure, you need to provide a
98 wrapper to make your data conform to the QAbstractItemModel interface. A
99 view uses this interface to read from and write to your data. Any instance
100 of a class that implements QAbstractItemModel is said to be a model. Once
101 the view receives a pointer to a model, it will read and display its content
102 and be its editor.
103
104 \section2 1.3 Overview of the Model/View Widgets
105
106 Here is an overview of the model/view widgets and their corresponding
107 standard widgets.
108
109 \table
110 \header
111 \li Widget
112 \li Standard Widget\br
113 (an item based convenience class)
114 \li Model/View View Class\br
115 (for use with external data)
116 \row
117 \li \inlineimage listview.png
118 {Directory displaying its contents as a list}
119 \li \l QListWidget
120 \li \l QListView
121 \row
122 \li \inlineimage tableview.png
123 {Directory displaying its contents as a table}
124 \li \l QTableWidget
125 \li \l QTableView
126 \row
127 \li \inlineimage treeview.png
128 {Directory displaying its contents as a tree}
129 \li \l QTreeWidget
130 \li \l QTreeView
131 \row
132 \li \inlineimage columnview.png
133 {Directory displaying its contents as columns}
134 \li
135 \li \l QColumnView shows a tree as a hierarchy of lists
136 \row
137 \li \inlineimage modelview-combobox.png
138 {Combobox showing an entry in the model}
139 \li {2, 1} \l QComboBox can work as both a view class and also
140 as a traditional widget
141 \endtable
142
143 \section2 1.4 Using Adapters between Forms and Models
144
145 Having adapters between forms and models can come in handy.
146
147 We can edit data stored in tables directly from within the table itself, but
148 it's much more comfortable to edit data in text fields. There is no direct
149 model/view counterpart that separates data and views for widgets that
150 operate on one value (QLineEdit, QCheckBox ...) instead of a dataset, so we
151 need an adapter in order to connect the form to the source of data.
152
153 \l QDataWidgetMapper is a great solution because it maps form widgets to a
154 table row and makes it very easy to build forms for database tables.
155
156 \image widgetmapper.png {Form with personal and other information}
157
158 Another example of an adapter is \l QCompleter. Qt has \l QCompleter for
159 providing auto-completions in Qt widgets such as \l QComboBox and, as shown
160 below, \l QLineEdit. \l QCompleter uses a model as its data source.
161
162 \image qcompleter.png {Completer with suggestions for the characters "Em"}
163
164
165 \section1 2. A Simple Model/View Application
166 If you want to develop a model/view application, where should you start?
167 We recommend starting with a simple example and extending it step-by-step.
168 This makes understanding the architecture a lot easier. Trying to understand
169 the model/view architecture in detail before invoking the IDE has proven
170 to be less convenient for many developers. It is substantially easier to
171 start with a simple model/view application that has demo data. Give it a
172 try! Simply replace the data in the examples below with your own.
173
174 Below are 7 very simple and independent applications that show different
175 sides of model/view programming. The source code can be found inside the
176 \c{examples/widgets/tutorials/modelview} directory.
177
178 \section2 2.1 A Read Only Table
179
180 We start with an application that uses a QTableView to show data. We will
181 add editing capabilities later.
182
183 (file source: examples/widgets/tutorials/modelview/1_readonly/main.cpp)
184 \snippet tutorials/modelview/1_readonly/main.cpp Quoting ModelView Tutorial
185
186 We have the usual \l {modelview-part2-main-cpp.html}{main()} function:
187
188 Here is the interesting part: We create an instance of MyModel and use
189 \l{QTableView::setModel()}{tableView.setModel(&myModel);} to pass a
190 pointer of it to \l{QTableView}{tableView}. \l{QTableView}{tableView}
191 will invoke the methods of the pointer it has received to find out two
192 things:
193
194 \list
195 \li How many rows and columns should be displayed.
196 \li What content should be printed into each cell.
197 \endlist
198
199 The model needs some code to respond to this.
200
201 We have a table data set, so let's start with QAbstractTableModel since it
202 is easier to use than the more general QAbstractItemModel.
203
204 (file source: examples/widgets/tutorials/modelview/1_readonly/mymodel.h)
205 \snippet tutorials/modelview/1_readonly/mymodel.h Quoting ModelView Tutorial
206
207 QAbstractTableModel requires the implementation of three abstract methods.
208
209 (file source: examples/widgets/tutorials/modelview/1_readonly/mymodel.cpp)
210 \snippet tutorials/modelview/1_readonly/mymodel.cpp Quoting ModelView Tutorial
211
212 The number of rows and columns is provided by
213 \l{QAbstractItemModel::rowCount()}{MyModel::rowCount()} and
214 \l{QAbstractItemModel::columnCount()}{MyModel::columnCount()}. When the view
215 has to know what the cell's text is, it calls the method
216 \l{QAbstractItemModel::data()}{MyModel::data()}. Row and column information
217 is specified with parameter \c index and the role is set to
218 \l{Qt::ItemDataRole}{Qt::DisplayRole}. Other roles are covered in the next
219 section. In our example, the data that should be displayed is generated. In
220 a real application, \c MyModel would have a member called \c MyData, which
221 serves as the target for all reading and writing operations.
222
223 This small example demonstrates the passive nature of a model. The model
224 does not know when it will be used or which data is needed. It simply
225 provides data each time the view requests it.
226
227 What happens when the model's data needs to be changed? How does the view
228 realize that data has changed and needs to be read again? The model has to
229 emit a signal that indicates what range of cells has changed. This will be
230 demonstrated in section 2.3.
231
232 \section2 2.2 Extending the Read Only Example with Roles
233
234 In addition to controlling what text the view displays, the model also
235 controls the text's appearance. When we slightly change the model, we get
236 the following result:
237
238 \image readonlytable_role.png {Table with custom formatting applied to its cells}
239
240 In fact, nothing except for the \l{QAbstractItemModel::}{data()} method
241 needs to be changed to set fonts, background colour, alignment and a
242 checkbox.
243 Below is the \l{QAbstractItemModel::data()}{data()} method that produces the
244 result shown above. The difference is that this time we use parameter int
245 role to return different pieces of information depending on its value.
246
247 (file source: examples/widgets/tutorials/modelview/2_formatting/mymodel.cpp)
248 \snippet tutorials/modelview/2_formatting/mymodel.cpp Quoting ModelView Tutorial
249
250 Each formatting property will be requested from the model with a separate
251 call to the \l{QAbstractItemModel::data()}{data()} method. The \c role
252 parameter is used to let the model know which property is being requested:
253
254 \table
255 \header
256 \li \l{Qt::ItemDataRole}{enum Qt::ItemDataRole}
257 \li Meaning
258 \li Type
259 \row
260 \li \l{Qt::ItemDataRole}{}Qt::DisplayRole
261 \li text
262 \li QString
263 \row
264 \li \l{Qt::ItemDataRole}{Qt::FontRole}
265 \li font
266 \li QFont
267 \row
268 \li \l{Qt::ItemDataRole}{BackgroundRole}
269 \li brush for the background of the cell
270 \li QBrush
271 \row
272 \li \l{Qt::ItemDataRole}{Qt::TextAlignmentRole}
273 \li text alignment
274 \li \l{Qt::AlignmentFlag}{enum Qt::AlignmentFlag}
275 \row
276 \li {1, 3} \l{Qt::ItemDataRole}{Qt::CheckStateRole}
277 \li {1, 3} suppresses checkboxes with \l{QVariant}{QVariant()},
278
279 sets checkboxes with \l{Qt::CheckState}{Qt::Checked}
280
281 or \l{Qt::CheckState}{Qt::Unchecked}
282 \li {1, 3} \l{Qt::ItemDataRole}{enum Qt::ItemDataRole}
283 \endtable
284
285 Refer to the Qt namespace documentation to learn more about the
286 \l{Qt::ItemDataRole}{Qt::ItemDataRole} enum's capabilities.
287
288 Now we need to determine how using a separated model impacts the
289 application's performance, so let's trace how often the view calls the
290 \l{QAbstractItemModel::}{data()} method. In order to track how often the
291 view calls the model, we have put a debug statement in the
292 \l{QAbstractItemModel::}{data()} method, which logs onto the error output
293 stream. In our small example, \l{QAbstractItemModel::}{data()} will be
294 called 42 times.
295 Each time you hover the cursor over the field,
296 \l{QAbstractItemModel::}{data()} will be called again -- 7 times for
297 each cell. That's why it is important to make sure that your data is
298 available when \l{QAbstractItemModel::}{data()} is invoked and expensive
299 lookup operations are cached.
300
301 \section2 2.3 A Clock inside a Table Cell
302
303 \image clock.png {Table that displays the time in a cell}
304
305 We still have a read only table, but this time the content changes every
306 second because we are showing the current time.
307
308 (file source: examples/widgets/tutorials/modelview/3_changingmodel/mymodel.cpp)
309 \snippet tutorials/modelview/3_changingmodel/mymodel.cpp quoting mymodel_QVariant
310
311 Something is missing to make the clock tick. We need to tell the view every
312 second that the time has changed and that it needs to be read again. We do
313 this with a timer. In the constructor, we set its interval to 1 second and
314 connect its timeout signal.
315
316 (file source: examples/widgets/tutorials/modelview/3_changingmodel/mymodel.cpp)
317 \snippet tutorials/modelview/3_changingmodel/mymodel.cpp quoting mymodel_a
318
319 Here is the corresponding slot:
320
321 (file source: examples/widgets/tutorials/modelview/3_changingmodel/mymodel.cpp)
322 \snippet tutorials/modelview/3_changingmodel/mymodel.cpp quoting mymodel_b
323
324 We ask the view to read the data in the top left cell again by emitting the
325 \l{QAbstractItemModel::}{dataChanged()} signal. Note that we did not
326 explicitly connect the \l{QAbstractItemModel::}{dataChanged()} signal to the
327 view. This happened automatically when we called \l{QTableView::}{setModel()}.
328
329 \section2 2.4 Setting up Headers for Columns and Rows
330
331 Headers can be hidden via a view method: \c{tableView->verticalHeader()->hide();}
332 \image modelview-header.png {Table showing the column headers}
333
334 The header content, however, is set via the model, so we reimplement the
335 \l{QAbstractItemModel::headerData()}{headerData()} method:
336
337 (file source: examples/widgets/tutorials/modelview/4_headers/mymodel.cpp)
338 \snippet tutorials/modelview/4_headers/mymodel.cpp quoting mymodel_c
339
340 Note that method \l{QAbstractItemModel::headerData()}{headerData()} also has
341 a parameter role which has the same meaning as in
342 \l{QAbstractItemModel::data()}{MyModel::data()}.
343
344 \section2 2.5 The Minimal Editing Example
345
346 In this example, we are going to build an application that automatically
347 populates a window title with content by repeating values entered into table
348 cells. To be able to access the window title easily we put the QTableView in
349 a QMainWindow.
350
351 The model decides whether editing capabilities are available. We only have
352 to modify the model in order for the available editing capabilities to be
353 enabled. This is done by reimplementing the following virtual methods:
354 \l{QAbstractItemModel::}{setData()} and \l{QAbstractItemModel::}{flags()}.
355
356 (file source: examples/widgets/tutorials/modelview/5_edit/mymodel.h)
357 \snippet tutorials/modelview/5_edit/mymodel.h Quoting ModelView Tutorial
358
359 We use \c the two-dimensional array QString \c m_gridData to store our data.
360 This makes \c m_gridData the core of \c MyModel. The rest of \c MyModel acts
361 like a wrapper and adapts \c m_gridData to the QAbstractItemModel
362 interface. We have also introduced the \c editCompleted() signal, which
363 makes it possible to transfer the modified text to the window title.
364
365 (file source: examples/widgets/tutorials/modelview/5_edit/mymodel.cpp)
366 \snippet tutorials/modelview/5_edit/mymodel.cpp quoting mymodel_e
367
368 \l{QAbstractItemModel::setData()}{setData()} will be called each time the
369 user edits a cell. The \c index parameter tells us which field has been
370 edited and \c value provides the result of the editing process. The role
371 will always be set to \l Qt::EditRole because our cells only contain text.
372 If a checkbox were present and user permissions are set to allow the
373 checkbox to be selected, calls would also be made with the role set to
374 \l Qt::CheckStateRole.
375
376 (file source: examples/widgets/tutorials/modelview/5_edit/mymodel.cpp)
377 \snippet tutorials/modelview/5_edit/mymodel.cpp quoting mymodel_f
378
379 Various properties of a cell can be adjusted with
380 \l{QAbstractItemModel::flags()}{flags()}.
381
382 Returning \l{Qt::ItemFlag}{Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled}
383 is enough to show an editor that a cell can be selected.
384
385 If editing one cell modifies more data than the data in that particular
386 cell, the model must emit a \l{QAbstractItemModel::}{dataChanged()} signal
387 in order for the data that has been changed to be read.
388
389
390 \section1 3. Intermediate Topics
391
392 \section2 3.1 TreeView
393
394 You can convert the example above into an application with a tree view.
395 Simply replace QTableView with QTreeView, which results in a read/write
396 tree. No changes have to be made to the model. The tree won't have any
397 hierarchies because there aren't any hierarchies in the model itself.
398
399 \image dummy_tree.png {Tree view displaying table data with no hierarchy}
400
401 QListView, QTableView and QTreeView all use a model abstraction, which is a
402 merged list, table and tree. This makes it possible to use several different
403 types of view classes from the same model.
404
405 \image list_table_tree.png
406 {Diagram comparing list model, table model, and tree model}
407
408 This is how our example model looks so far:
409
410 \image example_model.png {Diagram of current model structure}
411
412 We want to present a real tree. We have wrapped our data in the examples
413 above in order to make a model. This time we use QStandardItemModel, which
414 is a container for hierarchical data that also implements
415 QAbstractItemModel. To show a tree, QStandardItemModel must be populated
416 with \l{QStandardItem}s, which are able to hold all the standard properties
417 of items like text, fonts, checkboxes or brushes.
418
419 \image tree_2_with_algorithm.png {Diagram of the model and the view}
420
421 (file source: examples/widgets/tutorials/modelview/6_treeview/mainwindow.cpp)
422 \snippet tutorials/modelview/6_treeview/mainwindow.cpp Quoting ModelView Tutorial
423
424 We simply instantiate a QStandardItemModel and add a couple of
425 \l{QStandardItem}{QStandardItems} to the constructor. We can then make a
426 hierarchical data structure because a QStandardItem can hold other
427 \l{QStandardItem}{QStandardItems}. Nodes are collapsed and expanded within
428 the view.
429
430 \section2 3.2 Working with Selections
431
432 We want to access a selected item's content in order to output it into the
433 window title together with the hierarchy level.
434
435 \image selection2.png {View of a model with the selected content in blue}
436
437 So let's create a couple of items:
438
439 (file source: examples/widgets/tutorials/modelview/7_selections/mainwindow.cpp)
440 \snippet tutorials/modelview/7_selections/mainwindow.cpp quoting modelview_a
441
442 Views manage selections within a separate selection model, which can be
443 retrieved with the \l{QAbstractItemView::}{selectionModel()} method. We
444 retrieve the selection Model in order to connect a slot to its
445 \l{QAbstractItemView::}{selectionChanged()} signal.
446
447 (file source: examples/widgets/tutorials/modelview/7_selections/mainwindow.cpp)
448 \snippet tutorials/modelview/7_selections/mainwindow.cpp quoting modelview_b
449
450 We get the model index that corresponds to the selection by calling
451 \l{QItemSelectionModel::currentIndex()}{treeView->selectionModel()->currentIndex()}
452 and we get the field's string by using the model index. Then we just
453 calculate the item's \c hierarchyLevel. Top level items do not have parents
454 and the \l{QAbstractItemModel::}{parent()} method will return a default
455 constructed \l{QModelIndex}{QModelIndex()}. This is why we use the
456 \l{QAbstractItemModel::}{parent()} method to iterate to the top level while
457 counting the steps performed during iteration.
458
459 The selection model (as shown above) can be retrieved, but it can also be
460 set with \l{QAbstractItemView}{QAbstractItemView::setSelectionModel}. This
461 is how it's possible to have 3 view classes with synchronized selections
462 because only one instance of a selection model is used. To share a selection
463 model between 3 views use \l{QAbstractItemView::}{selectionModel()} and
464 assign the result to the second and third view class with
465 \l{QAbstractItemView::}{setSelectionModel()}.
466
467 \section2 3.3 Predefined Models
468
469 The typical way to use model/view is to wrap specific data to make it usable
470 with view classes. Qt, however, also provides predefined models for common
471 underlying data structures. If one of the available data structures is
472 suitable for your application, a predefined model can be a good choice.
473
474 \table
475 \row
476 \li QStringListModel
477 \li Stores a list of strings
478 \row
479 \li QStandardItemModel
480 \li Stores arbitrary hierarchical items
481 \row
482 \li QFileSystemModel
483 \li Encapsulate the local file system
484 \row
485 \li QSqlQueryModel
486 \li Encapsulate an SQL result set
487 \row
488 \li QSqlTableModel
489 \li Encapsulates an SQL table
490 \row
491 \li QSqlRelationalTableModel
492 \li Encapsulates an SQL table with foreign keys
493 \row
494 \li QSortFilterProxyModel
495 \li Sorts and/or filters another model
496
497 \endtable
498
499 \section2 3.4 Delegates
500
501 In all examples so far, data is presented as text or a checkbox in a cell
502 and is edited as text or a checkbox. The component that provides these
503 presentation and editing services is called a \e delegate. We are only just
504 beginning to work with the delegate because the view uses a default
505 delegate. But imagine that we want to have a different editor (e.g., a
506 slider or a drop down list) Or imagine that we want to present data as
507 graphics.
508 Let's take a look at an example called \l{Star Delegate Example}{Star
509 Delegate}, in which stars are used to show a rating:
510
511 \image stardelegate.png {Table showing songs and their star ratings}
512
513 The view has a \l{QAbstractItemView::}{setItemDelegate()} method that
514 replaces the default delegate and installs a custom delegate.
515 A new delegate can be written by creating a class that inherits from
516 QStyledItemDelegate. In order to write a delegate that displays stars and
517 has no input capabilities, we only need to override 2 methods.
518
519 \code
520 class StarDelegate : public QStyledItemDelegate
521 {
522 Q_OBJECT
523 public:
524 StarDelegate(QWidget *parent = nullptr);
525 void paint(QPainter *painter, const QStyleOptionViewItem &option,
526 const QModelIndex &index) const;
527 QSize sizeHint(const QStyleOptionViewItem &option,
528 const QModelIndex &index) const;
529 };
530 \endcode
531
532 \l{QStyledItemDelegate::}{paint()} draws stars depending on the content of
533 the underlying data. The data can be looked up by calling
534 \l{QModelIndex::data()}{index.data()}. The delegate's
535 \l{QAbstractItemDelegate::}{sizeHint()} method is used to obtain each
536 star's dimensions, so the cell will provide enough height and width to
537 accommodate the stars.
538
539 Writing custom delegates is the right choice if you want to show your data
540 with a custom graphical representation inside the grid of the view class. If
541 you want to leave the grid, you would not use a custom delegate but a custom
542 view class.
543
544 Other references to delegates in Qt Documentation:
545
546 \list
547 \li \l{Delegate Classes}
548 \li \l{QAbstractItemDelegate}{QAbstractItemDelegate Class Reference}
549 \li \l{QSqlRelationalDelegate}{QSqlRelationalDelegate Class Reference}
550 \li \l{QStyledItemDelegate}{QStyledItemDelegate Class Reference}
551 \li \l{QItemDelegate}{QItemDelegate Class Reference}
552 \endlist
553
554
555 \section2 3.5 Debugging with ModelTest
556
557 The passive nature of models provides new challenges for programmers.
558 Inconsistencies in the model can cause the application to crash. Since the
559 model is hit by numerous calls from the view, it is hard to find out which
560 call has crashed the application and which operation has introduced the
561 problem.
562
563 Qt Labs provides software called
564 \l{http://wiki.qt.io/Model_Test}{ModelTest},
565 which checks models while your programming is running. Every time the model
566 is changed, ModelTest scans the model and reports errors with an assert.
567 This is especially important for tree models, since their hierarchical
568 nature leaves many possibilities for subtle inconsistencies.
569
570 Unlike view classes, ModelTest uses out of range indexes to test the model.
571 This means your application may crash with ModelTest even if it runs
572 perfectly without it. So you also need to handle all of the indexes that are
573 out of range when using ModelTest.
574
575
576 \section1 Examples
577
578 Qt comes with multiple examples for model/view. You can find them on the
579 \l{Item Views Examples} page.
580*/
581
582/*!
583 \page modelview-part2-main-cpp.html
584 \title main.cpp
585 \quotefile tutorials/modelview/1_readonly/main.cpp
586*/