pyceo/ceo/urwid/widgets.py

179 lines
6.3 KiB
Python

import urwid, ldap
from ceo.urwid.window import raise_back, push_window
import ceo.ldapi as ldapi
csclub_uri = "ldap://ldap1.csclub.uwaterloo.ca/ ldap://ldap2.csclub.uwaterloo.ca"
csclub_base = "dc=csclub,dc=uwaterloo,dc=ca"
def make_menu(items):
items = [ urwid.AttrWrap( ButtonText( cb, data, txt ), 'menu', 'selected') for (txt, cb, data) in items ]
return urwid.ListBox( items )
def push_wizard(name, pages, dimensions=(50, 10)):
state = {}
wiz = Wizard()
for page in pages:
if type(page) != tuple:
page = (page, )
wiz.add_panel( page[0](state, *page[1:]) )
push_window( urwid.Filler( urwid.Padding(
urwid.LineBox(wiz), 'center', dimensions[0]),
'middle', dimensions[1] ), name )
class ButtonText(urwid.Text):
def __init__(self, callback, data, *args, **kwargs):
self.callback = callback
self.data = data
urwid.Text.__init__(self, *args, **kwargs)
def selectable(self):
return True
def keypress(self, size, key):
if key == 'enter' and self.callback:
self.callback(self.data)
else:
return key
class SingleEdit(urwid.Edit):
def keypress(self, size, key):
if key == 'enter':
return urwid.Edit.keypress(self, size, 'down')
else:
return urwid.Edit.keypress(self, size, key)
class SingleIntEdit(urwid.IntEdit):
def keypress(self, size, key):
if key == 'enter':
return urwid.Edit.keypress(self, size, 'down')
else:
return urwid.Edit.keypress(self, size, key)
class WordEdit(SingleEdit):
def valid_char(self, ch):
return urwid.Edit.valid_char(self, ch) and ch != ' '
class LdapWordEdit(WordEdit):
ldap = None
index = None
def __init__(self, uri, base, attr, *args):
try:
self.ldap = ldap.initialize(uri)
self.ldap.simple_bind_s("", "")
except ldap.LDAPError:
return WordEdit.__init__(self, *args)
self.base = base
self.attr = ldapi.escape(attr)
return WordEdit.__init__(self, *args)
def keypress(self, size, key):
if (key == 'tab' or key == 'shift tab') and self.ldap != None:
if self.index != None:
if key == 'tab':
self.index = (self.index + 1) % len(self.choices)
elif key == 'shift tab':
self.index = (self.index - 1) % len(self.choices)
text = self.choices[self.index]
self.set_edit_text(text)
self.set_edit_pos(len(text))
else:
try:
text = self.get_edit_text()
search = ldapi.escape(text)
matches = self.ldap.search_s(self.base,
ldap.SCOPE_SUBTREE, '(%s=%s*)' % (self.attr, search))
self.choices = [ text ]
for match in matches:
(_, attrs) = match
self.choices += attrs['uid']
self.choices.sort()
self.index = 0
self.keypress(size, key)
except ldap.LDAPError, e:
pass
else:
self.index = None
return WordEdit.keypress(self, size, key)
class LdapFilterWordEdit(LdapWordEdit):
def __init__(self, uri, base, attr, map, *args):
LdapWordEdit.__init__(self, uri, base, attr, *args)
self.map = map
def keypress(self, size, key):
if self.ldap != None:
if key == 'enter' or key == 'down' or key == 'up':
search = ldapi.escape(self.get_edit_text())
try:
matches = self.ldap.search_s(self.base,
ldap.SCOPE_SUBTREE, '(%s=%s)' % (self.attr, search))
if len(matches) > 0:
(_, attrs) = matches[0]
for (k, v) in self.map.items():
if attrs.has_key(k) and len(attrs[k]) > 0:
v.set_edit_text(attrs[k][0])
except ldap.LDAPError:
pass
return LdapWordEdit.keypress(self, size, key)
class PassEdit(SingleEdit):
def get_text(self):
text = urwid.Edit.get_text(self)
return (self.caption + " " * len(self.get_edit_text()), text[1])
class Wizard(urwid.WidgetWrap):
def __init__(self):
self.selected = None
self.panels = []
self.panelwrap = urwid.WidgetWrap( urwid.SolidFill() )
self.back = urwid.Button("Back", self.back)
self.next = urwid.Button("Next", self.next)
self.buttons = urwid.Columns( [ self.back, self.next ], dividechars=3, focus_column=1 )
pad = urwid.Padding( self.buttons, ('fixed right', 2), 19 )
self.pile = urwid.Pile( [self.panelwrap, ('flow', pad)], 0 )
urwid.WidgetWrap.__init__(self, self.pile)
def add_panel(self, panel):
self.panels.append( panel )
if len(self.panels) == 1:
self.select(0)
def select(self, panelno, set_focus=True):
if 0 <= panelno < len(self.panels):
self.selected = panelno
self.panelwrap.set_w( self.panels[panelno] )
self.panels[panelno].activate()
if set_focus:
if self.panels[panelno].focusable():
self.pile.set_focus( 0 )
else:
self.pile.set_focus( 1 )
def next(self, *args, **kwargs):
if self.panels[self.selected].check():
self.select( self.selected )
return
self.select(self.selected + 1)
def back(self, *args, **kwargs):
if self.selected == 0:
raise_back()
self.select(self.selected - 1, False)
class WizardPanel(urwid.WidgetWrap):
def __init__(self, state):
self.state = state
self.init_widgets()
self.box = urwid.ListBox( urwid.SimpleListWalker( self.widgets ) )
urwid.WidgetWrap.__init__( self, self.box )
def init_widgets(self):
self.widgets = []
def focus_widget(self, widget):
self.box.set_focus( self.widgets.index( widget ) )
def focusable(self):
return True
def check(self):
return
def activate(self):
return