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.2

    ApplicationWindow {
    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.



  • @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: blocknum

                MouseArea {
                    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 defined

    Here 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().



  • @jpnurmi said:

    QAbstractListModel

    That fixed it! Thank you so much!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.