我正在使用简单的自定义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 的顶级项目,每个项目包含一些子项目:
现在当我选择显示的项目 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()
信号时,删除模型完全正常,并使用空占位符模型重置自身