Mercurial > urwid-satext
comparison urwid_satext/files_management.py @ 123:f2589475269f
file_management: unicode was badly handled. As a quick solution, we handle everything as unicode, and ignore badly encoded filenames, this may change in the future
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 05 Mar 2016 14:32:35 +0100 |
parents | 00b012549f88 |
children | 1970df98643d |
comparison
equal
deleted
inserted
replaced
122:00b012549f88 | 123:f2589475269f |
---|---|
19 | 19 |
20 import urwid | 20 import urwid |
21 import sat_widgets | 21 import sat_widgets |
22 import os, os.path | 22 import os, os.path |
23 from xml.dom import minidom | 23 from xml.dom import minidom |
24 from logging import debug, info, error | 24 import logging as log |
25 from time import time | 25 from time import time |
26 from .keys import action_key_map as a_key | 26 from .keys import action_key_map as a_key |
27 | 27 |
28 import gettext | 28 import gettext |
29 gettext.install('urwid_satext', unicode=True) | 29 gettext.install('urwid_satext', unicode=True) |
30 | 30 |
31 class PathEdit(sat_widgets.AdvancedEdit): | 31 class PathEdit(sat_widgets.AdvancedEdit): |
32 """AdvancedEdit with manage file paths""" | 32 """AdvancedEdit with manage file paths""" |
33 | 33 |
34 def keypress(self, size, key): | 34 def keypress(self, size, key): |
35 if key == '~' and self.edit_pos==0: | 35 if key == u'~' and self.edit_pos==0: |
36 expanded = os.path.expanduser('~') | 36 expanded = os.path.expanduser(u'~') |
37 self.set_edit_text(os.path.normpath(expanded+'/'+self.edit_text)) | 37 self.set_edit_text(os.path.normpath(expanded+u'/'+self.edit_text)) |
38 self.set_edit_pos(len(expanded)+1) | 38 self.set_edit_pos(len(expanded)+1) |
39 elif key == a_key['EDIT_DELETE_LAST_WORD']: | 39 elif key == a_key['EDIT_DELETE_LAST_WORD']: |
40 if self.edit_pos<2: | 40 if self.edit_pos<2: |
41 return | 41 return |
42 before = self.edit_text[:self.edit_pos] | 42 before = self.edit_text[:self.edit_pos] |
89 break | 89 break |
90 else: | 90 else: |
91 return self._w.keypress(size, key) | 91 return self._w.keypress(size, key) |
92 | 92 |
93 def showDirectory(self, path): | 93 def showDirectory(self, path): |
94 path = path.encode('utf-8') | |
95 self.path = path | 94 self.path = path |
96 del self.files_list[:] | 95 del self.files_list[:] |
97 directories = [] | 96 directories = [] |
98 files = [] | 97 files = [] |
99 try: | 98 try: |
100 for filename in os.listdir(path): | 99 for filename in os.listdir(path): |
100 if not isinstance(filename, unicode): | |
101 log.warning(u"file [{}] has a badly encode filename, ignoring it".format(filename.decode('utf-8', 'replace'))) | |
102 continue | |
101 fullpath = os.path.join(path,filename) | 103 fullpath = os.path.join(path,filename) |
102 if os.path.isdir(fullpath): | 104 if os.path.isdir(fullpath): |
103 directories.append(filename) | 105 directories.append(filename) |
104 else: | 106 else: |
105 files.append(filename) | 107 files.append(filename) |
106 except OSError: | 108 except OSError: |
107 self.files_list.append(urwid.Text(("warning",_("Impossible to list directory")),'center')) | 109 self.files_list.append(urwid.Text(("warning",_("Impossible to list directory")),'center')) |
108 directories.sort() | 110 directories.sort() |
109 files.sort() | 111 files.sort() |
110 if os.path.abspath(path)!='/' and os.path.abspath(path) != '//': | 112 if os.path.abspath(path)!=u'/' and os.path.abspath(path) != u'//': |
111 previous_wid = sat_widgets.ClickableText(('directory','..')) | 113 previous_wid = sat_widgets.ClickableText((u'directory',u'..')) |
112 urwid.connect_signal(previous_wid,'click',self.onPreviousDir) | 114 urwid.connect_signal(previous_wid,'click',self.onPreviousDir) |
113 self.files_list.append(previous_wid) | 115 self.files_list.append(previous_wid) |
114 for directory in directories: | 116 for directory in directories: |
115 if directory.startswith('.') and not self.show_hidden: | 117 if directory.startswith('.') and not self.show_hidden: |
116 continue | 118 continue |
117 dir_wid = sat_widgets.ClickableText(('directory',directory)) | 119 dir_wid = sat_widgets.ClickableText((u'directory',directory)) |
118 urwid.connect_signal(dir_wid,'click',self.onDirClick) | 120 urwid.connect_signal(dir_wid,'click',self.onDirClick) |
119 self.files_list.append(dir_wid) | 121 self.files_list.append(dir_wid) |
120 self.files_list.append(urwid.AttrMap(urwid.Divider('-'),'separator')) | 122 self.files_list.append(urwid.AttrMap(urwid.Divider(u'-'),'separator')) |
121 for filename in files: | 123 for filename in files: |
122 if filename.startswith('.') and not self.show_hidden: | 124 if filename.startswith(u'.') and not self.show_hidden: |
123 continue | 125 continue |
124 file_wid = sat_widgets.ClickableText(filename) | 126 file_wid = sat_widgets.ClickableText(filename) |
125 if self.onFileClick: | 127 if self.onFileClick: |
126 urwid.connect_signal(file_wid,'click',self.onFileClick) | 128 urwid.connect_signal(file_wid,'click',self.onFileClick) |
127 self.files_list.append(file_wid) | 129 self.files_list.append(file_wid) |
128 | |
129 | 130 |
130 | 131 |
131 class FileDialog(urwid.WidgetWrap): | 132 class FileDialog(urwid.WidgetWrap): |
132 | 133 |
133 def __init__(self, ok_cb, cancel_cb, message=None, title=_("Please select a file"), style=[]): | 134 def __init__(self, ok_cb, cancel_cb, message=None, title=_("Please select a file"), style=[]): |
139 @param style: list of string: | 140 @param style: list of string: |
140 - 'dir' if a dir path must be selected | 141 - 'dir' if a dir path must be selected |
141 """ | 142 """ |
142 self.ok_cb = ok_cb | 143 self.ok_cb = ok_cb |
143 self._type = 'dir' if 'dir' in style else 'normal' | 144 self._type = 'dir' if 'dir' in style else 'normal' |
144 self.__home_path = os.path.expanduser('~') | 145 self.__home_path = os.path.expanduser(u'~') |
145 widgets = [] | 146 widgets = [] |
146 if message: | 147 if message: |
147 widgets.append(urwid.Text(message)) | 148 widgets.append(urwid.Text(message)) |
148 widgets.append(urwid.Divider(u'─')) | 149 widgets.append(urwid.Divider(u'─')) |
149 self.path_wid = PathEdit(_('Path: ')) | 150 self.path_wid = PathEdit(_(u'Path: ')) |
150 self.path_wid.setCompletionMethod(self._directory_completion) | 151 self.path_wid.setCompletionMethod(self._directory_completion) |
151 urwid.connect_signal(self.path_wid, 'change', self.onPathChange) | 152 urwid.connect_signal(self.path_wid, 'change', self.onPathChange) |
152 widgets.append(self.path_wid) | 153 widgets.append(self.path_wid) |
153 widgets.append(urwid.Divider(u'─')) | 154 widgets.append(urwid.Divider(u'─')) |
154 header = urwid.Pile(widgets) | 155 header = urwid.Pile(widgets) |
155 bookm_list = urwid.SimpleListWalker([]) | 156 bookm_list = urwid.SimpleListWalker([]) |
156 self.bookmarks = list(self.getBookmarks()) | 157 self.bookmarks = list(self.getBookmarks()) |
157 self.bookmarks.sort() | 158 self.bookmarks.sort() |
158 for bookmark in self.bookmarks: | 159 for bookmark in self.bookmarks: |
159 if bookmark.startswith(self.__home_path): | 160 if bookmark.startswith(self.__home_path): |
160 bookmark="~"+bookmark[len(self.__home_path):] | 161 bookmark=u"~"+bookmark[len(self.__home_path):] |
161 book_wid = sat_widgets.ClickableText(bookmark) | 162 book_wid = sat_widgets.ClickableText(bookmark) |
162 urwid.connect_signal(book_wid, 'click', self.onBookmarkSelected) | 163 urwid.connect_signal(book_wid, 'click', self.onBookmarkSelected) |
163 bookm_list.append(book_wid) | 164 bookm_list.append(book_wid) |
164 bookm_wid = urwid.Frame(urwid.ListBox(bookm_list), urwid.AttrMap(urwid.Text(_('Bookmarks'),'center'),'title')) | 165 bookm_wid = urwid.Frame(urwid.ListBox(bookm_list), urwid.AttrMap(urwid.Text(_(u'Bookmarks'),'center'),'title')) |
165 self.files_wid = FilesViewer(self.onPreviousDir, self.onDirClick, self.onFileClick if self._type == 'normal' else None) | 166 self.files_wid = FilesViewer(self.onPreviousDir, self.onDirClick, self.onFileClick if self._type == 'normal' else None) |
166 center_row = urwid.Columns([('weight',2,bookm_wid), | 167 center_row = urwid.Columns([('weight',2,bookm_wid), |
167 ('weight',8,sat_widgets.VerticalSeparator(self.files_wid))]) | 168 ('weight',8,sat_widgets.VerticalSeparator(self.files_wid))]) |
168 | 169 |
169 buttons = [] | 170 buttons = [] |
182 path = os.path.abspath(self.path_wid.get_edit_text()) | 183 path = os.path.abspath(self.path_wid.get_edit_text()) |
183 if os.path.isdir(path): | 184 if os.path.isdir(path): |
184 self.ok_cb(path) | 185 self.ok_cb(path) |
185 | 186 |
186 def _directory_completion(self, path, completion_data): | 187 def _directory_completion(self, path, completion_data): |
188 assert isinstance(path, unicode) | |
187 path=os.path.abspath(path) | 189 path=os.path.abspath(path) |
188 if not os.path.isdir(path): | 190 if not os.path.isdir(path): |
189 head,dir_start = os.path.split(path) | 191 head,dir_start = os.path.split(path) |
190 else: | 192 else: |
191 head=path | 193 head=path |
192 dir_start='' | 194 dir_start=u'' |
193 try: | 195 try: |
194 filenames = os.listdir(head) | 196 filenames = os.listdir(head) |
197 to_remove = [] | |
198 | |
199 # we remove badly encoded files | |
200 for filename in filenames: | |
201 if not isinstance(filename, unicode): | |
202 log.warning(u"file [{}] has a badly encode filename, ignoring it".format(filename.decode('utf-8', 'replace'))) | |
203 to_remove.append(filename) | |
204 for filename in to_remove: | |
205 filenames.remove(filename) | |
206 | |
195 filenames.sort() | 207 filenames.sort() |
196 try: | 208 try: |
197 start_idx=filenames.index(completion_data['last_dir'])+1 | 209 start_idx=filenames.index(completion_data['last_dir'])+1 |
198 if start_idx == len(filenames): | 210 if start_idx == len(filenames): |
199 start_idx = 0 | 211 start_idx = 0 |
207 except OSError: | 219 except OSError: |
208 pass | 220 pass |
209 return path | 221 return path |
210 | 222 |
211 def getBookmarks(self): | 223 def getBookmarks(self): |
212 gtk_bookm = os.path.expanduser("~/.gtk-bookmarks") | 224 gtk_bookm = os.path.expanduser(u"~/.gtk-bookmarks") |
213 kde_bookm = os.path.expanduser("~/.kde/share/apps/kfileplaces/bookmarks.xml") | 225 kde_bookm = os.path.expanduser(u"~/.kde/share/apps/kfileplaces/bookmarks.xml") |
214 bookmarks = set() | 226 bookmarks = set() |
215 try: | 227 try: |
216 with open(gtk_bookm) as gtk_fd: | 228 with open(gtk_bookm) as gtk_fd: |
217 for bm in gtk_fd.readlines(): | 229 for bm in gtk_fd.readlines(): |
218 if bm.startswith("file:///"): | 230 if bm.startswith("file:///"): |
219 bookmarks.add(bm[7:].replace('\n','')) | 231 bookmarks.add(bm[7:].replace('\n','').decode('utf-8', 'replace')) |
220 except IOError: | 232 except IOError: |
221 info(_('No GTK bookmarks file found')) | 233 log.info(_(u'No GTK bookmarks file found')) |
222 pass | 234 pass |
223 | 235 |
224 try: | 236 try: |
225 dom = minidom.parse(kde_bookm) | 237 dom = minidom.parse(kde_bookm) |
226 for elem in dom.getElementsByTagName('bookmark'): | 238 for elem in dom.getElementsByTagName('bookmark'): |
227 bm = elem.getAttribute("href") | 239 bm = elem.getAttribute("href") |
228 if bm.startswith("file:///"): | 240 if bm.startswith("file:///"): |
229 bookmarks.add(bm[7:]) | 241 bookmarks.add(bm[7:].decode('utf-8', 'replace')) |
230 except IOError: | 242 except IOError: |
231 info(_('No KDE bookmarks file found')) | 243 log.info(_('No KDE bookmarks file found')) |
232 pass | 244 pass |
233 | 245 |
234 return bookmarks | 246 return bookmarks |
235 | 247 |
236 def onBookmarkSelected(self, button): | 248 def onBookmarkSelected(self, button): |