doc/src/examples/editabletreemodel.qdoc
changeset 0 1918ee327afb
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     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/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 */