One of the major new features of Qt4 was said to be the model-view-controller environment. I eagarly waited for the release of the new Qt to see what does it offer in the concept of MVC.
What is the model-view-controller concept?
It is a programming concept which divides an information system (like a computer application) into three loosely-coupled parts. One of them, called the Model, holds the whole logic of the system. It serves data requests to other parts, feeding them data they require. It doesn’t care what do they do with it. The second part is the View — responsible for visualisation of the data obtained from the model. The third one is the controller, which integrates the two other parts, deciding how should the user interface react to user input. Typically the end user interacts with the view taking actions which cause requests to be passed to the model either changing it (read-write model) or demanding different data to be fed.
A fine example of the model-view-controller, sometimes simplified to become the model-view concept is the WebDAV protocol. The user interacts with his client (the view) which causes requests to be sent over the http protocol to the server (the controller), often containing different handlers (models) for different requests (like the SVN handler for SVN repositories) that generate the content demanded by the view. They don’t care what will the view do with the data — they only serve requests.
MVC implementation in Qt4
Qt uses the simplified approach to MVC, integrating the controller functionality in the framework itself (signals and slots, events). The user gains access only to the model and view APIs (through QAbstractItemModel and QAbstractItemView classes).
Qt already implements some usable models: QAbstractListModel, QAbstractTableModel, QDirModel, QStandardItemModel (and their derivatives) that can be used with standard views: QListView, QTableView and QTreeView. Worth noting is that Qt provides abstract models fitted for table and list views, but lacks an appropriate model for QTreeView! If one needs such a model, it can be found as one of Qt examples in the reference.
How are the models implemented?
A model can be seen as a multilevel two dimentional array. Each array contains rows and columns and each cell (model item) can have an array of children, every one of which can have an array of own children, etc. Each cell (item) is addressable by an index, consisting of a parent item, and row and column numbers. The model widely uses the index to address cells and extract information from them. With each index an id or a pointer can be assotiatied, which makes it easy to assign custom data to each item. A very nice thing is that each cell can hold an arbitrary amount of data, which can be addressed by specyfiing a so called Role the data applies to. There are some standard roles defined, like Display (which corresponds to data which is drawn as the item representation), Decoration (an icon or pixmap), ToolTip (a hint for the item) or WhatsThis (a more elaborative description of the item). Of course custom roles can be defined too.
How to implement own model?
It is easy as 1-2-3. Just subclass an appropriate model class and reimplement few simple methods:
- data – fetches data of a desired role from a cell
- index – returns a model index of a given item
- parent – returns an index of a parent of an item
- rowCount – returns the number of rows (array height) an item has
- columnCount – returns the number of columns (array width) an item has
If one wants more complex models (like an editable one), more methods need to be reimplemented (most commonly setData and flags).
Enough for today, now go and implement some models I will write more in one of the next episodes of my blog.