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

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);
        while(child.isValid())
        {
            QModelIndex idx = search(node, child);
            if(idx != QModelIndex() && static_cast<TreeItem*>(idx.internalPointer())->getNode() == node)
                return idx;
            else
                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