Top

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

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

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

prefix for incremental searches

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)