Subclass QAbstractListModel - count issue
-
Hello,
I have an issue using subclass of QAbstractListModel.
I want to use a custom model in a standard QML ListView.
The data is correctly updated but if the row size changed, the size of the listview doesn't change.Here is my code (simplified):
QMLListView{ id: rectangleListMenu anchors.fill: parent clip: true interactive: height < contentHeight ScrollBar.vertical: ScrollBar { id: scrollBar policy: rectangleListMenu.interactive?ScrollBar.AlwaysOn:ScrollBar.AlwaysOff } model: g_rectangleModel delegate: Rectangle{ width: rectangleListMenu.width - (rectangleListMenu.interactive ? (scrollBar.width + rectangleListMenu.anchors.margins) : 0) height: rectangleListMenu.itemHeight color: s_recColor } }
rectangleModel.h
class RectangleModel: public QAbstractListModel { Q_OBJECT public: enum RectangleModelRoles{ RectangleColorRole = Qt::UserRole + 1 }; explicit RectangleModel(QObject *op_parent = nullptr); ~RectangleModel(); int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QHash<int, QByteArray> roleNames() const override; void gv_updateRectangleList(QList<QString*> newRectangleColorList); private: QList<QString*> m_rectangleColorList; };
rectangleModel.cpp
#include "rectangleModel.h" RectangleModel::RectangleModel(QObject *op_parent) { Q_UNUSED(op_parent) } int RectangleModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent) return m_rectangleColorList.length(); } QVariant RectangleModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } if(index.row() >= m_rectangleColorList.length()) { return QVariant(); } switch(role) { case(RectangleColorRole): return m_rectangleColorList.at(index.row()); break; default: return QVariant(); break; } } QHash<int, QByteArray> RectangleModel::roleNames() const { static QHash<int, QByteArray> mapping{ {RectangleColorRole, "s_recColor"}, }; return mapping; } void RectangleModel::gv_updateRectangleList(QList<QString*> newRectangleColorList) { m_rectangleColorList = newRectangleColorList; const QModelIndex startIndex = index(0,0); const QModelIndex stopIndex = index(m_rectangleColorList.size()-1,0); emit dataChanged(startIndex,stopIndex); } RectangleModel::~RectangleModel(){}
I tried multiple things:
- Adding a count Q_PROPERTY with countChanged signal
- Removing rows and emitting beginRemoveRows and endRemoveRows then add new rows with related signals
- Emitting layoutChanged
But without any success...
Thanks for your help.
-
You are returning wrong count in
rowCount()
- it should be the size ofm_rectangleColorList
but you return size ofm_closeParcelList
(different variable).When changing items you absolutely should use
begin...()
andend...()
methods, without them theListView
will not know that anything has changed. -
@DeltaSim said in Subclass QAbstractListModel - count issue:
RectangleModel::gv_updateRectangleList(QList<QString*> newRectangleColorList)
IN this method, you are replacing all items, so you should call:
beginResetModel(); m_rectangleColorList = newRectangleColorList; endResetModel();
-
@sierdzio thanks for your feedback.
I tried to emit those signals but the list size still doesn't change and I have this error:
QObject::connect: Cannot queue arguments of type 'QQmlChangeSet' (Make sure 'QQmlChangeSet' is registered using qRegisterMetaType().)
-
They are not signals.
I don't think QML can handle a pointer to QString. Try changing your data to a QStringList.
Also, your constructor does not initialize the base class. This is very likely the root cause of your troubles.
RectangleModel::RectangleModel(QObject *op_parent) : QAbstractListModel(parent) { }
Regarding the error:
QObject::connect: Cannot queue arguments of type 'QQmlChangeSet'
I don't know where it comes from, the code you shared does not seem to try to do anything QQmlChangeSet.
-
Ok I created a small project with only this part using resetModel functions and it works.
The problem is actually a thread problem.
The function "gv_updateRectangleList" is called in another tread this is why I have the QQmlChangeSet... error.On main.ccp I create the model and the thread
RectangleModel * p_rectangleModel = new RectangleModel(); DummyThread *p_dummyThread = new DummyThread(p_rectangleModel); p_dummyThread->start();
And on the run I call the update function, example:
void DummyThread::run() { QList<QString*> rectList; while(true) { rectList.clear(); if(msn_rectCount < 20) { msn_rectCount++; } else { msn_rectCount = 1; } for(int i=0; i<msn_rectCount; i++) { QString *s_string = new QString("#0000FF"); rectList.push_back(s_string); } mp_rectangleModel->gv_updateRectangleList(rectList); sleep(3); } }
-
Use signals and slots to communicate between threads, then it won't cause you any problems.