PDA

View Full Version : Problem while deleting item in QTreeView



QtNewbieNeedsHelp
4th September 2013, 06:25
Hello,

I have a QTreeView with some simple custom items in it.
I also have a simple CustomTreeModel derived from QAbstractItemModel.

I have a QMenu setup so I can click on the items in the tree and press "Delete" which is supposed to delete the current selected item and all its children.

this is the code that I use to delete the items, it works but only for the children, If I call deleteLater() on the current selected item the app crashes.




void MyCustomItem::OnDelete()
{
const QObjectList& childrenList = children();
int numChildren = childrenList.size();
for(unsigned int i = 0; i < numChildren; ++i)
{
QObject* pChildObj = childrenList[0];
MyCustomItem* pChild = qobject_cast<MyCustomItem*>(pChildObj);
if(pChild)
{
pChild->OnDelete();
delete pChild;
}
}

QTreeView* pTV = mpAssociatedTreeView; //for simplicity assume that every object knows the treeview it is in
pTV->clearSelection();
pTV->reset();


deleteLater(); <== if I comment out this line it doesn't crash and all the children objects in the tree are gone
}


I have seen so many posts about using removeRows in the model rather than actually calling delete on the objects, but I fail to understand how these are exactly working.

this is the crash callstack that I get when using deleteLater() on my currently selected item in the tree.



> Qt5Cored.dll!QObject::parent() Line 386 C++
MyApp.exe!CustomTreeModel::parent(const QModelIndex & index={...}) Line 109 C++
Qt5Cored.dll!QModelIndex::parent() Line 462 C++
Qt5Widgetsd.dll!QTreeView::drawRow(QPainter * painter=0x000000000018a9a8, const QStyleOptionViewItem & option={...}, const QModelIndex & index={...}) Line 1545 C++
Qt5Widgetsd.dll!QTreeView::drawTree(QPainter * painter=0x000000000018a9a8, const QRegion & region={...}) Line 1456 C++
Qt5Widgetsd.dll!QTreeView::paintEvent(QPaintEvent * event=0x000000000018bca0) Line 1282 C++
Qt5Widgetsd.dll!QWidget::event(QEvent * event=0x000000000018bca0) Line 8030 C++
Qt5Widgetsd.dll!QFrame::event(QEvent * e=0x000000000018bca0) Line 534 C++
Qt5Widgetsd.dll!QAbstractScrollArea::viewportEvent (QEvent * e=0x000000000018bca0) Line 1163 C++
Qt5Widgetsd.dll!QAbstractItemView::viewportEvent(Q Event * event=0x000000000018bca0) Line 1680 C++
Qt5Widgetsd.dll!QTreeView::viewportEvent(QEvent * event=0x000000000018bca0) Line 1263 C++
Qt5Widgetsd.dll!QAbstractScrollAreaPrivate::viewpo rtEvent(QEvent * event=0x000000000018bca0) Line 105 C++
Qt5Widgetsd.dll!QAbstractScrollAreaFilter::eventFi lter(QObject * o=0x0000000008993450, QEvent * e=0x000000000018bca0) Line 121 C++
Qt5Cored.dll!QCoreApplicationPrivate::sendThroughO bjectEventFilters(QObject * receiver=0x0000000008993450, QEvent * event=0x000000000018bca0) Line 967 C++
Qt5Widgetsd.dll!QApplicationPrivate::notify_helper (QObject * receiver=0x0000000008993450, QEvent * e=0x000000000018bca0) Line 3451 C++
Qt5Widgetsd.dll!QApplication::notify(QObject * receiver=0x0000000008993450, QEvent * e=0x000000000018bca0) Line 3420 C++
Qt5Cored.dll!QCoreApplication::notifyInternal(QObj ect * receiver=0x0000000008993450, QEvent * event=0x000000000018bca0) Line 871 C++
Qt5Cored.dll!QCoreApplication::sendSpontaneousEven t(QObject * receiver=0x0000000008993450, QEvent * event=0x000000000018bca0) Line 235 C++
Qt5Widgetsd.dll!QWidgetPrivate::drawWidget(QPaintD evice * pdev=0x0000000008949888, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4, QPainter * sharedPainter=0x0000000000000000, QWidgetBackingStore * backingStore=0x0000000008b1f1c0) Line 5133 C++
Qt5Widgetsd.dll!QWidgetPrivate::paintSiblingsRecur sive(QPaintDevice * pdev=0x0000000008949888, const QList<QObject *> & siblings={...}, int index=0, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4, QPainter * sharedPainter=0x0000000000000000, QWidgetBackingStore * backingStore=0x0000000008b1f1c0) Line 5325 C++
Qt5Widgetsd.dll!QWidgetPrivate::paintSiblingsRecur sive(QPaintDevice * pdev=0x0000000008949888, const QList<QObject *> & siblings={...}, int index=2, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4, QPainter * sharedPainter=0x0000000000000000, QWidgetBackingStore * backingStore=0x0000000008b1f1c0) Line 5312 C++
Qt5Widgetsd.dll!QWidgetPrivate::drawWidget(QPaintD evice * pdev=0x0000000008949888, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4, QPainter * sharedPainter=0x0000000000000000, QWidgetBackingStore * backingStore=0x0000000008b1f1c0) Line 5183 C++
Qt5Widgetsd.dll!QWidgetPrivate::paintSiblingsRecur sive(QPaintDevice * pdev=0x0000000008949888, const QList<QObject *> & siblings={...}, int index=0, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4, QPainter * sharedPainter=0x0000000000000000, QWidgetBackingStore * backingStore=0x0000000008b1f1c0) Line 5325 C++
Qt5Widgetsd.dll!QWidgetPrivate::drawWidget(QPaintD evice * pdev=0x0000000008949888, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4, QPainter * sharedPainter=0x0000000000000000, QWidgetBackingStore * backingStore=0x0000000008b1f1c0) Line 5183 C++
Qt5Widgetsd.dll!QWidgetPrivate::paintSiblingsRecur sive(QPaintDevice * pdev=0x0000000008949888, const QList<QObject *> & siblings={...}, int index=4, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4, QPainter * sharedPainter=0x0000000000000000, QWidgetBackingStore * backingStore=0x0000000008b1f1c0) Line 5325 C++
Qt5Widgetsd.dll!QWidgetPrivate::drawWidget(QPaintD evice * pdev=0x0000000008949888, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4, QPainter * sharedPainter=0x0000000000000000, QWidgetBackingStore * backingStore=0x0000000008b1f1c0) Line 5183 C++
Qt5Widgetsd.dll!QWidgetPrivate::paintSiblingsRecur sive(QPaintDevice * pdev=0x0000000008949888, const QList<QObject *> & siblings={...}, int index=1, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4, QPainter * sharedPainter=0x0000000000000000, QWidgetBackingStore * backingStore=0x0000000008b1f1c0) Line 5325 C++
Qt5Widgetsd.dll!QWidgetPrivate::drawWidget(QPaintD evice * pdev=0x0000000008949888, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4, QPainter * sharedPainter=0x0000000000000000, QWidgetBackingStore * backingStore=0x0000000008b1f1c0) Line 5183 C++
Qt5Widgetsd.dll!QWidgetPrivate::paintSiblingsRecur sive(QPaintDevice * pdev=0x0000000008949888, const QList<QObject *> & siblings={...}, int index=0, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4, QPainter * sharedPainter=0x0000000000000000, QWidgetBackingStore * backingStore=0x0000000008b1f1c0) Line 5325 C++
Qt5Widgetsd.dll!QWidgetPrivate::drawWidget(QPaintD evice * pdev=0x0000000008949888, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4, QPainter * sharedPainter=0x0000000000000000, QWidgetBackingStore * backingStore=0x0000000008b1f1c0) Line 5183 C++
Qt5Widgetsd.dll!QWidgetPrivate::paintSiblingsRecur sive(QPaintDevice * pdev=0x0000000008949888, const QList<QObject *> & siblings={...}, int index=0, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4, QPainter * sharedPainter=0x0000000000000000, QWidgetBackingStore * backingStore=0x0000000008b1f1c0) Line 5325 C++
Qt5Widgetsd.dll!QWidgetPrivate::drawWidget(QPaintD evice * pdev=0x0000000008949888, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4, QPainter * sharedPainter=0x0000000000000000, QWidgetBackingStore * backingStore=0x0000000008b1f1c0) Line 5183 C++
Qt5Widgetsd.dll!QWidgetPrivate::paintSiblingsRecur sive(QPaintDevice * pdev=0x0000000008949888, const QList<QObject *> & siblings={...}, int index=9, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4, QPainter * sharedPainter=0x0000000000000000, QWidgetBackingStore * backingStore=0x0000000008b1f1c0) Line 5325 C++
Qt5Widgetsd.dll!QWidgetPrivate::drawWidget(QPaintD evice * pdev=0x0000000008949888, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=5, QPainter * sharedPainter=0x0000000000000000, QWidgetBackingStore * backingStore=0x0000000008b1f1c0) Line 5183 C++
Qt5Widgetsd.dll!QWidgetBackingStore::sync() Line 1093 C++



it looks to me as if the qtreeview is still drawing the items but I have just deleted one. In fact



QModelIndex CustomTreeModel::parent(const QModelIndex &index) const
{
if( !index.isValid() )
return QModelIndex();

QObject *indexObject = static_cast<QObject*>( index.internalPointer() );
QObject *parentObject = indexObject->parent(); //the indexObject is garbage at this point

if( parentObject == m_root )
return QModelIndex();

QObject *grandParentObject = parentObject->parent();

return createIndex( grandParentObject->children().indexOf( parentObject ), 0, parentObject );
}


one more thing I can say is that from looking at my CustomTreeModel (where I store the root of my tree) I can tell that the root is the only object left after I delete its only child (with 1 subchild).

this is the tree before calling pItemA->OnDelete()

root (invisible)
+--- ItemA
+-------- ItemA0



anyone has some suggestions ? I tried look at the Qt examples as well to understand how to create a clean QTreeView but its not very clear to me.

any help is appreciated.

Santosh Reddy
4th September 2013, 06:46
Use beginRemoveRows() and endRemoveRows() in the CustomTreeModel.
example


beginRemoveRows()
//Here delete the item/items from internal contaner.
endRemoveRows()
//Now tree view will not access the deleted item.