2

i am using python and PyQt5 library in order to display the list of directories and files existing in a required path.

where the user choose the desired folder and the program create a list that holds all the existing folders and sub_folders and files then it append this list to QlistWidget in order to display all the folders.

enter image description here

what i want is to transform this list into a TreeList to make the display like this :

folder1 
   subfolder1
      file1
      file2
folder2
   subfolder1
      file1
      file2
      file3
   subfolder2
      file1

the function is :

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))
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Pyt Leb
  • 99
  • 2
  • 10
  • I think what you need can be more easily achieved by [`pathlib.Path.glob`](https://docs.python.org/3/library/pathlib.html#pathlib.Path.glob) than `os.walk`, together with `Path.parents` and a [nested dict](https://stackoverflow.com/a/36299615/1562285) – Maarten Fabré Mar 29 '18 at 10:40

2 Answers2

1

This method will build the tree view recursively.

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

The make_tree method makes the root directory object and sets it as the top level object of the tree.

The populate method builds the folder hierarchy recursively by creating a tree item out of the supplied path, then if that path is a directory, adding each sub item as a child of the new tree item.

Be careful which folder you set as the root of this method, you could end up with many many thousands of tree items. It would be a good design idea to implement some sort of a depth limit.

MalloyDelacroix
  • 2,193
  • 1
  • 13
  • 17
0

I think what you need can be more easily achieved by pathlib.Path.glob than os.walk, together with Path.parts you can assemble a nested dict like this:

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

use this tree to populate your TreeWidget with something like this:

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
Maarten Fabré
  • 6,938
  • 1
  • 17
  • 36