[SOLVED] QAbstractItemModel, row numers shifting during removing



  • For example the following data structure

    rootNode
    |------Node1
    |------Node2
    |------Node3
    |------Node4
    |------Node5

    From the treeView, I try delete the Nodes 2 and 4.

    <code>
    QModelIndexList list = treeView->selectionModel()->selectedIndexes();
    foreach(QModelIndex index, list) {
    if (!index.isValid()) return;
    treeview->model()->removeRows(index.row(), 1, index.parent());
    }
    </code>

    As a result I have that in facts the following Nodes are removed: 2 and 5.
    As I understand after the first node removing, there is a shfting if row's numbers.

    How I can fixed it?



  • Hi,

    my solution is to get the list of selected rows, sort it in decreasing order, and remove in that order.
    For instance if you select rows (3, 1, 5) remove in order (5, 3, 1)



  • Hi...now shifting to another direction...
    Now deletes number 4 and 3



  • Hi,

    can you show your code??



  • bool decSort(const QModelIndex &idx1, const QModelIndex &idx2) {
    	return idx1.row() > idx2.row();
    }
    
    //IN the TreeView
    QModelIndexList list = this->selectionModel()->selectedIndexes();
    if (list.size() == 0) return;
    qSort(list.begin(), list.end(), decSort);
    
    foreach(QModelIndex index, list) {
    	if (!index.isValid()) return;
    	this->model()->removeRows(index.row(), 1, index.parent());
    }
    


  • bool TreeModel::removeRows(int row, int count, const QModelIndex &parent) {
        TreeItem *parentItem;
    	qDebug() << "REMOVE_ROWS";
        if (!parent.isValid())
            parentItem = rootItem;
        else
            parentItem = static_cast<TreeItem*>(parent.internalPointer());
    
    	if (row < 0 || row > parentItem->childCount()) {
    		return false;
    	}
    
        beginRemoveRows(parent, row, row + count - 1);
        for (int i=0; i < count; ++i) {
            if (!parentItem->removeChild(row))
                break;
        }
       endRemoveRows();
    }
    


  • Hi,

    my idea is

    QList <int> rows;
    QModelIndexList list = this->selectionModel()->selectedIndexes();
    for (const QModelIndex &idx: list)
        rows << idx.row();
    
    qSort(rows.begin(): rows.end(), qGreather<int>());
    
    for (int i: rows)
        this->model()->removeRows(i, 1);
    

    NOTE: This works only if, as you wrote in the first post, you have only top level items.



  • Yes, but I may to have not only top level items. Now I going to check another idea like as

    	QModelIndexList list = this->selectionModel()->selectedIndexes();
    	if (list.size() == 0) return;
    
    	QList<TreeItem*> itmList;
    	foreach(QModelIndex index, list) {
    		if (!index.isValid()) return;
    		TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
    		itmList << item;
    	}
    
           foreach(Item *item, itemList) {
                QModelIndex idx = model()->indexByItem(item);
                model()->removeRow(idx.row(), idx.parent());
           }
    

    then I am going write a function of searching indexByItem and use like above. What do you think?



  • So, the result is following

    void QxTreeView::deleteSelected(bool value) {
    	QModelIndexList list = this->selectionModel()->selectedIndexes();
    	if (list.size() == 0) return;
    
    	QList<TreeItem*> itmList;
    	foreach(QModelIndex index, list) {
    		if (!index.isValid()) return;
    		TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
    		itmList << item;
    	}
    	
    	TreeModel *model = static_cast<TreeModel*>(this->model());
    	
    	foreach(TreeItem *item, itmList) {
    		QModelIndex idxParent = this->rootIndex();
    		QModelIndex idx = model->indexByItem(idxParent, item);
    		model->removeRow(idx.row(), idx.parent());
    	}
    }
    

    and indexByItem

    QModelIndex TreeModel::indexByItem(const QModelIndex &parent, TreeItem *item) {
    	if (item == 0)
    		return QModelIndex();
    	
    	int row = 0;
    	while (row < rowCount(parent)) {
    		QModelIndex thisIndex = this->index(row, 0, parent);
    
    		TreeItem *thisItem = static_cast<TreeItem*>(thisIndex.internalPointer());
    		if (thisItem == item)
    			return thisIndex;
    		if (thisItem->childCount() > 0) {
    			thisIndex = indexByItem(thisIndex, item);
    
    			if (thisIndex.isValid())
    				return thisIndex;
    		}
    		++row;
    	}
    
    	return QModelIndex();
    }
    

Log in to reply
 

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