Creating Models from Scratch
From qtnode
This is a howto for building a model. The model we are choosing to build is called QSettingsModel, which is designed to present QSettings information in a Model format for easy browsing and editing. When done, we should have something similar to a registry editor when QSettingsModel is coupled with the QTreeView object.
Contents |
Overview
Below is an image of how the QSettingsModel can be used with QTreeView:

The data for the above image came from a simple qsmtest.ini file containing the following:
[General] test1=one test2=two test3=tre test4=qua [group%201] group%202\test1=g2 won group%202\test2=g2 too group%202\test3=g2 tree group%202\test4=g2 quad test1=g1 uni test2=g1 die test3=g1 tre test4=g1 qua [group%203] test1=g3 uni test2=g3 die test3=g3 tre test4=g3 qua
The code to get that window open is as follows:
QSettingsModel * qsm = new QSettingsModel("qsmtest.ini",QSettings::NativeFormat);
QTreeView * view = new QTreeView;
view->setModel(qsm);
view->setWindowTitle("Settings Model");
view->show();
Before reading through this document you should review the Trolltech Document on Creating a Simple Tree Model for a rudimentary explanation of how to build your own model. I've basically followed that document and have changed direction as needed to accomplish the task of building the QSettingsModel.
Step 1 - The Skeleton Header File
Models can be built upon several Model sub-classes. The model class that we will be inheriting from is QAbstractItemModel, which is considered an Abstract Class and, more-or-less, the root class of all the model classes. Given that, as we implement our new QSettingsModel class we will find that there are a few methods that we must implement - everything else is optional... important, but optional.
Consider the following code:
#ifndef QSETTINGSMODEL_H #define QSETTINGSMODEL_H /* ** Class for viewing QSettings like a model. ** */ class QSettingsModel : public QAbstractItemModel { Q_OBJECT // required for object interface public: /* ** Define Constructor for internal QSettings. ** */ QSettingsModel ( QString filename, // file where the settings are stored QSettings::Format format, // format of the file QObject * parent = 0 // parent object (defaults to none) ); /* ** Destructor ** */ ~QSettingsModel(); /******************************************************************** ** ** AbstractItemModel Interface (required methods) */ QModelIndex index (int row, int col, const QModelIndex & parent = QModelIndex() ) const; QModelIndex parent (const QModelIndex & child ) const; int rowCount (const QModelIndex & parent = QModelIndex() ) const; int columnCount (const QModelIndex & parent = QModelIndex() ) const; QVariant data (const QModelIndex & index, int role = Qt::DisplayRole ) const; private: /* ** Keep a pointer to the qsettings object that contains all the ** data we'll be accessing. ** */ QSettings * qsettings; }; // endclass QSettingsModel #endif // #ifndef QSETTINGSMODEL_H
This is about the minimum amount of code that you would need to get a class to inherit from QAbstractItemModel. The member functions (methods) that are required are index, parent, rowCount, columnCount, data.
Also, this object holds a pointer to the QSettings object, where the settings are being stored. There are probably many arguments on the pros and cons of storing data within the models themselves, or associating the data directly within the models. It's a matter of choice. To keep things simple at this point I've just placed the pointer to QSettings here.
The Skeleton Implementation File
This file (qsettingsmodel.cpp) contains the implementation for the QSettingsModel object.
Here is the constructor:
QSettingsModel::QSettingsModel
(
QString filename, // file where the settings are stored
QSettings::Format format, // format of the file
QObject * parent // parent object (defaults to none)
)
: QAbstractItemModel(parent) // initialize the parent class
{
/*
** Create a new QSettings object pointed to the requested filename
** using the requested format.
**
*/
qsettings = new QSettings(filename,format);
}
This is about as bare bones of a constructor you can get (trust me, there'll be more), but it works. It gets the object initialized and ready to run.
Since we're new to the whole Model/View theme, what I'm going to do is get the primary functions written so that I can simply see what's going on with the model system.
Here's some quick code to get things started:
QModelIndex QSettingsModel::index
(
int row,
int col,
const QModelIndex & parent
) const
{
qDebug("index row=%d col=%d",row,col);
return QModelIndex();
}
QModelIndex QSettingsModel::parent
(
const QModelIndex & child
) const
{
qDebug("parent");
return QModelIndex();
}
int QSettingsModel::rowCount
(
const QModelIndex & parent
) const
{
qDebug("rowCount");
return 0;
}
int QSettingsModel::columnCount
(
const QModelIndex & parent
) const
{
qDebug("columnCount");
return 2;
}
QVariant QSettingsModel::data
(
const QModelIndex & index,
int role
) const
{
qDebug("data role=%d",role);
return QVariant();
}
These implementations allow me to do one simple thing... compile a test program. And here would be that test program... repeated for your pleasure...
QSettingsModel * qsm = new QSettingsModel("qsmtest.ini",QSettings::NativeFormat);
QTreeView * view = new QTreeView;
view->setModel(qsm);
view->setWindowTitle("Settings Model");
view->show();
Step 3 -
More to come... in my spare time (ooo, spare time! what's that?)
Related Links
References
Trolltech Model/View Programming
Trolltech Document on Creating a Simple Tree Model
Author
Like I said, this is a work in progress. It comes from my first attempt to understand the internals of the model/view architecture and implement a real model that I actually had a use for. It is inspired from the properties editor in Designer which I was hoping to build into my project, so with any luck, one day, this module/tutorial will achieve the capabilities of the Designer property editor component.
Mark Petryk - love that c++