Defining roles in QAbstractItemModel
-
I'm having issues with QAbstractItemModel roles. I have test code, but I can't seem to figure out how to display data using the roles.
Here's the code.
main.cpp:
#include <QGuiApplication>
#include <QQmlApplicationEngine>#include <QtQml>
#include <display.h>
#include <modelclass.h>#include <string>
using namespace std;int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);QQmlApplicationEngine engine; ModelClass mc; for (int i = 0; i < 10; ++i) { QString s {"index"}; QModelIndex mi {}; QVariant v {s}; mc.setData(mi.child(i, 1), v, mc.BlockNum); } engine.rootContext()->setContextProperty("mc", &mc); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec();
}
modelclass.h:
#ifndef MODELCLASS_H
#define MODELCLASS_H#include <QObject>
#include <QAbstractListModel>
#include <QStringListModel>class ModelClass : public QAbstractItemModel
{
Q_OBJECT
public:
ModelClass();enum ModelRoles { BlockNum = Qt::UserRole + 1 }; int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; QModelIndex parent(const QModelIndex & index = QModelIndex()) const; QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const; QHash<int, QByteArray> roleNames() const;
};
#endif // MODELCLASS_H
modelclass.cpp:
#include "modelclass.h"ModelClass::ModelClass()
{}
int ModelClass::rowCount(const QModelIndex &parent) const {
return 10;
}int ModelClass::columnCount(const QModelIndex &parent) const
{
return 1;
}QVariant ModelClass::data(const QModelIndex & index, int role) const {
return QVariant();
}QModelIndex ModelClass::parent(const QModelIndex & index) const {
return index;
}QModelIndex ModelClass::index(int row, int column, const QModelIndex & parent) const {
return parent;
}QHash<int, QByteArray> ModelClass::roleNames() const {
QHash<int, QByteArray> roles;
roles[BlockNum] = "blocknum";
return roles;
}main.qml:
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.2
import QtQuick.Dialogs 1.2ApplicationWindow {
id: mainWindow
visible: true
width: 640
height: 480
title: qsTr("Block Explorer")GridView { id: list model: mc anchors.fill: parent delegate: Text { text: blocknum MouseArea { anchors.fill: parent onClicked: { list.currentIndex = index; messageDialog.show(display); } } } highlight: Rectangle { color: 'grey' } focus: true keyNavigationWraps: true Keys.onPressed: { var pageDown = currentIndex+10; var pageUp = currentIndex-10; if (event.key === Qt.Key_PageDown && event.modifiers === Qt.NoModifier) { currentIndex = pageDown >= count ? count-1 : pageDown; event.accepted = true; } if (event.key === Qt.Key_PageUp && event.modifiers === Qt.NoModifier) { currentIndex = pageUp < 0 ? 0 : pageUp; event.accepted = true; } } } MessageDialog { id: messageDialog title: qsTr("May I have your attention, please?") function show(caption) { messageDialog.text = caption; messageDialog.open(); } }
}
Thanks!
Ryan -
QAbstractItemModel is a model interface. It doesn't store any data. When you implement the interface, it's up to you to decide how the data is stored. For a read-only model, you would implement data() so that it reurns values from an internal data structure, which could be a QList or QVector, for instance. If you want to make the model read-write, you need to implement setData() to store the values into the internal data structure of your choice.
PS. For a simple list model, QAbstractListModel offers a little extra convenience. It implements columnCount() and index() for you, so you don't need to bother with them.
-
QAbstractItemModel is a model interface. It doesn't store any data. When you implement the interface, it's up to you to decide how the data is stored. For a read-only model, you would implement data() so that it reurns values from an internal data structure, which could be a QList or QVector, for instance. If you want to make the model read-write, you need to implement setData() to store the values into the internal data structure of your choice.
PS. For a simple list model, QAbstractListModel offers a little extra convenience. It implements columnCount() and index() for you, so you don't need to bother with them.
-
@jpnurmi How do roles factor in? Would data() return the QVector of the rows, and the roleNames return what position in the vector the columns are? For instance 0 = blocknum
-
data() returns data for the given index and role. For example
QVariant ModelClass::data(const QModelIndex & index, int role) const { if (!index.isValid() && role != BlockNum) return QVariant(); return m_blockNums.at(index.row()); }
@jpnurmi how do you register the roles?
I want to do something like this:
GridView {
id: list
model: mc
anchors.fill: parent
delegate: Text {
text: blocknumMouseArea { anchors.fill: parent onClicked: { list.currentIndex = index; messageDialog.show(display); } } }
-
@jpnurmi how do you register the roles?
I want to do something like this:
GridView {
id: list
model: mc
anchors.fill: parent
delegate: Text {
text: blocknumMouseArea { anchors.fill: parent onClicked: { list.currentIndex = index; messageDialog.show(display); } } }
-
It looks like you have already roleNames() implemented. That's enough to make the role visible to QML. The framework will call data() with the appropriate index and role.
@jpnurmi I keep getting the following error:
qrc:/main.qml:44: ReferenceError: blocknum is not definedHere is my code for roleNames():
QHash<int, QByteArray> ModelClass::roleNames() const {
QHash<int, QByteArray> roles;
roles[BlockNum] = "blocknum";
return roles;
} -
@jpnurmi I keep getting the following error:
qrc:/main.qml:44: ReferenceError: blocknum is not definedHere is my code for roleNames():
QHash<int, QByteArray> ModelClass::roleNames() const {
QHash<int, QByteArray> roles;
roles[BlockNum] = "blocknum";
return roles;
}I can't spot any mistake in roleNames(), but how does the rest of the code look like now? In the first snippet, index() and parent() seemed wrong. Have you switched to QAbstractListModel? Then you can simply remove your reimplementations of index(), parent() and columnCount().
-
I can't spot any mistake in roleNames(), but how does the rest of the code look like now? In the first snippet, index() and parent() seemed wrong. Have you switched to QAbstractListModel? Then you can simply remove your reimplementations of index(), parent() and columnCount().