Как преобразовать список каталогов и файлов из обычного списка в древовидный список, используя python & PyQt5

Я использую Python и библиотеку PyQt5 для отображения списка каталогов и файлов, существующих по требуемому пути.

где пользователь выбирает нужную папку, а программа создает список, в котором хранятся все существующие папки, вложенные папки и файлы, затем он добавляет этот список в QlistWidget для отображения всех папок.

введите описание изображения здесь

что я хочу, чтобы преобразовать этот список в TreeList, чтобы сделать отображение следующим образом:

folder1 
   subfolder1
      file1
      file2
folder2
   subfolder1
      file1
      file2
      file3
   subfolder2
      file1

функция:

def checkPath(self,folder):
        fileList=[]    
        try:
            directory=folder

            '''
             check if entered path exist 
             sleep for 2 seconds
            '''
            if os.path.exists(folder):
                print("{0} is a valid Path".format(folder))
                time.sleep(2)
                self.listWidgetPDFlist.clear()
                '''
                 looping over the path  using os,walk 
                ==> filter the PDF files then join the path entered with the fileName 
                ==> append the filtered files into a list  in order to apply list functions.
                '''
                for root,dirs,files in os.walk(directory):

                    for filename in files:
                        if filename.endswith(self.lineEdit_Ext.text()):

                            t=os.path.join(root,filename)

                            print(t)
                            fileList.append(t)

                # add the list into the  listWidgetPDFlist          
                self.listWidgetPDFlist.addItems(fileList)

                # get the total number of existing  PDF files in the requested path
                totalPDFNum=len(fileList)

                '''
                check if the length of the list if <= 0 
                yes ==> no PDF files were founded  TOTAL = 0 
                no ==>  PDF files were founded  TOTAL = totalPDFNum
                '''
                if(totalPDFNum <= 0 ):
                    print("{0} path doesn't includes any {1} files ".format(directory,self.lineEdit_Ext.text()))
                    self.lineEditTotalPDFnumber.setText(str(totalPDFNum))

                else:    
                    self.lineEditTotalPDFnumber.setText(str(totalPDFNum))
                    print ("\nthe ToTal Number of files  = {0} ".format(totalPDFNum) )        
                return folder

            #if entered path doesn't exist      
            else:    
                print("{0}is not a valid Path".format(folder))
                return False

        except Exception as e:
            print("this error occure {0}".format(e))

2 ответа

Этот метод построит представление дерева рекурсивно.

def make_tree(self, folder):  # folder here is a path to a folder
    root = self.populate(folder)
    self.tree_view.insertTopLevelItem(0, root)

def populate(self, path):
    tree_item = QTreeWidgetItem()
    tree_item.setText(0, os.path.basename(path))
    for file in os.listdir(path):
        if os.path.isdir(os.path.join(path, file)):
            tree_item.addChild(self.populate(os.path.join(path, file)))
        else:
            sub_item = QTreeWidgetItem()
            sub_item .setText(0, file)
            tree_item.addChild(sub_item )
    return tree_item

make_tree Метод создает объект корневого каталога и устанавливает его как объект верхнего уровня дерева.

populate Метод рекурсивно строит иерархию папок, создавая элемент дерева по указанному пути, а затем, если этот путь является каталогом, добавляя каждый дочерний элемент как дочерний элемент нового элемента дерева.

Будьте осторожны, какую папку вы установите в качестве корня этого метода, в результате вы можете получить много-много тысяч элементов дерева. Было бы хорошей идеей для реализации какого-либо ограничения глубины.

Я думаю, что то, что вам нужно, может быть легко достигнуто pathlib.Path.glob чем os.walk, вместе с Path.parts вы можете собрать вложенный dict следующим образом:

from collections import defaultdict
from pathlib import Path
nested_dict = lambda: defaultdict(nested_dict)

def place_in_nested_dict(nested, place, value):
    if isinstance(place, str):
        place = [place]
    place = list(place)
    last = place.pop()
    for node in reversed(place):
        nested = nested[node]
    nested[last] = value

def find_files(root=Path('.'), pattern='**/*.pdf'):
    tree = nested_dict()
    for file in root.glob(pattern):
        if file.is_dir():
            continue
        parts = file.relative_to(root).parts
        name = file.name
        place_in_nested_dict(tree, parts, file.relative_to(root))
    return tree

используйте это дерево, чтобы заполнить свой TreeWidget чем-то вроде этого:

def populate(tree: dict, root: Path):
    tree_item = QTreeWidgetItem()
    tree_item.setText(0, str(root))
    for key, value in tree:
        if isinstance(value, dict):
            tree_item.addChild(populate(tree, key))
        else:
            tree_item.addChild(key)
    return tree_item
Другие вопросы по тегам