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);)
-
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.
-
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.
-
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
45 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.