pythonpyqt6qtreeviewqtreewidgetqtreewidgetitem

How can I append directories with many subdirectories to a QTree from a list of paths?


The function I am using works, but not as I would like it to. With each new entry from the list of paths, it adds a new line in the tree instead of appending it to the previous one if the path is similar. I hope the added images and the data list will clarify my issue. What can I do to make the entries append subsequent directories to existing rows in the tree view instead of creating a new row each time in the tree view?

My input data and the resulting tree view don't look good. I would like subsequent entries to expand the corresponding rows in the tree instead of creating new ones each time, as it appears in the attached images.

List of paths from server:

data = ['Default', 'GRAFIKA', 'GRAFIKA/PROGRAMY', 'GRAFIKA/PROGRAMY/POLONIA24_2020', 'GRAFIKA/PROGRAMY/POLONIA24_2020/ASSET', 'GRAFIKA/PROGRAMY/POLONIA24_2020/ASSET/IMG', 'GRAFIKA/PROGRAMY/POLONIA24_2020/ASSET/LIVE', 'GRAFIKA/PROGRAMY/POLONIA24_2020/ASSET/LOGO', 'GRAFIKA/PROGRAMY/POLONIA24_2020/ASSET/PLACE', 'GRAFIKA/PROGRAMY/POLONIA24_2020/ASSET/STILL_BELKA', 'GRAFIKA/PROGRAMY/POLONIA24_2020/ASSET/TYLOWKA', 'GRAFIKA/PROGRAMY/POLONIA24_2020/FONT', 'GRAFIKA/PROGRAMY/POLONIA24_2020/PREV', 'GRAFIKA/PROGRAMY/POLONIA24_2020/SCENE', 'GRAFIKA/PROGRAMY/POLONIA24_2020/SCENE/BACKUP', 'GRAFIKA/PROGRAMY/polonia_backup', 'GRAFIKA/PROGRAMY/polonia_backup/POLONIA24_2020', 'GRAFIKA/PROGRAMY/polonia_backup/POLONIA24_2020/ASSET', 'GRAFIKA/PROGRAMY/polonia_backup/POLONIA24_2020/ASSET/IMG', 'GRAFIKA/PROGRAMY/polonia_backup/POLONIA24_2020/ASSET/LIVE', 'GRAFIKA/PROGRAMY/polonia_backup/POLONIA24_2020/ASSET/LOGO', 'GRAFIKA/PROGRAMY/polonia_backup/POLONIA24_2020/ASSET/PLACE', 'GRAFIKA/PROGRAMY/polonia_backup/POLONIA24_2020/ASSET/STILL_BELKA', 'GRAFIKA/PROGRAMY/polonia_backup/POLONIA24_2020/ASSET/TYLOWKA', 'GRAFIKA/PROGRAMY/polonia_backup/POLONIA24_2020/FONT', 'GRAFIKA/PROGRAMY/polonia_backup/POLONIA24_2020/PREV', 'GRAFIKA/PROGRAMY/polonia_backup/POLONIA24_2020/SCENE', 'PROGRAMY', 'PROGRAMY/VOICE_2022', 'PROGRAMY/VOICE_2022/SLUPKI', 'PROGRAMY/VOICE_2022/SLUPKI/CZESCI_GRAFIKI', 'PROGRAMY/VOICE_21', 'VOICE', 'VOICE/SLUPKI', 'VOICE/SLUPKI/WYNIKI_PARY']

My code:

class FunctionsWindow(QWidget, Ui_Function):

    def __init__(self, parent=None):
        super().__init__()
        self.setupUi_Function(self)
        self.show()

        self.pushButton_Scan.clicked.connect(self.makeTree)

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

    def makeTree(self):

        data = VizTree(Server.IPSerwer)
        treeWidget = self.treeWidget

        items = []

        for item in data:
            itemparts = item.split('/')

            entry = QTreeWidgetItem(None, [itemparts[0]])
            partentitem = entry

            if len(itemparts) > 1:
                for i in itemparts[1:]:
                    childitem = QTreeWidgetItem(None, [i])
                    partentitem.addChild(childitem)
                    partentitem = childitem

            items.append(entry)
        treeWidget.insertTopLevelItems(0, items)

This is how my tree looks in PYQT6:

enter image description here

enter image description here


Solution

  • When dealing with tree structures, you almost always need some level of recursion in order to effectively "browse" (or create) its contents.

    One possible solution for a list of paths is to create a dictionary that uses the full path of each item (including "folders") as key and the related QTreeWidgetItem as value.

            items = {}
    
            def makeChild(parentPath, name):
                if parentPath in items:
                    # a parent QTreeWidgetItem exists for the given path
                    parent = items[parentPath]
                else:
                    if not parentPath:
                        # the item is top level, the parent is the tree
                        parent = items[''] = treeWidget
                    else:
                        # recursively create the parents
                        splitPath = parentPath.split('/')
                        parent = makeChild('/'.join(splitPath[:-1]), splitPath[-1])
    
                if parentPath:
                    itemPath = parentPath + '/' + name
                else:
                    itemPath = name
    
                # create the entry in the dictionary
                item = items[itemPath] = QTreeWidgetItem(parent, [name])
                return item
    
            for item in data:
                splitPath = item.split('/')
                makeChild('/'.join(splitPath[:-1]), splitPath[-1])