changeset 113:e5ca22113280

Primitivus: profile manager - new custom widgets: Password, List, GenericDialog, InputDialog, ConfirmationDialog
author Goffi <goffi@goffi.org>
date Thu, 01 Jul 2010 15:35:56 +0800
parents f551e44adb25
children 77f48939ad6e
files frontends/primitivus/custom_widgets.py frontends/primitivus/primitivus frontends/primitivus/profile_manager.py frontends/wix/profile_manager.py
diffstat 4 files changed, 256 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/frontends/primitivus/custom_widgets.py	Thu Jul 01 15:35:56 2010 +0800
@@ -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)
--- a/frontends/primitivus/primitivus	Wed Jun 30 14:24:24 2010 +0800
+++ b/frontends/primitivus/primitivus	Thu Jul 01 15:35:56 2010 +0800
@@ -51,7 +51,12 @@
 ###
 
 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 @@
             raise urwid.ExitMainLoop()
 
     def __buildMainWidget(self):
+        #main_widget = urwid.Filler(ProfileManager(self))
         main_widget = ProfileManager(self)
         return main_widget
 
--- a/frontends/primitivus/profile_manager.py	Wed Jun 30 14:24:24 2010 +0800
+++ b/frontends/primitivus/profile_manager.py	Thu Jul 01 15:35:56 2010 +0800
@@ -20,15 +20,81 @@
 """
 
 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
--- a/frontends/wix/profile_manager.py	Wed Jun 30 14:24:24 2010 +0800
+++ b/frontends/wix/profile_manager.py	Thu Jul 01 15:35:56 2010 +0800
@@ -138,7 +138,6 @@
         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)