QTreeView Interaction (selection and setting selection)

  • I have a QTreeView with a custom QAbstractItemModel that loads up QTreeItems that have MyType *data in them.

    It works fine but I want to enable selecting stuff from the QTreeView widget (getting a selected QTreeItem) and setting selected items from outside the QTreeView (setting a QTreeItem selected).

    I saw QItemSelectionModel but all that works with indexes. How do I start from a MyType* and get it's index in the QTreeView to then set it as selected and vice-versa ? (QTreeView->selectionMode->select(QModelIndex);)

  • Lifetime Qt Champion

    Hi and welcome to devnet,

    You should add getters to your model that can return a QModelIndex based on a MyType instance and the corresponding MyType getter for a given index. With that you have everything you need to implement your selection.

    Hope it helps

  • How do I create a QModelIndex if I dont have the row/column of the item ? Thats the only way I've read about creating a QModelIndex.

  • Lifetime Qt Champion

    Don't you already have your model working for accessing your MyType instances ?

  • My current model is setup like this: http://doc.qt.io/qt-5/qtwidgets-itemviews-simpletreemodel-example.html

    I create my TreeModel.

    My singleton data class (Scene) emits a signal when data is changed, which is sent to my TreeModel which calls the update method (equivalent to setupModelData() in the example) which re-creates the root/children TreeItems.

    It "updates" by querying my singleton data class (Scene) for the root item, creates a TreeItem out of it. Then it iterates through root's childrens, creates TreeItems out of those, and assigns the root TreeItem as their parent. Each TreeItem has a pointer to it's data object, a Node (see below).

    The nature of my singleton data class is a scene graph (3D objects), so there is a root (Group) with children, these childrens beings Nodes, which can either be Groups themselves or Objects (polygon,text, circle). I want to be able to highlight the corresponding Node in the QTreeView when it is highlighted in the 3D world and vice-versa.

    PS: I know the iteration to create TreeItems should be recursive, but I stopped at 1 level (root + childrens) to focus on interaction.

    PPS: I'm getting the creeping feeling I need to do the logic to get "row" and "colum" from my parent-child objects. I.e row 3 colum <anything> would be the root's child's 2nd child (root being row 0, it's child being row 1, and that first child being row 2). But I'dd be surpised I can't retreive a TreeItem from the TreeModel w/o it's row/column.

  • Lifetime Qt Champion

    Indeed you have to do the parsing of your model to get the right item. You can get the row and column information from the QModelIndex

  • @SGaist So right now I can do QTreeView->selectionModel->selection().indexes().at(0) to get the selected item as a QModelIndex. It has row = 0, column = 0, and parent = Group (which is a QModelIndex itself).

    But I really don't understand how to dig out that item using only row/column and parent row/column. And for setting the selection, I need to create a QModelIndex with the selection data ? How is that even possible ? Isn't there a way to get the data a QModelIndex points to ? Is there an example of all this ? Why is all this QModelIndex abstraction needed ?

    I'm just having a hard time understanding the translation of row/column/parentrow/parent/column to my parent/child implementation.

    EDIT: Ok ok ok, I tried some stuff. Noticed I can do QModelIndex::internalPointer to get my TreeItem.

    So selecting in the scene from the Tree is easy, just do getSelectedIndex()->internalPointer()->getNode() which returns the Node I need to select.

    And finding the QModelIndex to select from a Node, I did this:

    QModelIndex TreeModel::search(Node *node, QModelIndex index)
        if(index.internalPointer() != NULL && static_cast<TreeItem*>(index.internalPointer())->getNode() == node) 
            return index;
        int row = 0;
        QModelIndex child = index.child(row,0);
            QModelIndex idx = search(node, child);
            if(idx != QModelIndex() && static_cast<TreeItem*>(idx.internalPointer())->getNode() == node)
                return idx;
                child = index.child(row++, 0);//go to next child
        return QModelIndex();

    It's 4 5 am so I think there are a few things I could improve, so if you see something, do point it out, but the logic seems to work right now.

Log in to reply

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