Clearing elements from a QML ListView
-
I have a ListView which uses a C++ model which is populated w/data from a backstore(a SQLite db, in this case). I am now able to correctly bind the model to the view and populate the list. However, when I try to refresh the list(through a slot attached to a Button in the QML), the ListView successfully clears but I am not able to re-load any data on this or any subsequent attempts.
I am implementing QAbstractItemModel::removeRows but this does not seem to be working correctly. I suspect there may be some QML property I am missing on the ListView object, such as an index counter or something which controls this. I have confirmed that my model correctly contains data when I re-fresh the model. It is just now being displayed in the view.
My QML code is:
import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.12 Rectangle { visible: true width: 640 height: 480 Button { id: button x: 49 y: 6 text: qsTr("View Color Libraries") onClicked: colorLibraryViewModel.loadColorLibraries(); } ColorLibrariesList { width: 532 height: 324 anchors.centerIn: parent } }
import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.3 import QtGraphicalEffects 1.0 ColumnLayout { Frame { Layout.fillWidth: true ListView { id: listView x: 49 y: 78 implicitWidth: 250 implicitHeight: 250 clip: true model: colorLibraryListModel delegate: RowLayout { width: parent.width Text { text: name } Image { source: type } Text { text: isReadOnly } } } } }
My view/model class, as I call it(which handles the binding of my model to the QQmlContext), is defined and implemented as such:
#ifndef COLORLIBRARYVIEWMODEL_H #define COLORLIBRARYVIEWMODEL_H #include <QObject> #include <QQuickView> #include "datasourceinterface.h" #include "ColorLibraryListModel.h" class ColorLibraryViewModel : public QObject { Q_OBJECT public: ColorLibraryViewModel(QQmlContext* ctxt, DataSourceInterface *dataSource); ColorLibraryViewModel(){} Q_INVOKABLE void loadColorLibraries(); signals: //void librariesLoaded(); public slots: private: DataSourceInterface * _DataSource; QQmlContext * _ctxt; ColorLibraryListModel _colorLibraryListModel; void initialize(); }; #endif // COLORLIBRARYVIEWMODEL_H
#include "colorlibraryviewmodel.h" #include "colorlibrariesform.h" #include "ColorLibraryListModel.h" #include "generallistitem.h" #include "datasourceinterface.h" #include <QQmlContext> ColorLibraryViewModel::ColorLibraryViewModel(QQmlContext *ctxt, DataSourceInterface *dataSource) { _DataSource = dataSource; _ctxt = ctxt; initialize(); } void ColorLibraryViewModel::initialize() { _ctxt->setContextProperty("colorLibraryListModel", &_colorLibraryListModel); } void ColorLibraryViewModel::loadColorLibraries() { ColorLibrariesForm colorLibrariesForm; colorLibrariesForm.Initialize(_DataSource, false, false); QVector<GeneralListItem> m_generalListItems; colorLibrariesForm.GetListItems(m_generalListItems); // Clear any previously loaded data if(_colorLibraryListModel.rowCount() > 0) _colorLibraryListModel.removeRows(0, _colorLibraryListModel.rowCount()); foreach(GeneralListItem m_generalListItem, m_generalListItems){ QIcon type = QIcon(":Images/Images/Color_Libraries_button.png") ; QString name = m_generalListItem._Name; bool isReadOnly = m_generalListItem._IsReadOnly; StandardDisplayItem m_standardDisplayItem(type, name, isReadOnly); _colorLibraryListModel.addStandardDisplayItem(m_standardDisplayItem); } }
My model which is actually bound to the ListView is defined and implemented as such:
#ifndef COLORLIBRARYLISTMODEL_H #define COLORLIBRARYLISTMODEL_H #include <QObject> #include <QAbstractListModel> #include <QStringList> #include <StandardDisplayItem.h> class ColorLibraryListModel : public QAbstractListModel { Q_OBJECT public: enum ColorLibraryRoles { NameRole, TypeRole, IsReadOnlyRole }; ColorLibraryListModel(QObject *parent = nullptr); void addStandardDisplayItem(const StandardDisplayItem &standardDisplayItem); void clearStandardDisplayItems(){m_standardDisplayItems.clear();} Qt::ItemFlags flags(const QModelIndex &index); int rowCount(const QModelIndex & parent = QModelIndex()) const; QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); signals: public slots: protected: QHash<int, QByteArray> roleNames() const; private: QList<StandardDisplayItem> m_standardDisplayItems; }; #endif // COLORLIBRARYLISTMODEL_H
#include "ColorLibraryListModel.h" #include <QAbstractListModel> ColorLibraryListModel::ColorLibraryListModel(QObject *parent) : QAbstractListModel(parent) { } QHash<int, QByteArray>ColorLibraryListModel::roleNames() const { QHash<int, QByteArray> roles; roles[NameRole]= "name"; roles[TypeRole] = "type"; roles[IsReadOnlyRole] = "isReadOnly"; return roles; } void ColorLibraryListModel::addStandardDisplayItem(const StandardDisplayItem &standardDisplayItem) { beginInsertRows(QModelIndex(), rowCount(), rowCount()); m_standardDisplayItems << standardDisplayItem; endInsertRows(); } int ColorLibraryListModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return m_standardDisplayItems.count(); } QVariant ColorLibraryListModel::data(const QModelIndex &index, int role) const { if(!index.isValid()) return QVariant(); if(index.row() < 0 || index.row() >= m_standardDisplayItems.count()) return QVariant(); const StandardDisplayItem &standardDisplayItem = m_standardDisplayItems[index.row()]; if(role == NameRole) return standardDisplayItem._name(); else if(role == TypeRole) return standardDisplayItem._type(); else if(role == IsReadOnlyRole) return standardDisplayItem._isReadOnly() ? QString("Yes") : QString("No"); return QVariant(); } bool ColorLibraryListModel::removeRows(int row, int count, const QModelIndex &parent) { Q_UNUSED(parent) beginRemoveRows(QModelIndex(), row, row+count-1); for(int currentRow=0; currentRow < count; ++currentRow) { m_standardDisplayItems.removeAt(currentRow); } endRemoveRows(); return true; }
The process is initiated through a main.cpp implementation as such:
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include <QtQuick> #include "colorlibraryviewmodel.h" #include "ColorLibraryListModel.h" #include "colorlibrariesform.h" #include "DBsource.h" #include "GeneralListDetailForm.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); QQuickView view; view.setResizeMode(QQuickView::SizeRootObjectToView); QQmlContext *ctxt = view.rootContext(); DBSource m_dbSource; ColorLibraryViewModel colorLibraryViewModel(ctxt, &m_dbSource); ctxt->setContextProperty("colorLibraryViewModel", &colorLibraryViewModel); view.setSource(QUrl("qrc:/main.qml")); view.show(); return app.exec(); }
Does anyone spot the problem based on my implementation? Many thanks in advance!