PDA

View Full Version : [SOLVED] Deleting an item from QTreeWidget



xsid
29th December 2014, 19:10
Well, I'm confused a little: I'm trying to delete selected item from QTreeWidget (in my case it have multiple columns) and always my app crashes on this action. Sorry for asking this question again and again, but I realy can't understand where my mistake is. Here are couple of solutions I've tryed (please, forgive me my english):


QList<QTreeWidgetItem *> items = ui->treeWidget->selectedItems();
if (!items.isEmpty()) {
foreach (QTreeWidgetItem *item, items)
delete item;
}


QTreeWidgetItem *twi = ui->treeWidget->currentItem();
delete twi;


QTreeWidgetItem *parent = ui->treeWidget->currentItem()->parent();
int index;

if (parent) {
index = parent->indexOfChild(ui->treeWidget->currentItem());
delete parent->takeChild(index);
} else {
index = ui->treeWidget->indexOfTopLevelItem(ui->treeWidget->currentItem());
delete ui->treeWidget->takeTopLevelItem(index);
}

I've tryed to set focus on another item before call "delete" but with no result... Please, any help. I started to code with Qt/C++ a couple of weeks ago and many things looks difficult to me.

Radek
29th December 2014, 19:42
Do not delete tree items this way. A tree is a linked structure so that a direct delete causes an invalid pointer in the tree. A crash will follow soon. You need to remove the item from the tree first and then delete it. QTreeWidgetItem has the following methods:

removeChild( QTreeWidgetItem *child ) - Removes a child of this item from the tree structure but it does not delete it.
parent() - returns a parent of this item.

Therefore:


QList<QTreeWidgetItem *> items = ui->treeWidget->selectedItems();
QTreeWidgetItem *pp = nullptr;

if ( !items.isEmpty() )
{
foreach (QTreeWidgetItem *item, items)
{
pp = item->parent();
pp->removeChild(item);
delete item;
}
}

and so on. Note that every "real" item has a parent, at least, the invisible root item. Note also, that the removed item can have childs. removeChild() will remove the whole branch and delete will delete all items in the branch recursively.

xsid
29th December 2014, 20:33
No, still crash with message "ASSERT failure in QList<T>::at: "index out of range"". What am I doing wrong? Crash appears even I'm trying to clear treeWidget and load data in it again, not just on item deleting.

Radek
29th December 2014, 20:58
Then the problem is with foreach. Most likely, as you delete the list items, the indexing of items (crashing is QTreeWidget::at()) becomes invalid. I suggest while and using QList::takeFirst() as a more sure processing the list. takeFirst() removes the first item from the list and returns it (or it returns nullptr if the list is empty).

xsid
29th December 2014, 21:12
The problem was not in code. Every solutions above works. In the widget properties MUST be set selectionBehavior->SelectRows (I guess in case of multiple columns such mine case). Thank you, Radek, your code is very usefull and thanks for clarification about how to delete TreeWidget item correctly!