A SectionScroller essentially allows quick scrolling in large lists. Though, there are some pitfalls when you want to use a custom C++/Qt based model with a SectionScroller in QML. Please note that this should work with a QAbstractItemModel based model class as well as with a model class derived from QAbstractList model. Though, I didn’t test an implementation based on QAbstractItemModel yet.
Here is an example of a QML SectionScroller in action:
The working principle of a SectionScroller is pretty simple. You simply create a ListModel, a ListView, and a SectionScroller and QML takes care of the whole magic. See the following listing for a simple example (This is an excerpt of the source code that had been used for the above screenshot.):
ListModel{
id: myModel
ListElement{ name: "foo"; category: "abc" }
ListElement{ name: "bar"; category: "abc" }
...
ListElement{ name: "12"; category: "xyz" }
...
ListElement{ name: "12"; category: "xyz" }
ListElement{ name: "34"; category: "def" }
...
ListElement{ name: "78"; category: "def" }
}
ListView {
id: myListView
anchors.fill: parent
model: myModel
delegate: Text{
text: name
font.pointSize: 30
}
section {
property: "category"
criteria: ViewSection.FullString
delegate: Rectangle {
color: "lightblue"
width: parent.width
height: childrenRect.height + 4
Text {
anchors.horizontalCenter: parent.horizontalCenter
font.pointSize: 24
text: section
}
}
}
}
SectionScroller {
listView: myListView
}
The above example uses a QML ListModel. When using a custom C++/Qt based model things are getting a little bit more complicated.
In this example the following data model is used. A simple C++/Qt class is used as entity. In the following listing only the parts relevant for this example are shown:
class Entry : public QObject
{
Q_OBJECT
Q_PROPERTY(QString category READ category WRITE setCategory NOTIFY categoryChanged)
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:
...
QString category() const { return m_category; }
QString name() const { return m_name; }
void setCategory(QString category){
m_category = category;
emit categoryChanged(category);
}
void setName(QString name){
m_name = name;
emit nameChanged(name);
}
signals:
void categoryChanged(QString);
void nameChanged(QString);
private:
QString m_category;
QString m_name;
}
This model class has two properties “name” and “category”. In the corresponding model these properties are accessible via the “name” and “category” roles.
class EntryListModel : public QAbstractListModel
{
Q_OBJECT
// Needed to make SectionScroller happy.
Q_PROPERTY(int count READ rowCount)
public:
enum EntryRoles {
NameRole = Qt::UserRole + 1,
CategoryRole = Qt::UserRole + 2,
...
}
...
// Needed to make SectionScroller happy.
Q_INVOKABLE Entry* get(int index) { return new Entry(m_entries.at(index); }
...
Q_INVOKABLE int rowCount(const QModelIndex &parent = QModelIndex()) const;
private:
QList<Entry> m_entries;
...
}
This listing already shows two important points when using a SelectionScroller with a custom model. First, the model must provide a “count” property which indicates the number of elements in the model. This can be achieved easily by using the Q_PROPERTY macro and using the “rowCount” method as accessor for the “count” property. The “rowCount” method must be implemented for a QAbstractItemModel anyways. Second, the QML (more specific the accompanying JavaScript) code expects a “get(index)” method which returns the element in the model at the given index.
Last but not least the QML/JavaScript code in the SectionScroller “backend” expects the property used as section (here “category”) to be named equal in the model item class (Entry) and the model class role.
EntryListModel::EntryListModel(QObject *parent) :
QAbstractListModel(parent)
{
QHash roles;
roles[NameRole] = "name";
/*
* Needed to make SectionScroller happy.
* Take care to give the property used for naming the
* section in the ListView the same name as in the
* model element class (here Entry, see entry.h).
*/
roles[CategoryRole] = "category";
...
setRoleNames(roles);
}

Pingback: SectionScroller vs. QAbstractProxyModel « ruedigergad