Mercurial > urwid-satext
diff urwid_satext/files_management.py @ 30:1aeb3540aa49
files reorganisation after project separation. new README, and COPYING files
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 28 Dec 2010 11:53:18 +0100 |
parents | frontends/primitivus/files_management.py@fcc20ac7b68a |
children | 818393067e54 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/urwid_satext/files_management.py Tue Dec 28 11:53:18 2010 +0100 @@ -0,0 +1,233 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Primitivus: a SAT frontend +Copyright (C) 2009, 2010 Jérôme Poisson (goffi@goffi.org) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +""" + +import urwid +import sat_widgets +import os, os.path +from xml.dom import minidom +from logging import debug, info, error +from time import time + +class PathEdit(sat_widgets.AdvancedEdit): + """AdvancedEdit with manage file paths""" + + def keypress(self, size, key): + if key == '~' and self.edit_pos==0: + expanded = os.path.expanduser('~') + self.set_edit_text(os.path.normpath(expanded+'/'+self.edit_text)) + self.set_edit_pos(len(expanded)+1) + elif key == 'ctrl w': + if self.edit_pos<2: + return + before = self.edit_text[:self.edit_pos] + pos = (before[:-1] if before.endswith('/') else before).rfind("/")+1 + self.set_edit_text(before[:pos] + self.edit_text[self.edit_pos:]) + self.set_edit_pos(pos) + return + else: + return super(PathEdit, self).keypress(size, key) + +class FilesViewer(urwid.WidgetWrap): + """List specialised for files""" + + def __init__(self, onPreviousDir, onDirClick, onFileClick): + self.path='' + self.key_cache = '' + self.key_time = time() + self.onPreviousDir = onPreviousDir + self.onDirClick = onDirClick + self.onFileClick = onFileClick + self.files_list = urwid.SimpleListWalker([]) + self.show_hidden = True + listbox = urwid.ListBox(self.files_list) + urwid.WidgetWrap.__init__(self, listbox) + + def keypress(self, size, key): + if key=='meta h': + #(un)hide hidden files + self.show_hidden = not self.show_hidden + self.showDirectory(self.path) + if key=='meta d': + #jump to directories + if self.files_list: + self._w.set_focus(0) + elif key=='meta f': + for idx in range(len(self.files_list)): + if isinstance(self.files_list[idx].base_widget,urwid.Divider): + if idx<len(self.files_list)-1: + self._w.set_focus(idx+1) + break + elif len(key) == 1: + if time() - self.key_time > 2: + self.key_cache=key + else: + self.key_cache+=key + self.key_time = time() + for idx in range(len(self.files_list)): + if isinstance(self.files_list[idx],sat_widgets.ClickableText) and self.files_list[idx].get_text().lower().startswith(self.key_cache.lower()): + self._w.set_focus(idx) + break + else: + return self._w.keypress(size, key) + + def showDirectory(self, path): + self.path = path + del self.files_list[:] + directories = [] + files = [] + try: + for filename in os.listdir(path): + fullpath = os.path.join(path,filename) + if os.path.isdir(fullpath): + directories.append(filename) + else: + files.append(filename) + except OSError: + self.files_list.append(urwid.Text(("warning",_("Impossible to list directory")),'center')) + directories.sort() + files.sort() + if os.path.abspath(path)!='/' and os.path.abspath(path) != '//': + previous_wid = sat_widgets.ClickableText(('directory','..')) + urwid.connect_signal(previous_wid,'click',self.onPreviousDir) + self.files_list.append(previous_wid) + for directory in directories: + if directory.startswith('.') and not self.show_hidden: + continue + dir_wid = sat_widgets.ClickableText(('directory',directory)) + urwid.connect_signal(dir_wid,'click',self.onDirClick) + self.files_list.append(dir_wid) + self.files_list.append(urwid.AttrMap(urwid.Divider('-'),'separator')) + for filename in files: + if filename.startswith('.') and not self.show_hidden: + continue + file_wid = sat_widgets.ClickableText(filename) + urwid.connect_signal(file_wid,'click',self.onFileClick) + self.files_list.append(file_wid) + + + +class FileDialog(urwid.WidgetWrap): + + def __init__(self, ok_cb, cancel_cb, title=_("Please select a file"), style=[]): + """Create file dialog + @param title: title of the window/popup + @param style: NOT USED YET #FIXME + """ + self.ok_cb = ok_cb + self.__home_path = os.path.expanduser('~') + self.path_wid = PathEdit(_('Path: ')) + self.path_wid.setCompletionMethod(self._directory_completion) + urwid.connect_signal(self.path_wid, 'change', self.onPathChange) + header = urwid.Pile([self.path_wid, urwid.Divider(u'─')]) + bookm_list = urwid.SimpleListWalker([]) + self.bookmarks = list(self.getBookmarks()) + self.bookmarks.sort() + for bookmark in self.bookmarks: + if bookmark.startswith(self.__home_path): + bookmark="~"+bookmark[len(self.__home_path):] + book_wid = sat_widgets.ClickableText(bookmark) + urwid.connect_signal(book_wid, 'click', self.onBookmarkSelected) + bookm_list.append(book_wid) + bookm_wid = urwid.Frame(urwid.ListBox(bookm_list), urwid.AttrMap(urwid.Text(_('Bookmarks'),'center'),'title')) + self.files_wid = FilesViewer(self.onPreviousDir, self.onDirClick, self.onFileClick) + center_row = urwid.Columns([('weight',2,bookm_wid), + ('weight',8,sat_widgets.VerticalSeparator(self.files_wid))]) + + buttons = [] + buttons.append(sat_widgets.CustomButton(_('Cancel'),cancel_cb)) + max_len = max([button.getSize() for button in buttons]) + buttons_wid = urwid.GridFlow(buttons,max_len,1,0,'center') + main_frame = sat_widgets.FocusFrame(center_row, header, buttons_wid) + decorated = sat_widgets.LabelLine(main_frame, sat_widgets.SurroundedText(title)) + urwid.WidgetWrap.__init__(self, decorated) + self.path_wid.set_edit_text(os.getcwdu()) + + def _directory_completion(self, path, completion_data): + path=os.path.abspath(path) + if not os.path.isdir(path): + head,dir_start = os.path.split(path) + else: + head=path + dir_start='' + try: + filenames = os.listdir(head) + filenames.sort() + try: + start_idx=filenames.index(completion_data['last_dir'])+1 + if start_idx == len(filenames): + start_idx = 0 + except (KeyError,ValueError): + start_idx = 0 + for idx in range(start_idx,len(filenames)) + range(0,start_idx): + full_path = os.path.join(head,filenames[idx]) + if filenames[idx].lower().startswith(dir_start.lower()) and os.path.isdir(full_path): + completion_data['last_dir'] = filenames[idx] + return full_path + except OSError: + pass + return path + + def getBookmarks(self): + gtk_bookm = os.path.expanduser("~/.gtk-bookmarks") + kde_bookm = os.path.expanduser("~/.kde/share/apps/kfileplaces/bookmarks.xml") + bookmarks = set() + try: + with open(gtk_bookm) as gtk_fd: + for bm in gtk_fd.readlines(): + if bm.startswith("file:///"): + bookmarks.add(bm[7:].replace('\n','')) + except IOError: + info(_('No GTK bookmarks file found')) + pass + + try: + dom = minidom.parse(kde_bookm) + for elem in dom.getElementsByTagName('bookmark'): + bm = elem.getAttribute("href") + if bm.startswith("file:///"): + bookmarks.add(bm[7:]) + except IOError: + info(_('No KDE bookmarks file found')) + pass + + return bookmarks + + def onBookmarkSelected(self, button): + self.path_wid.set_edit_text(os.path.expanduser(button.get_text())) + + def onPathChange(self, edit, path): + if os.path.isdir(path): + self.files_wid.showDirectory(path) + + def onPreviousDir(self, wid): + path = os.path.abspath(self.path_wid.get_edit_text()) + if not os.path.isdir(path): + path = dirname(path) + self.path_wid.set_edit_text(os.path.split(path)[0]) + + def onDirClick(self, wid): + path = os.path.abspath(self.path_wid.get_edit_text()) + if not os.path.isdir(path): + path = dirname(path) + self.path_wid.set_edit_text(os.path.join(path,wid.get_text())) + + def onFileClick(self, wid): + self.ok_cb(os.path.abspath(os.path.join(self.files_wid.path,wid.get_text())))