CopperSpice API
1.9.2
|
CopperSpice contains view classes which use a model/view architecture to manage the relationship between data and the way it is graphically presented to the user. The ideas introduced by using this approach provide a better mechanism for displaying data and processing user edits.
UI developers should be familiar with the basic usage of a List, Table, Tree components which are frequently used in GUI applications.
There are two different ways how these widgets can access their data. The traditional way involves widgets which include internal containers for storing data. This approach is intuitive, however, in many non-trivial applications, it leads to data synchronization issues.
The second approach is model/view programming, in which widgets do not maintain internal data containers. They access external data through a standardized interface and therefore avoid data duplication. This may seem complicated at first, but once you take a closer look, it is not only easy to grasp, but the many benefits of model/view programming also become clearer.
Model/View is a technology used to separate data from the view. The visual appearance of the widget classes and the view classes look similar, however they interact with data very differently.
Widget classes which use data that is contained inside the widget | |
View classes use data stored in a model |
A design pattern is general solution to a commonly occurring problem in software design. It is not considered a final or complete solution. It is a narrative for a standardized way to solve a given set of problems. For more information about this subject the book "Design Patterns - Elements of Reusable Object-Oriented Software", is considered the authority.
One of the design patterns described in this book is the Model-View-Controller (MVC) architecture which can be used when developing GUI software. The general idea centers around structuring your application using three kinds of objects.
If the view and the controller objects are combined, as they are in CopperSpice, the result is a model/view architecture. Separating the data from the view makes it easier to display the same data set in multiple views at the same time. The model/view approach also provides a way to implement new types of views, without changing the underlying data structures.
CopperSpice has delegate classes which can be used to override the way user input is processed or how the view will display certain data.
In the model/view architecture the model will communicate with a data source and provide data to the given view. The view retrieves a model index from the model to access a specific piece of data. A delegate can be used to change the appearance of the data displayed in a particular view. |
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 which provide common interfaces and in some cases, default implementations. 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.
CopperSpice has three classes which are derived from the view classes. These classes are available for the benefit of applications which rely on the older item based technology. They are not intended to be subclassed and have less flexibility than using the model/view classes. Item-based classes can not be used with a predefined model or a user defined model.
Developers are encouraged to use the model/view classes shown below instead of the item-based classes listed above. Using one of the following model/view classes with the QStandardItemModel is the simplest way to transition to a model/view design.
The following table shows an overview of the widget classes and the model/view classes.
Sample Image | Widget Classes | Model/View Classes |
---|---|---|
QListWidget | QListView | |
QTableWidget | QTableView | |
QTreeWidget | QTreeView |
Every item model inherits from the QAbstractItemModel class. This class defines an interface which is used by views and delegates to access data. The data itself does not have to be stored in the model, it can be held in a data structure or repository provided by a separate class, a file, a database, or some other application component. The QAbstractItemModel class is usually flexible enough to be used by most views which represent data in the form of list, table, or tree.
Inheriting from QAbstractListModel or QAbstractTableModel should be considered if the data is a list or a table. These classes may provide a better starting point because they provide appropriate default implementations.
This is a list of the built in CopperSpice models which can be used directly or as the base class for a custom model.
If none of these models shown above satisfy your application requirements, inherit from one of the abstract classes QAbstractItemModel, QAbstractListModel, or QAbstractTableModel to create your own custom models. This is discussed in more detail in the section about Custom Models.
The Model/view design eliminates the data consistency problems that may occur with standard widgets. This approach also makes it easier to display the same data in multiple ways, because one model can be used with different views at the same time. The most important difference is that view classes do not store data. Since view classes do not know your data's structure, you may need to provide a wrapper to make your data conform to the QAbstractItemModel interface.
Views and delegates use a model index to access the data stored within a model. As a result, only the model needs to know how to retrieve the data. As data is added and deleted the model may reorganize the internal data structures and the model indexes may become invalid or modified. You should not store a model index or use it after modifying the model data.
If a long term reference to a piece of data is required, a persistent model index must be created. Temporary model indexes are provided by the QModelIndex class and persistent model indexes are provided by the QPersistentModelIndex class.
To obtain a model index corresponding to some data, three properties must be specified to the model. The model index of the parent is only required when the model is a tree.
A model will notify any attached views about changes to data by emitting various signals. For example, QAbstractItemModel::rowsRemoved() is emitted after a row or groups of rows has been removed from the model.
QAbstractItemDelegate is the abstract base class for delegates in the model/view architecture. The default delegate implementation is provided by QStyledItemDelegate, and this is used as the default delegate by the CopperSpice standard views. However, QStyledItemDelegate and QItemDelegate are independent alternatives to painting and providing editors for items in views. The difference between them is that QStyledItemDelegate uses the current style to paint its items. We therefore recommend using QStyledItemDelegate as the base class when implementing custom delegates or when working with CopperSpice style sheets.
Delegates are described in the section Delegate Classes.
There are two ways of implementing sorting in the model/view architecture.
(1) One way is to provide a method which overrides the QAbstractItemModel::sort() method.
(2) Another way is to use a proxy model to transform the structure of your model before presenting the data in the view. This is covered in detail in the section on Proxy Model.
With either approach, methods like QTableView::sortByColumn() and QTreeView::sortByColumn() can be used to define the sort order
To allow the user to set the sort order by clicking on a column header, connect the QHeaderView::sortIndicatorChanged() signal to the QTableView::sortByColumn() slot or the QTreeView::sortByColumn() slot, respectively.