Strange problem with QTreeWidgetItemIterator



  • Hi,

    I need to delete checked items in a QTreeWidget when the user presses a button. I've made the following slot:
    @
    void AbstractMainTasksList::deleteItems(QTreeWidget* tasksList, QTreeWidgetItemIterator::IteratorFlags flags)
    {
    QTreeWidgetItemIterator i(tasksList, flags);
    while (*i)
    {
    if ((*i)->text(0) != "À classer") // DO NOT REMOVE!
    {
    delSavedItem(*i);
    delete *i;
    }
    ++(i);
    }
    }
    @
    So far so good, no major problem. But sometimes, when there are multiple QTreeWidgetItems selected, I need to call this slot many times for all of them to be deleted. It looks just like the iterator would skip some of them. The QTreeWidget over which the function iterate has a pretty simple structure: QTreeWidgetItems having at maximum one level of children, each with only one column.

    It's my first Qt program and my first post in a forum, so please don't be too harsh on me. Also, as you may have deduced from line 6, english is not my first language. I hope it's not too bad!


  • Moderators

    welcome to devnet

    What is happening in delSavedItem ?
    Possibly the iterator is manipulated in there.

    Your English is perfect. Most of us are no English native speakers.



  • Thanks for such a fast reply! delSavedItem is just a little function I use to remove files and directories from the disk. I don't think there is much iterator manipulation going on in it, as even without invoking it, I have the same problem. Anyway, here's its code:
    @
    void AbstractMainTasksList::delSavedItem(QTreeWidgetItem* item)
    {
    if (item->parent())
    {
    m_dir = new QDir(m_dir->homePath() + "/" + SAVEDIR + item->parent()->text(0));
    m_dir->remove(item->text(0));
    }
    else
    {
    m_dir = new QDir(m_dir->homePath() + "/" + SAVEDIR);
    m_dir->rmdir(item->text(0));
    }

    }
    @



  • Ok that one was a no-brainer. The while loop goes throught all checked items. For any item, it deletes it, thus decreasing the index of other items by one. Since at the end of the loop, the iterator is increased, no wonder that one out of two item was skipped! Anyway, I rewrote the slot without QTreeWidgetItemIterator; back to the good old for loop. For those of you who may be interested, here is the code:
    @
    void AbstractMainTasksList::cleanItems(QTreeWidget* tasksList, Qt::CheckState flag, bool hardDelete)
    {
    // First, we delete every checked pomodoros (i.e. non toplevel items).
    for (int i = 0; i < tasksList->topLevelItemCount(); i++)
    {
    for (int j = 0; j < tasksList->topLevelItem(i)->childCount(); j++)
    {
    if (tasksList->topLevelItem(i)->child(j)->checkState(0) == flag)
    {
    // Gotta do that before taking the child, otherwise delSavedItem wont work properly.
    if (hardDelete)
    {
    delSavedItem(tasksList->topLevelItem(i)->child(j));
    }
    QTreeWidgetItem* it = tasksList->topLevelItem(i)->takeChild(j);
    emit itemDeleted(it);
    delete it;
    j--;
    }
    }
    }

    // Then, we delete every checked categories (i.e. toplevel items) and move their children to "À classer" category.
    for (int i = 0; i < tasksList->topLevelItemCount(); i++)
    {
        if (tasksList->topLevelItem(i)->checkState(0) == flag && tasksList->topLevelItem(i)->text(0) != "À classer")
        {
            QTreeWidgetItem* it = tasksList->topLevelItem(i);
            while (tasksList->topLevelItem(i)->childCount() > 0)
            {
                delSavedItem(it->child(0)); // Again, gotta do that before taking the child.
                QTreeWidgetItem* child = it->takeChild(0);
                newItem(tasksList, child, NULL, "À classer");
                delete child;
            }
            delSavedItem(it); // Won't work if "it" has childrens.
            emit catDel(it);
            delete it;
            i--;
        }
    }
    

    }
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.