treeView.selectedIndexes() returns same item multiple times

Trying to get the indexes from multi-selection of items in a treeView. But each item is returned multiple times.

Looking at the raw returned items, each one has a different memory address, so it’s not simply calling the same object multiple times, but creating multiple instances and returning each one.

I’ve tried to use a for loop to try and eliminate all but one of the responses, but it doesn’t work.

        def get_items(self):
             indexes = self.treeView.selectedIndexes()
             seen = []
             for item in indexes:
                if item not in seen:
                    self.console.on_update_text(str(item))
                    self.console.on_update_text("\n")
                    seen.append(item)

(Sorry. I can’t seem to get the code tags to actually present the code correctly.)

I think I might have solved it.

    def get_items(self):
        indexes = self.treeView.selectedIndexes()
        items = []
        for index in indexes:
            item = self.fileSystemModel.filePath(index)
            items.append(item)

        seen = []
        for item in items:
            if item not in seen:
                seen.append(item)
                self.console.on_update_text(item)
                self.console.on_update_text("\n")

Using this results in the following:

If someone has a better way of doing this, please let me know. Also, if someone can tell me why Qt seems to quadruple the results of selectedIndexes(), I would appreciate it.

Hey @Cody_Jackson based on this Qt forum post on a multi-column treeview .selectedIndexes() will return an index for each column.

I only see 2 column in your screenshot, but perhaps you have some hidden?

@martin I didn’t even realize that. Yes, I have the default columns created by a File Explorer example I found. So I need to figure out how to set only one column, as I don’t need the other columns.

Thank you. That really helps a lot.

FWIW, here is the File Explorer code:
class ProjectExplorerTree(QTreeView):
“”“Project Explorer box”""

def __init__(self, tree: QTreeView, console) -> None:
    super().__init__()
    self.treeView = tree
    self.default_dir = f"{str(Path.home())}/opencpi"  # May have to change this later
    self.console_output = console

    self.fileSystemModel = QFileSystemModel(self.treeView)
    self.fileSystemModel.setReadOnly(False)
    root: Optional[QModelIndex] = self.fileSystemModel.setRootPath(f"{self.default_dir}/projects")
    self.treeView.setModel(self.fileSystemModel)
    self.treeView.setRootIndex(root)
    self.treeView.setSelectionMode(self.treeView.ExtendedSelection)
    self.treeView.setRootIsDecorated(True)
    self.treeView.setAlternatingRowColors(True)
    self.treeView.setDragEnabled(True)  # Allow items to be dragged from this panel
1 Like

Had to add self.treeView.hideColumn(int) to the init() method.

    self.treeView.setModel(self.fileSystemModel)
    self.treeView.hideColumn(1)
    self.treeView.hideColumn(2)
    self.treeView.hideColumn(3)
    self.treeView.setRootIndex(root)
1 Like

Great! This has caught me out before, don’t really think of the treeview as 2d model.

If you can’t limit the selection to a single column on the view/model, you could filter out a single column in your method e.g.

indexes = [i for i in indexes if i.column() == 0]
# or 
indexes = filter(lambda i: i.column() == 0, indexes)

I think what’s most painful with Qt is that there are so many places to look due to inheritance, and there is some naming inconsistency between the classes, e.g. headers vs. columns.

For example, to add a column, you use setHeader(), or maybe setHeaderData(), but to remove columns, you use hideColumn(), but there’s also setHeaderHidden().

For me, it’s a lot of trial and error, plus hours of searching for tutorials.