删除行时QModelIndex变为无效

时间:2015-07-22 16:54:37

标签: c++ qt qabstractitemmodel

我将QAbstractItemModel子类化为显示QTreeView中的项目,并且在此子类(projectModel)中,我有一个函数来删除树视图中当前选择的索引。 Component是用于表示模型的所有成员的类:

void
projectModel::deleteComponent()
{
    QModelIndex child_index = _treeview->selectionModel()->currentIndex();
    Component* child = static_cast<Component*>(child_index.internalPointer());

    Component* parent = child->Parent();
    QModelIndex parent_index = createIndex(parent->row(), 0, parent);

    int row = child->row();

    beginRemoveRows(parent_index, row, row);
    parent->delete_child(child);
    endRemoveRows();
}

在致电beginRemoveRows之前,父母和孩子的指示和原始指针都很好;调试器显示它们指向正确的项目及其父项。但是,在调用beginRemoveRows后程序崩溃了。具体来说,它在projectModel::parent()

中崩溃了
QModelIndex
projectModel::parent(const QModelIndex &index) const
{    
    if (!index.isValid())
        return QModelIndex();

    Component* item = getItem(index);        //Fails to cast index internal pointer to a valid Component*
    Component* parentItem = item->Parent();

    if (parentItem == _rootnode)
        return QModelIndex();

    return createIndex(parentItem->row(), 0, parentItem);
}

当我打破崩溃并检查调试器输出时,它显示item函数中的变量parent()是垃圾。不知何故,我的QModelIndexdeleteComponent的调用和parent的调用之间被破坏了。我正在做的事情有什么明显的错误,或者问题可能更微妙?

1 个答案:

答案 0 :(得分:8)

这是完全可以预期的。

在您更改模型的结构之前,非持久性索引有效。结构更改是指发出其他而不是发出dataChanged的任何更改。

结构变化必须被视为索引生命周期的障碍:您必须丢弃在结构更改之前保留的任何非持久性索引。

根据调用deleteComponent的位置,可能会发生的情况是调用者持有一些索引,deleteComponent使所有索引无效,并且您从此处开始处于未定义的行为区域。< / p>

如果您希望持久性索引在结构更改中保持有效,则需要使用持久性索引,即使这样,只有在给定项目仍然存在的情况下它们才有效。如果您正在使用自己的模型,则需要明确支持持久性索引,并且模型的用户必须使用它们。