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