Remove rows from QAbstractListModel

丶灬走出姿态 提交于 2019-11-29 07:19:29

The code below works fine for me. Your problem is probably elsewhere. This is for Qt 5 due to use of Qt Quick Controls.

There are two views accessing the same model, this visually confirms that the model emits proper signals to inform the views of the changes. The page additions and removals are done via the standard insertRows and removeRows methods, exported through Q_INVOKABLE. There's no need for any custom methods on this model, so far. The Q_INVOKABLE is a workaround for some missing functionality for the interface between QML and QAbstractItemModel.

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickWindow>
#include <QAbstractListModel>
#include <QQmlContext>
#include <QtQml>

class GPage : public QObject {
    Q_OBJECT
    Q_PROPERTY(QString name NOTIFY nameChanged MEMBER m_name)
    Q_PROPERTY(int number NOTIFY numberChanged MEMBER m_number)
    QString m_name;
    int m_number;
public:
    GPage(QObject * parent = 0) : QObject(parent), m_number(0) {}
    GPage(QString name, int number, QObject * parent = 0) :
        QObject(parent), m_name(name), m_number(number) {}
    Q_SIGNAL void nameChanged(const QString &);
    Q_SIGNAL void numberChanged(int);
};

class PageModel : public QAbstractListModel {
    Q_OBJECT
    QList<GPage*> m_pageList;
public:
    PageModel(QObject * parent = 0) : QAbstractListModel(parent) {}
    ~PageModel() { qDeleteAll(m_pageList); }
    int rowCount(const QModelIndex &) const Q_DECL_OVERRIDE {
        return m_pageList.count();
    }
    QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE {
        if (role == Qt::DisplayRole || role == Qt::EditRole) {
            return QVariant::fromValue<QObject*>(m_pageList.at(index.row()));
        }
        return QVariant();
    }
    bool setData(const QModelIndex &index, const QVariant &value, int role) Q_DECL_OVERRIDE {
        Q_UNUSED(role);
        GPage* page = value.value<GPage*>();
        if (!page) return false;
        if (page == m_pageList.at(index.row())) return true;
        delete m_pageList.at(index.row());
        m_pageList[index.row()] = page;
        QVector<int> roles;
        roles << role;
        emit dataChanged(index, index, roles);
        return true;
    }
    Q_INVOKABLE bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE {
        Q_UNUSED(parent);
        beginInsertRows(QModelIndex(), row, row + count - 1);
        for (int i = row; i < row + count; ++ i) {
            QString const name = QString("Page %1").arg(i + 1);
            GPage * page = new GPage(name, i + 1, this);
            m_pageList.insert(i, page);
            QQmlEngine::setObjectOwnership(page, QQmlEngine::CppOwnership);
        }
        endInsertRows();
        return true;
    }
    Q_INVOKABLE bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE {
        Q_UNUSED(parent);
        beginRemoveRows(QModelIndex(), row, row + count - 1);
        while (count--) delete m_pageList.takeAt(row);
        endRemoveRows();
        return true;
    }
};

int main(int argc, char *argv[])
{
    PageModel model1;
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    model1.insertRows(0, 1);
    engine.rootContext()->setContextProperty("model1", &model1);
    qmlRegisterType<GPage>();
    engine.load(QUrl("qrc:/main.qml"));
    QObject *topLevel = engine.rootObjects().value(0);
    QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
    window->show();
    return app.exec();
}

#include "main.moc"

main.qml

import QtQuick 2.0
import QtQml.Models 2.1
import QtQuick.Controls 1.0

ApplicationWindow {
    width: 300; height: 300
    Row {
        width: parent.width
        anchors.top: parent.top
        anchors.bottom: column.top
        Component {
            id: commonDelegate
            Rectangle {
                width: view.width
                implicitHeight: editor.implicitHeight + 10
                color: "transparent"
                border.color: "red"
                border.width: 2
                radius: 5
                TextInput {
                    id: editor
                    anchors.margins: 1.5 * parent.border.width
                    anchors.fill: parent
                    text: edit.name // "edit" role of the model, to break the binding loop
                    onTextChanged: {
                        display.name = text;
                        model.display = display
                    }
                }
            }
        }
        ListView {
            id: view
            width: parent.width / 2
            height: parent.height
            model: DelegateModel {
                id: delegateModel1
                model: model1
                delegate: commonDelegate
            }
            spacing: 2
        }
        ListView {
            width: parent.width / 2
            height: parent.height
            model: DelegateModel {
                model: model1
                delegate: commonDelegate
            }
            spacing: 2
        }
    }
    Column {
        id: column;
        anchors.bottom: parent.bottom
        Row {
            Button {
                text: "Add Page";
                onClicked: model1.insertRows(delegateModel1.count, 1)
            }
            Button {
                text: "Remove Page";
                onClicked: model1.removeRows(pageNo.value - 1, 1)
            }
            SpinBox {
                id: pageNo
                minimumValue: 1
                maximumValue: delegateModel1.count;
            }
        }
    }
}

main.qrc

<RCC>
    <qresource prefix="/">
        <file>main.qml</file>
    </qresource>
</RCC>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!