![]() |
Home · Examples |
[Previous: Proxy Models][Model/View Programming]
The functions that need to be implemented in a model subclass can be divided into three groups:
flags() | Used by other components to obtain information about each item provided by the model. In many models, the combination of flags should include Qt::ItemIsEnabled and Qt::ItemIsSelectable. |
data() | Used to supply item data to views and delegates. Generally, models only need to supply data for Qt::DisplayRole and any application-specific user roles, but it is also good practice to provide data for Qt::ToolTipRole, Qt::AccessibleTextRole, and Qt::AccessibleDescriptionRole. |
headerData() | Provides views with information to show in their headers. The information is only retrieved by views that can display header information. |
rowCount() | Provides the number of rows of data exposed by the model. |
Additionally, the following functions must be implemented in direct subclasses of QAbstractTableModel and QAbstractItemModel:
columnCount() | Provides the number of columns of data exposed by the model. List models do not provide this function because it is already implemented in QAbstractListModel. |
flags() | Must return an appropriate combination of flags for each item. In particular, the value returned by this function must include Qt::ItemIsEditable in addition to the values applied to items in a read-only model. |
setData() | Used to modify the item of data associated with a specified model index. To be able to accept user input, provided by user interface elements, this function must handle data associated with Qt::EditRole. The implementation may also accept data associated with many different kinds of roles specified by Qt::ItemDataRole. After changing the item of data, models must emit the dataChanged() signal to inform other components of the change. |
setHeaderData() | Used to modify horizontal and vertical header information. After changing the item of data, models must emit the headerDataChanged() signal to inform other components of the change. |
insertRows() | Used to add new rows and items of data to all types of model. Implementations must call beginInsertRows()before inserting new rows into any underlying data structures, and call endInsertRows()immediately afterwards. |
removeRows() | Used to remove rows and the items of data they contain from all types of model. Implementations must call beginRemoveRows()before inserting new columns into any underlying data structures, and call endRemoveRows()immediately afterwards. |
insertColumns() | Used to add new columns and items of data to table models and hierarchical models. Implementations must call beginInsertColumns()before rows are removed from any underlying data structures, and call endInsertColumns()immediately afterwards. |
removeColumns() | Used to remove columns and the items of data they contain from table models and hierarchical models. Implementations must call beginRemoveColumns()before columns are removed from any underlying data structures, and call endRemoveColumns()immediately afterwards. |
The signals emitted by the functions called in implementations of the resizing API give attached components the chance to take action before any data becomes unavailable. The encapsulation of insert and remove operations with begin and end functions also enable the model to manage persistent model indexes correctly.
Normally, the begin and end functions are capable of informing other components about changes to the model's underlying structure. For more complex changes to the model's structure, perhaps involving internal reorganization or sorting of data, it is necessary to emit the layoutChanged() signal to cause any attached views to be updated. Some models need to obtain data from remote sources, or must perform time-consuming operations to obtain information about the way the data is organized. Since views generally request as much information as possible in order to accurately display model data, it can be useful to restrict the amount of information returned to them to reduce unnecessary follow-up requests for data. In hierarchical models where finding the number of children of a given item is an expensive operation, it is useful to ensure that the model's rowCount() implementation is only called when necessary. In such cases, the hasChildren() function can be reimplemented to provide an inexpensive way for views to check for the presence of children and, in the case of QTreeView, draw the appropriate decoration for their parent item. Whether the reimplementation of hasChildren() returns true or false, it may not be necessary for the view to call rowCount() to find out how many children are present. For example, QTreeView does not need to know how many children there are if the parent item has not been expanded to show them. If it is known that many items will have children, reimplementing hasChildren() to unconditionally return true is sometimes a useful approach to take. This ensures that each item can be later examined for children while making initial population of model data as fast as possible. The only disadvantage is that items without children may be displayed incorrectly in some views until the user attempts to view the non-existent child items.Lazy Population of Model Data
Lazy population of model data effectively allows requests for information about the model to be deferred until it is actually needed by views. Navigation and Model Index Creation
Hierarchical models need to provide functions that views can call to navigate the tree-like structures they expose, and obtain model indexes for items.Parents and Children
Since the structure exposed to views is determined by the underlying data structure, it is up to each model subclass to create its own model indexes by providing implementations of the following functions:
index() | Given a model index for a parent item, this function allows views and delegates to access children of that item. If no valid child item - corresponding to the specified row, column, and parent model index, can be found, the function must return QModelIndex(), which is an invalid model index. |
parent() | Provides a model index corresponding to the parent of any given child item. If the model index specified corresponds to a top-level item in the model, or if there is no valid parent item in the model, the function must return an invalid model index, created with the empty QModelIndex() constructor. |
Additionally, the convenience view classes implement specialized behavior that should closely follow that expected by existing developers. The Convenience Views section provides an overview of this behavior. Data encoded using this MIME type can be obtained by calling QAbstractItemModel::mimeData() with a QModelIndexList containing the items to be serialized. When implementing drag and drop support in a custom model, it is possible to export items of data in specialized formats by reimplementing the following function: MIME Data
By default, the built-in models and views use an internal MIME type (application/x-qabstractitemmodeldatalist) to pass around information about model indexes. This specifies data for a list of items, containing the row and column numbers of each item, and information about the roles that each item supports.
mimeData() | This function can be reimplemented to return data in formats other than the default application/x-qabstractitemmodeldatalist internal MIME type. Subclasses can obtain the default QMimeData object from the base class and add data to it in additional formats. |
When serialized item data is dropped onto a view, the data is inserted into the current model using its implementation of QAbstractItemModel::dropMimeData(). The default implementation of this function will never overwrite any data in the model; instead, it tries to insert the items of data either as siblings of an item, or as children of that item.
To take advantage of QAbstractItemModel's default implementation for the built-in MIME type, new models must provide reimplementations of the following functions:
insertRows() | These functions enable the model to automatically insert new data using the existing implementation provided by QAbstractItemModel::dropMimeData(). |
insertColumns() | |
setData() | Allows the new rows and columns to be populated with items. |
setItemData() | This function provides more efficient support for populating new items. |
supportedDropActions() | Used to return a combination of drop actions, indicating the types of drag and drop operations that the model accepts. |
mimeTypes() | Used to return a list of MIME types that can be decoded and handled by the model. Generally, the MIME types that are supported for input into the model are the same as those that it can use when encoding data for use by external components. |
dropMimeData() | Performs the actual decoding of the data transferred by drag and drop operations, determines where in the model it will be set, and inserts new rows and columns where necessary. How this function is implemented in subclasses depends on the requirements of the data exposed by each model. |
In order to ensure drag operations work properly, it is important to reimplement the following functions that remove data from the model:
For more information about drag and drop with item views, refer to Using Drag and Drop with Item Views.Another example would be dynamically populated tree models, where we reimplement fetchMore() when a branch in the tree model is expanded.
Note: Both functions must be reimplemented as the default implementation of canFetchMore() returns false and fetchMore() does nothing.
Copyright © 2008 Trolltech | Trademarks | Qt Jambi 4.4.2_01 |