3

Qt provides QTreeWidgetItemIterator class to iterate through tree view's items. There is even a constructor version which takes the item pointer instead of a view's. Unfortunately, even in this case, the iteration will go down to the very last item. Often, that is not expected behavior. If I start from the item, I want iterate only it's children and grandchildren. Of course, I could get another loop up the tree to check if I didn't go beyond the starting item, but that's ugly. Is there way to do this nicely?

 QTreeWidgetItemIterator it(treeWidget);
        while (*it) {
            if ((*it)->text(0) == itemText)
                (*it)->setSelected(true);
            ++it;
        }
def
  • 521
  • 4
  • 16

3 Answers3

3

If you have the parent item to start with, then just loop through its children:

for (int i = 0; i < item->childCount (); i++)
{
    QTreeWidgetItem *child = item->child (i);
    // ... perform work here ...
}

I don't see an iterator that loops through an item's children, but there's really no need for it.

goug
  • 2,294
  • 1
  • 11
  • 15
0

A complete example :

QObject::connect(ui.treeWidget_2, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(treeWidget2_itemClickedButtonAction(QTreeWidgetItem*)));

void treeWidget2_itemClickedButtonAction(QTreeWidgetItem* item)
{
    Qt::CheckState state = item->checkState(0);
    setChildState(item, state);
}

void setChildState(QTreeWidgetItem* item, Qt::CheckState state) {
    for (int i = 0; i < item->childCount(); i++)
    {
        QTreeWidgetItem* child = item->child(i);
        child->setCheckState(0, state);
        if (child->childCount() > 0)
            setChildState(child, state);
    }
}
Salvo Parisi
  • 119
  • 1
  • 10
0

Kind of old question but I just stumbled upon. @goug answer is quite correct and it doesn't have any overhead (O(n) is literally the minimum you can achieve to access N elements and it is equivalent to an iterator solution). But if you dislike row indexing (as I do ) QTreeWidgetItemIterrator supports a wide variety of filters so in most cases it is sufficient for me to write something like:

QTreeWidget * tree;
QTreeWidgetItemIterator it(tree,QTreeWidgetItemIterator::HasChildren);

But with the exact description you gave I don't believe the filters are viable so I would do

QTreeWidgetItemIterator it(treeWidget);
        while (*it) {
            while ((*it)->parent() && (*it)->parent()->parent()
                &&(*it)->parent()->parent()->parent())
                ++it; //while item has grand-grandparent skip it 
            //do things
            ++it;
        }

Spyros Mourelatos
  • 484
  • 1
  • 8
  • 19
  • QTreeWidgetItem::child() doesn't have an extra loop as other pointed out already, but it can indeed cause some slowdowns, as it calls executePendingSort(). If you are editing the tree while iterating, each call to child() will trigger a sort. See [qtreewidget.h](https://code.woboq.org/qt5/qtbase/src/widgets/itemviews/qtreewidget.h.html#187) – Sergio Monteleone Jan 27 '22 at 10:43