1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the documentation of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:FDL$
9 ** GNU Free Documentation License
10 ** Alternatively, this file may be used under the terms of the GNU Free
11 ** Documentation License version 1.3 as published by the Free Software
12 ** Foundation and appearing in the file included in the packaging of
16 ** Alternatively, this file may be used in accordance with the terms
17 ** and conditions contained in a signed written agreement between you
26 ****************************************************************************/
29 \example itemviews/editabletreemodel
30 \title Editable Tree Model Example
32 This example shows how to implement a simple item-based tree model that can
33 be used with other classes the model/view framework.
35 \image itemviews-editabletreemodel.png
37 The model supports editable items, custom headers, and the ability to
38 insert and remove rows and columns. With these features, it is also
39 possible to insert new child items, and this is shown in the supporting
42 \note The model only shows the basic principles used when creating an
43 editable, hierarchical model. You may wish to use the \l{ModelTest}
44 project to test production models.
48 As described in the \l{Model Subclassing Reference}, models must
49 provide implementations for the standard set of model functions:
50 \l{QAbstractItemModel::}{flags()}, \l{QAbstractItemModel::}{data()},
51 \l{QAbstractItemModel::}{headerData()},
52 \l{QAbstractItemModel::}{columnCount()}, and
53 \l{QAbstractItemModel::}{rowCount()}. In addition, hierarchical models,
54 such as this one, need to provide implementations of
55 \l{QAbstractItemModel::}{index()} and \l{QAbstractItemModel::}{parent()}.
57 An editable model needs to provide implementations of
58 \l{QAbstractItemModel::}{setData()} and
59 \l{QAbstractItemModel::}{setHeaderData()}, and must return a suitable
60 combination of flags from its \l{QAbstractItemModel::}{flags()} function.
62 Since this example allows the dimensions of the model to be changed,
63 we must also implement \l{QAbstractItemModel::}{insertRows()},
64 \l{QAbstractItemModel::}{insertColumns()},
65 \l{QAbstractItemModel::}{removeRows()}, and
66 \l{QAbstractItemModel::}{removeColumns()}.
70 As with the \l{itemviews/simpletreemodel}{Simple Tree Model} example,
71 the model simply acts as a wrapper around a collection
72 of instances of a \c TreeItem class. Each \c TreeItem is designed to
73 hold data for a row of items in a tree view, so it contains a list of
74 values corresponding to the data shown in each column.
76 Since QTreeView provides a row-oriented view onto a model, it is
77 natural to choose a row-oriented design for data structures that
78 will supply data via a model to this kind of view. Although this makes
79 the tree model less flexible, and possibly less useful for use with
80 more sophisticated views, it makes it less complex to design and easier
83 \target Relations-between-internal-items
85 \row \o \inlineimage itemviews-editabletreemodel-items.png
86 \o \bold{Relations between internal items}
88 When designing a data structure for use with a custom model, it is useful
89 to expose each item's parent via a function like
90 \l{TreeItem::parent}{TreeItem::parent()} because it will make
91 writing the model's own \l{QAbstractItemModel::}{parent()} function easier.
92 Similarly, a function like \l{TreeItem::child}{TreeItem::child()} is
93 helpful when implementing the model's \l{QAbstractItemModel::}{index()}
94 function. As a result, each \c TreeItem maintains information about
95 its parent and children, making it possible for us to traverse the tree
98 The diagram shows how \c TreeItem instances are connected via their
99 \l{TreeItem::parent}{parent()} and \l{TreeItem::child}{child()}
102 In the example shown, two top-level items, \bold{A} and
103 \bold{B}, can be obtained from the root item by calling its child()
104 function, and each of these items return the root node from their
105 parent() functions, though this is only shown for item \bold{A}.
108 Each \c TreeItem stores data for each column in the row it represents
109 in its \c itemData private member (a list of QVariant objects).
110 Since there is a one-to-one mapping between each column in the view
111 and each entry in the list, we provide a simple
112 \l{TreeItem::data}{data()} function to read entries in the \c itemData
113 list and a \l{TreeItem::setData}{setData()} function to allow them to
115 As with other functions in the item, this simplifies the implemention
116 of the model's \l{QAbstractItemModel::}{data()} and
117 \l{QAbstractItemModel::}{setData()} functions.
119 We place an item at the root of the tree of items. This root item
120 corresponds to the null model index, \l{QModelIndex::}{QModelIndex()},
121 that is used to represent the parent of a top-level item when handling
123 Although the root item does not have a visible representation in any of
124 the standard views, we use its internal list of QVariant objects to
125 store a list of strings that will be passed to views for use as
126 horizontal header titles.
129 \row \o \inlineimage itemviews-editabletreemodel-model.png
130 \o \bold{Accessing data via the model}
132 In the case shown in the diagram, the piece of information represented
133 by \bold{a} can be obtained using the standard model/view API:
135 \snippet doc/src/snippets/code/doc_src_examples_editabletreemodel.cpp 0
137 Since each items holds pieces of data for each column in a given row,
138 there can be many model indexes that map to the same \c TreeItem object.
139 For example, the information represented by \bold{b} can be obtained
140 using the following code:
142 \snippet doc/src/snippets/code/doc_src_examples_editabletreemodel.cpp 1
144 The same underlying \c TreeItem would be accessed to obtain information
145 for the other model indexes in the same row as \bold{b}.
148 In the model class, \c TreeModel, we relate \c TreeItem objects to
149 model indexes by passing a pointer for each item when we create its
150 corresponding model index with QAbstractItemModel::createIndex() in
151 our \l{TreeModel::index}{index()} and \l{TreeModel::parent}{parent()}
153 We can retrieve pointers stored in this way by calling the
154 \l{QModelIndex::}{internalPointer()} function on the relevant model
155 index - we create our own \l{TreeModel::getItem}{getItem()} function to
156 do this work for us, and call it from our \l{TreeModel::data}{data()}
157 and \l{TreeModel::parent}{parent()} implementations.
159 Storing pointers to items is convenient when we control how they are
160 created and destroyed since we can assume that an address obtained from
161 \l{QModelIndex::}{internalPointer()} is a valid pointer.
162 However, some models need to handle items that are obtained from other
163 components in a system, and in many cases it is not possible to fully
164 control how items are created or destroyed. In such situations, a pure
165 pointer-based approach needs to be supplemented by safeguards to ensure
166 that the model does not attempt to access items that have been deleted.
169 \row \o \bold{Storing information in the underlying data structure}
171 Several pieces of data are stored as QVariant objects in the \c itemData
172 member of each \c TreeItem instance
174 The diagram shows how pieces of information,
175 represented by the labels \bold{a}, \bold{b} and \bold{c} in the
176 previous two diagrams, are stored in items \bold{A}, \bold{B} and
177 \bold{C} in the underlying data structure. Note that pieces of
178 information from the same row in the model are all obtained from the
179 same item. Each element in a list corresponds to a piece of information
180 exposed by each column in a given row in the model.
182 \o \inlineimage itemviews-editabletreemodel-values.png
185 Since the \c TreeModel implementation has been designed for use with
186 QTreeView, we have added a restriction on the way it uses \c TreeItem
187 instances: each item must expose the same number of columns of data.
188 This makes viewing the model consistent, allowing us to use the root
189 item to determine the number of columns for any given row, and only
190 adds the requirement that we create items containing enough data for
191 the total number of columns. As a result, inserting and removing
192 columns are time-consuming operations because we need to traverse the
193 entire tree to modify every item.
195 An alternative approach would be to design the \c TreeModel class so
196 that it truncates or expands the list of data in individual \c TreeItem
197 instances as items of data are modified. However, this "lazy" resizing
198 approach would only allow us to insert and remove columns at the end of
199 each row and would not allow columns to be inserted or removed at
200 arbitrary positions in each row.
202 \target Relating-items-using-model-indexes
205 \o \inlineimage itemviews-editabletreemodel-indexes.png
206 \o \bold{Relating items using model indexes}
208 As with the \l{itemviews/simpletreemodel}{Simple Tree Model} example,
209 the \c TreeModel needs to be able to take a model index, find the
210 corresponding \c TreeItem, and return model indexes that correspond to
211 its parents and children.
213 In the diagram, we show how the model's \l{TreeModel::parent}{parent()}
214 implementation obtains the model index corresponding to the parent of
215 an item supplied by the caller, using the items shown in a
216 \l{Relations-between-internal-items}{previous diagram}.
218 A pointer to item \bold{C} is obtained from the corresponding model index
219 using the \l{QModelIndex::internalPointer()} function. The pointer was
220 stored internally in the index when it was created. Since the child
221 contains a pointer to its parent, we use its \l{TreeItem::parent}{parent()}
222 function to obtain a pointer to item \bold{B}. The parent model index is
223 created using the QAbstractItemModel::createIndex() function, passing
224 the pointer to item \bold{B} as the internal pointer.
227 \section1 TreeItem Class Definition
229 The \c TreeItem class provides simple items that contain several
230 pieces of data, and which can provide information about their parent
233 \snippet examples/itemviews/editabletreemodel/treeitem.h 0
235 We have designed the API to be similar to that provided by
236 QAbstractItemModel by giving each item functions to return the number
237 of columns of information, read and write data, and insert and remove
238 columns. However, we make the relationship between items explicit by
239 providing functions to deal with "children" rather than "rows".
241 Each item contains a list of pointers to child items, a pointer to its
242 parent item, and a list of QVariant objects that correspond to
243 information held in columns in a given row in the model.
245 \section1 TreeItem Class Implementation
247 Each \c TreeItem is constructed with a list of data and an optional
250 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 0
252 Initially, each item has no children. These are added to the item's
253 internal \c childItems member using the \c insertChildren() function
256 The destructor ensures that each child added to the item is deleted
257 when the item itself is deleted:
259 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 1
261 \target TreeItem::parent
262 Since each item stores a pointer to its parent, the \c parent() function
265 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 9
267 \target TreeItem::child
268 Three functions provide information about the children of an item.
269 \c child() returns a specific child from the internal list of children:
271 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 2
273 The \c childCount() function returns the total number of children:
275 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 3
277 The \c childNumber() function is used to determine the index of the child
278 in its parent's list of children. It accesses the parent's \c childItems
279 member directly to obtain this information:
281 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 4
283 The root item has no parent item; for this item, we return zero to be
284 consistent with the other items.
286 The \c columnCount() function simply returns the number of elements in
287 the internal \c itemData list of QVariant objects:
289 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 5
291 \target TreeItem::data
292 Data is retrieved using the \c data() function, which accesses the
293 appropriate element in the \c itemData list:
295 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 6
297 \target TreeItem::setData
298 Data is set using the \c setData() function, which only stores values
299 in the \c itemData list for valid list indexes, corresponding to column
302 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 11
304 To make implementation of the model easier, we return true to indicate
305 whether the data was set successfully, or false if an invalid column
307 Editable models often need to be resizable, enabling rows and columns to
308 be inserted and removed. The insertion of rows beneath a given model index
309 in the model leads to the insertion of new child items in the corresponding
310 item, handled by the \c insertChildren() function:
312 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 7
314 This ensures that new items are created with the required number of columns
315 and inserted at a valid position in the internal \c childItems list.
316 Items are removed with the \c removeChildren() function:
318 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 10
320 As discussed above, the functions for inserting and removing columns are
321 used differently to those for inserting and removing child items because
322 they are expected to be called on every item in the tree. We do this by
323 recursively calling this function on each child of the item:
325 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 8
327 \section1 TreeModel Class Definition
329 The \c TreeModel class provides an implementation of the QAbstractItemModel
330 class, exposing the necessary interface for a model that can be edited and
333 \snippet examples/itemviews/editabletreemodel/treemodel.h 0
335 The constructor and destructor are specific to this model.
337 \snippet examples/itemviews/editabletreemodel/treemodel.h 1
339 Read-only tree models only need to provide the above functions. The
340 following public functions provide support for editing and resizing:
342 \snippet examples/itemviews/editabletreemodel/treemodel.h 2
344 To simplify this example, the data exposed by the model is organized into
345 a data structure by the model's \l{TreeModel::setupModelData}{setupModelData()}
346 function. Many real world models will not process the raw data at all, but
347 simply work with an existing data structure or library API.
349 \section1 TreeModel Class Implementation
351 The constructor creates a root item and initializes it with the header
354 \snippet examples/itemviews/editabletreemodel/treemodel.cpp 0
356 We call the internal \l{TreeModel::setupModelData}{setupModelData()}
357 function to convert the textual data supplied to a data structure we can
358 use with the model. Other models may be initialized with a ready-made
359 data structure, or use an API to a library that maintains its own data.
361 The destructor only has to delete the root item; all child items will
362 be recursively deleted by the \c TreeItem destructor.
364 \snippet examples/itemviews/editabletreemodel/treemodel.cpp 1
366 \target TreeModel::getItem
367 Since the model's interface to the other model/view components is based
368 on model indexes, and the internal data structure is item-based, many of
369 the functions implemented by the model need to be able to convert any
370 given model index to its corresponding item. For convenience and
371 consistency, we have defined a \c getItem() function to perform this
374 \snippet examples/itemviews/editabletreemodel/treemodel.cpp 4
376 This function assumes that each model index it is passed corresponds to
377 a valid item in memory. If the index is invalid, or its internal pointer
378 does not refer to a valid item, the root item is returned instead.
380 The model's \c rowCount() implementation is simple: it first uses the
381 \c getItem() function to obtain the relevant item, then returns the
382 number of children it contains:
384 \snippet examples/itemviews/editabletreemodel/treemodel.cpp 8
386 By contrast, the \c columnCount() implementation does not need to look
387 for a particular item because all items are defined to have the same
388 number of columns associated with them.
390 \snippet examples/itemviews/editabletreemodel/treemodel.cpp 2
392 As a result, the number of columns can be obtained directly from the root
395 To enable items to be edited and selected, the \c flags() function needs
396 to be implemented so that it returns a combination of flags that includes
397 the Qt::ItemIsEditable and Qt::ItemIsSelectable flags as well as
400 \snippet examples/itemviews/editabletreemodel/treemodel.cpp 3
402 \target TreeModel::index
403 The model needs to be able to generate model indexes to allow other
404 components to request data and information about its structure. This task
405 is performed by the \c index() function, which is used to obtain model
406 indexes corresponding to children of a given parent item:
408 \snippet examples/itemviews/editabletreemodel/treemodel.cpp 5
410 In this model, we only return model indexes for child items if the parent
411 index is invalid (corresponding to the root item) or if it has a zero
414 We use the custom \l{TreeModel::getItem}{getItem()} function to obtain
415 a \c TreeItem instance that corresponds to the model index supplied, and
416 request its child item that corresponds to the specified row.
418 \snippet examples/itemviews/editabletreemodel/treemodel.cpp 6
420 Since each item contains information for an entire row of data, we create
421 a model index to uniquely identify it by calling
422 \l{QAbstractItemModel::}{createIndex()} it with the row and column numbers
423 and a pointer to the item. In the \l{TreeModel::data}{data()} function,
424 we will use the item pointer and column number to access the data
425 associated with the model index; in this model, the row number is not
426 needed to identify data.
428 \target TreeModel::parent
429 The \c parent() function supplies model indexes for parents of items
430 by finding the corresponding item for a given model index, using its
431 \l{TreeItem::parent}{parent()} function to obtain its parent item,
432 then creating a model index to represent the parent. (See
433 \l{Relating-items-using-model-indexes}{the above diagram}).
435 \snippet examples/itemviews/editabletreemodel/treemodel.cpp 7
437 Items without parents, including the root item, are handled by returning
438 a null model index. Otherwise, a model index is created and returned as
439 in the \l{TreeModel::index}{index()} function, with a suitable row number,
440 but with a zero column number to be consistent with the scheme used in
441 the \l{TreeModel::index}{index()} implementation.
443 \target TreeModel::data
444 \target TreeModel::setupModelData