QAbstractListModel & QML



  • Hello

    I have some problems to get my qml to work with a QAbstractListModel.

    Here is my code:

    Data.h
    @
    #ifndef DATA_H
    #define DATA_H

    #include <QAbstractListModel>
    #include <QApplication>
    #include <QDebug>
    #include <QHash>
    #include <QList>
    #include <QObject>
    #include <QVariant>
    #include <QVariantMap>

    class Data : public QAbstractListModel
    {
    Q_OBJECT

    protected:
    Data(QObject *parent);

    private:
    enum Role
    {
    Role_Name = Qt::UserRole + 1,
    Role_Age
    };

    public:
    static Data* instance();

    private:
    QHash<int, QByteArray> mRoleNames;
    QList<QVariantMap> mItems;

    public:
    virtual QHash<int, QByteArray> roleNames() const;
    virtual QVariant data(const QModelIndex &index, int role) const;
    virtual int rowCount(const QModelIndex &) const;
    };

    #endif // DATA_H
    @

    Data.cpp
    @
    #include "Data.h"

    Data::Data(QObject *parent)
    : QAbstractListModel(parent)
    {
    mRoleNames[Role_Name] = "name";
    mRoleNames[Role_Age] = "age";

    for (int i = 0; i < 10; ++i)
    {
        QVariantMap item;
    
        item[mRoleNames[Role_Name]] = QString("Name %1").arg(i);
        item[mRoleNames[Role_Age]]  = i;
    
        mItems << item;
    }
    

    }

    Data *Data::instance()
    {
    static Data *p = new Data(qApp);
    return p;
    }

    QHash<int, QByteArray> Data::roleNames() const
    {
    return mRoleNames;
    }

    QVariant Data::data(const QModelIndex &index, int role) const
    {
    Q_ASSERT(index.isValid());

    if ((role >= Role_Name) && (role <= Role_Age))
    {
        return mItems[index.row()][mRoleNames[role]];
    }
    
    return QVariant();
    

    }

    int Data::rowCount(const QModelIndex &) const
    {
    return mItems.count();
    }
    @

    main.cpp
    @
    #include <QApplication>
    #include <QQmlApplicationEngine>
    #include <QtQml>

    #include "Data.h"

    int main(int argc, char *argv[])
    {
    QApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("data", Data::instance());
    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
    
    return app.exec();
    

    }
    @

    main.qml
    @
    import QtQuick 2.2
    import QtQuick.Controls 1.1

    ApplicationWindow {
    visible: true
    width: 300
    height: 300
    title: qsTr("Hello World")

    ListView {
        anchors.fill: parent
        model: data
        delegate: Text {
            text: name + ", " + age
        }
    }
    

    }
    @

    When i run the application i get this message:
    @
    QQmlExpression: Expression qrc:///main.qml:68:16 depends on non-NOTIFYable properties: QQuickListView::data
    @

    Also i see that no one methods of the Data class, except instance(), are called.

    What is wrong with my code?



  • You hava to implement the notification if the data changed.

    There is a good tutorial about C++ models to QML "see: ":http://lemirep.wordpress.com/2013/04/06/a-practical-case-exposing-qt-c-models-to-qml/



  • Thanks for your reply.

    But in the "documentation":http://qt-project.org/doc/qt-5/qtquick-modelviewsdata-cppmodels.html#qabstractitemmodel i found next:
    @A QAbstractItemModel can also automatically notify a QML view when the model data changes.@



  • I modified my Data.cpp:
    @
    #include "Data.h"

    Data::Data(QObject *parent)
    : QAbstractListModel(parent)
    {
    qDebug() << "Data::Data()";
    mRoleNames[Role_Name] = "name";
    mRoleNames[Role_Age] = "age";

    const int n = 10;
    
    beginInsertRows(QModelIndex(), 0, n);
    
    for (int i = 0; i < n; ++i)
    {
        QVariantMap item;
    
        item[mRoleNames[Role_Name]] = QString("Name %1").arg(i);
        item[mRoleNames[Role_Age]]  = i;
    
        mItems << item;
    }
    qDebug() << mItems.count();
    
    endInsertRows();
    

    }

    Data *Data::instance()
    {
    qDebug() << "Data::instance()";
    static Data *p = new Data(qApp);
    return p;
    }

    QHash<int, QByteArray> Data::roleNames() const
    {
    qDebug() << "Data::roleNames()";
    return mRoleNames;
    }

    QVariant Data::data(const QModelIndex &index, int role) const
    {
    qDebug() << "Data::data()";
    Q_ASSERT(index.isValid());

    if ((role >= Role_Name) && (role <= Role_Age))
    {
        return mItems[index.row()][mRoleNames[role]];
    }
    
    return QVariant();
    

    }

    int Data::rowCount(const QModelIndex &) const
    {
    qDebug() << "Data::rowCount()" << mItems.count();
    return mItems.count();
    }
    @

    So now i get this output:
    @
    Data::instance()
    Data::Data()
    Data::rowCount() 0
    10
    QQmlExpression: Expression qrc:///main.qml:76:16 depends on non-NOTIFYable properties: QQuickListView::data
    @

    Strange...



  • Change the model name in QML's ListView to something other than data, seems like it is referring to Item's "data":http://qt-project.org/doc/qt-5/qml-qtquick-item.html#data-prop property. I renamed my working model to data and had the same error.



  • Oh, right. Thanks


Log in to reply
 

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