Mercurial > libervia-backend
comparison frontends/primitivus/files_management.py @ 179:d6c0c5dca9b9
Primitivus: new FileDialog
Advanced file choosing dialog with:
- path understanding when removing part with C-w
- completion
- listing of GTK & KDE's bookmarks
- selection of file by typing the first letters of the name
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 16 Aug 2010 21:11:00 +0800 |
parents | a50953ac6191 |
children | 879beacb8e16 |
comparison
equal
deleted
inserted
replaced
178:bd24f2aed80c | 179:d6c0c5dca9b9 |
---|---|
23 import custom_widgets | 23 import custom_widgets |
24 from tools.jid import JID | 24 from tools.jid import JID |
25 import os, os.path | 25 import os, os.path |
26 from xml.dom import minidom | 26 from xml.dom import minidom |
27 from logging import debug, info, error | 27 from logging import debug, info, error |
28 from time import time | |
28 | 29 |
29 class PathEdit(custom_widgets.AdvancedEdit): | 30 class PathEdit(custom_widgets.AdvancedEdit): |
31 """AdvancedEdit with manage file paths""" | |
30 | 32 |
31 def keypress(self, size, key): | 33 def keypress(self, size, key): |
32 if key == 'ctrl w': | 34 if key == '~' and self.edit_pos==0: |
35 expanded = os.path.expanduser('~') | |
36 self.set_edit_text(os.path.normpath(expanded+'/'+self.edit_text)) | |
37 self.set_edit_pos(len(expanded)+1) | |
38 elif key == 'ctrl w': | |
33 if self.edit_pos<2: | 39 if self.edit_pos<2: |
34 return | 40 return |
35 before = self.edit_text[:self.edit_pos] | 41 before = self.edit_text[:self.edit_pos] |
36 pos = (before[:-1] if before.endswith('/') else before).rfind("/")+1 | 42 pos = (before[:-1] if before.endswith('/') else before).rfind("/")+1 |
37 self.set_edit_text(before[:pos] + self.edit_text[self.edit_pos:]) | 43 self.set_edit_text(before[:pos] + self.edit_text[self.edit_pos:]) |
38 self.set_edit_pos(pos) | 44 self.set_edit_pos(pos) |
39 return | 45 return |
40 else: | 46 else: |
41 return super(PathEdit, self).keypress(size, key) | 47 return super(PathEdit, self).keypress(size, key) |
42 | 48 |
49 class FilesViewer(urwid.WidgetWrap): | |
50 """List specialised for files""" | |
51 | |
52 def __init__(self, onPreviousDir, onDirClick, onFileClick): | |
53 self.path='' | |
54 self.key_cache = '' | |
55 self.key_time = time() | |
56 self.onPreviousDir = onPreviousDir | |
57 self.onDirClick = onDirClick | |
58 self.onFileClick = onFileClick | |
59 self.files_list = urwid.SimpleListWalker([]) | |
60 self.show_hidden = True | |
61 listbox = urwid.ListBox(self.files_list) | |
62 urwid.WidgetWrap.__init__(self, listbox) | |
63 | |
64 def keypress(self, size, key): | |
65 if key=='meta h': | |
66 #(un)hide hidden files | |
67 self.show_hidden = not self.show_hidden | |
68 self.showDirectory(self.path) | |
69 if key=='meta d': | |
70 #jump to directories | |
71 if self.files_list: | |
72 self._w.set_focus(0) | |
73 elif key=='meta f': | |
74 for idx in range(len(self.files_list)): | |
75 if isinstance(self.files_list[idx].base_widget,urwid.Divider): | |
76 if idx<len(self.files_list)-1: | |
77 self._w.set_focus(idx+1) | |
78 break | |
79 elif len(key) == 1: | |
80 if time() - self.key_time > 2: | |
81 self.key_cache=key | |
82 else: | |
83 self.key_cache+=key | |
84 self.key_time = time() | |
85 for idx in range(len(self.files_list)): | |
86 if isinstance(self.files_list[idx],custom_widgets.ClickableText) and self.files_list[idx].get_text().lower().startswith(self.key_cache.lower()): | |
87 self._w.set_focus(idx) | |
88 break | |
89 else: | |
90 return self._w.keypress(size, key) | |
91 | |
92 def showDirectory(self, path): | |
93 self.path = path | |
94 del self.files_list[:] | |
95 directories = [] | |
96 files = [] | |
97 try: | |
98 for filename in os.listdir(path): | |
99 fullpath = os.path.join(path,filename) | |
100 if os.path.isdir(fullpath): | |
101 directories.append(filename) | |
102 else: | |
103 files.append(filename) | |
104 except OSError: | |
105 self.files_list.append(urwid.Text(("warning",_("Impossible to list directory")),'center')) | |
106 directories.sort() | |
107 files.sort() | |
108 if os.path.abspath(path)!='/' and os.path.abspath(path) != '//': | |
109 previous_wid = custom_widgets.ClickableText('..',default_attr='directory') | |
110 urwid.connect_signal(previous_wid,'click',self.onPreviousDir) | |
111 self.files_list.append(previous_wid) | |
112 for directory in directories: | |
113 if directory.startswith('.') and not self.show_hidden: | |
114 continue | |
115 dir_wid = custom_widgets.ClickableText(directory,default_attr='directory') | |
116 urwid.connect_signal(dir_wid,'click',self.onDirClick) | |
117 self.files_list.append(dir_wid) | |
118 self.files_list.append(urwid.AttrMap(urwid.Divider('-'),'separator')) | |
119 for filename in files: | |
120 if filename.startswith('.') and not self.show_hidden: | |
121 continue | |
122 file_wid = custom_widgets.ClickableText(filename) | |
123 urwid.connect_signal(file_wid,'click',self.onFileClick) | |
124 self.files_list.append(file_wid) | |
125 | |
126 | |
127 | |
43 class FileDialog(urwid.WidgetWrap): | 128 class FileDialog(urwid.WidgetWrap): |
44 | 129 |
45 def __init__(self,title=_("Please select a file")): | 130 def __init__(self, ok_cb, cancel_cb, title=_("Please select a file"), style=[]): |
131 """Create file dialog | |
132 @param title: title of the window/popup | |
133 @param style: NOT USED YET #FIXME | |
134 """ | |
135 self.ok_cb = ok_cb | |
46 self.__home_path = os.path.expanduser('~') | 136 self.__home_path = os.path.expanduser('~') |
47 self.path_wid = PathEdit(_('Path: '), os.getcwdu()) | 137 self.path_wid = PathEdit(_('Path: ')) |
138 self.path_wid.setCompletionMethod(self._directory_completion) | |
48 urwid.connect_signal(self.path_wid, 'change', self.onPathChange) | 139 urwid.connect_signal(self.path_wid, 'change', self.onPathChange) |
49 header = urwid.Pile([self.path_wid, urwid.Divider(u'─')]) | 140 header = urwid.Pile([self.path_wid, urwid.Divider(u'─')]) |
50 bookm_list = urwid.SimpleListWalker([]) | 141 bookm_list = urwid.SimpleListWalker([]) |
51 self.bookmarks = list(self.getBookmarks()) | 142 self.bookmarks = list(self.getBookmarks()) |
52 self.bookmarks.sort() | 143 self.bookmarks.sort() |
55 bookmark="~"+bookmark[len(self.__home_path):] | 146 bookmark="~"+bookmark[len(self.__home_path):] |
56 book_wid = custom_widgets.ClickableText(bookmark) | 147 book_wid = custom_widgets.ClickableText(bookmark) |
57 urwid.connect_signal(book_wid, 'click', self.onBookmarkSelected) | 148 urwid.connect_signal(book_wid, 'click', self.onBookmarkSelected) |
58 bookm_list.append(book_wid) | 149 bookm_list.append(book_wid) |
59 bookm_wid = urwid.Frame(urwid.ListBox(bookm_list), urwid.AttrMap(urwid.Text(_('Bookmarks'),'center'),'title')) | 150 bookm_wid = urwid.Frame(urwid.ListBox(bookm_list), urwid.AttrMap(urwid.Text(_('Bookmarks'),'center'),'title')) |
60 self.files_list = urwid.SimpleListWalker([urwid.Text('toto.mkv')]) | 151 self.files_wid = FilesViewer(self.onPreviousDir, self.onDirClick, self.onFileClick) |
61 files_wid = urwid.ListBox(self.files_list) | |
62 center_row = urwid.Columns([('weight',2,bookm_wid), | 152 center_row = urwid.Columns([('weight',2,bookm_wid), |
63 ('weight',8,custom_widgets.VerticalSeparator(files_wid))]) | 153 ('weight',8,custom_widgets.VerticalSeparator(self.files_wid))]) |
64 main_frame = custom_widgets.FocusFrame(center_row, header) | 154 |
155 buttons = [] | |
156 buttons.append(custom_widgets.CustomButton(_('Cancel'),cancel_cb)) | |
157 max_len = max([button.getSize() for button in buttons]) | |
158 buttons_wid = urwid.GridFlow(buttons,max_len,1,0,'center') | |
159 main_frame = custom_widgets.FocusFrame(center_row, header, buttons_wid) | |
65 decorated = custom_widgets.LabelLine(main_frame, custom_widgets.SurroundedText(title)) | 160 decorated = custom_widgets.LabelLine(main_frame, custom_widgets.SurroundedText(title)) |
66 urwid.WidgetWrap.__init__(self, decorated) | 161 urwid.WidgetWrap.__init__(self, decorated) |
162 self.path_wid.set_edit_text(os.getcwdu()) | |
163 | |
164 def _directory_completion(self, path, completion_data): | |
165 path=os.path.abspath(path) | |
166 if not os.path.isdir(path): | |
167 head,dir_start = os.path.split(path) | |
168 else: | |
169 head=path | |
170 dir_start='' | |
171 try: | |
172 filenames = os.listdir(head) | |
173 filenames.sort() | |
174 try: | |
175 start_idx=filenames.index(completion_data['last_dir'])+1 | |
176 if start_idx == len(filenames): | |
177 start_idx = 0 | |
178 except (KeyError,ValueError): | |
179 start_idx = 0 | |
180 for idx in range(start_idx,len(filenames)) + range(0,start_idx): | |
181 full_path = os.path.join(head,filenames[idx]) | |
182 if filenames[idx].lower().startswith(dir_start.lower()) and os.path.isdir(full_path): | |
183 completion_data['last_dir'] = filenames[idx] | |
184 return full_path | |
185 except OSError: | |
186 pass | |
187 return path | |
67 | 188 |
68 def getBookmarks(self): | 189 def getBookmarks(self): |
69 gnome_bookm = os.path.expanduser("~/.gtk-bookmarks") | 190 gtk_bookm = os.path.expanduser("~/.gtk-bookmarks") |
70 kde_bookm = os.path.expanduser("~/.kde/share/apps/kfileplaces/bookmarks.xm") | 191 kde_bookm = os.path.expanduser("~/.kde/share/apps/kfileplaces/bookmarks.xml") |
71 bookmarks = set() | 192 bookmarks = set() |
72 try: | 193 try: |
73 with open(gnome_bookm) as gnome_fd: | 194 with open(gtk_bookm) as gtk_fd: |
74 for bm in gnome_fd.readlines(): | 195 for bm in gtk_fd.readlines(): |
75 if bm.startswith("file:///"): | 196 if bm.startswith("file:///"): |
76 bookmarks.add(bm[7:].replace('\n','')) | 197 bookmarks.add(bm[7:].replace('\n','')) |
77 except IOError: | 198 except IOError: |
78 info(_('No Gnome bookmarks file found')) | 199 info(_('No GTK bookmarks file found')) |
79 pass | 200 pass |
80 | 201 |
81 try: | 202 try: |
82 dom = minidom.parse(kde_bookm) | 203 dom = minidom.parse(kde_bookm) |
83 for elem in getElementsByTagName('bookmark'): | 204 for elem in dom.getElementsByTagName('bookmark'): |
84 bm = elem.getAttribute("href") | 205 bm = elem.getAttribute("href") |
85 if bm.startswith("file:///"): | 206 if bm.startswith("file:///"): |
86 bookmarks.add(bm[7:]) | 207 bookmarks.add(bm[7:]) |
87 except IOError: | 208 except IOError: |
88 info(_('No KDE bookmarks file found')) | 209 info(_('No KDE bookmarks file found')) |
91 return bookmarks | 212 return bookmarks |
92 | 213 |
93 def onBookmarkSelected(self, button): | 214 def onBookmarkSelected(self, button): |
94 self.path_wid.set_edit_text(os.path.expanduser(button.get_text())) | 215 self.path_wid.set_edit_text(os.path.expanduser(button.get_text())) |
95 | 216 |
96 def onPathChange(self, edit, text): | 217 def onPathChange(self, edit, path): |
97 if os.path.isdir(text): | 218 if os.path.isdir(path): |
98 del self.files_list[:] | 219 self.files_wid.showDirectory(path) |
99 files = os.listdir(text) | 220 |
100 files.sort() | 221 def onPreviousDir(self, wid): |
101 self.files_list.extend([custom_widgets.ClickableText(filename) for filename in files]) | 222 path = os.path.abspath(self.path_wid.get_edit_text()) |
223 if not os.path.isdir(path): | |
224 path = dirname(path) | |
225 self.path_wid.set_edit_text(os.path.split(path)[0]) | |
226 | |
227 def onDirClick(self, wid): | |
228 path = os.path.abspath(self.path_wid.get_edit_text()) | |
229 if not os.path.isdir(path): | |
230 path = dirname(path) | |
231 self.path_wid.set_edit_text(os.path.join(path,wid.get_text())) | |
232 | |
233 def onFileClick(self, wid): | |
234 self.ok_cb(os.path.abspath(os.path.join(self.files_wid.path,wid.get_text()))) |