PDA

View Full Version : QModelIndex validity during beginRemoveRows



jkv
18th November 2010, 18:49
Hello, I'm having a slight problem with model/proxy/view -combo.

As I call beginRemoveRows(.., FIRST, LAST) to remove all items from the model I get selectionChanged(..) from the View's SelectionModel (assuming I had some items selected). The receiving slot then results in following functions being called


void FileVersionManager::installSelectionChanged(
const QItemSelection& selected, const QItemSelection& deselected)
{
installSet_.listSelectionChanged(selected, deselected); // keep track of # of selected rows

if (installSet_.selectedRowCount == 1)
{
hoverInstallInfo_ = false;
setActiveInstallFromFile(installSet_.selectedFile( ));
}
else
{
hoverInstallInfo_ = true;
setActiveInstallFromFile(installSet_.hoverFile()); // <-- relevant call
}
updateInstallActions();
}


FileNode* FileSet::hoverFile() const
{
QPoint pnt = view->viewport()->mapFromGlobal(QCursor::pos());
return proxy->mapToFile(view->indexAt(pnt));
}

FileNode* FileSetSortFilterProxyModel::mapToFile(const QModelIndex& index) const
{
return model_.mapToFile(mapToSource(index));
}

FileNode* InstallSetModel::mapToFile(const QModelIndex& index) const
{
if (index.isValid())
return static_cast<FileNode*>(index.internalPointer());
return 0;
}

The problem is that the FileNode* I get is not NULL as I'd hope it to be due to beginRemoveRows() call. This will eventually segfault later due to the "deleted" file being set where it shouldn't.

Is it normal behaviour that the view returns valid QModelIndex even when the underlying model's all rows are being removed ? Or should I just avoid calling indexAt() or any other functions that return indexes from the views until after endRemoveRows() ?

Thanks.

dw
18th November 2010, 21:50
Why can't you get the selections before calling beginRemoveRows?

jkv
18th November 2010, 22:29
Why can't you get the selections before calling beginRemoveRows?
The selection itself is not important. I'm not interested in that because the code where beginRemoveRows() gets called is kind of separate from the view part. It just removes the items from model and informs the model about it.

But the side effect of the call is that selectionChanged() gets emitted. At this point there is nothing selected and every index is in process being deleted. Still the call view->indexAt(pnt) returns valid index which I'd hope it didn't because the attached data is about to be deleted.

dw
19th November 2010, 00:42
Might the selectionChanged() and the actual deletion run asynchronously? If not, that is one runs after another then how could a segfault happen?

What about checking somehow at the beginning of your installSelectionChanged() method whether a delete process is going on?

jkv
19th November 2010, 11:02
Might the selectionChanged() and the actual deletion run asynchronously? If not, that is one runs after another then how could a segfault happen?

I think it is in sync, because signal gets emitted before beginRemoveRows returns. The segfault happens because FileNode* (from mouse-hovered index) is used in setActiveInstallFromFile(..) as if it was still valid pointer. Well technically it is but after endRemoveRows() it is really deleted.


What about checking somehow at the beginning of your installSelectionChanged() method whether a delete process is going on?

I think something like that is what I'm going to have to do in the end. Or somehow disable the signal before beginRemoveRows(). I'm just still wondering the result of view->indexAt(pnt) :confused: