PDA

View Full Version : setRootIndex on QTreeWidget causes application to crash



levi
25th May 2011, 14:43
I have implemented a tree subcalassing QTreeWidget and subclassed QItemDelegate to paint the items. The items are a set of custom widgets. So far so good. The problem arise when I try to show only the children of a chosen node by doing the following:


connect(TreeWidget, SIGNAL(expanded(QModelIndex)), SLOT(setRootIndex(QModelIndex)));

Then I get: "This application has requested the Runtime to terminate it in an unusual way. (...)"

Any suggestions on what causes my application to crash?

Santosh Reddy
25th May 2011, 14:52
Did you check the call stack?
More over there is problem in you connect statement


connect(TreeWidget, SIGNAL(expanded(QModelIndex)), SLOT(setRootIndex(QModelIndex)));

//static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType = Qt::AutoConnection);
// receiver - is missing

levi
25th May 2011, 15:28
The call stack is emptied when the application crashes. By stepping through the code I observe the following call stack

0 QMetaObject::metacall qmetaobject.cpp238 0x6a20445c
1 QMetaObject::activate qobject.cpp 3272 0x6a214bbe
2 QTreeView::expanded moc_qtreeview.cpp 201 0x03c95332
3 QTreeViewPrivate::expand qtreeview.cpp 2884 0x03c90beb
4 QTreeViewPrivate::expandOrCollapseItemAtPos qtreeview.cpp 1319 0x03c89f54
5 QTreeView::mousePressEvent qtreeview.cpp 1816 0x03c8c5e4
6 QWidget::event qwidget.cpp 8183 0x037c4182
7 QFrame::event qframe.cpp 557 0x03b3e6bc
8 QAbstractScrollArea::viewportEvent qabstractscrollarea.cpp 1043 0x03bcbf0f
9 QAbstractItemView::viewportEvent qabstractitemview.cpp 1619 0x03c55785
10 QTreeView::viewportEvent qtreeview.cpp 1256 0x03c89aa3
11 QAbstractScrollAreaPrivate::viewportEvent qabstractscrollarea_p.h 100 0x03e26a13
12 QAbstractScrollAreaFilter::eventFilter qabstractscrollarea_p.h 116 0x03e2506c
13 QCoreApplicationPrivate::sendThroughObjectEventFil ters qcoreapplication.cpp 847 0x6a1ffc73
14 QApplicationPrivate::notify_helper qapplication.cpp 4392 0x037796e5
15 QApplication::notify qapplication.cpp 3959 0x03777909
16 QCoreApplication::notifyInternal qcoreapplication.cpp 732 0x6a1ff9dc
17 QCoreApplication::sendSpontaneousEvent qcoreapplication.h 218 0x03ded53e
18 QApplicationPrivate::sendMouseEvent qapplication.cpp 3056 0x03776118
19 QETWidget::translateMouseEvent qapplication_win.cpp 3317 0x037dfc63
20 QtWndProc@16 qapplication_win.cpp 1657 0x037daaa6
... <More>

and that it finally crashes on:

USER32!IsWindow in C:\Windows\syswow64\user.32.dll


To me it seams like its two variants of the connect statement.


// I wrote TreeWidget instead of 'this' to highlight that it is the tree. I actually use:
connect((this, SIGNAL(expanded(QModelIndex)),SLOT(setRootIndex(QM odelIndex)));

// which should be the same as:
connect((this, SIGNAL(expanded(QModelIndex)),this,SLOT(setRootInd ex(QModelIndex)));

//connect(const QObject *sender, const char *signal, const char *member, Qt::ConnectionType type = Qt::AutoConnection)

Santosh Reddy
25th May 2011, 17:58
I have implemented a tree subcalassing QTreeWidget and subclassed QItemDelegate to paint the items. The items are a set of custom widgets. So far so good. The problem arise when I try to show only the children of a chosen node by doing the following:


connect(TreeWidget, SIGNAL(expanded(QModelIndex)), SLOT(setRootIndex(QModelIndex)));

Then I get: "This application has requested the Runtime to terminate it in an unusual way. (...)"

Any suggestions on what causes my application to crash?

expanded() signal is emitted when you clik on the a parent to view it's children, ok while it is doing so, you try to change the root index of the View, i.e. you make the item you clicked to be set as view's root. I don't think this is legal to do, the TreeWidget will feel bad.

If you are just trying to show the children, while keeping the other parents and other parent's children to be still on view, then this type of connect will not work, in fact you should not be chaning the root index.

levi
26th May 2011, 07:56
Thanks for quick responses ;)

I need the tree to only show the selected node's children. In order to get back to a parent higher up in the hierarchy I have a widget that keeps track of the path so that you can click on any ancestor. It should work similar to a file browser where you see the current folder's contents and a clickable path to this folder. Any suggestions on how I can achieve this without changing the root index?

Would it be an idea to change the root index after the tree has finished its work with expanding a node. In that case, how can I know when the tree is done?

BTW, I compiled the application with necessitas and it seems to be running perfectly on android.

Santosh Reddy
26th May 2011, 08:21
further

connect(TreeWidget, SIGNAL(expanded(QModelIndex)), SLOT(setRootIndex(QModelIndex)));
I don't see expanded() signal in QTreeWidget, so I am assume this is a custom signal in your custom TreeWidget, which is emitted when child item (based off QTreeWidgetItem) is clicked (or double clicked), is it right?

If you are not implementing a Model for TreeView, I suggest not using QModelIndex, this means to Model/View/Delegates to talk.

I don't think you should be using QModelIndex with QTreeWidgetItem.

So, don't try depending on QModelIndex, and use QTreeWidgetItem, use something like this to set root / top level items

void addTopLevelItem ( QTreeWidgetItem * item )

This is assuming you are using QTreeWidgetItem based approach, and not implementing model. If you are using Model then using QModelIndex is better.


BTW, I compiled the application with necessitas and it seems to be running perfectly on android.
I cannot comment on this.

levi
26th May 2011, 09:20
The expanded() signal comes from QTreeView which is inherrited by QTreeWidget, and I thought it would be convinient to use this signal to set the root index.


If you are not implementing a Model for TreeView, I suggest not using QModelIndex, this means to Model/View/Delegates to talk.

As far as I've understood the QTreeWidget class uses the QTreeModel by default. Doc: "The QTreeWidget class provides a tree view that uses a predefined tree model."

My data is initially read from an xml file and put into the QTreeWidget using addTopLevelItem(QTreeWidgetItem *item) and addChild(QTreeWidgetItem *item) to build up the hierarchy.


// Add item to tree.
if (treeitemRoot)
treeitemRoot->addChild(treeitemQuestion);
else
this->addTopLevelItem(treeitemQuestion);
My approach with setting the root index was an attempt to not having to clear the QTreeWidget and rebuild the subtree when opening a childnode. However, I see that when a child is expanded I could clear the tree and add the childs children as top level items. This way, items would be taken in and out of the tree when navigating. The way I implemented it, the whole tree will only be built once.

Santosh Reddy
26th May 2011, 10:16
I understand, If I were to suggest, what I mean my earlier post is that, you created the tree using "addTopLevelItem(QTreeWidgetItem *item) and addChild(QTreeWidgetItem *item)"
so you should be updating the tree again with addTopLevelItem(QTreeWidgetItem *item) and addChild(QTreeWidgetItem *item)" or similar methods which deal with TreeWidgetItem * (as parameters), and not using methods which deal with QModelIndex.

anyways look like you have it working, nice to here that.

wysota
26th May 2011, 15:52
Replace your tree with a table, implement a proper model for it and connect the table's clicked() signal to setRootIndex() slot (or to a custom slot that will call setRootIndex() if the index has any children).