707
|
1 # Display a paged lsit of files and directories
|
|
2 # Allow moving up and down directory trees
|
|
3
|
|
4 import os
|
|
5
|
|
6 from pyntnclick.widgets.base import Box
|
|
7 from pyntnclick.widgets.text import TextButton, LabelWidget
|
|
8
|
|
9
|
|
10 class FileChooser(Box):
|
|
11
|
|
12 def __init__(self, rect, gd, curdir, page_length=12, padding=2):
|
|
13 super(FileChooser, self).__init__(rect, gd)
|
|
14 self.page_length = page_length
|
|
15 self.page = 0
|
|
16 self.curdir = os.path.realpath(os.path.normpath(curdir))
|
|
17 self.selected = None
|
|
18 self.padding = padding
|
|
19 self.dirs = []
|
|
20 self.files = []
|
|
21 self.modal = True
|
|
22 self.prev_but = None
|
|
23 self.next_but = None
|
|
24 self.get_lists()
|
|
25 self.fill_page()
|
|
26
|
|
27 def get_lists(self):
|
|
28 self.dirs = []
|
|
29 self.files = []
|
|
30 for entry in sorted(os.listdir(self.curdir)):
|
|
31 path = os.path.join(self.curdir, entry)
|
|
32 if os.path.isdir(path):
|
|
33 self.dirs.append(entry)
|
|
34 else:
|
|
35 self.files.append(entry)
|
|
36
|
|
37 def _dir_button(self, entry):
|
|
38 widget = TextButton((0, 0), self.gd, entry + '/',
|
|
39 fontname=self.gd.constants.bold_font,
|
|
40 fontsize=10)
|
|
41 widget.add_callback('clicked', self.change_dir, entry)
|
|
42 return widget
|
|
43
|
|
44 def _file_button(self, entry):
|
|
45 if entry == self.selected:
|
|
46 # highlight
|
|
47 widget = TextButton((0, 0), self.gd, entry,
|
|
48 fontsize=10, border=2, border_color='yellow')
|
|
49 else:
|
|
50 widget = TextButton((0, 0), self.gd, entry, fontsize=10)
|
|
51 self.add_callback('clicked', self.change_selection, entry)
|
|
52 return widget
|
|
53
|
|
54 def fill_page(self):
|
|
55 for widget in self.children[:]:
|
|
56 self.remove(widget)
|
|
57 start_page = self.page * self.page_length
|
|
58 end_page = start_page + self.page_length
|
|
59 entries = self.dirs + self.files
|
|
60 top = self.rect.top + self.padding
|
|
61 left = self.rect.left + self.padding
|
|
62 # Add current directory at the top
|
|
63 widget = LabelWidget((0, 0), self.gd, self.curdir[-30:], color='black')
|
|
64 widget.rect.topleft = (left, top)
|
|
65 self.add(widget)
|
|
66 upbut = TextButton((left + self.padding + widget.rect.width, top),
|
|
67 self.gd, u'\N{LEFTWARDS ARROW WITH HOOK}Back one level')
|
|
68 upbut.add_callback('clicked', self.change_dir, os.pardir)
|
|
69 self.add(upbut)
|
|
70 top += max(widget.rect.height, upbut.rect.height) + 4 * self.padding
|
|
71 page_top = top
|
|
72 page_left = left
|
|
73 for entry in entries[start_page:end_page]:
|
|
74 if entry in self.dirs:
|
|
75 widget = self._dir_button(entry)
|
|
76 else:
|
|
77 widget = self._file_button(entry)
|
|
78 widget.rect.topleft = (left, top)
|
|
79 self.add(widget)
|
|
80 top += widget.rect.height + self.padding
|
|
81 page_left = max(page_left, left + widget.rect.width)
|
|
82 # Add page list buttons
|
|
83 if not self.prev_but:
|
|
84 self.prev_but = TextButton((0, 0), self.gd, u'\N{UPWARDS ARROW}')
|
|
85 self.prev_but.add_callback('clicked', self.change_page, -1)
|
|
86 self.prev_but.rect.topleft = (page_left, page_top)
|
|
87 if not self.next_but:
|
|
88 self.next_but = TextButton((0, 0), self.gd, u'\N{DOWNWARDS ARROW}')
|
|
89 self.next_but.add_callback('clicked', self.change_page, -1)
|
|
90 page_top = max(top - self.next_but.rect.height,
|
|
91 self.prev_but.rect.bottom + self.padding)
|
|
92 self.next_but.rect.topleft = (page_left, page_top)
|
|
93 if self.page > 0:
|
|
94 self.prev_but.enable()
|
|
95 else:
|
|
96 self.prev_but.disable()
|
|
97 if end_page < len(entries):
|
|
98 self.next_but.enable()
|
|
99 else:
|
|
100 self.next_but.disable()
|
|
101 self.add(self.next_but)
|
|
102 self.add(self.prev_but)
|
|
103 # Add OK and Cancel buttons
|
|
104 ok_but = TextButton((left, top), self.gd, 'OK')
|
|
105 ok_but.add_callback('clicked', self.ok)
|
|
106 self.add(ok_but)
|
|
107 cancel_but = TextButton(
|
|
108 (left + ok_but.rect.width + 4 * self.padding, top),
|
|
109 self.gd, 'Cancel')
|
|
110 cancel_but.add_callback('clicked', self.cancel)
|
|
111 self.add(cancel_but)
|
|
112
|
|
113 def change_page(self, ev, widget, change):
|
|
114 self.page += change
|
|
115 self.fill_page()
|
|
116 return True
|
|
117
|
|
118 def change_dir(self, ev, widget, newdir):
|
|
119 """Change directory and refresh the widget."""
|
|
120 self.curdir = os.path.normpath(os.path.join(self.curdir, newdir))
|
|
121 self.page = 0
|
|
122 self.selected = None
|
|
123 self.get_lists()
|
|
124 self.fill_page()
|
|
125
|
|
126 def change_selection(self, ev, widget, entry):
|
|
127 """Update selection"""
|
|
128 self.selected = entry
|
|
129
|
|
130 def cancel(self, ev, widget):
|
|
131 if hasattr(self.parent, 'paused'):
|
|
132 self.parent.paused = False
|
|
133 self.parent.remove(self)
|
|
134 self.selected = None
|
|
135 return True
|
|
136
|
|
137 def ok(self, ev, widget):
|
|
138 if hasattr(self.parent, 'paused'):
|
|
139 self.parent.paused = False
|
|
140 self.parent.remove(self)
|
|
141 return True
|