Guilherme Polo | a7d2797 | 2009-01-28 16:06:51 +0000 | [diff] [blame] | 1 | """A directory browser using Ttk Treeview. |
| 2 | |
| 3 | Based on the demo found in Tk 8.5 library/demos/browse |
| 4 | """ |
| 5 | import os |
| 6 | import glob |
| 7 | import tkinter |
| 8 | from tkinter import ttk |
| 9 | |
| 10 | def populate_tree(tree, node): |
| 11 | if tree.set(node, "type") != 'directory': |
| 12 | return |
| 13 | |
| 14 | path = tree.set(node, "fullpath") |
| 15 | tree.delete(*tree.get_children(node)) |
| 16 | |
| 17 | parent = tree.parent(node) |
| 18 | special_dirs = [] if parent else glob.glob('.') + glob.glob('..') |
| 19 | |
| 20 | for p in special_dirs + os.listdir(path): |
| 21 | ptype = None |
| 22 | p = os.path.join(path, p).replace('\\', '/') |
| 23 | if os.path.isdir(p): ptype = "directory" |
| 24 | elif os.path.isfile(p): ptype = "file" |
| 25 | |
| 26 | fname = os.path.split(p)[1] |
| 27 | id = tree.insert(node, "end", text=fname, values=[p, ptype]) |
| 28 | |
| 29 | if ptype == 'directory': |
| 30 | if fname not in ('.', '..'): |
| 31 | tree.insert(id, 0, text="dummy") |
| 32 | tree.item(id, text=fname) |
| 33 | elif ptype == 'file': |
| 34 | size = os.stat(p).st_size |
| 35 | tree.set(id, "size", "%d bytes" % size) |
| 36 | |
| 37 | |
| 38 | def populate_roots(tree): |
| 39 | dir = os.path.abspath('.').replace('\\', '/') |
| 40 | node = tree.insert('', 'end', text=dir, values=[dir, "directory"]) |
| 41 | populate_tree(tree, node) |
| 42 | |
| 43 | def update_tree(event): |
| 44 | tree = event.widget |
| 45 | populate_tree(tree, tree.focus()) |
| 46 | |
| 47 | def change_dir(event): |
| 48 | tree = event.widget |
| 49 | node = tree.focus() |
| 50 | if tree.parent(node): |
| 51 | path = os.path.abspath(tree.set(node, "fullpath")) |
| 52 | if os.path.isdir(path): |
| 53 | os.chdir(path) |
| 54 | tree.delete(tree.get_children('')) |
| 55 | populate_roots(tree) |
| 56 | |
| 57 | def autoscroll(sbar, first, last): |
| 58 | """Hide and show scrollbar as needed.""" |
| 59 | first, last = float(first), float(last) |
| 60 | if first <= 0 and last >= 1: |
| 61 | sbar.grid_remove() |
| 62 | else: |
| 63 | sbar.grid() |
| 64 | sbar.set(first, last) |
| 65 | |
| 66 | root = tkinter.Tk() |
| 67 | |
| 68 | vsb = ttk.Scrollbar(orient="vertical") |
| 69 | hsb = ttk.Scrollbar(orient="horizontal") |
| 70 | |
| 71 | tree = ttk.Treeview(columns=("fullpath", "type", "size"), |
| 72 | displaycolumns="size", yscrollcommand=lambda f, l: autoscroll(vsb, f, l), |
| 73 | xscrollcommand=lambda f, l:autoscroll(hsb, f, l)) |
| 74 | |
| 75 | vsb['command'] = tree.yview |
| 76 | hsb['command'] = tree.xview |
| 77 | |
| 78 | tree.heading("#0", text="Directory Structure", anchor='w') |
| 79 | tree.heading("size", text="File Size", anchor='w') |
| 80 | tree.column("size", stretch=0, width=100) |
| 81 | |
| 82 | populate_roots(tree) |
| 83 | tree.bind('<<TreeviewOpen>>', update_tree) |
| 84 | tree.bind('<Double-Button-1>', change_dir) |
| 85 | |
| 86 | # Arrange the tree and its scrollbars in the toplevel |
| 87 | tree.grid(column=0, row=0, sticky='nswe') |
| 88 | vsb.grid(column=1, row=0, sticky='ns') |
| 89 | hsb.grid(column=0, row=1, sticky='ew') |
| 90 | root.grid_columnconfigure(0, weight=1) |
| 91 | root.grid_rowconfigure(0, weight=1) |
| 92 | |
| 93 | root.mainloop() |