PDA

View Full Version : Issue with Ordering of selected Nodes in a QTreeView



apatwork
12th September 2018, 13:50
Hi there,

I'm having a little bit of trouble with the ordering of tree nodes selected in a QTreeView. I want to create a textual representation of tree nodes selected in a QTreeView and store it on the clipboard. Here is an example of how such a tree could look like:


Path 1902

path_group
startpoint
endpoint
delay_type
[...]

The indented nodes are child nodes of the node named "Path 1902". The selection handling in this QTreeView is configured as follows:



setSelectionBehavior(QAbstractItemView::SelectRows );
setSelectionMode(QAbstractItemView::ExtendedSelect ion);

When I select the tree elements shown above starting with "Path 1902" and until (and including) "delay_type" then afterwards I can iterate over the selected elements as follows:



QItemSelectionModel *selItemsModel(selectionModel());
for (QModelIndex index : selItemsModel->selectedIndexes()) {

// Create textual representation of selected tree nodes.

}

My problem with this procedure is that the ordering of the selected items is different from what I'd expect. It looks as follows:



path_group
startpoint
endpoint
delay_type
Path 1902

As can be seen the selected tree nodes seem to be ordered from bottom to top, i.e. first the child nodes and then their parent.
I'd prefer to have the selected items ordered from top to bottom. I studied the class documentation of QItemSelectionModel. In the code snippet above I used the method selectedIndexes() to get the indexes of the selected tree items. There is another method selectedRows() in class QItemSelectionModel but it seems to return the selected nodes in the same order.

I wonder if there is a possibility to retrieve the selected nodes ordered from top to bottom.

Any ideas?

tuli
12th September 2018, 15:31
The documentation clearly states that the selection is not sorted:


Returns a list of all selected model item indexes. The list contains no duplicates, and is not sorted.


Means you have to sort the QModelIndexList yourself:



QModelIndexList selection = selItemsModel->selectedIndexes();
sort(selection.begin(), selection.end(),
[](const QModelIndex & a, const QModelIndex & b)
{
return a.row() < b.row();
});

d_stranz
14th September 2018, 17:40
And since you are selecting on multiple levels of the tree hierarchy, your sort condition needs to not only take into account the row, but also the parent-child relationship of those rows. (E.g. both "Path 1902" and "path_group" could have a row index of zero).

This would be especially important if you selected two top-level groups - then you would have duplicate row indexes for each of the two "Path" parents.

If what you want to do is to allow extended selection, but in effect select all children of the selected "Path" nodes, then I would iterate over the returned list of QModelIndex entries, pull out only the Path nodes into another list and sort that new list by row number. Then I would go over that sorted list and pull all of the child nodes of each Path node out of the model and insert those into the sorted list following their parent Path node. Everything will then be in the same order as it appears in the tree.

In effect, you ignore the child nodes returned by the initial selection, but then go back into the model and pull out the complete list of them based on the Path nodes that were selected.

apatwork
17th September 2018, 15:13
Thanks a lot, d_stranz for your valuable hints! You identified my problem absolutely correct. And your proposal how to manage the proper sorting of the selected tree nodes convinced me completely. So I'll go for it.