Unable to update Listview using QAbstractItemModel class
-
I am trying to update the Listview from c++ data model which is the subclass of QAbstractItemModel. When the run the program the listview is empty
During debugging I observed that the following functions are not called which I think it is required for displaying the model data to the viewQVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const;I have added the required snippets of the code below
================testmodel.h=================================
#include <QAbstractItemModel>
class Data {
QString name ;
int strength;public:
Data(QString name ,int strength); int getStrength() const; void setStrength(int value); QString getName() const; void setName(const QString &value);
};
class TestModel : public QAbstractItemModel
{
Q_OBJECTpublic:
enum Roles { nameRole = Qt::UserRole + 1, strengthRole }; explicit TestModel(QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; void addRows(Data data);
protected:
QHash<int, QByteArray> roleNames() const;private:
QList<Data> list;};
================testmodel.cpp=================================
QVariant TestModel::data(const QModelIndex &index, int role) const
{
if (index.row() < 0 || index.row() >= list.count())
return QVariant();const Data &animal = list[index.row()]; if (role == nameRole) return animal.getName(); else if (role == strengthRole) return animal.getStrength(); return QVariant();
}
void TestModel::addRows(Data data)
{
beginInsertRows(QModelIndex(), rowCount(), rowCount());
list << data;
endInsertRows();
}QHash<int, QByteArray> TestModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[nameRole] = "name";
roles[strengthRole] = "strength";
return roles;}
==============main.cpp========================================
int main(int argc, char ** argv)
{
QGuiApplication app(argc, argv);TestModel testmodel; testmodel.addRows(Data("name1",5)); testmodel.addRows(Data("name2",10)); QQuickView view; view.setResizeMode(QQuickView::SizeRootObjectToView); QQmlContext *ctxt = view.rootContext(); ctxt->setContextProperty("myModel", &testmodel); view.setSource(QUrl("qrc:view.qml")); view.show(); return app.exec();
}
==================view.qml====================================
import QtQuick 2.0
Item {
width: 200; height: 250ListView { width: 200; height: 250 anchors.fill: parent model: myModel delegate: Text { text: "mydata" + name + ", " + strength } }
}
-
@James-A
since you inherit from QAbstractItemModel you should also implement columnCount() - and return at least 1 column.
Maybe inheriting from QAbstractListModel is more suited for you? It implements a few methods for lists already. -
@raven-worx
I tried inheriting from the QAbstractListModel class and implemented columnCount() function and returned columnCount as 2 , sines there are 2 roles , but the listview is not updating after this change -
- either implement columnCount() OR inherit from QAbstractListModel
- no need to return a column count of 2, since a list always has 1 column
- each model index can return multiple roles
Does the count property in the listview change?
ListView { onCountChanged: console.log("count changed: " + count) }
-
Now I tried inheriting from QAbstractListModel class and the count property shows :
qml: count changed: 0 -
@James-A
i dont see any issue in your code. The last thing that could be wrong is the rowCount() implementation? -
Thanks for pointing it out. It was the issue with rowCount() implementation.
I commented the old code and updated as shown below , Now the Listview is updatingint TestModel::rowCount(const QModelIndex &parent) const
{
// if (!parent.isValid())
// return 0;
// return list.count();Q_UNUSED(parent); return list.count();
}
And while going through the documentation , I found the below virtual function for inserting rows into the model. But how to pass the "Data" Object to this function ?
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
I want to replace this user defined function testmodel.addRows(Data ) with the insertRows virtual function
-
@James-A
actually the following would be more accurate:int TestModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) return 0; return list.count(); }
The insertRow() method is used by other Qt classes (drag-n-drop, etc.) for example.
Going this route means calling insertRow() to add a (default) item at the given position and call setData() on that newly inserted item.So the way you are currently using is way more efficient and ok.
-
Thanks for the Update