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())))