Primitivus: profile manager
- new custom widgets: Password, List, GenericDialog, InputDialog, ConfirmationDialog
This commit is contained in:
parent
b6ef271fd2
commit
ab067174ff
4 changed files with 256 additions and 6 deletions
179
frontends/primitivus/custom_widgets.py
Normal file
179
frontends/primitivus/custom_widgets.py
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
#!/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
|
||||
|
||||
class Password(urwid.Edit):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.hidden_char=kwargs['hidden_char'] if kwargs.has_key('hidden_char') else '*'
|
||||
self.__real_text=''
|
||||
super(Password, self).__init__(*args, **kwargs)
|
||||
|
||||
def set_edit_text(self, text):
|
||||
self.__real_text = text
|
||||
hidden_txt = len(text)*'*'
|
||||
super(Password, self).set_edit_text(hidden_txt)
|
||||
|
||||
def get_edit_text(self):
|
||||
return self.__real_text
|
||||
|
||||
class SelectableText(urwid.FlowWidget):
|
||||
signals = ['change']
|
||||
|
||||
def __init__(self, text, align='left'):
|
||||
self.text=unicode(text)
|
||||
self.align = align
|
||||
self.__selected=False
|
||||
|
||||
def getValue(self):
|
||||
return self.text
|
||||
|
||||
def setState(self, selected, invisible=False):
|
||||
"""Change state
|
||||
@param selected: boolean state value
|
||||
@param invisible: don't emit change signal if True"""
|
||||
assert(type(selected)==bool)
|
||||
self.__selected=selected
|
||||
if not invisible:
|
||||
self._emit("change", self.__selected)
|
||||
self._invalidate()
|
||||
|
||||
def getState(self):
|
||||
return self.__selected
|
||||
|
||||
def selectable(self):
|
||||
return True
|
||||
|
||||
def keypress(self, size, key):
|
||||
if key==' ' or key=='enter':
|
||||
self.setState(not self.__selected)
|
||||
else:
|
||||
return key
|
||||
|
||||
def rows(self,size,focus=False):
|
||||
return self.display_widget(size, focus).rows(size, focus)
|
||||
|
||||
def render(self, size, focus=False):
|
||||
return self.display_widget(size, focus).render(size, focus)
|
||||
|
||||
def display_widget(self, size, focus):
|
||||
attr = 'selected' if self.__selected else 'default'
|
||||
if focus:
|
||||
attr+="_focus"
|
||||
return urwid.Text((attr,self.text), align=self.align)
|
||||
|
||||
class List(urwid.WidgetWrap):
|
||||
signals = ['change']
|
||||
|
||||
def __init__(self, options, style=[], align='left', on_state_change=None, user_data=None):
|
||||
assert(options)
|
||||
self.single = 'single' in style
|
||||
self.align = align
|
||||
|
||||
if on_state_change:
|
||||
urwid.connect_signal(self, 'change', on_state_change, user_data)
|
||||
|
||||
widgets = [SelectableText(option,align) for option in options]
|
||||
for widget in widgets:
|
||||
urwid.connect_signal(widget, 'change', self.__onStateChange)
|
||||
self.content = urwid.SimpleListWalker(widgets)
|
||||
self.list_box = urwid.ListBox(self.content)
|
||||
if self.single:
|
||||
self.content[0].setState(True)
|
||||
display_widget = urwid.BoxAdapter(self.list_box, min(len(options),5))
|
||||
|
||||
urwid.WidgetWrap.__init__(self, display_widget)
|
||||
|
||||
def __onStateChange(self, widget, selected):
|
||||
if self.single:
|
||||
if not selected:
|
||||
#if in single mode, it's forbidden to unselect a value
|
||||
widget.setState(True, invisible=True)
|
||||
return
|
||||
else:
|
||||
self.unselectAll(invisible=True)
|
||||
widget.setState(True, invisible=True)
|
||||
self._emit("change")
|
||||
|
||||
|
||||
def unselectAll(self, invisible=False):
|
||||
for widget in self.content:
|
||||
if widget.getState():
|
||||
widget.setState(False, invisible)
|
||||
widget._invalidate()
|
||||
|
||||
def getValues(self):
|
||||
result = []
|
||||
for widget in self.content:
|
||||
if widget.getState():
|
||||
result.append(widget.getValue())
|
||||
return result
|
||||
|
||||
def changeValues(self, new_values):
|
||||
widgets = [SelectableText(self, option) for option in new_values]
|
||||
self.content[:] = widgets
|
||||
|
||||
def selectValue(self, value):
|
||||
self.unselectAll()
|
||||
idx = 0
|
||||
for widget in self.content:
|
||||
if widget.getValue() == value:
|
||||
widget.setState(True)
|
||||
self.list_box.set_focus(idx)
|
||||
return
|
||||
idx+=1
|
||||
|
||||
class genericDialog(urwid.WidgetWrap):
|
||||
|
||||
def __init__(self, widgets_lst, title, style=[], **kwargs):
|
||||
frame_header = urwid.AttrMap(urwid.Text(title,'center'),'title')
|
||||
|
||||
buttons = None
|
||||
|
||||
if "OK/CANCEL" in style:
|
||||
buttons = [urwid.Button(_("Cancel"), kwargs['cancel_cb']),
|
||||
urwid.Button(_("Ok"), kwargs['ok_cb'], kwargs['ok_value'])]
|
||||
elif "YES/NO" in style:
|
||||
buttons = [urwid.Button(_("Yes"), kwargs['yes_cb']),
|
||||
urwid.Button(_("No"), kwargs['no_cb'], kwargs['yes_value'])]
|
||||
if buttons:
|
||||
buttons_flow = urwid.GridFlow(buttons, max([len(button.get_label()) for button in buttons])+4, 1, 1, 'center')
|
||||
widgets_lst.append(buttons_flow)
|
||||
body_content = urwid.SimpleListWalker(widgets_lst)
|
||||
frame_body = urwid.ListBox(body_content)
|
||||
frame = urwid.Frame(frame_body, frame_header)
|
||||
decorated_frame = urwid.LineBox(frame)
|
||||
urwid.WidgetWrap.__init__(self, decorated_frame)
|
||||
|
||||
|
||||
|
||||
class InputDialog(genericDialog):
|
||||
|
||||
def __init__(self, title, instrucions, style=['OK/CANCEL'], **kwargs):
|
||||
instr_wid = urwid.Text(instrucions+':')
|
||||
edit_box = urwid.Edit()
|
||||
genericDialog.__init__(self, [instr_wid,edit_box], title, style, ok_value=edit_box, **kwargs)
|
||||
|
||||
class ConfirmDialog(genericDialog):
|
||||
|
||||
def __init__(self, title, style=['YES/NO'], **kwargs):
|
||||
genericDialog.__init__(self, [], title, style, yes_value=None, **kwargs)
|
||||
|
|
@ -51,7 +51,12 @@ logging.basicConfig(level=logging.CRITICAL, #TODO: configure it to put messages
|
|||
###
|
||||
|
||||
const_APP_NAME = "Primitivus"
|
||||
const_PALETTE = [('title', 'black', 'light gray', 'standout,underline'),]
|
||||
const_PALETTE = [('title', 'black', 'light gray', 'standout,underline'),
|
||||
('selected', 'default', 'dark red'),
|
||||
('selected_focus', 'default,bold', 'dark red'),
|
||||
('default', 'default', 'default'),
|
||||
('default_focus', 'default,bold', 'default'),
|
||||
]
|
||||
|
||||
class PrimitivusApp(QuickApp):
|
||||
|
||||
|
|
@ -70,6 +75,7 @@ class PrimitivusApp(QuickApp):
|
|||
raise urwid.ExitMainLoop()
|
||||
|
||||
def __buildMainWidget(self):
|
||||
#main_widget = urwid.Filler(ProfileManager(self))
|
||||
main_widget = ProfileManager(self)
|
||||
return main_widget
|
||||
|
||||
|
|
|
|||
|
|
@ -20,15 +20,81 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
"""
|
||||
|
||||
import urwid
|
||||
from custom_widgets import Password,List,InputDialog,ConfirmDialog
|
||||
|
||||
|
||||
class ProfileManager(urwid.WidgetWrap):
|
||||
|
||||
def __init__(self, host):
|
||||
self.host = host
|
||||
#profiles list
|
||||
profiles = self.host.bridge.getProfilesList()
|
||||
widgets = [urwid.Text(str(profiles))]
|
||||
content = urwid.SimpleListWalker(widgets)
|
||||
display_widget = urwid.Frame(urwid.ListBox(content),urwid.AttrMap(urwid.Text("Profile Manager",align='center'),'title'))
|
||||
urwid.WidgetWrap.__init__(self, display_widget)
|
||||
profiles.sort()
|
||||
|
||||
#login & password box must be created before list because of onProfileChange
|
||||
self.login_wid = urwid.Edit(_('Login:'),align='center')
|
||||
self.pass_wid = Password(_('Password:'),align='center')
|
||||
|
||||
self.list_profile = List(profiles, style=['single'], align='center', on_state_change=self.onProfileChange)
|
||||
|
||||
#toto = urwid.Padding(urwid.Text('toto'), align='center')
|
||||
|
||||
#new & delete buttons
|
||||
buttons = [urwid.Button(_("New"), self.onNewProfile),
|
||||
urwid.Button(_("Delete"), self.onDeleteProfile)]
|
||||
buttons_flow = urwid.GridFlow(buttons, max([len(button.get_label()) for button in buttons])+4, 1, 1, 'center')
|
||||
|
||||
#second part: login information:
|
||||
divider = urwid.Divider('-')
|
||||
|
||||
#connect button
|
||||
connect_button = urwid.Button(_("Connect"), self.onConnectProfile)
|
||||
|
||||
#we now build the widget
|
||||
body_content = urwid.SimpleListWalker([buttons_flow,self.list_profile,divider,self.login_wid, self.pass_wid, connect_button])
|
||||
frame_body = urwid.ListBox(body_content)
|
||||
frame = urwid.Frame(frame_body,urwid.AttrMap(urwid.Text("Profile Manager",align='center'),'title'))
|
||||
self.main_widget = urwid.LineBox(frame)
|
||||
urwid.WidgetWrap.__init__(self, self.main_widget)
|
||||
|
||||
def __refillProfiles(self):
|
||||
"""Update the list of profiles"""
|
||||
profiles = self.host.bridge.getProfilesList()
|
||||
profiles.sort()
|
||||
self.list_profile.changeValues(profiles)
|
||||
|
||||
def cancelDialog(self, button):
|
||||
self._set_w(self.main_widget)
|
||||
|
||||
def newProfile(self, button, edit):
|
||||
self._set_w(self.main_widget)
|
||||
name = edit.get_edit_text()
|
||||
self.host.bridge.createProfile(name)
|
||||
self.__refillProfiles()
|
||||
self.list_profile.selectValue(name)
|
||||
|
||||
def deleteProfile(self, button):
|
||||
self._set_w(self.main_widget)
|
||||
self.host.bridge.deleteProfile(self.list_profile.getValues()[0])
|
||||
self.__refillProfiles()
|
||||
|
||||
|
||||
def onNewProfile(self, e):
|
||||
pop_up_widget = InputDialog(_("New profile"), _("Please enter a new profile name"), cancel_cb=self.cancelDialog, ok_cb=self.newProfile)
|
||||
display_widget = urwid.Overlay(pop_up_widget, self.main_widget, 'center', ('relative', 40), 'middle', ('relative', 40))
|
||||
self._set_w(display_widget)
|
||||
|
||||
def onDeleteProfile(self, e):
|
||||
pop_up_widget = ConfirmDialog(_("Are you sure you want to delete the profile %s ?") % self.list_profile.getValues()[0], no_cb=self.cancelDialog, yes_cb=self.deleteProfile)
|
||||
display_widget = urwid.Overlay(pop_up_widget, self.main_widget, 'center', ('relative', 40), 'middle', ('relative', 40))
|
||||
self._set_w(display_widget)
|
||||
|
||||
def onProfileChange(self, list_wid):
|
||||
profile_name = list_wid.getValues()[0]
|
||||
jabberID = self.host.bridge.getParamA("JabberID", "Connection", profile_key=profile_name)
|
||||
password = self.host.bridge.getParamA("Password", "Connection", profile_key=profile_name)
|
||||
self.login_wid.set_edit_text(jabberID)
|
||||
self.pass_wid.set_edit_text(password)
|
||||
|
||||
def onConnectProfile(self, button):
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -138,7 +138,6 @@ class ProfileManager(wx.Panel):
|
|||
old_pass = self.host.bridge.getParamA("Password", "Connection", profile_key=profile)
|
||||
new_jid = self.login_jid.GetValue()
|
||||
new_pass = self.login_pass.GetValue()
|
||||
print "old: %s, new: %s, old_pass: %s, new_pass: %s" % (old_jid, new_jid, old_pass, new_pass)
|
||||
if old_jid != new_jid:
|
||||
debug(_('Saving new JID and server'))
|
||||
self.host.bridge.setParam("JabberID", new_jid, "Connection", profile)
|
||||
|
|
|
|||
Loading…
Reference in a new issue