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