Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QTreeView remove rows - whats wrong



  • Hey

    I'm trying to delete all selected rows - children and so on in qtreeView and I'm getting weird error I don't get sigh...

    Code :

        QModelIndexList indexList = selectedIndexes();
        QVector<QStandardItem *> itemList;
        QStandardItemModel *modelPtr = dynamic_cast<QStandardItemModel *>(model());
        for (QModelIndex &index:indexList) {
            itemList.push_back(modelPtr->itemFromIndex(index));
        }
        for (QStandardItem *itm:itemList) {
            if (itm) {
                QModelIndex inx = QModelIndex();
                if (itm->parent()) { //// here is error :- ( itm is d was 0xFFFFFFFFFFFFFFFF. but above if (itm) appear to be valid so whats wrong?
                    inx = itm->parent()->index();
                }
                modelPtr->removeRow(itm->row(), inx);
            }
        }
    

    What am I doing here wrong? I'm lost :- (



  • Hey

    Got some progress on this, one of errors was due to multiple columns during the function execution. I filtered my QModelIndex loop to check if (index.column()==0) to only take 1 item per row.

    That fixed some of issues, but other still remain. weird. Removing child items remain problematic.



  • I'm really lost with this. I know that QModelIndex tend to get invalidated when ever I remove row or do stuff in qtreeview/model. But I don't get why this keeps breaking. Tried another loop. Same issue as before still crashing.

    I want to loop over items I previously storred in array or other place. So thats why I stay away from selectionModel() and this answer here > https://forum.qt.io/topic/49836/how-to-inside-a-qtreeview-delete-a-selected-row-and-all-his-children/3

        QModelIndexList indexList = selectedIndexes();
        qSort(indexList.begin(), indexList.end(), qGreater<QModelIndex>());
        QVector<QStandardItem *> itemList;
        QStandardItemModel *modelPtr = dynamic_cast<QStandardItemModel *>(model());
        for (QModelIndex &index:indexList) {
            if (index.column() == 0) {
                itemList.push_back(modelPtr->itemFromIndex(index));
            }
        }
        while(itemList.size()>0){
            modelPtr->removeRow(itemList[0]->row(), itemList[0]->index().parent());
            itemList.remove(0);
        }
    

    Any help would be great.

    TIA


  • Lifetime Qt Champion

    Hi,

    What custom data do you have ?
    How are you handling it ?
    Did you try to run your application through the debugger to see where exactly it crashes ?



  • Hey

    I dont have any custom data at all.

    I just try to store my selection and then delete the items later. Or something like that. It turned out to be quite a pain to solve as well !

    The only think I could think off to fix it is this function : - which feels like a dirty hack!

    ////itemList - is a QVector<QStandardItem*> I saved early.
        for (auto *item:itemList) {
            selectionModel()->select(QItemSelection(item->index(), item->index()),
                                     QItemSelectionModel::Select | QItemSelectionModel::Rows);
        }
    
        while (!selectionModel()->selectedIndexes().isEmpty()) {
            auto idx = selectionModel()->selectedIndexes().first();
            model()->removeRow(idx.row(), idx.parent());
        }
    

  • Lifetime Qt Champion

    Can you explain exactly what procedure you want to follow in order to delete these rows ?

    AFAIK, the link you posted earlier shows the correct way to do it.



  • Should be something like this:

    bool removedByParent(const QHash<QModelIndex,QSet<int> >& mapper, const QModelIndex& childCheck){
    if(!childCheck.isValid()) return false;
    if(mapper.value(childCheck.parent()).constains(childCheck.row())) return true;
    return removedByParent(childCheck.parent());
    };
    
    const QModelIndexList selectedIndexList = selectedIndexes();
    QHash<QModelIndex /*parent*/, QSet<int> /*rows*/> > indexMapper;
    for(auto& idx : selectedIndexList)
    indexMapper[idx.parent()].insert(idx.row);
    for(auto i=indexMapper.cbegin();i!=indexMapper.cend();++i){
    if(removedByParent(i.key())) continue;
    auto sortedRows = i.value().toList();
    std::sort(sortedRows.begin(),sortedRows.end(),std::greater<int>());
    for(int singleRow : qAsConst(sortedRows))
    model->removeRow(singleRow,i.key());
    }
    


  • @SGaist For the moment I use the hacky example I posted early.
    "Can you explain exactly what procedure you want to follow in order to delete these rows ?"
    I just shift/ctrl click on random items in my treeView and then hit delete button.

    @VRonin oh dear humh. I see that but won't the QModelINdex list indexes get invalidated after I remove 1 row?

    I also try to deal with items directly because of that. Tricky will need to test ur example looks curious! Thanks for chipping in!

    Regards
    Dariusz



  • @Dariusz said in QTreeView remove rows - whats wrong:

    I see that but won't the QModelIndex list indexes get invalidated after I remove 1 row?

    It's really implementation specific, since you are using QStandardItemModel you are fine, the indexes will still be valid.
    In general, however, you are right and QPersistentModelIndex should be used instead.


Log in to reply