Important: Please read the Qt Code of Conduct -

Get all selected items in a treeview

  • Hello,

    I'm using QTreeView : tree, an AbstractItemModel : model, and a SelectionModel : selection.

    My tree is as follows:


    When I select, for instance, Item5, my selection model is updated.
    I then ask it for selectedRows(). I am given the appropriate corresponding row number.

    When I select a child node, however, I am given the row number inside the node, such as Item4's Child1 returns a row number of 0..... but so does Item1

    So if I select Item1 and Child1 of Item4, both row numbers are 0.

    This results in Child1 and Item1 being iterated over back to back as below

    Ex. I select Item1, Item 2, and Item 4's Child 1.

    I then use
    foreach(const QModelIndex &id, selection->selectedRows())
    //copy the row's contents to my clibpoard.

    My hope is it displays:

    Instead, I get


    Is there a way to get the desired output instead? My "foreach" seems to go "row 0, row 0, row 0, row 1, row 1, row 2, row 3, row 4, row 5"

    where row 0 is each of the child nodes first, then the actual row 0

    instead of iterating over them as they are displayed.

  • Hi,

    to distinguish between parent items and child items you could set a user role at every item of the model.

    create a user role:

    enum ITEM_ROLES {
      MY_ITEM_LEVEL = Qt::UserRole

    create values for this role

    enum ITEM_LEVELS {

    then set this role to the items

    item->setData( MY_ITEM_LEVEL, ITEM_LEVEL_PARENT ) ;

    and then check

    QModelIndexList idxSelectedItems = ui->treeView->selectionModel()->selectedRows();
    for ( auto iter = idxSelectedItems .constBegin();
            iter != idxSelectedItems .constEnd();
            ++iter )
        if ( iter->data( MY_ITEM_LEVEL ) == ITEM_LEVEL_PARENT )
            // handle parent
        else if ( iter->data( MY_ITEM_LEVEL ) == ITEM_LEVEL_CHILD )
            // get parent of child item
            // handle child

  • Child Item have valid parent, so you can use it row number

    if (idx.parent().isValid()) {
        qDebug() << parent.row() << ":" << idx:row();

  • @mcosta

    Thank you for your responses! Both of these are great points. I have a similar implementation to Sahadum's suggestion in place regarding item roles, and Mcosta, that's the EXACT thing I was doing to determine if it's a child node.

    The only problem is, when I query my selectionModel->selectedRows(), my rows still are out of order. When I run my foreach loop, this is what's given to me:
    rows - 0, 0, 0, 1, 1, 1, 2, 3, 4, 5
    deconstructed as below:

    item3:child1.row() ==0,
    item4:child1.row() == 0,


    This is the order that the rows are presented to me in the foreach loop. I tried ignoring child nodes, and then adding their data to my QStringList when I encounter a parent. This orders things properly, but what if I select ONLY a child line, for instance Item3:Child1 - this will be ignored and not be copyable. I must then copy the parent and get ALL the children.

    I still need a means of walking through my selectionModel that will give me the rows in the order they appear in my Treeview.

Log in to reply