从自定义QAbstractItemModel树模型中删除行

时间:2015-01-11 14:01:43

标签: c++ qt

我正在使用简单的自定义QAbstractItemModel以及从中删除行时遇到奇怪的崩溃。

模型

假设以下基于QAbstractItemModel的简单树:

#include <QAbstractItemModel>
#include <QModelIndex>
#include <QStringList>
#include <QVariant>
#include <QString>
#include <QObject>

class UnitsModel:
    public QAbstractItemModel {

    Q_OBJECT

    public:
        UnitsModel(QObject *parent):
            QAbstractItemModel(parent) {

            dimensions.append(qMakePair(
                QString("Length"),
                QStringList() << "Meter" << "Kilometer"));

            dimensions.append(qMakePair(
                QString("Weight"),
                QStringList() << "Gram" << "Kilogram" << "Ton"));
        }


        QModelIndex index(int row, int column, const QModelIndex &parent) const {
            if (column >= 1)
                return QModelIndex();

            if (!parent.isValid()) {
                /* Index to dimension */
                if (row < dimensions.count())
                    return createIndex(row, column, static_cast<quintptr>(-1));
            }
            else if (parent.row() < dimensions.count()) {
                /* Index to unit */
                const QStringList &units = dimensions.at(parent.row()).second;
                if (row < units.count())
                    return createIndex(row, column, static_cast<quintptr>(parent.row()));
            }

            return QModelIndex();
        }

        QModelIndex parent(const QModelIndex &child) const {
            if (!child.isValid())
                return QModelIndex();

            const int i = static_cast<qintptr>(child.internalId());
            if (i < 0) {
                /* Child is index to dimension */
                return QModelIndex();
            }
            else {
                /* Child is index to unit */
                if (i < dimensions.count())
                    return createIndex(i, 0, static_cast<quintptr>(-1));
            }

            return QModelIndex();
        }

        int rowCount(const QModelIndex &parent) const {
            if (!parent.isValid())
                return dimensions.count();

            const int i = static_cast<qintptr>(parent.internalId());
            if (i < 0) {
                /* Index to dimension */
                if (parent.row() < dimensions.count()) {
                    const QStringList &units = dimensions.at(parent.row()).second;
                    return units.count();
                }
            }
            else {
                /* Index to unit */
                return 0;
            }

            return 0;
        }

        int columnCount(const QModelIndex &parent) const {
            Q_UNUSED(parent);
            return 1;
        }

        QVariant data(const QModelIndex &index, int role) const {
            if (!index.isValid())
                return QVariant();

            const QModelIndex parent = index.parent();
            if (!parent.isValid()) {
                if (index.row() >= dimensions.count())
                    return QVariant();

                /* Index to dimension */
                if (role == Qt::DisplayRole)
                    return dimensions.at(index.row()).first;
            }
            else {
                /* Index to unit */
                const QStringList &units = dimensions.at(parent.row()).second;
                if (index.row() >= units.count())
                    return QVariant();

                if (role == Qt::DisplayRole)
                    return units.at(index.row());
            }

            return QVariant();
        }



        void removeFirstRow() {
            beginRemoveRows(QModelIndex(), 0, 0);
            dimensions.removeAt(0);
            endRemoveRows();
        }


    private:
        QList< QPair<QString, QStringList> > dimensions;
};

可以将此模型实例化并提供给QTreeView,其中它将显示两个名为 Length Weight 的顶级项目,每个项目包含一些子项目: Tree model in <code>QTreeView</code>

问题

现在当我选择显示的项目 Kilogram ,然后拨打UnitsMode::removeFirstRow()第一个顶级项目 Length 时,会被正确删除。但是,选择丢失

更糟糕的是,当再次呼叫UnitsModel::removeFirstRow()时,它会在终端上生成此警告:

QAbstractItemModel::endRemoveRows:  Invalid index ( 0 , 0 ) in model UnitsModel(0xb46c70)

更糟糕的是,如果我重新启动并选择 Kilogram 然后再调用UnitsModel::removeFirstRow()两次以删除顶级项目,则树视图会被正确清除(包括上面提到的警告)。然后在QTreeView使用时仍然在使用时删除模型在退出时崩溃。回溯追溯到QPersistentModelIndex d-tor,所以我想上面提到的警告是关于删除行时无法调整的持久性索引。当退出应用程序时,此模型索引&#39; d-tor试图从已经被破坏的模型中注销自己。

我认为警告表明了主要问题。该模型有什么问题,为什么它没有正确调整持久性指数?

作为旁注:在QTreeView连接到模型的destroyed()信号时,删除模型完全正常,并使用空占位符模型重置自身

0 个答案:

没有答案