source: trunk/doc/src/examples/editabletreemodel.qdoc@ 561

Last change on this file since 561 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 20.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the documentation of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42/*!
43 \example itemviews/editabletreemodel
44 \title Editable Tree Model Example
45
46 This example shows how to implement a simple item-based tree model that can
47 be used with other classes the model/view framework.
48
49 \image itemviews-editabletreemodel.png
50
51 The model supports editable items, custom headers, and the ability to
52 insert and remove rows and columns. With these features, it is also
53 possible to insert new child items, and this is shown in the supporting
54 example code.
55
56 \note The model only shows the basic principles used when creating an
57 editable, hierarchical model. You may wish to use the \l{ModelTest}
58 project to test production models.
59
60 \section1 Overview
61
62 As described in the \l{Model Subclassing Reference}, models must
63 provide implementations for the standard set of model functions:
64 \l{QAbstractItemModel::}{flags()}, \l{QAbstractItemModel::}{data()},
65 \l{QAbstractItemModel::}{headerData()}, and
66 \l{QAbstractItemModel::}{rowCount()}. In addition, hierarchical models,
67 such as this one, need to provide implementations of
68 \l{QAbstractItemModel::}{index()} and \l{QAbstractItemModel::}{parent()}.
69
70 An editable model needs to provide implementations of
71 \l{QAbstractItemModel::}{setData()} and
72 \l{QAbstractItemModel::}{headerData()}, and must return a suitable
73 combination of flags from its \l{QAbstractItemModel::}{flags()} function.
74
75 Since this example allows the dimensions of the model to be changed,
76 we must also implement \l{QAbstractItemModel::}{insertRows()},
77 \l{QAbstractItemModel::}{insertColumns()},
78 \l{QAbstractItemModel::}{removeRows()}, and
79 \l{QAbstractItemModel::}{removeColumns()}.
80
81 \section1 Design
82
83 As with the \l{itemviews/simpletreemodel}{Simple Tree Model} example,
84 the model simply acts as a wrapper around a collection
85 of instances of a \c TreeItem class. Each \c TreeItem is designed to
86 hold data for a row of items in a tree view, so it contains a list of
87 values corresponding to the data shown in each column.
88
89 Since QTreeView provides a row-oriented view onto a model, it is
90 natural to choose a row-oriented design for data structures that
91 will supply data via a model to this kind of view. Although this makes
92 the tree model less flexible, and possibly less useful for use with
93 more sophisticated views, it makes it less complex to design and easier
94 to implement.
95
96 \target Relations-between-internal-items
97 \table
98 \row \o \inlineimage itemviews-editabletreemodel-items.png
99 \o \bold{Relations between internal items}
100
101 When designing a data structure for use with a custom model, it is useful
102 to expose each item's parent via a function like
103 \l{TreeItem::parent}{TreeItem::parent()} because it will make
104 writing the model's own \l{QAbstractItemModel::}{parent()} function easier.
105 Similarly, a function like \l{TreeItem::child}{TreeItem::child()} is
106 helpful when implementing the model's \l{QAbstractItemModel::}{index()}
107 function. As a result, each \c TreeItem maintains information about
108 its parent and children, making it possible for us to traverse the tree
109 structure.
110
111 The diagram shows how \c TreeItem instances are connected via their
112 \l{TreeItem::parent}{parent()} and \l{TreeItem::child}{child()}
113 functions.
114
115 In the example shown, two top-level items, \bold{A} and
116 \bold{B}, can be obtained from the root item by calling its child()
117 function, and each of these items return the root node from their
118 parent() functions, though this is only shown for item \bold{A}.
119 \endtable
120
121 Each \c TreeItem stores data for each column in the row it represents
122 in its \c itemData private member (a list of QVariant objects).
123 Since there is a one-to-one mapping between each column in the view
124 and each entry in the list, we provide a simple
125 \l{TreeItem::data}{data()} function to read entries in the \c itemData
126 list and a \l{TreeItem::setData}{setData()} function to allow them to
127 be modified.
128 As with other functions in the item, this simplifies the implemention
129 of the model's \l{QAbstractItemModel::}{data()} and
130 \l{QAbstractItemModel::}{setData()} functions.
131
132 We place an item at the root of the tree of items. This root item
133 corresponds to the null model index, \l{QModelIndex::}{QModelIndex()},
134 that is used to represent the parent of a top-level item when handling
135 model indexes.
136 Although the root item does not have a visible representation in any of
137 the standard views, we use its internal list of QVariant objects to
138 store a list of strings that will be passed to views for use as
139 horizontal header titles.
140
141 \table
142 \row \o \inlineimage itemviews-editabletreemodel-model.png
143 \o \bold{Accessing data via the model}
144
145 In the case shown in the diagram, the piece of information represented
146 by \bold{a} can be obtained using the standard model/view API:
147
148 \snippet doc/src/snippets/code/doc_src_examples_editabletreemodel.qdoc 0
149
150 Since each items holds pieces of data for each column in a given row,
151 there can be many model indexes that map to the same \c TreeItem object.
152 For example, the information represented by \bold{b} can be obtained
153 using the following code:
154
155 \snippet doc/src/snippets/code/doc_src_examples_editabletreemodel.qdoc 1
156
157 The same underlying \c TreeItem would be accessed to obtain information
158 for the other model indexes in the same row as \bold{b}.
159 \endtable
160
161 In the model class, \c TreeModel, we relate \c TreeItem objects to
162 model indexes by passing a pointer for each item when we create its
163 corresponding model index with QAbstractItemModel::createIndex() in
164 our \l{TreeModel::index}{index()} and \l{TreeModel::parent}{parent()}
165 implementations.
166 We can retrieve pointers stored in this way by calling the
167 \l{QModelIndex::}{internalPointer()} function on the relevant model
168 index - we create our own \l{TreeModel::getItem}{getItem()} function to
169 do this work for us, and call it from our \l{TreeModel::data}{data()}
170 and \l{TreeModel::parent}{parent()} implementations.
171
172 Storing pointers to items is convenient when we control how they are
173 created and destroyed since we can assume that an address obtained from
174 \l{QModelIndex::}{internalPointer()} is a valid pointer.
175 However, some models need to handle items that are obtained from other
176 components in a system, and in many cases it is not possible to fully
177 control how items are created or destroyed. In such situations, a pure
178 pointer-based approach needs to be supplemented by safeguards to ensure
179 that the model does not attempt to access items that have been deleted.
180
181 \table
182 \row \o \bold{Storing information in the underlying data structure}
183
184 Several pieces of data are stored as QVariant objects in the \c itemData
185 member of each \c TreeItem instance
186
187 The diagram shows how pieces of information,
188 represented by the labels \bold{a}, \bold{b} and \bold{c} in the
189 previous two diagrams, are stored in items \bold{A}, \bold{B} and
190 \bold{C} in the underlying data structure. Note that pieces of
191 information from the same row in the model are all obtained from the
192 same item. Each element in a list corresponds to a piece of information
193 exposed by each column in a given row in the model.
194
195 \o \inlineimage itemviews-editabletreemodel-values.png
196 \endtable
197
198 Since the \c TreeModel implementation has been designed for use with
199 QTreeView, we have added a restriction on the way it uses \c TreeItem
200 instances: each item must expose the same number of columns of data.
201 This makes viewing the model consistent, allowing us to use the root
202 item to determine the number of columns for any given row, and only
203 adds the requirement that we create items containing enough data for
204 the total number of columns. As a result, inserting and removing
205 columns are time-consuming operations because we need to traverse the
206 entire tree to modify every item.
207
208 An alternative approach would be to design the \c TreeModel class so
209 that it truncates or expands the list of data in individual \c TreeItem
210 instances as items of data are modified. However, this "lazy" resizing
211 approach would only allow us to insert and remove columns at the end of
212 each row and would not allow columns to be inserted or removed at
213 arbitrary positions in each row.
214
215 \target Relating-items-using-model-indexes
216 \table
217 \row
218 \o \inlineimage itemviews-editabletreemodel-indexes.png
219 \o \bold{Relating items using model indexes}
220
221 As with the \l{itemviews/simpletreemodel}{Simple Tree Model} example,
222 the \c TreeModel needs to be able to take a model index, find the
223 corresponding \c TreeItem, and return model indexes that correspond to
224 its parents and children.
225
226 In the diagram, we show how the model's \l{TreeModel::parent()}{parent()}
227 implementation obtains the model index corresponding to the parent of
228 an item supplied by the caller, using the items shown in a
229 \l{Relations-between-internal-items}{previous diagram}.
230
231 A pointer to item \bold{C} is obtained from the corresponding model index
232 using the \l{QModelIndex::internalPointer()} function. The pointer was
233 stored internally in the index when it was created. Since the child
234 contains a pointer to its parent, we use its \l{TreeItem::parent}{parent()}
235 function to obtain a pointer to item \bold{B}. The parent model index is
236 created using the QAbstractItemModel::createIndex() function, passing
237 the pointer to item \bold{B} as the internal pointer.
238 \endtable
239
240 \section1 TreeItem Class Definition
241
242 The \c TreeItem class provides simple items that contain several
243 pieces of data, and which can provide information about their parent
244 and child items:
245
246 \snippet examples/itemviews/editabletreemodel/treeitem.h 0
247
248 We have designed the API to be similar to that provided by
249 QAbstractItemModel by giving each item functions to return the number
250 of columns of information, read and write data, and insert and remove
251 columns. However, we make the relationship between items explicit by
252 providing functions to deal with "children" rather than "rows".
253
254 Each item contains a list of pointers to child items, a pointer to its
255 parent item, and a list of QVariant objects that correspond to
256 information held in columns in a given row in the model.
257
258 \section1 TreeItem Class Implementation
259
260 Each \c TreeItem is constructed with a list of data and an optional
261 parent item:
262
263 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 0
264
265 Initially, each item has no children. These are added to the item's
266 internal \c childItems member using the \c insertChildren() function
267 described later.
268
269 The destructor ensures that each child added to the item is deleted
270 when the item itself is deleted:
271
272 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 1
273
274 \target TreeItem::parent
275 Since each item stores a pointer to its parent, the \c parent() function
276 is trivial:
277
278 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 9
279
280 \target TreeItem::child
281 Three functions provide information about the children of an item.
282 \c child() returns a specific child from the internal list of children:
283
284 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 2
285
286 The \c childCount() function returns the total number of children:
287
288 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 3
289
290 The \c childNumber() function is used to determine the index of the child
291 in its parent's list of children. It accesses the parent's \c childItems
292 member directly to obtain this information:
293
294 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 4
295
296 The root item has no parent item; for this item, we return zero to be
297 consistent with the other items.
298
299 The \c columnCount() function simply returns the number of elements in
300 the internal \c itemData list of QVariant objects:
301
302 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 5
303
304 \target TreeItem::data
305 Data is retrieved using the \c data() function, which accesses the
306 appropriate element in the \c itemData list:
307
308 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 6
309
310 \target TreeItem::setData
311 Data is set using the \c setData() function, which only stores values
312 in the \c itemData list for valid list indexes, corresponding to column
313 values in the model:
314
315 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 11
316
317 To make implementation of the model easier, we return true to indicate
318 whether the data was set successfully, or false if an invalid column
319
320 Editable models often need to be resizable, enabling rows and columns to
321 be inserted and removed. The insertion of rows beneath a given model index
322 in the model leads to the insertion of new child items in the corresponding
323 item, handled by the \c insertChildren() function:
324
325 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 7
326
327 This ensures that new items are created with the required number of columns
328 and inserted at a valid position in the internal \c childItems list.
329 Items are removed with the \c removeChildren() function:
330
331 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 10
332
333 As discussed above, the functions for inserting and removing columns are
334 used differently to those for inserting and removing child items because
335 they are expected to be called on every item in the tree. We do this by
336 recursively calling this function on each child of the item:
337
338 \snippet examples/itemviews/editabletreemodel/treeitem.cpp 8
339
340 \section1 TreeModel Class Definition
341
342 The \c TreeModel class provides an implementation of the QAbstractItemModel
343 class, exposing the necessary interface for a model that can be edited and
344 resized.
345
346 \snippet examples/itemviews/editabletreemodel/treemodel.h 0
347
348 The constructor and destructor are specific to this model.
349
350 \snippet examples/itemviews/editabletreemodel/treemodel.h 1
351
352 Read-only tree models only need to provide the above functions. The
353 following public functions provide support for editing and resizing:
354
355 \snippet examples/itemviews/editabletreemodel/treemodel.h 2
356
357 To simplify this example, the data exposed by the model is organized into
358 a data structure by the model's \l{TreeModel::setupModelData}{setupModelData()}
359 function. Many real world models will not process the raw data at all, but
360 simply work with an existing data structure or library API.
361
362 \section1 TreeModel Class Implementation
363
364 The constructor creates a root item and initializes it with the header
365 data supplied:
366
367 \snippet examples/itemviews/editabletreemodel/treemodel.cpp 0
368
369 We call the internal \l{TreeModel::setupModelData}{setupModelData()}
370 function to convert the textual data supplied to a data structure we can
371 use with the model. Other models may be initialized with a ready-made
372 data structure, or use an API to a library that maintains its own data.
373
374 The destructor only has to delete the root item; all child items will
375 be recursively deleted by the \c TreeItem destructor.
376
377 \snippet examples/itemviews/editabletreemodel/treemodel.cpp 1
378
379 \target TreeModel::getItem
380 Since the model's interface to the other model/view components is based
381 on model indexes, and the internal data structure is item-based, many of
382 the functions implemented by the model need to be able to convert any
383 given model index to its corresponding item. For convenience and
384 consistency, we have defined a \c getItem() function to perform this
385 repetitive task:
386
387 \snippet examples/itemviews/editabletreemodel/treemodel.cpp 4
388
389 This function assumes that each model index it is passed corresponds to
390 a valid item in memory. If the index is invalid, or its internal pointer
391 does not refer to a valid item, the root item is returned instead.
392
393 The model's \c rowCount() implementation is simple: it first uses the
394 \c getItem() function to obtain the relevant item, then returns the
395 number of children it contains:
396
397 \snippet examples/itemviews/editabletreemodel/treemodel.cpp 8
398
399 By contrast, the \c columnCount() implementation does not need to look
400 for a particular item because all items are defined to have the same
401 number of columns associated with them.
402
403 \snippet examples/itemviews/editabletreemodel/treemodel.cpp 2
404
405 As a result, the number of columns can be obtained directly from the root
406 item.
407
408 To enable items to be edited and selected, the \c flags() function needs
409 to be implemented so that it returns a combination of flags that includes
410 the Qt::ItemIsEditable and Qt::ItemIsSelectable flags as well as
411 Qt::ItemIsEnabled:
412
413 \snippet examples/itemviews/editabletreemodel/treemodel.cpp 3
414
415 \target TreeModel::index
416 The model needs to be able to generate model indexes to allow other
417 components to request data and information about its structure. This task
418 is performed by the \c index() function, which is used to obtain model
419 indexes corresponding to children of a given parent item:
420
421 \snippet examples/itemviews/editabletreemodel/treemodel.cpp 5
422
423 In this model, we only return model indexes for child items if the parent
424 index is invalid (corresponding to the root item) or if it has a zero
425 column number.
426
427 We use the custom \l{TreeModel::getItem}{getItem()} function to obtain
428 a \c TreeItem instance that corresponds to the model index supplied, and
429 request its child item that corresponds to the specified row.
430
431 \snippet examples/itemviews/editabletreemodel/treemodel.cpp 6
432
433 Since each item contains information for an entire row of data, we create
434 a model index to uniquely identify it by calling
435 \l{QAbstractItemModel::}{createIndex()} it with the row and column numbers
436 and a pointer to the item. In the \l{TreeModel::data}{data()} function,
437 we will use the item pointer and column number to access the data
438 associated with the model index; in this model, the row number is not
439 needed to identify data.
440
441 \target TreeModel::parent
442 The \c parent() function supplies model indexes for parents of items
443 by finding the corresponding item for a given model index, using its
444 \l{TreeItem::parent}{parent()} function to obtain its parent item,
445 then creating a model index to represent the parent. (See
446 \l{Relating-items-using-model-indexes}{the above diagram}).
447
448 \snippet examples/itemviews/editabletreemodel/treemodel.cpp 7
449
450 Items without parents, including the root item, are handled by returning
451 a null model index. Otherwise, a model index is created and returned as
452 in the \l{TreeModel::index}{index()} function, with a suitable row number,
453 but with a zero column number to be consistent with the scheme used in
454 the \l{TreeModel::index}{index()} implementation.
455
456 \target TreeModel::data
457 \target TreeModel::setupModelData
458
459*/
Note: See TracBrowser for help on using the repository browser.