Search code examples
pythonqtpyqtpyqt5treeview

QStandardItem object has no attribute findItems


Hello I am trying to oragnise multiples paths in one treeview but this code is not working

I got error like below :

AttributeError: 'QStandardItem' object has no attribute 'findItems'
its like QStandardItem do no have a function to find the item

do you have any idea

import sys
from PyQt5 import QtGui, QtCore

from PyQt5.QtWidgets import QApplication, QMainWindow, QTreeView, QVBoxLayout, QWidget

class TreeViewExample(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("QTreeView Example")
        self.setGeometry(100, 100, 800, 600)

        self.central_widget = QWidget(self)
        self.setCentralWidget(self.central_widget)

        self.tree_view = QTreeView(self.central_widget)
        self.model = QtGui.QStandardItemModel()
        self.tree_view.setModel(self.model)

        # Replace this list with your own list of file paths
        file_paths = [
            "/home/user/documents/file1.txt",
            "/home/user/documents/folder1/file2.txt",
            "/home/user/documents/folder1/file3.txt",
            "/home/user/pictures/photo1.jpg",
            "/home/user/pictures/folder2/photo2.jpg",
        ]

        # Organize file paths in parent-child hierarchy
        self.organize_paths(file_paths)

        # Set up the layout
        layout = QVBoxLayout(self.central_widget)
        layout.addWidget(self.tree_view)

    def organize_paths(self, file_paths):
        for path in file_paths:
            components = path.split("/")
            current_parent = None

            for component in components:
                print(component)
                item = self.get_or_create_item(component, parent=current_parent)
                current_parent = item

    def get_or_create_item(self, text, parent=None):
        items = parent.findItems(text) if parent else self.model.findItems(text)
        if items:
            return items[0]
        else:
            item = QtGui.QStandardItem(text)
            if parent:
                parent.appendRow(item)
            else:
                self.model.appendRow(item)
            return item

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = TreeViewExample()
    window.show()
    sys.exit(app.exec_())

Solution

  • QStandardItem doesn't have findItems() so you have to run different code for parent.

    You can use for-loop with .rowCount() to get every .child(row) in QStandardItem and check child.text() == text

        def get_or_create_item(self, text, parent=None):
    
            if parent:
                # find item for QStandardItem
                item = None
                
                for row in range(parent.rowCount()):
                    child = parent.child(row)
                    if child.text() == text:
                        item = child
                        break
                    
                if item:
                    return item
                else:
                    item = QtGui.QStandardItem(text)
                    parent.appendRow(item)
                    return item
            else:
                # find items for model
                items = self.model.findItems(text)
                
                if items:
                    return items[0]
                else:
                    item = QtGui.QStandardItem(text)
                    self.model.appendRow(item)
                    return item
    

    Result:

    enter image description here


    Full working code:

    Because path.split('/') gives empty string as first element so I use [1:] to skip it in components = path.split("/")[1:]

    import sys
    from PyQt5 import QtGui, QtCore
    from PyQt5.QtWidgets import QApplication, QMainWindow, QTreeView, QVBoxLayout, QWidget
    
    class TreeViewExample(QMainWindow):
    
        def __init__(self):
            super().__init__()
    
            self.setWindowTitle("QTreeView Example")
            self.setGeometry(100, 100, 800, 600)
    
            self.central_widget = QWidget(self)
            self.setCentralWidget(self.central_widget)
    
            self.tree_view = QTreeView(self.central_widget)
            self.model = QtGui.QStandardItemModel()
            self.tree_view.setModel(self.model)
    
            # Replace this list with your own list of file paths
            file_paths = [
                "/home/user/documents/file1.txt",
                "/home/user/documents/folder1/file2.txt",
                "/home/user/documents/folder1/file3.txt",
                "/home/user/pictures/photo1.jpg",
                "/home/user/pictures/folder2/photo2.jpg",
            ]
    
            # Organize file paths in parent-child hierarchy
            self.organize_paths(file_paths)
    
            # Set up the layout
            layout = QVBoxLayout(self.central_widget)
            layout.addWidget(self.tree_view)
    
        def organize_paths(self, file_paths):
            for path in file_paths:
                components = path.split("/")[1:]
                current_parent = None
    
                for component in components:
                    #print('component:', component)
                    item = self.get_or_create_item(component, parent=current_parent)
                    current_parent = item
    
        def get_or_create_item(self, text, parent=None):
    
            if parent:
                #print('add to parent:', text, parent)
                item = None
                
                # find item
                for row in range(parent.rowCount()):
                    child = parent.child(row)
                    #print('>> child:', child.text(), child)
                    if child.text() == text:
                        item = child
                        break
                    
                if item:
                    #print('  parent return:', item)
                    return item
                else:
                    item = QtGui.QStandardItem(text)
                    parent.appendRow(item)
                    #print('  parent create:', text, item)
                    return item
            else:
                #print('add to model:', text)
                items = self.model.findItems(text)
                
                if items:
                    #print('  model return:', items[0])
                    return items[0]
                else:
                    item = QtGui.QStandardItem(text)
                    self.model.appendRow(item)
                    #print('  model create:', text, item)
                    return item
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        window = TreeViewExample()
        window.show()
        sys.exit(app.exec())