Qt 4 introduced a new set of item view classes that use a model/view architecture to manage the relationship between data and the way it is presented to the user. The separation of functionality introduced by this architecture gives developers greater flexibility
to customize the presentation of items, and provides a standard model interface to allow a wide range of data sources to be used with existing item views. In this document, we give a brief introduction to the model/view paradigm, outline the concepts involved,
and describe the architecture of the item view system. Each of the components in the architecture is explained, and examples are given that show how to use the classes provided.
<a></a>
Model-View-Controller (MVC) is a design pattern originating from Smalltalk that is often used when building user interfaces. In
MVC consists of three kinds of objects. The Model is the application object, the View is its screen presentation, and the Controller defines the way the user interface reacts to user input. Before MVC, user interface designs tended to lump these objects together. MVC decouples them to increase flexibility and reuse.
If the view and the controller objects are combined, the result is the model/view architecture. This still separates the way that data is stored from the way that it is presented to the user, but provides a simpler framework based on the same principles.
This separation makes it possible to display the same data in several different views, and to implement new types of views, without changing the underlying data structures. To allow flexible handling of user input, we introduce the concept of the
delegate. The advantage of having a delegate in this framework is that it allows the way items of data are rendered and edited to be customized.
The model/view architecture
The model communicates with a source of data, providing an interface for the other components in the architecture. The nature of the communication depends on the type of data source, and the way the model is implemented.
The view obtains model indexes from the model; these are references to items of data. By supplying model indexes to the model, the view can retrieve items of data from the data source.
In standard views, a delegate renders the items of data. When an item is edited, the delegate communicates with the model directly using model indexes.
Generally, the model/view classes can be separated into the three groups described above: models, views, and delegates. Each of these components is defined by
abstract classes that provide common interfaces and, in some cases, default implementations of features. Abstract classes are meant to be subclassed in order to provide the full set of functionality expected by other components; this also allows specialized
components to be written.
Models, views, and delegates communicate with each other using signals and slots:
Signals from the model inform the view about changes to the data held by the data source.
Signals from the view provide information about the user's interaction with the items being displayed.
Signals from the delegate are used during editing to tell the model and view about the state of the editor.
a database, or some other application component.
Qt provides some ready-made models that can be used to handle items of data:
There are two ways of approaching sorting in the model/view architecture; which approach to choose depends on your underlying model.
The alternative approach, if your model do not have the required interface or if you want to use a list view to present your data, is to use a proxy model to transform the structure of your model before presenting the data in the view. This is covered in
A number of convenience classes are derived from the standard view classes for the benefit of applications that rely on Qt's item-based item view and table classes. They are not intended to be subclassed, but simply exist to provide a familiar interface
QListBox, QListView, and QTable classes in Qt 3.
These classes are less flexible than the view classes, and cannot be used with arbitrary models. We recommend that you use a model/view approach to handling data in item views unless you strongly need an item-based set of classes.
If you wish to take advantage of the features provided by the model/view approach while still using an item-based interface, consider using view classes, such as
The following sections explain how to use the model/view pattern in Qt. Each section includes an an example and is followed by a section showing how to create new components.
the local filing system.
views, and explore how to manipulate data using model indexes.
the model is performed from within a single main() function:
We create two views so that we can examine the items held in the model in two different ways:
The views are constructed in the same way as other widgets. Setting up a view to display the items in the model is simply a matter of calling its
model index from the file system model for the current directory.
The rest of the function just displays the views within a splitter widget, and runs the application's event loop:
In the above example, we neglected to mention how to handle selections of items. This subject is covered in more detail in the section about
Before examining how selections are handled, you may find it useful to examine the concepts used in the model/view framework.
In the model/view architecture, the model provides a standard interface that views and delegates use to access data. In Qt, the standard interface is defined by the
convention to access items of data in the model, but they are not restricted in the way that they present this information to the user.
Models also notify any attached views about changes to data through the signals and slots mechanism.
This section describes some basic concepts that are central to the way item of data are accessed by other components via a model class. More advanced concepts are discussed in later sections.
To ensure that the representation of the data is kept separate from the way it is accessed, the concept of a
model index is introduced. Each piece of information that can be obtained via a model is represented by a model index. Views and delegates use these indexes to request items of data to display.
As a result, only the model needs to know how to obtain data, and the type of data managed by the model can be defined fairly generally. Model indexes contain a pointer to the model that created them, and this prevents confusion when working with more than
one model.
Model indexes provide temporary references to pieces of information, and can be used to retrieve or modify data via the model. Since models may reorganize their internal structures from time to time, model indexes may become invalid, and
should not be stored. If a long-term reference to a piece of information is required, a
persistent model index must be created. This provides a reference to the information that the model keeps up-to-date. Temporary model indexes are provided by the
To obtain a model index that corresponds to an item of data, three properties must be specified to the model: a row number, a column number, and the model index of a parent item. The following sections describe and explain these properties in detail.
In its most basic form, a model can be accessed as a simple table in which items are located by their row and column numbers.
This does not mean that the underlying pieces of data are stored in an array structure; the use of row and column numbers is only a convention to allow components to communicate with each other. We can retrieve information about any given item by specifying
its row and column numbers to the model, and we receive an index that represents the item:
Models that provide interfaces to simple, single level data structures like lists and tables do not need any other information to be provided but, as the above code indicates, we need to supply more information when obtaining a model index.
Rows and columns
The diagram shows a representation of a basic table model in which each item is located by a pair of row and column numbers. We obtain a model index that refers to an item of data by passing the relevant row and column numbers to the model.
Top level items in a model are always referenced by specifying QModelIndex() as their parent item. This is discussed in the next section.
The table-like interface to item data provided by models is ideal when using data in a table or list view; the row and column number system maps exactly to the way the views display items. However, structures such as tree views require the model to expose
a more flexible interface to the items within. As a result, each item can also be the parent of another table of items, in much the same way that a top-level item in a tree view can contain another list of items.
When requesting an index for a model item, we must provide some information about the item's parent. Outside the model, the only way to refer to an item is through a model index, so a parent model index must also be given:
Parents, rows, and columns
The diagram shows a representation of a tree model in which each item is referred to by a parent, a row number, and a column number.
Items "A" and "C" are represented as top-level siblings in the model:
Item "A" has a number of children. A model index for item "B" is obtained with the following code:
Items in a model can perform various roles for other components, allowing different kinds of data to be supplied for different situations. For example,
We can ask the model for the item's data by passing it the model index corresponding to the item, and by specifying a role to obtain the type of data we want:
Item roles
The role indicates to the model which type of data is being referred to. Views can display the roles in different ways, so it is important to supply appropriate information for each role.
It is also possible to define additional roles for application-specific purposes.
Model indexes give views and delegates information about the location of items provided by models in a way that is independent of any underlying data structures.
Items are referred to by their row and column numbers, and by the model index of their parent items.
Model indexes are constructed by models at the request of other components, such as views and delegates.
If a valid model index is specified for the parent item when an index is requested using
If an invalid model index is specified for the parent item when an index is requested using
To demonstrate how data can be retrieved from a model, using model indexes, we set up a
when dealing with model indexes.
We construct a file system model in the following way:
For simplicity, we are only interested in the items in the first column of the model. We examine each row in turn, obtaining a model index for the first item in each row, and read the data stored for that item in the model.
To obtain a model index, we specify the row number, column number (zero for the first column), and the appropriate model index for the parent of all the items that we want. The text stored in each item is retrieved using the model's
The above example demonstrates the basic principles used to retrieve data from a model:
Model indexes are used to access items in the model. The row, column, and parent model index are needed to specify the item.
To access top-level items in a model, specify a null model index as the parent index with
QModelIndex().
Items contain data for different roles. To obtain the data for a particular role, both the model index and the role must be supplied to the model.
In the model/view architecture, the view obtains items of data from the model and presents them to the user. The way that the data is presented need not resemble the representation of the data provided by the model, and may be
completely different from the underlying data structure used to store items of data.
The separation of content and presentation is achieved by the use of a standard model interface provided by
As well as presenting data, views handle navigation between items, and some aspects of item selection. The views also implement basic user interface features, such as context menus and drag and drop. A view can provide default editing facilities for items,
A view can be constructed without a model, but a model must be provided before it can display useful information. Views keep track of the items that the user has selected through the use of
Qt provides three ready-to-use view classes that present data from models in ways that are familiar to most users.
The default behavior of the standard views shown above should be sufficient for most applications. They provide basic editing facilities, and can be customized to suit the needs of more specialized user interfaces.
The view is shown in the normal way:
The view renders the contents of a model, accessing data via the model's interface. When the user tries to edit an item, the view uses a default delegate to provide an editor widget.
Providing multiple views onto the same model is simply a matter of setting the same model for each view. In the following code we create two table views, each using the same simple table model which we have created for this example:
The use of signals and slots in the model/view architecture means that changes to the model can be propagated to all the attached views, ensuring that we can always access the same data regardless of the view being used.
The above image shows two different views onto the same model, each containing a number of selected items. Although the data from the model is shown consistently across view, each view maintains its own internal selection model. This can be useful in certain
situations but, for many applications, a shared selection model is desirable.
The mechanism for handling selections of items within views is provided by the
Generally, unless you are subclassing a model or view, you don't need to manipulate the contents of selections directly. However, the interface to the selection model can be accessed, if required, and this is explored in
Although it is convenient that the view classes provide their own selection models by default, when we use more than one view onto the same model it is often desirable that both the model's data and the user's selection are shown consistently in all views.
Since the view classes allow their internal selection models to be replaced, we can achieve a unified selection between views with the following line:
The second view is given the selection model for the first view. Both views now operate on the same selection model, keeping both the data and the selected items synchronized.
In the example shown above, two views of the same type were used to display the same model's data. However, if two different types of view were used, the selected items may be represented very differently in each view; for example, a contiguous selection
in a table view can be represented as a fragmented set of highlighted items in a tree view.
Unlike the Model-View-Controller pattern, the model/view design does not include a completely separate component for managing interaction with the user. Generally, the view is responsible for the presentation of model data to the user, and for processing
user input. To allow some flexibility in the way this input is obtained, the interaction is performed by delegates. These components provide input capabilities and are also responsible for rendering individual items in some views. The standard interface for
Delegates are expected to be able to render their contents themselves by implementing the
Editors for delegates can be implemented either by using widgets to manage the editing process or by handling events directly. The first approach is covered later in this section, and it is also shown in the
All the standard roles are handled by the default delegate used by the standard views. The way these are interpreted is described in the
Note that no editor widgets are set up when the delegate is constructed. We only construct an editor widget when it is needed.
In this example, when the table view needs to provide an editor, it asks the delegate to provide an editor widget that is appropriate for the item being modified. The
Note that we do not need to keep a pointer to the editor widget because the view takes responsibility for destroying it when it is no longer needed.
We install the delegate's default event filter on the editor to ensure that it provides the standard editing shortcuts that users expect. Additional shortcuts can be added to the editor to allow more sophisticated behavior; these are discussed in the section
The view ensures that the editor's data and geometry are set correctly by calling functions that we define later for these purposes. We can create different editors depending on the model index supplied by the view. For example, if we have a column of integers
and a column of strings we could return either a QSpinBox or a QLineEdit, depending on which column is being edited.
The delegate must provide a function to copy model data into the editor. In this example, we read the data stored in the
In this example, we know that the editor widget is a spin box, but we could have provided different editors for different types of data in the model, in which case we would need to cast the widget to the appropriate type before accessing its member functions.
When the user has finished editing the value in the spin box, the view asks the delegate to store the edited value in the model by calling the
Since the view manages the editor widgets for the delegate, we only need to update the model with the contents of the editor supplied. In this case, we ensure that the spin box is up-to-date, and update the model with the value it contains using the index
specified.
values, but we can still use this delegate with different kinds of models because
It is the responsibility of the delegate to manage the editor's geometry. The geometry must be set when the editor is created, and when the item's size or position in the view is changed. Fortunately, the view provides all the necessary geometry information
In this case, we just use the geometry information provided by the view option in the item rectangle. A delegate that renders items with several elements would not use the item rectangle directly. It would position the editor in relation to the other elements
in the item.
After editing, delegates should provide hints to the other components about the result of the editing process, and provide hints that will assist any subsequent editing operations. This is achieved by emitting the
The behavior of the spin box could be adjusted to make it more user friendly. In the default event filter supplied by
Return to confirm their choice in the spin box, the delegate commits the value to the model and closes the spin box. We can change this behavior by installing our own event filter on the spin box, and provide editing hints that suit our needs;
Another approach that does not require the use of an event filter is to provide our own editor widget, perhaps subclassing
in the delegate if you need to customize the behavior of a standard Qt editor widget.
Delegates do not have to emit these hints, but those that do not will be less integrated into applications, and will be less usable than those that emit hints to support common editing actions.
The selection model used in the item view classes offers many improvements over the selection model used in Qt 3. It provides a more general description of selections based on the facilities of the model/view architecture. Although the standard classes for
manipulating selections are sufficient for the item views provided, the selection model allows you to create specialized selection models to suit the requirements for your own item models and views.
Information about the items selected in a view is stored in an instance of the
between views, allowing applications to show multiple views in a consistent way.
Selections are made up of selection ranges. These efficiently maintain information about large selections of items by recording only the starting and ending model indexes for each range of selected items. Non-contiguous selections of items are constructed
by using more than one selection range to describe the selection.
Selections are applied to a collection of model indexes held by a selection model. The most recent selection of items applied is known as the
current selection. The effects of this selection can be modified even after its application through the use of certain types of selection commands. These are discussed later in this section.
In a view, there is always a current item and a selected item - two independent states. An item can be the current item and selected at the same time. The view is responsible for ensuring that there is always a current item as keyboard navigation, for example,
requires a current item.
The table below highlights the differences between current item and selected items.
Current Item
Selected Items
There can only be one current item.
There can be multiple selected items.
The current item will be changed with key navigation or mouse button clicks.
The selected state of items is set or unset, depending on several pre-defined modes - e.g., single selection, multiple selection, etc. - when the user interacts with the items.
The current item will be edited if the edit key, F2, is pressed or the item is double-clicked (provided that editing is enabled).
The current item can be used together with an anchor to specify a range that should be selected or deselected (or a combination of the two).
The current item is indicated by the focus rectangle.
The selected items are indicated with the selection rectangle.
already selected. The indexes of all selected items can be retrieved at any time, and other components can be informed of changes to the selection model via the signals and slots mechanism.
The standard view classes provide default selection models that can be used in most applications. A selection model belonging to one view can be obtained using the view's
A selection is created by specifying a model, and a pair of model indexes to a
in a model requires the selection to be submitted to a selection model; this can be achieved in a number of ways, each having a different effect on the selections already present in the selection model.
To demonstrate some of the principal features of selections, we construct an instance of a custom table model with 32 items in total, and open a table view onto its data:
The table view's default selection model is retrieved for later use. We do not modify any items in the model, but instead select a few items that the view will display at the top-left of the table. To do this, we need to retrieve the model indexes corresponding
to the top-left and bottom-right items in the region to be selected:
To select these items in the model, and see the corresponding change in the table view, we need to construct a selection object then apply it to the selection model:
The selection is applied to the selection model using a command defined by a combination of
The selection of items can be modified using various operations that are defined by the selection flags. The selection that results from these operations may have a complex structure, but it is represented efficiently by the selection model. The use of different
selection flags to manipulate the selected items is described when we examine how to update a selection.
The selection model emits signals to indicate changes in the selection. These notify other components about changes to both the selection as a whole and the currently focused item in the item model. We can connect the
Monitoring selections made by the user is straightforward with these signals, but we can also update the selection model directly.
Selection commands are provided by a combination of selection flags, defined by
Individual items in the selection model are updated by creating a selection of items, and applying them to the selection model. In the following code, we apply a second selection of items to the table model shown above, using the
The results of this operation are displayed in the table view, providing a convenient way of visualizing what we have achieved:
By default, the selection commands only operate on the individual items specified by the model indexes. However, the flag used to describe the selection command can be combined with additional flags to change entire rows and columns. For example if you call
Although only four indexes are supplied to the selection model, the use of the
The commands performed on the example model have all involved accumulating a selection of items in the model. It is also possible to clear the selection, or to replace the current selection with a new one.
To replace the current selection with a new selection, combine the other selection flags with the
To select all items in a model, it is necessary to create a selection for each level of the model that covers all items in that level. We do this by retrieving the indexes corresponding to the top-left and bottom-right items with a given parent index:
A selection is constructed with these indexes and the model. The corresponding items are then selected in the selection model:
This needs to be performed for all levels in the model. For top-level items, we would define the parent index in the usual way:
The separation of functionality between the model/view components allows models to be created that can take advantage of existing views. This approach lets us present data from a variety of sources using standard graphical user interface components, such
will be inserted, removed, modified, or sorted in some way. It also provides support for drag and drop operations.
In this section, we create a simple read-only model to explore the basic principles of the model/view architecture. Later in this section, we adapt this simple model so that items can be modified by the user.
When creating a new model for an existing data structure, it is important to consider which type of model should be used to provide an interface onto the data. If the data structure can be represented as a list or table of items, you can subclass
However, if the underlying data structure can only be represented by a hierarchical tree structure, it is necessary to subclass
In this section, we implement a simple model based on a list of strings, so the
Whatever form the underlying data structure takes, it is usually a good idea to supplement the standard
other general model/view components to interact with it using the standard API. The model described below provides a custom constructor for just this purpose.
The model implemented here is a simple, non-hierarchical, read-only data model based on the standard
interface. The class declaration is as follows:
Note that this is a non-hierarchical model, so we don't have to worry about the parent-child relationships. If our model was hierarchical, we would also have to implement the
The list of strings is stored internally in the stringList private member variable.
We want the number of rows in the model to be the same as the number of strings in the string list. We implement the
Since the model is non-hierarchical, we can safely ignore the model index corresponding to the parent item. By default, models derived from
Not all views display headers with the item data, and those that do may be configured to hide them. Nonetheless, it is recommended that you implement the
An item can have several roles, giving out different data depending on the role specified. The items in our model only have one role,
The read-only model shows how simple choices could be presented to the user but, for many applications, an editable list model is much more useful. We can modify the read-only model to make the items editable by changing the data() function we implemented
A delegate checks whether an item is editable before creating an editor. The model must let the delegate know that its items are editable. We do this by returning the correct flags for each item in the model; in this case, we enable all items and make them
both selectable and editable:
Note that we do not have to know how the delegate performs the actual editing process. We only have to provide a way for the delegate to set the data in the model. This is achieved through the
In this model, the item in the string list that corresponds to the model index is replaced by the value provided. However, before we can modify the string list, we must make sure that the index is valid, the item is of the correct type, and that the role
with standard components.
When the data has been set, the model must let the views know that some data has changed. This is done by emitting the
It is possible to change the number of rows and columns in a model. In the string list model it only makes sense to change the number of rows, so we only reimplement the functions for inserting and removing rows. These are declared in the class definition:
Since rows in this model correspond to strings in a list, the insertRows() function inserts a number of empty strings into the string list before the specified position. The number of strings inserted is equivalent to the number of rows specified.
The parent index is normally used to determine where in the model the rows should be added. In this case, we only have a single top-level list of strings, so we just insert empty strings into that list.
The function to remove rows from the model is also simple to write. The rows to be removed from the model are specified by the position and the number of rows given. We ignore the parent index to simplify our implementation, and just remove the corresponding
items from the string list.
Qt 4 also introduced some standard widgets to provide classic item-based container widgets. These behave in a similar way to the item view classes in Qt 3, but have been rewritten to use the underlying model/view framework for performance and maintainability.
The old item view classes are still available in the compatibility library (see the
The item-based widgets have been given names which reflect their uses: QListWidget provides a list of items,
QTreeWidget displays a multi-level tree structure, and QTableWidget provides a table of cell items. Each class inherits the behavior of the
QAbstractItemView class which implements common behavior for item selection and header management.
Single level lists of items are typically displayed using a QListWidget and a number of
QListWidgetItems. A list widget is constructed in the same way as any other widget:
List items can be added directly to the list widget when they are constructed:
They can also be constructed without a parent list widget and added to a list at some later time:
Each item in a list can display a text label and an icon. The colors and font used to render the text can be changed to provide a customized appearance for items. Tooltips, status tips, and "What's This?" help are all easily configured to ensure that the
list is properly integrated into the application.
By default, items in a list are presented in the order of their creation. Lists of items can be sorted according to the criteria given in
Trees or hierarchical lists of items are provided by the QTreeWidget and
QTreeWidgetItem classes. Each item in the tree widget can have child items of its own, and can display a number of columns of information. Tree widgets are created just like any other widget:
Before items can be added to the tree widget, the number of columns must be set. For example, we could define two columns, and create a header to provide labels at the top of each column:
The easiest way to set up the labels for each section is to supply a string list. For more sophisticated headers, you can construct a tree item, decorate it as you wish, and use that as the tree widget's header.
Top-level items in the tree widget are constructed with the tree widget as their parent widget. They can be inserted in an arbitrary order, or you can ensure that they are listed in a particular order by specifying the previous item when constructing each
item:
Tree widgets deal with top-level items slightly differently to other items from deeper within the tree. Items can be removed from the top level of the tree by calling the tree widget's
It is easy to move items around between the top level and lower levels in the tree. We just need to check whether the items are top-level items or not, and this information is supplied by each item's
parent() function. For example, we can remove the current item in the tree widget regardless of its location:
Inserting the item somewhere else in the tree widget follows the same pattern:
Tables of items similar to those found in spreadsheet applications are constructed with the
QTableWidget and QTableWidgetItem. These provide a scrolling table widget with headers and items to use within it.
Tables can be created with a set number of rows and columns, or these can be added to an unsized table as they are needed.
Items are constructed outside the table before being added to the table at the required location:
Horizontal and vertical headers can be added to the table by constructing items outside the table and using them as headers:
Note that the rows and columns in the table begin at zero.
There are a number of item-based features common to each of the convenience classes that are available through the same interfaces in each class. We present these in the following sections with some examples for different widgets. Look at the list of
It is sometimes useful to be able to hide items in an item view widget rather than remove them. Items for all of the above widgets can be hidden and later shown again. You can determine whether an item is hidden by calling the isItemHidden() function, and
items can be hidden with setItemHidden().
Since this operation is item-based, the same function is available for all three convenience classes.
items and, in many-item selections, whether the selection must be a continuous range of items. The selection mode works in the same way for all of the above widgets.
Single item selections: Where the user needs to choose a single item from a widget, the default
SingleSelection mode is most suitable. In this mode, the current item and the selected item are the same.
Multi-item selections: In this mode, the user can toggle the selection state of any item in the widget without changing the existing selection, much like the way non-exclusive checkboxes can be toggled independently.
Extended selections: Widgets that often require many adjacent items to be selected, such as those found in spreadsheets, require the
ExtendedSelection mode. In this mode, continuous ranges of items in the widget can be selected with both the mouse and the keyboard. Complex selections, involving many items that are not adjacent to other selected items in the widget, can also be created
if modifier keys are used.
If the user selects an item without using a modifier key, the existing selection is cleared.
The selected items in a widget are read using the selectedItems() function, providing a list of relevant items that can be iterated over. For example, we can find the sum of all the numeric values within a list of selected items with the following
code:
Note that for the single selection mode, the current item will be in the selection. In the multi-selection and extended selection modes, the current item may not lie within the selection, depending on the way the user formed the selection.
It is often useful to be able to find items within an item view widget, either as a developer or as a service to present to users. All three item view convenience classes provide a common
findItems() function to make this as consistent and simple as possible.
Items are searched for by the text that they contain according to criteria specified by a selection of values from
findItems() function:
The above code causes items in a tree widget to be selected if they contain the text given in the search string. This pattern can also be used in the list and table widgets.
Qt's drag and drop infrastructure is fully supported by the model/view framework. Items in lists, tables, and trees can be dragged within the views, and data can be imported and exported as MIME-encoded data.
The standard views automatically support internal drag and drop, where items are moved around to change the order in which they are displayed. By default, drag and drop is not enabled for these views because they are configured for the simplest, most common
uses. To allow items to be dragged around, certain properties of the view need to be enabled, and the items themselves must also allow dragging to occur.
The requirements for a model that only allows items to be exported from a view, and which does not allow data to be dropped into it, are fewer than those for a fully-enabled drag and drop model.
Although all of the standard items have one or both flags set for drag and drop, you generally need to set various properties in the view itself to take advantage of the built-in support for drag and drop:
To allow the user to drop either internal or external items within the view, set the view's
true.
To show the user where the item currently being dragged will be placed if dropped, set the view's
For example, we can enable drag and drop in a list widget with the following lines of code:
The result is a list widget which allows the items to be copied around within the view, and even lets the user drag items between views containing the same type of data. In both situations, the items are copied rather than moved.
To enable the user to move the items around within the view, we must set the list widget's
Setting up a view for drag and drop follows the same pattern used with the convenience views. For example, a
Since access to the data displayed by the view is controlled by a model, the model used also has to provide support for drag and drop operations. The actions supported by a model can be specified by reimplementing the
Models indicate to views which items can be dragged, and which will accept drops, by reimplementing the
Note that items can be dropped into the top level of the model, but dragging is only enabled for valid items.
When items of data are exported from a model in a drag and drop operation, they are encoded into an appropriate format corresponding to one or more MIME types. Models declare the MIME types that they can use to supply items by reimplementing the
For example, a model that only provides plain text would provide the following implementation:
The model must also provide code to encode data in the advertised format. This is achieved by reimplementing the
The following code shows how each item of data, corresponding to a given list of indexes, is encoded as plain text and stored in a
Since a list of model indexes is supplied to the function, this approach is general enough to be used in both hierarchical and non-heirarchical models.
The way that any given model handles dropped data depends on both its type (list, table, or tree) and the way its contents is likely to be presented to the user. Generally, the approach taken to accommodate dropped data should be the one that most suits
the model's underlying data store.
Different types of model tend to handle dropped data in different ways. List and table models only provide a flat structure in which items of data are stored. As a result, they may insert new rows (and columns) when data is dropped on an existing item in
a view, or they may overwrite the item's contents in the model using some of the data supplied. Tree models are often able to add child items containing new data to their underlying data stores, and will therefore behave more predictably as far as the user
is concerned.
item).
The model first has to make sure that the operation should be acted on, the data supplied is in a format that can be used, and that its destination within the model is valid:
A simple one column string list model can indicate failure if the data supplied is not plain text, or if the column number given for the drop is invalid.
The data to be inserted into the model is treated differently depending on whether it is dropped onto an existing item or not. In this simple example, we want to allow drops between existing items, before the first item in the list, and after the last item.
When a drop occurs, the model index corresponding to the parent item will either be valid, indicating that the drop occurred on an item, or it will be invalid, indicating that the drop occurred somewhere in the view that corresponds to top level of the model.
We initially examine the row number supplied to see if we can use it to insert items into the model, regardless of whether the parent index is valid or not.
If the parent model index is valid, the drop occurred on an item. In this simple list model, we find out the row number of the item and use that value to insert dropped items into the top level of the model.
When a drop occurs elsewhere in the view, and the row number is unusable, we append items to the top level of the model.
In hierarchical models, when a drop occurs on an item, it would be better to insert new items into the model as children of that item. In the simple example shown here, the model only has one level, so this approach is not appropriate.
For a simple string list model, the encoded items can be decoded and streamed into a
The strings can then be inserted into the underlying data store. For consistency, this can be done through the model's own interface:
In the model/view framework, items of data supplied by a single model can be shared by any number of views, and each of these can possibly represent the same information in completely different ways. Custom views and delegates are effective ways to provide
radically different representations of the same data. However, applications often need to provide conventional views onto processed versions of the same data, such as differently-sorted views onto a list of items.
Although it seems appropriate to perform sorting and filtering operations as internal functions of views, this approach does not allow multiple views to share the results of such potentially costly operations. The alternative approach, involving sorting
within the model itself, leads to the similar problem where each view has to display items of data that are organized according to the most recent processing operation.
To solve this problem, the model/view framework uses proxy models to manage the information supplied between individual models and views. Proxy models are components that behave like ordinary models from the perspective of a view, and access data from source
models on behalf of that view. The signals and slots used by the model/view framework ensure that each view is updated appropriately no matter how many proxy models are placed between itself and the source model.
Proxy models can be inserted between an existing model and any number of views. Qt is supplied with a standard proxy model,
the required comparison operations.
Generally, the type of processing used in a proxy model involves mapping each item of data from its original location in the source model to either a different location in the proxy model. In some models, some items may have no corresponding location in
the proxy model; these models are filtering proxy models. Views access items using model indexes provided by the proxy model, and these contain no information about the source model or the locations of the original items in that model.
data.
structure of the source model. To provide custom sorting behavior, reimplement the
Model subclasses need to provide implementations of many of the virtual functions defined in the
The functions that need to be implemented in a model subclass can be divided into three groups:
Item data handling: All models need to implement functions to enable views and delegates to query the dimensions of the model, examine items, and retrieve data.
Navigation and 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.
Drag and drop support and MIME type handling: Models inherit functions that control the way that internal and external drag and drop operations are performed. These functions allow items of data to be described in terms of MIME types that
other components and applications can understand.
Models can provide varying levels of access to the data they provide: They can be simple read-only components, some models may support resizing operations, and others may allow items to be edited.
To provide read-only access to data provided by a model, the following functions
must be implemented in the model's subclass:
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#flags">flags()</a>
Used by other components to obtain information about each item provided by the model. In many models, the combination of flags should include
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#data">data()</a>
Used to supply item data to views and delegates. Generally, models only need to supply data for
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#headerData">headerData()</a>
Provides views with information to show in their headers. The information is only retrieved by views that can display header information.
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#rowCount">rowCount()</a>
Provides the number of rows of data exposed by the model.
subclasses).
Additionally, the following functions must be implemented in direct subclasses of
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#columnCount">columnCount()</a>
Provides the number of columns of data exposed by the model. List models do not provide this function because it is already implemented in
Editable models allow items of data to be modified, and may also provide functions to allow rows and columns to be inserted and removed. To enable editing, the following functions must be implemented correctly:
Must return an appropriate combination of flags for each item. In particular, the value returned by this function must include
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#setData">setData()</a>
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
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#setHeaderData">setHeaderData()</a>
Used to modify horizontal and vertical header information. After changing the item of data, models must emit the
All types of model can support the insertion and removal of rows. Table models and hierarchical models can also support the insertion and removal of columns. It is important to notify other components about changes to the model's dimensions both
before and after they occur. As a result, the following functions can be implemented to allow the model to be resized, but implementations must ensure that the appropriate functions are called to notify attached views and delegates:
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#insertRows">insertRows()</a>
Used to add new rows and items of data to all types of model. Implementations must call
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#beginInsertRows">beginInsertRows()</a>
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#removeRows">removeRows()</a>
Used to remove rows and the items of data they contain from all types of model. Implementations must call
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#beginRemoveRows">beginRemoveRows()</a>
before inserting new columns into any underlying data structures, and call
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#endRemoveRows">endRemoveRows()</a>
immediately afterwards.
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#insertColumns">insertColumns()</a>
Used to add new columns and items of data to table models and hierarchical models. Implementations must call
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#endInsertColumns">endInsertColumns()</a>
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#removeColumns">removeColumns()</a>
Used to remove columns and the items of data they contain from table models and hierarchical models. Implementations must call
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#endRemoveColumns">endRemoveColumns()</a>
Generally, these functions should return true if the operation was successful. However, there may be cases where the operation only partly succeeded; for example, if less than the specified number of rows could be inserted. In such cases, the model should
return false to indicate failure to enable any attached components to handle the situation.
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
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
Lazy population of model data effectively allows requests for information about the model to be deferred until it is actually needed by views.
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
items without children may be displayed incorrectly in some views until the user attempts to view the non-existent child items.
Hierarchical models need to provide functions that views can call to navigate the tree-like structures they expose, and obtain model indexes for items.
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:
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#index">index()</a>
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.
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#parent">parent()</a>
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.
The model/view classes support drag and drop operations, providing default behavior that is sufficient for many applications. However, it is also possible to customize the way items are encoded during drag and drop operations, whether they are copied or
moved by default, and how they are inserted into existing models.
Additionally, the convenience view classes implement specialized behavior that should closely follow that expected by existing developers. The
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.
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:
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#mimeData">mimeData()</a>
This function can be reimplemented to return data in formats other than the default
application/x-qabstractitemmodeldatalist internal MIME type.
For many models, it is useful to provide the contents of items in common format represented by MIME types such as
text/plain and image/png. Note that images, colors and HTML documents can easily be added to a
When a drag and drop operation is performed over a view, the underlying model is queried to determine which types of operation it supports and the MIME types it can accept. This information is provided by the
When serialized item data is dropped onto a view, the data is inserted into the current model using its implementation of
siblings of an item, or as children of that item.
These functions enable the model to automatically insert new data using the existing implementation provided by
Allows the new rows and columns to be populated with items.
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#setItemData">setItemData()</a>
This function provides more efficient support for populating new items.
To accept other forms of data, these functions must be reimplemented:
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#supportedDropActions">supportedDropActions()</a>
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#mimeTypes">mimeTypes()</a>
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.
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#dropMimeData">dropMimeData()</a>
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:
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#removeRow">removeRow()</a>
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html#removeColumn">removeColumn()</a>
Another example would be dynamically populated tree models, where we reimplement
These classes use the model/view design pattern in which the underlying data (in the model) is kept separate from the way the data is presented and manipulated by the user (in the view).
<a href="http://doc.qt.digia.com/4.7/qabstractitemdelegate.html">QAbstractItemDelegate</a>
Used to display and edit data items from a model
<a href="http://doc.qt.digia.com/4.7/qabstractitemmodel.html">QAbstractItemModel</a>
The abstract interface for item model classes
<a href="http://doc.qt.digia.com/4.7/qabstractitemview.html">QAbstractItemView</a>
The basic functionality for item view classes
<a href="http://doc.qt.digia.com/4.7/qabstractlistmodel.html">QAbstractListModel</a>
Abstract model that can be subclassed to create one-dimensional list models
<a href="http://doc.qt.digia.com/4.7/qabstractproxymodel.html">QAbstractProxyModel</a>
Base class for proxy item models that can do sorting, filtering or other data processing tasks
<a href="http://doc.qt.digia.com/4.7/qabstracttablemodel.html">QAbstractTableModel</a>
Abstract model that can be subclassed to create table models
<a href="http://doc.qt.digia.com/4.7/qcolumnview.html">QColumnView</a>
Model/view implementation of a column view
<a href="http://doc.qt.digia.com/4.7/qdatawidgetmapper.html">QDataWidgetMapper</a>
Mapping between a section of a data model to widgets
<a href="http://doc.qt.digia.com/4.7/qfilesystemmodel.html">QFileSystemModel</a>
Data model for the local filesystem
<a href="http://doc.qt.digia.com/4.7/qheaderview.html">QHeaderView</a>
Header row or header column for item views
<a href="http://doc.qt.digia.com/4.7/qitemdelegate.html">QItemDelegate</a>
Display and editing facilities for data items from a model
<a href="http://doc.qt.digia.com/4.7/qitemeditorcreator.html">QItemEditorCreator</a>
Makes it possible to create item editor creator bases without subclassing QItemEditorCreatorBase
<a href="http://doc.qt.digia.com/4.7/qitemeditorcreatorbase.html">QItemEditorCreatorBase</a>
Abstract base class that must be subclassed when implementing new item editor creators
<a href="http://doc.qt.digia.com/4.7/qitemeditorfactory.html">QItemEditorFactory</a>
Widgets for editing item data in views and delegates
<a href="http://doc.qt.digia.com/4.7/qitemselection.html">QItemSelection</a>
Manages information about selected items in a model
<a href="http://doc.qt.digia.com/4.7/qitemselectionmodel.html">QItemSelectionModel</a>
Keeps track of a view's selected items
<a href="http://doc.qt.digia.com/4.7/qitemselectionrange.html">QItemSelectionRange</a>
Manages information about a range of selected items in a model
<a href="http://doc.qt.digia.com/4.7/qlistview.html">QListView</a>
List or icon view onto a model
<a href="http://doc.qt.digia.com/4.7/qlistwidget.html">QListWidget</a>
Item-based list widget
<a href="http://doc.qt.digia.com/4.7/qlistwidgetitem.html">QListWidgetItem</a>
Item for use with the QListWidget item view class
<a href="http://doc.qt.digia.com/4.7/qmodelindex.html">QModelIndex</a>
Used to locate data in a data model
<a href="http://doc.qt.digia.com/4.7/qpersistentmodelindex.html">QPersistentModelIndex</a>
<a href="http://doc.qt.digia.com/4.7/qsortfilterproxymodel.html">QSortFilterProxyModel</a>
Support for sorting and filtering data passed between another model and a view
<a href="http://doc.qt.digia.com/4.7/qstandarditem.html">QStandardItem</a>
Item for use with the QStandardItemModel class
<a href="http://doc.qt.digia.com/4.7/qstandarditemeditorcreator.html">QStandardItemEditorCreator</a>
The possibility to register widgets without having to subclass QItemEditorCreatorBase
<a href="http://doc.qt.digia.com/4.7/qstandarditemmodel.html">QStandardItemModel</a>
Generic model for storing custom data
<a href="http://doc.qt.digia.com/4.7/qstringlistmodel.html">QStringListModel</a>
Model that supplies strings to views
<a href="http://doc.qt.digia.com/4.7/qstyleditemdelegate.html">QStyledItemDelegate</a>
<a href="http://doc.qt.digia.com/4.7/qtableview.html">QTableView</a>
Default model/view implementation of a table view
<a href="http://doc.qt.digia.com/4.7/qtablewidget.html">QTableWidget</a>
Item-based table view with a default model
<a href="http://doc.qt.digia.com/4.7/qtablewidgetitem.html">QTableWidgetItem</a>
Item for use with the QTableWidget class
<a href="http://doc.qt.digia.com/4.7/qtablewidgetselectionrange.html">QTableWidgetSelectionRange</a>
Way to interact with selection in a model without using model indexes and a selection model
<a href="http://doc.qt.digia.com/4.7/qtreeview.html">QTreeView</a>
Default model/view implementation of a tree view
<a href="http://doc.qt.digia.com/4.7/qtreewidget.html">QTreeWidget</a>
Tree view that uses a predefined tree model
<a href="http://doc.qt.digia.com/4.7/qtreewidgetitem.html">QTreeWidgetItem</a>
Item for use with the QTreeWidget convenience class
<a href="http://doc.qt.digia.com/4.7/qtreewidgetitemiterator.html">QTreeWidgetItemIterator</a>
Way to iterate over the items in a QTreeWidget instance
<a href="http://doc.qt.digia.com/4.7/itemviews-dirview.html">Dir View</a>
<a href="http://doc.qt.digia.com/4.7/itemviews-spinboxdelegate.html">Spin Box Delegate</a>
<a href="http://doc.qt.digia.com/4.7/itemviews-pixelator.html">Pixelator</a>
<a href="http://doc.qt.digia.com/4.7/itemviews-simpletreemodel.html">Simple Tree Model</a>
<a href="http://doc.qt.digia.com/4.7/itemviews-chart.html">Chart</a>