PDA

View Full Version : problem with custom QAbstractItemModel derived class when changing data



slodki
12th May 2010, 09:42
Hi!

I have a problem with my class derived from QAbstractItemModel when I want to delete an item.

I already tried signals layoutChanged() and beginRemoveRows()/endRemoveRows() and have no idea, what can be wrong.

I attached a simple example of my problem.
As you run it, please select the third row. After a few seconds I'm removing the second item and sometimes it causes segfault. The backtrace from GDB looks like this:



(gdb) backtrace
#0 0x0804e667 in AbstractModel::parent(QModelIndex const&) const ()
#1 0x0086660c in ?? () from /usr/lib/libQtGui.so.4
#2 0x00866dcb in ?? () from /usr/lib/libQtGui.so.4
#3 0x00867111 in QItemSelectionModel::qt_metacall(QMetaObject::Call , int, void**) () from /usr/lib/libQtGui.so.4
#4 0x00d17c9a in QMetaObject::metacall(QObject*, QMetaObject::Call, int, void**) () from /usr/lib/libQtCore.so.4
#5 0x00d263d5 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () from /usr/lib/libQtCore.so.4
#6 0x00d76d77 in QAbstractItemModel::layoutChanged() () from /usr/lib/libQtCore.so.4
#7 0x0805529b in AbstractModel::qt_metacall(QMetaObject::Call, int, void**) ()
#8 0x00d17c9a in QMetaObject::metacall(QObject*, QMetaObject::Call, int, void**) () from /usr/lib/libQtCore.so.4
#9 0x00d263d5 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () from /usr/lib/libQtCore.so.4
#10 0x08054ff9 in AbstractItem::updateModel() ()
#11 0x0804d335 in AbstractItem::operator-=(AbstractItem*) ()
#12 0x0804ddc8 in AbstractItem::update() ()
#13 0x0805505d in AbstractItem::qt_metacall(QMetaObject::Call, int, void**) ()
#14 0x00d17c9a in QMetaObject::metacall(QObject*, QMetaObject::Call, int, void**) () from /usr/lib/libQtCore.so.4
#15 0x00d263d5 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () from /usr/lib/libQtCore.so.4
#16 0x00d77aa7 in QTimer::timeout() () from /usr/lib/libQtCore.so.4


My question is: How can I safely delete data and inform the model (and treeview) about this change?

Lykurg
12th May 2010, 10:00
Hi,

it is a simple "out of range" problem in AbstractModel::index() line 133. Write
if ( (row >= 0) && parentObject->children().count() > row ) { instead. Then you just have to make sure your selection is updated.

slodki
12th May 2010, 13:32
Thanks for a quick answer. This line was obviously incorrect, but it does not solve all the issues.

If you try a random combination of double clicking or holding mouse button on the item that is going to be removed there is still an issue with parent() function.

The backtrace from GDB gives something like:



(gdb) back
#0 0x0804e73d in AbstractModel::parent(QModelIndex const&) const ()
#1 0x008478a6 in QTreeView::drawRow(QPainter*, QStyleOptionViewItem const&, QModelIndex const&) const () from /usr/lib/libQtGui.so.4
#2 0x008514a9 in QTreeView::drawTree(QPainter*, QRegion const&) const () from /usr/lib/libQtGui.so.4
#3 0x008545bd in QTreeView::paintEvent(QPaintEvent*) () from /usr/lib/libQtGui.so.4
#4 0x002c16b6 in QWidget::event(QEvent*) () from /usr/lib/libQtGui.so.4
#5 0x006bdfd3 in QFrame::event(QEvent*) () from /usr/lib/libQtGui.so.4
#6 0x00758382 in QAbstractScrollArea::viewportEvent(QEvent*) () from /usr/lib/libQtGui.so.4
#7 0x0080cbd7 in QAbstractItemView::viewportEvent(QEvent*) () from /usr/lib/libQtGui.so.4
#8 0x0084df7c in QTreeView::viewportEvent(QEvent*) () from /usr/lib/libQtGui.so.4
#9 0x0075ac65 in ?? () from /usr/lib/libQtGui.so.4
#10 0x00d11cda in QCoreApplicationPrivate::sendThroughObjectEventFil ters(QObject*, QEvent*) () from /usr/lib/libQtCore.so.4
#11 0x002634b9 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/libQtGui.so.4
#12 0x0026a0f9 in QApplication::notify(QObject*, QEvent*) () from /usr/lib/libQtGui.so.4
#13 0x00d12a3b in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib/libQtCore.so.4
#14 0x002ca9d6 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib/libQtGui.so.4
#15 0x004a17d7 in ?? () from /usr/lib/libQtGui.so.4
#16 0x002bab93 in QWidgetPrivate::syncBackingStore() () from /usr/lib/libQtGui.so.4
#17 0x002c1e76 in QWidget::event(QEvent*) () from /usr/lib/libQtGui.so.4
#18 0x006bdfd3 in QFrame::event(QEvent*) () from /usr/lib/libQtGui.so.4
#19 0x00758d97 in QAbstractScrollArea::event(QEvent*) () from /usr/lib/libQtGui.so.4
#20 0x0080582c in QAbstractItemView::event(QEvent*) () from /usr/lib/libQtGui.so.4
#21 0x002634dc in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/libQtGui.so.4
#22 0x0026a0f9 in QApplication::notify(QObject*, QEvent*) () from /usr/lib/libQtGui.so.4
#23 0x00d12a3b in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib/libQtCore.so.4
#24 0x00d15473 in QCoreApplicationPrivate::sendPostedEvents(QObject* , int, QThreadData*) () from /usr/lib/libQtCore.so.4
#25 0x00d155dd in QCoreApplication::sendPostedEvents(QObject*, int) () from /usr/lib/libQtCore.so.4


I should mention that this of course is a simple code for bug catching taken from a bigger application with enhanced functionality.