Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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!


Log in to reply