PDA

View Full Version : Removing the selected row in a QTreeView



vfernandez
29th May 2006, 04:29
I'm using a QTreeView and a custom model to display a tree of MIME types by group. The top-level items are the MIME groups (application, image, text,...) and each one has the list of MIME types belonging to that group (application/octet-stream, text/plain,...).

I get the selected MIME type and clear the selection, then I remove it from my internal data structures and I want to remove it also from the model. I'm using this method:


void MIMETypesModel::removeMimeType(QString mimeType)
{
QString group = mimeType.left(mimeType.indexOf('/'));
MIMETypesItem *groupItem = m_rootItem->findChild(group);
if(!groupItem)
return;

MIMETypesItem *mimeItem = groupItem->findChild(mimeType);
if(mimeItem != NULL) {
QModelIndex parentIndex = createIndex(groupItem->row(), 0, m_rootItem);
beginRemoveRows(parentIndex, mimeItem->row(), mimeItem->row());
groupItem->removeChild(mimeItem);
endRemoveRows();
}

if(groupItem->childCount() == 0) {
beginRemoveRows(QModelIndex(), groupItem->row(), groupItem->row());
m_rootItem->removeChild(groupItem);
endRemoveRows();
}
}

MIMETypesItem is based in the "Simple Tree Model" example from QT. MIMETypesItem::findChild() returns the child item that contains the specified MIME type/group (it searches for the string in the child items).

It's really strange, but if I remove, let's say, the second MIME type in the first group, it works flawlessly. But if I remove, let's say, the tenth MIME type in the first group, the program crashes in the beginRemoveRows() with a SIGABRT and this is printed to stdout:


ASSERT failure in QList<T>::at: "index out of range", file /usr/lib/qt4/include/QtCore/qlist.h, line 361

This is the backtrace:


(gdb) bt
#0 0xffffe410 in __kernel_vsyscall ()
#1 0xb72a37d0 in raise () from /lib/libc.so.6
#2 0xb72a4ea3 in abort () from /lib/libc.so.6
#3 0xb75044ec in qt_message_output (msgType=QtFatalMsg,
buf=0xbf99f4d0 "ASSERT failure in QList<T>::at: \"index out of range\", file /usr/lib/qt4/include/QtCore/qlist.h, line 361")
at global/qglobal.cpp:1958
#4 0xb750453e in qFatal (msg=0xb75e9e8c "ASSERT failure in %s: \"%s\", file %s, line %d") at global/qglobal.cpp:2174
#5 0xb7504574 in qt_assert_x (where=0x80960a3 "QList<T>::at", what=0x8096090 "index out of range",
file=0x809606c "/usr/lib/qt4/include/QtCore/qlist.h", line=361) at global/qglobal.cpp:1731
#6 0x080902cc in QList<MIMETypesItem*>::at (this=0x82cb2bc, i=11) at /usr/lib/qt4/include/QtCore/qlist.h:361
#7 0x0808f8b9 in MIMETypesItem::child (this=0x82cb2b8, row=11) at mimetypesitem.cpp:80
#8 0x0808ee78 in MIMETypesModel::index (this=0x82cacf0, row=11, column=0, parent=@0xbf9a1bec) at mimetypesmodel.cpp:104
#9 0xb7d2ceec in QTreeView::rowsAboutToBeRemoved (this=0x82c0dd8, parent=@0xbf9a1bec, start=11, end=11) at itemviews/qtreeview.cpp:1341
#10 0xb7cfd46e in QAbstractItemView::qt_metacall (this=0x82c0dd8, _c=QMetaObject::InvokeMetaMethod, _id=17, _a=0xbf9a1b54)
at .moc/debug-shared/moc_qabstractitemview.cpp:176
#11 0xb7d8071e in QTreeView::qt_metacall (this=0x82c0dd8, _c=QMetaObject::InvokeMetaMethod, _id=43, _a=0xbf9a1b54)
at .moc/debug-shared/moc_qtreeview.cpp:88
#12 0xb75c7614 in QMetaObject::activate (sender=0x82cacf0, from_signal_index=9, to_signal_index=9, argv=0xbf9a1b54)
at kernel/qobject.cpp:2671
#13 0xb75c845f in QMetaObject::activate (sender=0x82cacf0, m=0x80b9a58, local_signal_index=5, argv=0xbf9a1b54) at kernel/qobject.cpp:2709
#14 0xb75e8a13 in QAbstractItemModel::rowsAboutToBeRemoved (this=0x82cacf0, _t1=@0xbf9a1bec, _t2=11, _t3=11)
at .moc/debug-shared/moc_qabstractitemmodel.cpp:149
#15 0xb75ac044 in QAbstractItemModel::beginRemoveRows (this=0x82cacf0, parent=@0xbf9a1bec, first=11, last=11)
at kernel/qabstractitemmodel.cpp:1727
#16 0x0808e519 in MIMETypesModel::removeMimeType (this=0x82cacf0, mimeType=@0xbf9a1c6c) at mimetypesmodel.cpp:215
#17 0x080870d3 in MIMETypesEditor::removeMimeType (this=0x8255b90, type=@0xbf9a1ca0) at mimetypeseditor.cpp:291
#18 0x0808ab1a in MIMETypesPanel::removeMimeType (this=0x82bab58) at mimetypespanel.cpp:172
#19 0x08092294 in MIMETypesPanel::qt_metacall (this=0x82bab58, _c=QMetaObject::InvokeMetaMethod, _id=0, _a=0xbf9a21ec)
at moc_mimetypespanel.cpp:67
#20 0xb75c7614 in QMetaObject::activate (sender=0x82c4078, from_signal_index=25, to_signal_index=26, argv=0xbf9a21ec)
at kernel/qobject.cpp:2671
#21 0xb75c7801 in QMetaObject::activate (sender=0x82c4078, m=0xb7ea3690, from_local_signal_index=2, to_local_signal_index=3, argv=0xbf9a21ec)
at kernel/qobject.cpp:2718
#22 0xb7d79148 in QAbstractButton::clicked (this=0x82c4078, _t1=false) at .moc/debug-shared/moc_qabstractbutton.cpp:170

Any idea?

wysota
29th May 2006, 08:50
If I understand correctly, you are doing it the wrong way.

You should reimplement QAbstractItemModel::removeRow() so that it removes an item from your internal data structures. This way calling removeRow (or removeRows, as it uses removeRow internally) will update the model and inform all views about it. If you operate on internal structures using your own methods, you don't have to use beginRemoveRows() (and the "index" approach in general) as the data is already removed from the model -- just remove internal structures associated with items and emit layoutChanged() from the model, so that views can update themselves.

vfernandez
29th May 2006, 12:21
It worked, thanks!