ped_dialog.file_dialog module
module that implements file open/new dialog for the ped editor
# Copyright 2009 James P Goodwin ped tiny python editor """ module that implements file open/new dialog for the ped editor """ import curses import curses.ascii import sys import os from ped_dialog import dialog from ped_core import keytab def get_dir(path,showhidden=False): """ get a directory listing of path, directories are prefixed with <DIR> if showhidden == False hidden files are not include, otherwise they are returns the directory path, the list of directories and list of files as a tuple""" (dirpath, dirnames, filenames) = next(os.walk(path)) if not showhidden: dirnames = [d for d in dirnames if d[0] != "."] filenames = [f for f in filenames if f[0] != "." and f[-1] != "~" and not f.endswith(".bak")] dirnames.sort() filenames.sort() dirnames = ["<DIR> .."] + ["<DIR> "+d for d in dirnames] return (dirpath, dirnames, filenames) class FileListBox(dialog.ListBox): """ list box subclass for file lists, handles searching past the <DIR> prefix for incremental searches""" def find(self,searchfor): """ subclass the find method to find the string either with the dir prefix or without it """ if not dialog.ListBox.find(self,"<DIR> "+searchfor): return dialog.ListBox.find(self,searchfor) else: return True class FileDialog(dialog.Dialog): """ dialog subclass that implements a file open dialog allowing browsing files and directories and selecting a file or typing in a file name """ def __init__(self,scr,title = "File Dialog", path="."): """ takes a curses window scr, title for the border, and a starting path """ (dirpath, dirnames, filenames) = get_dir(path) max_y, max_x = scr.getmaxyx() dw = max_x - 4 self.file_list = FileListBox("files",1,2,3,10,dw-4,"Directory Listing",0,dirnames+filenames) self.current_dir = dialog.Prompt("dir",5,2,2,"Path: ",dw-10,os.path.abspath(dirpath)) self.file_name = dialog.Prompt("file",2,2,14,"File: ",dw-10) dialog.Dialog.__init__(self,scr,"FileDialog",20,dw, [ dialog.Frame(title), self.file_list, self.current_dir, self.file_name, dialog.Button("Ok",3,2,16,"OK",dialog.Component.CMP_KEY_OK), dialog.Button("Cancel",4,9,16,"CANCEL",dialog.Component.CMP_KEY_CANCEL)]) self.set_history(False) def handle(self,ch): """ key handler for selection from the file and directory list, browsing another directory selecting a file or entering one """ focus_index = self.current focus_field = self.focus_list[self.current][1] ret_ch = dialog.Dialog.handle(self,ch) if focus_field == self.file_list and ch in [keytab.KEYTAB_SPACE,keytab.KEYTAB_CR]: (selection, items) = focus_field.getvalue() choice = items[selection] if choice.startswith('<DIR>'): (dirpath,dirnames,filenames) = get_dir(os.path.join(self.current_dir.getvalue(),choice[6:])) focus_field.setvalue((0,dirnames+filenames)) self.setvalue({"dir":os.path.abspath(dirpath)}) # important to do it this way to work with history os.chdir(os.path.abspath(dirpath)) self.current = focus_index ret_ch = dialog.Component.CMP_KEY_NOP else: self.file_name.setvalue(choice) elif focus_field == self.current_dir and ch in [keytab.KEYTAB_TAB,keytab.KEYTAB_BTAB,keytab.KEYTAB_CR]: dir = focus_field.getvalue() (dirpath,dirnames,filenames) = get_dir(dir) self.file_list.setvalue((0,dirnames+filenames)) os.chdir(os.path.abspath(dirpath)) return ret_ch def main(stdscr): """ test main for the file dialog """ d = FileDialog(stdscr) d.main() if __name__ == '__main__': curses.wrapper(main)
Functions
def get_dir(
path, showhidden=False)
get a directory listing of path, directories are prefixed with
def get_dir(path,showhidden=False): """ get a directory listing of path, directories are prefixed with <DIR> if showhidden == False hidden files are not include, otherwise they are returns the directory path, the list of directories and list of files as a tuple""" (dirpath, dirnames, filenames) = next(os.walk(path)) if not showhidden: dirnames = [d for d in dirnames if d[0] != "."] filenames = [f for f in filenames if f[0] != "." and f[-1] != "~" and not f.endswith(".bak")] dirnames.sort() filenames.sort() dirnames = ["<DIR> .."] + ["<DIR> "+d for d in dirnames] return (dirpath, dirnames, filenames)
def main(
stdscr)
test main for the file dialog
def main(stdscr): """ test main for the file dialog """ d = FileDialog(stdscr) d.main()
Classes
class FileDialog
dialog subclass that implements a file open dialog allowing browsing files and directories and selecting a file or typing in a file name
class FileDialog(dialog.Dialog): """ dialog subclass that implements a file open dialog allowing browsing files and directories and selecting a file or typing in a file name """ def __init__(self,scr,title = "File Dialog", path="."): """ takes a curses window scr, title for the border, and a starting path """ (dirpath, dirnames, filenames) = get_dir(path) max_y, max_x = scr.getmaxyx() dw = max_x - 4 self.file_list = FileListBox("files",1,2,3,10,dw-4,"Directory Listing",0,dirnames+filenames) self.current_dir = dialog.Prompt("dir",5,2,2,"Path: ",dw-10,os.path.abspath(dirpath)) self.file_name = dialog.Prompt("file",2,2,14,"File: ",dw-10) dialog.Dialog.__init__(self,scr,"FileDialog",20,dw, [ dialog.Frame(title), self.file_list, self.current_dir, self.file_name, dialog.Button("Ok",3,2,16,"OK",dialog.Component.CMP_KEY_OK), dialog.Button("Cancel",4,9,16,"CANCEL",dialog.Component.CMP_KEY_CANCEL)]) self.set_history(False) def handle(self,ch): """ key handler for selection from the file and directory list, browsing another directory selecting a file or entering one """ focus_index = self.current focus_field = self.focus_list[self.current][1] ret_ch = dialog.Dialog.handle(self,ch) if focus_field == self.file_list and ch in [keytab.KEYTAB_SPACE,keytab.KEYTAB_CR]: (selection, items) = focus_field.getvalue() choice = items[selection] if choice.startswith('<DIR>'): (dirpath,dirnames,filenames) = get_dir(os.path.join(self.current_dir.getvalue(),choice[6:])) focus_field.setvalue((0,dirnames+filenames)) self.setvalue({"dir":os.path.abspath(dirpath)}) # important to do it this way to work with history os.chdir(os.path.abspath(dirpath)) self.current = focus_index ret_ch = dialog.Component.CMP_KEY_NOP else: self.file_name.setvalue(choice) elif focus_field == self.current_dir and ch in [keytab.KEYTAB_TAB,keytab.KEYTAB_BTAB,keytab.KEYTAB_CR]: dir = focus_field.getvalue() (dirpath,dirnames,filenames) = get_dir(dir) self.file_list.setvalue((0,dirnames+filenames)) os.chdir(os.path.abspath(dirpath)) return ret_ch
Ancestors (in MRO)
- FileDialog
- ped_dialog.dialog.Dialog
- ped_dialog.dialog.Component
- builtins.object
Class variables
var CMP_KEY_CANCEL
var CMP_KEY_NOP
var CMP_KEY_OK
var history
Static methods
def __init__(
self, scr, title='File Dialog', path='.')
takes a curses window scr, title for the border, and a starting path
def __init__(self,scr,title = "File Dialog", path="."): """ takes a curses window scr, title for the border, and a starting path """ (dirpath, dirnames, filenames) = get_dir(path) max_y, max_x = scr.getmaxyx() dw = max_x - 4 self.file_list = FileListBox("files",1,2,3,10,dw-4,"Directory Listing",0,dirnames+filenames) self.current_dir = dialog.Prompt("dir",5,2,2,"Path: ",dw-10,os.path.abspath(dirpath)) self.file_name = dialog.Prompt("file",2,2,14,"File: ",dw-10) dialog.Dialog.__init__(self,scr,"FileDialog",20,dw, [ dialog.Frame(title), self.file_list, self.current_dir, self.file_name, dialog.Button("Ok",3,2,16,"OK",dialog.Component.CMP_KEY_OK), dialog.Button("Cancel",4,9,16,"CANCEL",dialog.Component.CMP_KEY_CANCEL)]) self.set_history(False)
def btab(
self)
def btab(self): if self.focus_list: self.push_history(self.focus_list[self.current][1]) self.current -= 1 if self.current < 0: self.current = len(self.focus_list)-1
def focus(
self)
called when component is the focus
def focus(self): self.focus_list = [] for c in self.children: self.pop_history(c) if c.getorder() > 0: self.focus_list.append((c.getorder(),c)) if not self.focus_list: self.current = 0 return self.focus_list.sort(key=lambda x: x[0]) self.current = 0
def getname(
self)
get the name of this component
def getname(self): """ get the name of this component """ return self.name
def getorder(
self)
get this component's tab order number
def getorder(self): """ get this component's tab order number """ return self.order
def getparent(
self)
get this component's curses target window
def getparent(self): """ get this component's curses target window """ return self.parent
def getvalue(
self)
return the current value of the component
def getvalue(self): value = {} for c in self.children: if c.getname(): value[c.getname()] = c.getvalue() return value
def goto(
self, component)
move focus to this component
def goto(self, component): """ move focus to this component """ for i in range(0,len(self.focus_list)): if self.focus_list[i][1] == component: self.current = i return True return False
def handle(
self, ch)
key handler for selection from the file and directory list, browsing another directory selecting a file or entering one
def handle(self,ch): """ key handler for selection from the file and directory list, browsing another directory selecting a file or entering one """ focus_index = self.current focus_field = self.focus_list[self.current][1] ret_ch = dialog.Dialog.handle(self,ch) if focus_field == self.file_list and ch in [keytab.KEYTAB_SPACE,keytab.KEYTAB_CR]: (selection, items) = focus_field.getvalue() choice = items[selection] if choice.startswith('<DIR>'): (dirpath,dirnames,filenames) = get_dir(os.path.join(self.current_dir.getvalue(),choice[6:])) focus_field.setvalue((0,dirnames+filenames)) self.setvalue({"dir":os.path.abspath(dirpath)}) # important to do it this way to work with history os.chdir(os.path.abspath(dirpath)) self.current = focus_index ret_ch = dialog.Component.CMP_KEY_NOP else: self.file_name.setvalue(choice) elif focus_field == self.current_dir and ch in [keytab.KEYTAB_TAB,keytab.KEYTAB_BTAB,keytab.KEYTAB_CR]: dir = focus_field.getvalue() (dirpath,dirnames,filenames) = get_dir(dir) self.file_list.setvalue((0,dirnames+filenames)) os.chdir(os.path.abspath(dirpath)) return ret_ch
def handle_mouse(
self)
def handle_mouse(self): if self.focus_list and self.win: try: mid, mx, my, mz, mtype = curses.getmouse() by,bx = self.win.getbegyx() oy = my - by ox = mx - bx for i in range(0,len(self.focus_list)): c = self.focus_list[i][1] ret = c.mouse_event(ox,oy,mtype) if ret >= 0: self.current = i return ret else: return -1 except: return -1
def isempty(
self)
test if the component entry is empty
def isempty(self): """ test if the component entry is empty """ return False
def main(
self, blocking=True, force=False, ch_in=None)
def main(self,blocking = True,force=False,ch_in = None): curses.mousemask( curses.BUTTON1_PRESSED| curses.BUTTON1_RELEASED| curses.BUTTON1_CLICKED) self.win.nodelay(1) self.win.notimeout(0) self.win.timeout(0) old_cursor = curses.curs_set(1) while (1): if (not keymap.keypending(self.win)) or force: self.render() if not ch_in: ch = self.handle(keymap.get_keyseq(self.win,keymap.getch(self.win))) else: ch = self.handle(ch_in) if blocking: if ch == Component.CMP_KEY_CANCEL: curses.curs_set(old_cursor) return {} elif ch == Component.CMP_KEY_OK: curses.curs_set(old_cursor) return self.getvalue() else: if ch == Component.CMP_KEY_CANCEL: curses.curs_set(old_cursor) return (ch, {}) else: curses.curs_set(old_cursor) return (ch, self.getvalue())
def mouse_event(
self, ox, oy, mtype)
handle mouse events return key value or -1 for not handled
def mouse_event(self, ox, oy, mtype): """ handle mouse events return key value or -1 for not handled """ return -1
def pop_history(
self, child)
def pop_history( self, child ): if not self.enable_history: return if not issubclass(child.__class__, Prompt): return if self.getname() and child.getname() and child.getorder() >= 0: key = (self.getname(), child.getname()) if key in Dialog.history: hist = Dialog.history[key] self.hist_idx += 1 if self.hist_idx > len(hist): self.hist_idx = 0 child.setvalue(hist[-self.hist_idx])
def push_history(
self, child)
def push_history( self, child ): if not self.enable_history: return if not issubclass(child.__class__, Prompt): return if self.getname() and child.getname() and child.getorder() >= 0 and not child.isempty(): key = (self.getname(), child.getname()) if key in Dialog.history: if Dialog.history[key][-1] != child.getvalue(): Dialog.history[key].append(child.getvalue()) else: Dialog.history[key] = [child.getvalue()]
def render(
self)
render the component use parent as target
def render(self): self.win.leaveok(1) for c in self.children: if not self.focus_list or self.focus_list[self.current][1] != c: c.render() self.win.leaveok(0) if self.focus_list: self.focus_list[self.current][1].focus() self.focus_list[self.current][1].render() self.win.refresh()
def resize(
self)
def resize(self): pass
def set_history(
self, state)
def set_history( self, state ): self.enable_history = state
def setparent(
self, parent)
set the parent curses target window
def setparent(self,parent): """ set the parent curses target window """ self.parent = parent
def setpos(
self, x, y)
set the position of this component
def setpos(self, x, y ): """ set the position of this component """ self.x = x self.y = y
def setsize(
self, height, width)
set the width of this component
def setsize(self, height, width ): """ set the width of this component """ self.height = height self.width = width
def setvalue(
self, value)
set the components value, may be tuple or other data structure
def setvalue(self, value): for c in self.children: if c.getname() in value: c.setvalue(value[c.getname()]) self.push_history(c)
def tab(
self)
def tab(self): if self.focus_list: self.push_history(self.focus_list[self.current][1]) self.current += 1 if self.current >= len(self.focus_list): self.current = 0
Instance variables
var current_dir
var file_list
var file_name
class FileListBox
list box subclass for file lists, handles searching past the
class FileListBox(dialog.ListBox): """ list box subclass for file lists, handles searching past the <DIR> prefix for incremental searches""" def find(self,searchfor): """ subclass the find method to find the string either with the dir prefix or without it """ if not dialog.ListBox.find(self,"<DIR> "+searchfor): return dialog.ListBox.find(self,searchfor) else: return True
Ancestors (in MRO)
- FileListBox
- ped_dialog.dialog.ListBox
- ped_dialog.dialog.Component
- builtins.object
Class variables
var CMP_KEY_CANCEL
var CMP_KEY_NOP
var CMP_KEY_OK
Static methods
def __init__(
self, name, order, x, y, height, width, label, selection=0, lst=[])
all components have a name and a tab order, order == -1 means exclude from tab
def __init__(self, name, order, x, y, height, width, label, selection = 0, lst = []): Component.__init__(self,name,order) self.x = x self.y = y self.height = height self.width = width self.label = label self.selection = selection self.search = "" self.top = selection if self.top < 0: self.top = 0 self.list = lst self.isfocus = False
def cdown(
self)
def cdown(self): if len(self.list): self.selection += 1 if self.selection >= len(self.list): self.selection = len(self.list)-1 if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3)
def cpgdn(
self)
def cpgdn(self): if len(self.list): self.selection += (self.height-2) if self.selection >= len(self.list): self.selection = len(self.list)-1 if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3)
def cpgup(
self)
def cpgup(self): if len(self.list): self.selection -= (self.height-2) if self.selection < 0: self.selection = 0 if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3)
def cup(
self)
def cup(self): if len(self.list): self.selection -= 1 if self.selection < 0: self.selection = 0 if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3)
def end(
self)
def end(self): if len(self.list): self.selection = len(self.list)-1 self.top = self.selection-(self.height-3) if self.top < 0: self.top = 0
def find(
self, searchfor)
subclass the find method to find the string either with the dir prefix or without it
def find(self,searchfor): """ subclass the find method to find the string either with the dir prefix or without it """ if not dialog.ListBox.find(self,"<DIR> "+searchfor): return dialog.ListBox.find(self,searchfor) else: return True
def focus(
self)
called when component is the focus
def focus(self): self.isfocus = True
def getname(
self)
get the name of this component
def getname(self): """ get the name of this component """ return self.name
def getorder(
self)
get this component's tab order number
def getorder(self): """ get this component's tab order number """ return self.order
def getparent(
self)
get this component's curses target window
def getparent(self): """ get this component's curses target window """ return self.parent
def getvalue(
self)
return the current value of the component
def getvalue(self): return (self.selection,self.list)
def handle(
self, ch)
handle keystrokes for this component
def handle(self,ch): if len(ch) == 1 and curses.ascii.isprint(ord(ch[0])): self.search += ch self.find(self.search) elif ch == keytab.KEYTAB_BACKSPACE: if self.search: self.search = self.search[0:-1] self.find(self.search) elif ch == keytab.KEYTAB_F03: if self.search: self.cdown() if not self.find(self.search): self.cup() elif ch == keytab.KEYTAB_LEFT or ch == keytab.KEYTAB_UP: self.cup() elif ch == keytab.KEYTAB_RIGHT or ch == keytab.KEYTAB_DOWN: self.cdown() elif ch == keytab.KEYTAB_HOME: self.home() elif ch == keytab.KEYTAB_END: self.end() elif ch == keytab.KEYTAB_PAGEUP: self.cpgup() elif ch == keytab.KEYTAB_PAGEDOWN: self.cpgdn() elif ch == keytab.KEYTAB_RESIZE: return ch elif ch in [keytab.KEYTAB_SPACE,keytab.KEYTAB_CR,keytab.KEYTAB_TAB,keytab.KEYTAB_ESC,keytab.KEYTAB_BTAB]: self.search = "" return ch return Component.CMP_KEY_NOP
def home(
self)
def home(self): if len(self.list): self.selection = 0 self.top = 0
def isempty(
self)
test if the component entry is empty
def isempty(self): """ test if the component entry is empty """ return False
def mouse_event(
self, ox, oy, mtype)
handle mouse events return key value or -1 for not handled
def mouse_event(self, ox, oy, mtype): if ox >= self.x and ox < self.x+self.width and oy >= self.y and oy <= self.y+self.height: oy = (oy - self.y) - 1 if oy >= 0: if mtype & curses.BUTTON1_CLICKED: if self.top+oy < len(self.list): self.selection = self.top+oy return keytab.KEYTAB_CR return -1
def render(
self)
render the component use parent as target
def render(self): win = self.getparent() if win: if self.isfocus: lattr = curses.A_BOLD else: lattr = curses.A_NORMAL x = self.x y = self.y width = self.width height = self.height rect(win,x,y,width,height,self.label,lattr) x+=1 y+=1 width -=2 height -=2 top = self.top off = 0 cy = -1 while top < len(self.list) and off < height: if top == self.selection: rattr = curses.A_REVERSE cy = y+off else: if self.isfocus: rattr = curses.A_BOLD else: rattr = curses.A_NORMAL win.addstr(y+off,x,pad(self.list[top],width)[0:width],rattr) top += 1 off += 1 if self.isfocus and cy > 0: win.move(cy,x) self.isfocus = False
def setparent(
self, parent)
set the parent curses target window
def setparent(self,parent): """ set the parent curses target window """ self.parent = parent
def setpos(
self, x, y)
set the position of this component
def setpos(self, x, y ): """ set the position of this component """ self.x = x self.y = y
def setsize(
self, height, width)
set the width of this component
def setsize(self, height, width ): """ set the width of this component """ self.height = height self.width = width
def setvalue(
self, value)
set the components value, may be tuple or other data structure
def setvalue(self,value): self.selection = value[0] self.list = value[1] if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3)