source: trunk/doc/src/examples/simpletreemodel.qdoc@ 1168

Last change on this file since 1168 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 14.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the documentation of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:FDL$
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 a
14** written agreement between you and Nokia.
15**
16** GNU Free Documentation License
17** Alternatively, this file may be used under the terms of the GNU Free
18** Documentation License version 1.3 as published by the Free Software
19** Foundation and appearing in the file included in the packaging of this
20** file.
21**
22** If you have questions regarding the use of this file, please contact
23** Nokia at [email protected].
24** $QT_END_LICENSE$
25**
26****************************************************************************/
27
28/*!
29 \example itemviews/simpletreemodel
30 \title Simple Tree Model Example
31
32 The Simple Tree Model example shows how to create a basic, read-only
33 hierarchical model to use with Qt's standard view classes. For a
34 description of simple non-hierarchical list and table models, see the
35 \l{Model/View Programming} overview.
36
37 \image simpletreemodel-example.png
38
39 Qt's model/view architecture provides a standard way for views to
40 manipulate information in a data source, using an abstract model
41 of the data to simplify and standardize the way it is accessed.
42 Simple models represent data as a table of items, and allow views
43 to access this data via an
44 \l{Model/View Programming#Models}{index-based} system. More generally,
45 models can be used to represent data in the form of a tree structure
46 by allowing each item to act as a parent to a table of child items.
47
48 Before attempting to implement a tree model, it is worth considering whether
49 the data is supplied by an external source, or whether it is going to be
50 maintained within the model itself. In this example, we will implement an
51 internal structure to hold data rather than discuss how to package data from
52 an external source.
53
54 \section1 Design and Concepts
55
56 The data structure that we use to represent the structure of the data takes
57 the form of a tree built from \c TreeItem objects. Each \c TreeItem
58 represents an item in a tree view, and contains several columns of data.
59
60 \target SimpleTreeModelStructure
61 \table
62 \row \i \inlineimage treemodel-structure.png
63 \i \bold{Simple Tree Model Structure}
64
65 The data is stored internally in the model using \c TreeItem objects that
66 are linked together in a pointer-based tree structure. Generally, each
67 \c TreeItem has a parent item, and can have a number of child items.
68 However, the root item in the tree structure has no parent item and it
69 is never referenced outside the model.
70
71 Each \c TreeItem contains information about its place in the tree
72 structure; it can return its parent item and its row number. Having
73 this information readily available makes implementing the model easier.
74
75 Since each item in a tree view usually contains several columns of data
76 (a title and a summary in this example), it is natural to store this
77 information in each item. For simplicity, we will use a list of QVariant
78 objects to store the data for each column in the item.
79 \endtable
80
81 The use of a pointer-based tree structure means that, when passing a
82 model index to a view, we can record the address of the corresponding
83 item in the index (see QAbstractItemModel::createIndex()) and retrieve
84 it later with QModelIndex::internalPointer(). This makes writing the
85 model easier and ensures that all model indexes that refer to the same
86 item have the same internal data pointer.
87
88 With the appropriate data structure in place, we can create a tree model
89 with a minimal amount of extra code to supply model indexes and data to
90 other components.
91
92 \section1 TreeItem Class Definition
93
94 The \c TreeItem class is defined as follows:
95
96 \snippet examples/itemviews/simpletreemodel/treeitem.h 0
97
98 The class is a basic C++ class. It does not inherit from QObject or
99 provide signals and slots. It is used to hold a list of QVariants,
100 containing column data, and information about its position in the tree
101 structure. The functions provide the following features:
102
103 \list
104 \o The \c appendChildItem() is used to add data when the model is first
105 constructed and is not used during normal use.
106 \o The \c child() and \c childCount() functions allow the model to obtain
107 information about any child items.
108 \o Information about the number of columns associated with the item is
109 provided by \c columnCount(), and the data in each column can be
110 obtained with the data() function.
111 \o The \c row() and \c parent() functions are used to obtain the item's
112 row number and parent item.
113 \endlist
114
115 The parent item and column data are stored in the \c parentItem and
116 \c itemData private member variables. The \c childItems variable contains
117 a list of pointers to the item's own child items.
118
119 \section1 TreeItem Class Implementation
120
121 The constructor is only used to record the item's parent and the data
122 associated with each column.
123
124 \snippet examples/itemviews/simpletreemodel/treeitem.cpp 0
125
126 A pointer to each of the child items belonging to this item will be
127 stored in the \c childItems private member variable. When the class's
128 destructor is called, it must delete each of these to ensure that
129 their memory is reused:
130
131 \snippet examples/itemviews/simpletreemodel/treeitem.cpp 1
132
133 Since each of the child items are constructed when the model is initially
134 populated with data, the function to add child items is straightforward:
135
136 \snippet examples/itemviews/simpletreemodel/treeitem.cpp 2
137
138 Each item is able to return any of its child items when given a suitable
139 row number. For example, in the \l{#SimpleTreeModelStructure}{above diagram},
140 the item marked with the letter "A" corresponds to the child of the root item
141 with \c{row = 0}, the "B" item is a child of the "A" item with \c{row = 1},
142 and the "C" item is a child of the root item with \c{row = 1}.
143
144 The \c child() function returns the child that corresponds to
145 the specified row number in the item's list of child items:
146
147 \snippet examples/itemviews/simpletreemodel/treeitem.cpp 3
148
149 The number of child items held can be found with \c childCount():
150
151 \snippet examples/itemviews/simpletreemodel/treeitem.cpp 4
152
153 The \c TreeModel uses this function to determine the number of rows that
154 exist for a given parent item.
155
156 The \c row() function reports the item's location within its parent's
157 list of items:
158
159 \snippet examples/itemviews/simpletreemodel/treeitem.cpp 8
160
161 Note that, although the root item (with no parent item) is automatically
162 assigned a row number of 0, this information is never used by the model.
163
164 The number of columns of data in the item is trivially returned by the
165 \c columnCount() function.
166
167 \snippet examples/itemviews/simpletreemodel/treeitem.cpp 5
168
169 Column data is returned by the \c data() function, taking advantage of
170 QList's ability to provide sensible default values if the column number
171 is out of range:
172
173 \snippet examples/itemviews/simpletreemodel/treeitem.cpp 6
174
175 The item's parent is found with \c parent():
176
177 \snippet examples/itemviews/simpletreemodel/treeitem.cpp 7
178
179 Note that, since the root item in the model will not have a parent, this
180 function will return zero in that case. We need to ensure that the model
181 handles this case correctly when we implement the \c TreeModel::parent()
182 function.
183
184 \section1 TreeModel Class Definition
185
186 The \c TreeModel class is defined as follows:
187
188 \snippet examples/itemviews/simpletreemodel/treemodel.h 0
189
190 This class is similar to most other subclasses of QAbstractItemModel that
191 provide read-only models. Only the form of the constructor and the
192 \c setupModelData() function are specific to this model. In addition, we
193 provide a destructor to clean up when the model is destroyed.
194
195 \section1 TreeModel Class Implementation
196
197 For simplicity, the model does not allow its data to be edited. As a
198 result, the constructor takes an argument containing the data that the
199 model will share with views and delegates:
200
201 \snippet examples/itemviews/simpletreemodel/treemodel.cpp 0
202
203 It is up to the constructor to create a root item for the model. This
204 item only contains vertical header data for convenience. We also use it
205 to reference the internal data structure that contains the model data,
206 and it is used to represent an imaginary parent of top-level items in
207 the model.
208
209 The model's internal data structure is populated with items by the
210 \c setupModelData() function. We will examine this function separately
211 at the end of this document.
212
213 The destructor ensures that the root item and all of its descendants
214 are deleted when the model is destroyed:
215
216 \snippet examples/itemviews/simpletreemodel/treemodel.cpp 1
217
218 Since we cannot add data to the model after it is constructed and set
219 up, this simplifies the way that the internal tree of items is managed.
220
221 Models must implement an \c index() function to provide indexes for
222 views and delegates to use when accessing data. Indexes are created
223 for other components when they are referenced by their row and column
224 numbers, and their parent model index. If an invalid model
225 index is specified as the parent, it is up to the model to return an
226 index that corresponds to a top-level item in the model.
227
228 When supplied with a model index, we first check whether it is valid.
229 If it is not, we assume that a top-level item is being referred to;
230 otherwise, we obtain the data pointer from the model index with its
231 \l{QModelIndex::internalPointer()}{internalPointer()} function and use
232 it to reference a \c TreeItem object. Note that all the model indexes
233 that we construct will contain a pointer to an existing \c TreeItem,
234 so we can guarantee that any valid model indexes that we receive will
235 contain a valid data pointer.
236
237 \snippet examples/itemviews/simpletreemodel/treemodel.cpp 6
238
239 Since the row and column arguments to this function refer to a
240 child item of the corresponding parent item, we obtain the item using
241 the \c TreeItem::child() function. The
242 \l{QAbstractItemModel::createIndex()}{createIndex()} function is used
243 to create a model index to be returned. We specify the row and column
244 numbers, and a pointer to the item itself. The model index can be used
245 later to obtain the item's data.
246
247 The way that the \c TreeItem objects are defined makes writing the
248 \c parent() function easy:
249
250 \snippet examples/itemviews/simpletreemodel/treemodel.cpp 7
251
252 We only need to ensure that we never return a model index corresponding
253 to the root item. To be consistent with the way that the \c index()
254 function is implemented, we return an invalid model index for the
255 parent of any top-level items in the model.
256
257 When creating a model index to return, we must specify the row and
258 column numbers of the parent item within its own parent. We can
259 easily discover the row number with the \c TreeItem::row() function,
260 but we follow a convention of specifying 0 as the column number of
261 the parent. The model index is created with
262 \l{QAbstractItemModel::createIndex()}{createIndex()} in the same way
263 as in the \c index() function.
264
265 The \c rowCount() function simply returns the number of child items
266 for the \c TreeItem that corresponds to a given model index, or the
267 number of top-level items if an invalid index is specified:
268
269 \snippet examples/itemviews/simpletreemodel/treemodel.cpp 8
270
271 Since each item manages its own column data, the \c columnCount()
272 function has to call the item's own \c columnCount() function to
273 determine how many columns are present for a given model index.
274 As with the \c rowCount() function, if an invalid model index is
275 specified, the number of columns returned is determined from the
276 root item:
277
278 \snippet examples/itemviews/simpletreemodel/treemodel.cpp 2
279
280 Data is obtained from the model via \c data(). Since the item manages
281 its own columns, we need to use the column number to retrieve the data
282 with the \c TreeItem::data() function:
283
284 \snippet examples/itemviews/simpletreemodel/treemodel.cpp 3
285
286 Note that we only support the \l{Qt::ItemDataRole}{DisplayRole}
287 in this implementation, and we also return invalid QVariant objects for
288 invalid model indexes.
289
290 We use the \c flags() function to ensure that views know that the
291 model is read-only:
292
293 \snippet examples/itemviews/simpletreemodel/treemodel.cpp 4
294
295 The \c headerData() function returns data that we conveniently stored
296 in the root item:
297
298 \snippet examples/itemviews/simpletreemodel/treemodel.cpp 5
299
300 This information could have been supplied in a different way: either
301 specified in the constructor, or hard coded into the \c headerData()
302 function.
303
304 \section1 Setting Up the Data in the Model
305
306 We use the \c setupModelData() function to set up the initial data in
307 the model. This function parses a text file, extracting strings of
308 text to use in the model, and creates item objects that record both
309 the data and the overall model structure.
310 Naturally, this function works in a way that is very specific to
311 this model. We provide the following description of its behavior,
312 and refer the reader to the example code itself for more information.
313
314 We begin with a text file in the following format:
315
316 \snippet doc/src/snippets/code/doc_src_examples_simpletreemodel.qdoc 0
317 \dots
318 \snippet doc/src/snippets/code/doc_src_examples_simpletreemodel.qdoc 1
319
320 We process the text file with the following two rules:
321
322 \list
323 \o For each pair of strings on each line, create an item (or node)
324 in a tree structure, and place each string in a column of data
325 in the item.
326 \o When the first string on a line is indented with respect to the
327 first string on the previous line, make the item a child of the
328 previous item created.
329 \endlist
330
331 To ensure that the model works correctly, it is only necessary to
332 create instances of \c TreeItem with the correct data and parent item.
333*/
Note: See TracBrowser for help on using the repository browser.