changeset 222:3198bfd66daa

primitivus: refactoring to use urwid-satext which is now a separate project
author Goffi <goffi@goffi.org>
date Tue, 28 Dec 2010 23:10:13 +0100
parents 96186f36d8cb
children 86d249b6d9b7
files frontends/primitivus/card_game.py frontends/primitivus/chat.py frontends/primitivus/contact_list.py frontends/primitivus/custom_widgets.py frontends/primitivus/files_management.py frontends/primitivus/gateways.py frontends/primitivus/primitivus frontends/primitivus/profile_manager.py frontends/primitivus/progress.py frontends/primitivus/xmlui.py
diffstat 10 files changed, 63 insertions(+), 1317 deletions(-) [+]
line wrap: on
line diff
--- a/frontends/primitivus/card_game.py	Mon Dec 27 21:56:12 2010 +0100
+++ b/frontends/primitivus/card_game.py	Tue Dec 28 23:10:13 2010 +0100
@@ -23,7 +23,7 @@
 from tools.games import TarotCard
 from quick_frontend.quick_card_game import QuickCardGame
 from xmlui import XMLUI
-import custom_widgets
+from urwid_satext import sat_widgets
 
 class CardDisplayer(urwid.Text):
     """Show a card"""
@@ -314,7 +314,7 @@
                 self.hand_wid.update(self.hand)
         if self.state ==  "ecart":
             if len(self.hand_wid.getSelected()) == 6:
-                pop_up_widget = custom_widgets.ConfirmDialog(_("Do you put these cards in chien ?"), yes_cb=self.onEcartDone, no_cb=self.parent.host.removePopUp)
+                pop_up_widget = sat_widgets.ConfirmDialog(_("Do you put these cards in chien ?"), yes_cb=self.onEcartDone, no_cb=self.parent.host.removePopUp)
                 self.parent.host.showPopUp(pop_up_widget)
         elif self.state == "play":
             card = card_wid.getCard()
--- a/frontends/primitivus/chat.py	Mon Dec 27 21:56:12 2010 +0100
+++ b/frontends/primitivus/chat.py	Tue Dec 28 23:10:13 2010 +0100
@@ -22,11 +22,11 @@
 import urwid
 from quick_frontend.quick_contact_list import QuickContactList
 from quick_frontend.quick_chat import QuickChat
-import custom_widgets
+from urwid_satext import sat_widgets
 import time
 from tools.jid  import JID
 from card_game import CardGame
-from files_management import FileDialog
+from urwid_satext.files_management import FileDialog
 
 
 class ChatText(urwid.FlowWidget):
@@ -107,7 +107,7 @@
             for wid in self.content:
                 wid._invalidate()
         elif key == "meta l": #user wants to (un)hide widget decoration
-            show = not isinstance(self._w, custom_widgets.LabelLine)
+            show = not isinstance(self._w, sat_widgets.LabelLine)
             self.showDecoration(show)
             self._invalidate()
         elif key == "meta s": #user wants to (un)hide group's subject or change its apperance
@@ -126,7 +126,7 @@
     
     def getMenu(self):
         """Return Menu bar"""
-        menu = custom_widgets.Menu(self.host.loop)
+        menu = sat_widgets.Menu(self.host.loop)
         if self.type == 'group':
             game = _("Game")
             menu.addMenu(game, "Tarot", self.onTarotRequest)
@@ -141,11 +141,11 @@
         elif type == 'group':
             if len(self.chat_colums.widget_list) == 1:
                 present_widget = self.__buildPresentList()
-                self.present_panel = custom_widgets.VerticalSeparator(present_widget)
+                self.present_panel = sat_widgets.VerticalSeparator(present_widget)
                 self.__appendPresentPanel()
           
     def __getDecoration(self, widget):
-        return custom_widgets.LabelLine(widget, custom_widgets.SurroundedText(unicode(self.target)))
+        return sat_widgets.LabelLine(widget, sat_widgets.SurroundedText(unicode(self.target)))
 
     def showDecoration(self, show=True):
         """Show/Hide the decoration around the chat window"""
@@ -157,7 +157,7 @@
 
 
     def __buildPresentList(self):
-        self.present_wid = custom_widgets.GenericList([],option_type = custom_widgets.ClickableText)
+        self.present_wid = sat_widgets.GenericList([],option_type = sat_widgets.ClickableText)
         return self.present_wid
    
     def __appendPresentPanel(self):
@@ -241,7 +241,7 @@
             normal: general info like "toto has joined the room"
             me: "/me" information like "/me clenches his fist" ==> "toto clenches his fist"
         """
-        self.content.append(custom_widgets.ClickableText(msg))
+        self.content.append(sat_widgets.ClickableText(msg))
         self.text_list.set_focus(len(self.content)-1)
         self.host.redraw()
     
@@ -263,7 +263,7 @@
     #MENU EVENTS#
     def onTarotRequest(self, menu):
         if len(self.occupants) != 4:
-            self.host.showPopUp(custom_widgets.Alert(_("Can't start game"), _("You need to be exactly 4 peoples in the room to start a Tarot game"), ok_cb=self.host.removePopUp)) 
+            self.host.showPopUp(sat_widgets.Alert(_("Can't start game"), _("You need to be exactly 4 peoples in the room to start a Tarot game"), ok_cb=self.host.removePopUp)) 
         else:
             self.host.bridge.tarotGameCreate(self.id, list(self.occupants), self.host.profile)
     
--- a/frontends/primitivus/contact_list.py	Mon Dec 27 21:56:12 2010 +0100
+++ b/frontends/primitivus/contact_list.py	Tue Dec 28 23:10:13 2010 +0100
@@ -22,7 +22,7 @@
 import urwid
 from quick_frontend.quick_contact_list import QuickContactList
 from tools.jid import JID
-import custom_widgets
+from urwid_satext import sat_widgets
 
 
 class ContactList(urwid.WidgetWrap, QuickContactList):
@@ -36,7 +36,7 @@
         
         #we now build the widget
         self.frame = urwid.Frame(self.__buildList())
-        self.main_widget = custom_widgets.LabelLine(self.frame, custom_widgets.SurroundedText(_("Contacts")))
+        self.main_widget = sat_widgets.LabelLine(self.frame, sat_widgets.SurroundedText(_("Contacts")))
         urwid.WidgetWrap.__init__(self, self.main_widget)
         if on_click:
             urwid.connect_signal(self, 'click', on_click, user_data)
@@ -75,7 +75,7 @@
     def __contactClicked(self, contact_wid, selected):
         self.selected = contact_wid.data
         for widget in self.frame.body.body:
-            if widget.__class__ == custom_widgets.SelectableText:
+            if widget.__class__ == sat_widgets.SelectableText:
                 widget.setState(widget.data == self.selected, invisible=True)
         if self.selected in self.alert_jid:
             self.alert_jid.remove(self.selected)
@@ -95,7 +95,7 @@
             nick = self.CM.getAttr(jid,'nick')
             display = nick or name or jid.node or jid.short
             header = '(*) ' if contact in self.alert_jid else ''
-            widget = custom_widgets.SelectableText(('alert' if contact in self.alert_jid else 'default',display),
+            widget = sat_widgets.SelectableText(('alert' if contact in self.alert_jid else 'default',display),
                                                     selected = contact==self.selected, header=header)
             widget.data = contact
             content.append(widget)
@@ -110,7 +110,7 @@
             unfolded = self.groups[key][0]
             if key!=None:
                 header = '[-]' if unfolded else '[+]'
-                widget = custom_widgets.ClickableText(key,header=header+' ')
+                widget = sat_widgets.ClickableText(key,header=header+' ')
                 content.append(widget)
                 urwid.connect_signal(widget, 'click', self.__groupClicked)
             if unfolded:
@@ -121,7 +121,7 @@
         """Unselect all contacts"""
         self.selected = None
         for widget in self.frame.body.body:
-            if widget.__class__ == custom_widgets.SelectableText:
+            if widget.__class__ == sat_widgets.SelectableText:
                 widget.setState(False, invisible=True)
 
 
--- a/frontends/primitivus/custom_widgets.py	Mon Dec 27 21:56:12 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1020 +0,0 @@
-#!/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
-from urwid.escape import utf8decode
-from logging import debug, info, warning, error
-
-class Password(urwid.Edit):
-    """Edit box which doesn't show what is entered (show '*' or other char instead)"""
-
-    def __init__(self, *args, **kwargs):
-        """Same args than Edit.__init__ with an additional keyword arg 'hidden_char'
-        @param hidden_char: char to show instead of what is actually entered: default '*'
-        """
-        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
-
-    def insert_text(self, text):
-        self._edit_text = self.__real_text
-        super(Password,self).insert_text(text)
-
-    def render(self, size, focus=False):
-        return super(Password, self).render(size, focus)
-
-class AdvancedEdit(urwid.Edit):
-    """Edit box with some custom improvments
-    new chars:
-              - C-a: like 'home'
-              - C-e: like 'end'
-              - C-k: remove everything on the right of the cursor
-              - C-w: remove the word on the back
-    new behaviour: emit a 'click' signal when enter is pressed"""
-    signals = urwid.Edit.signals + ['click']
-
-    def setCompletionMethod(self, callback):
-        """Define method called when completion is asked
-        @callback: method with 2 arguments:
-                    - the text to complete
-                    - if there was already a completion, a dict with
-                        - 'completed':last completion
-                        - 'completion_pos': cursor position where the completion starts 
-                        - 'position': last completion cursor position
-                      this dict must be used (and can be filled) to find next completion)
-                   and which return the full text completed"""
-        self.completion_cb = callback
-        self.completion_data = {}
-
-    def keypress(self, size, key):
-        #TODO: insert mode is not managed yet
-        if key == 'ctrl a':
-            key = 'home'
-        elif key == 'ctrl e':
-            key = 'end'
-        elif key == 'ctrl k':
-            self._delete_highlighted()
-            self.set_edit_text(self.edit_text[:self.edit_pos])
-        elif key == 'ctrl w':    
-            before = self.edit_text[:self.edit_pos]
-            pos = before.rstrip().rfind(" ")+1
-            self.set_edit_text(before[:pos] + self.edit_text[self.edit_pos:])
-            self.set_edit_pos(pos)
-        elif key == 'enter':
-            self._emit('click')
-        elif key == 'shift tab':
-            try:
-                before = self.edit_text[:self.edit_pos]
-                if self.completion_data:
-                    if (not self.completion_data['completed']
-                        or self.completion_data['position'] != self.edit_pos
-                        or not before.endswith(self.completion_data['completed'])):
-                        self.completion_data.clear()
-                    else:
-                        before = before[:-len(self.completion_data['completed'])]
-                complet = self.completion_cb(before, self.completion_data)
-                self.completion_data['completed'] = complet[len(before):]
-                self.set_edit_text(complet+self.edit_text[self.edit_pos:])
-                self.set_edit_pos(len(complet))
-                self.completion_data['position'] = self.edit_pos
-                return
-            except AttributeError:
-                #No completion method defined
-                pass
-        return super(AdvancedEdit, self).keypress(size, key) 
-       
-
-class SurroundedText(urwid.FlowWidget):
-    """Text centered on a repeated character (like a Divider, but with a text in the center)"""
-
-    def __init__(self,text,car=utf8decode('─')):
-        self.text=text
-        self.car=car
-
-    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):
-        (maxcol,) = size
-        middle = (maxcol-len(self.text))/2
-        render_text = middle * self.car + self.text + (maxcol - len(self.text) - middle) * self.car
-        return urwid.Text(render_text)
-
-class SelectableText(urwid.WidgetWrap):
-    """Text which can be selected with space"""
-    signals = ['change']
-    
-    def __init__(self, text, align='left', header='', focus_attr='default_focus', selected_text=None, selected=False, data=None):
-        """@param text: same as urwid.Text's text parameter
-        @param align: same as urwid.Text's align parameter
-        @select_attr: attrbute to use when selected
-        @param selected: is the text selected ?"""
-        self.focus_attr = focus_attr
-        self.__selected = False
-        self.__was_focused = False
-        self.header = self.__valid_text(header)
-        self.default_txt = self.__valid_text(text)
-        urwid.WidgetWrap.__init__(self, urwid.Text("",align=align))
-        self.setSelectedText(selected_text)
-        self.setState(selected)
-
-    def __valid_text(self, text):
-        """Tmp method needed until dbus and urwid are more friends"""
-        if isinstance(text,basestring):
-            return unicode(text)
-        elif isinstance(text,tuple):
-            return (unicode(text[0]),text[1])
-        elif isinstance(text,list):
-            for idx in range(len(text)):
-                elem = text[idx]
-                if isinstance(elem,basestring):
-                    text[idx] = unicode(elem)
-                if isinstance(elem,tuple):
-                    text[idx] = (unicode(elem[0]),elem[1])
-        else:
-            warning (_('WARNING: unknown text type'))
-        return text
-
-    def getValue(self):
-        if isinstance(self.default_txt,basestring):
-            return self.default_txt
-        list_attr = self.default_txt if isinstance(self.default_txt, list) else [self.default_txt]
-        txt = ""
-        for attr in list_attr:
-            if isinstance(attr,tuple):
-                txt+=attr[1]
-            else:
-                txt+=attr
-        return txt
-
-    def get_text(self):
-        """for compatibility with urwid.Text"""
-        return self.getValue()
-
-    def set_text(self, text):
-        """/!\ set_text doesn't change self.selected_txt !"""
-        self.default_txt = self.__valid_text(text)
-        self.setState(self.__selected,invisible=True)
-
-    def setSelectedText(self, text=None):
-        """Text to display when selected
-        @text: text as in urwid.Text or None for default value"""
-        if text == None:
-            text = ('selected',self.getValue())
-        self.selected_txt = self.__valid_text(text)
-        if self.__selected:
-            self.setState(self.__selected)
-
-
-    def __set_txt(self):
-        txt_list = [self.header]
-        txt = self.selected_txt if self.__selected else self.default_txt
-        if isinstance(txt,list):
-            txt_list.extend(txt)
-        else:
-            txt_list.append(txt)
-        self._w.base_widget.set_text(txt_list)
-
-    
-    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
-        self.__set_txt()
-        self.__was_focused = False
-        self._invalidate()
-        if not invisible:
-            self._emit("change", self.__selected)
-   
-    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 mouse_event(self, size, event, button, x, y, focus):
-        if urwid.is_mouse_press(event) and button == 1:
-            self.setState(not self.__selected)
-            return True
-        
-        return False
-   
-    def render(self, size, focus=False):
-        attr_list = self._w.base_widget._attrib
-        if not focus:
-            if self.__was_focused:
-                self.__set_txt()
-                self.__was_focused = False
-        else:
-            if not self.__was_focused:
-                if not attr_list:
-                    attr_list.append((self.focus_attr,len(self._w.base_widget.text)))
-                else:
-                    for idx in range(len(attr_list)):
-                        attr,attr_len = attr_list[idx]
-                        if attr == None:
-                            attr = self.focus_attr
-                            attr_list[idx] = (attr,attr_len)
-                        else:
-                            if not attr.endswith('_focus'):
-                                attr+="_focus"
-                                attr_list[idx] = (attr,attr_len)
-                self._w.base_widget._invalidate()
-                self.__was_focused = True #bloody ugly hack :)
-        return self._w.render(size, focus)
-
-class ClickableText(SelectableText):
-    signals = SelectableText.signals + ['click']
-    
-    def setState(self, selected, invisible=False):
-        super(ClickableText,self).setState(False,True)
-        if not invisible:
-            self._emit('click')
-
-class CustomButton(ClickableText):
-
-    def __init__(self, label, on_press=None, user_data=None, left_border = "[ ", right_border = " ]"):
-        self.label = label
-        self.left_border = left_border
-        self.right_border = right_border
-        super(CustomButton, self).__init__([left_border, label, right_border]) 
-        self.size = len(self.get_text())
-        if on_press:
-            urwid.connect_signal(self, 'click', on_press, user_data)
-
-    def getSize(self):
-        """Return representation size of the button"""
-        return self.size
-
-    def get_label(self):
-        return self.label[1] if isinstance(self.label,tuple) else self.label
-
-    def set_label(self, label):
-        self.label = label
-        self.set_text([self.left_border, label, self.right_border])
-
-class GenericList(urwid.WidgetWrap):
-    signals = ['click','change']
-
-    def __init__(self, options, style=[], align='left', option_type = SelectableText, on_click=None, on_change=None, user_data=None):
-        """
-        Widget managing list of string and their selection
-        @param options: list of strings used for options
-        @param style: list of string:
-            - 'single' if only one must be selected
-            - 'no_first_select' nothing selected when list is first displayed 
-            - 'can_select_none' if we can select nothing
-        @param align: alignement of text inside the list
-        @param on_click: method called when click signal is emited
-        @param user_data: data sent to the callback for click signal
-        """
-        self.single = 'single' in style
-        self.no_first_select = 'no_first_select' in style
-        self.can_select_none = 'can_select_none' in style
-        self.align = align
-        self.option_type = option_type
-        self.first_display = True
-        
-        if on_click:
-            urwid.connect_signal(self, 'click', on_click, user_data)
-        
-        if on_change:
-            urwid.connect_signal(self, 'change', on_change, user_data)
-        
-        self.content = urwid.SimpleListWalker([])
-        self.list_box = urwid.ListBox(self.content)
-        urwid.WidgetWrap.__init__(self, self.list_box)
-        self.changeValues(options)
-
-    def __onStateChange(self, widget, selected):
-        if self.single:
-            if not selected and not self.can_select_none:
-                #if in single mode, it's forbidden to unselect a value
-                widget.setState(True, invisible=True)
-                return
-            if selected:
-                self.unselectAll(invisible=True)
-                widget.setState(True, invisible=True)
-        self._emit("click")
-
-
-    def unselectAll(self, invisible=False):
-        for widget in self.content:
-            if widget.getState():
-                widget.setState(False, invisible)
-                widget._invalidate()
-
-    def deleteValue(self, value):
-        """Delete the first value equal to the param given"""
-        for widget in self.content:
-            if widget.getValue() == value:
-                self.content.remove(widget)
-                self._emit('change')
-                return
-        raise ValueError("%s ==> %s" %  (str(value),str(self.content)))
-
-    def getSelectedValue(self):
-        """Convenience method to get the value selected as a string in single mode, or None"""
-        values = self.getSelectedValues()
-        return values[0] if values else None
-
-    def getAllValues(self):
-        """Return values of all items"""
-        return [widget.getValue() for widget in self.content]
-
-    def getSelectedValues(self):
-        """Return values of selected items"""
-        result = []
-        for widget in self.content:
-            if widget.getState():
-                result.append(widget.getValue())
-        return result
-
-    def getDisplayWidget(self):
-        return self.list_box
-
-    def changeValues(self, new_values):
-        """Change all value in one shot"""
-        if not self.first_display:
-            old_selected = self.getSelectedValues()
-        widgets = []
-        for option in new_values:
-            widget = self.option_type(option, self.align)
-            if not self.first_display and option in old_selected:
-                widget.setState(True)
-            widgets.append(widget)
-            try:
-                urwid.connect_signal(widget, 'change', self.__onStateChange)
-            except NameError:
-                pass #the widget given doesn't support 'change' signal
-        self.content[:] = widgets
-        if self.first_display and self.single and new_values and not self.no_first_select:
-            self.content[0].setState(True)
-        display_widget = self.getDisplayWidget()
-        self._set_w(display_widget)
-        self._emit('change')
-        self.first_display = False 
-
-    def selectValue(self, value):
-        """Select the first item which has the given 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 List(urwid.FlowWidget):
-    """FlowWidget list, same arguments as GenericList, with an additional one 'max_height'"""
-    signals = ['click','change']
-
-    def __init__(self, options, style=[], max_height=5, align='left', option_type = SelectableText, on_click=None, on_change=None, user_data=None):
-        self.genericList = GenericList(options, style, align, option_type, on_click, on_change, user_data)
-        self.max_height = max_height 
-
-    def selectable(self):
-        return True
-
-    def keypress(self, size, key):
-        return self.displayWidget(size,True).keypress(size, key)
-        
-    def unselectAll(self, invisible=False):
-        return self.genericList.unselectAll(invisible)
-    
-    def deleteValue(self, value):
-        return self.genericList.deleteValue(value)
-
-    def getSelectedValue(self):
-        return self.genericList.getSelectedValue()
-
-    def getAllValues(self):
-        return self.genericList.getAllValues()
-
-    def getSelectedValues(self):
-        return self.genericList.getSelectedValues()
-
-    def changeValues(self, new_values):
-        return self.genericList.changeValues(new_values)
-
-    def selectValue(self, value):
-        return self.genericList.selectValue(value)
-
-    def render(self, size, focus=False):
-        return self.displayWidget(size, focus).render(size, focus)
-    
-    def rows(self, size, focus=False):
-        return self.displayWidget(size, focus).rows(size, focus)
-
-    def displayWidget(self, size, focus):
-        list_size = sum([wid.rows(size, focus) for wid in self.genericList.content])
-        height = min(list_size,self.max_height) or 1 
-        return urwid.BoxAdapter(self.genericList, height)
-
-## MISC ##
-
-class NotificationBar(urwid.WidgetWrap):
-    """Bar used to show misc information to user"""
-    signals = ['change']
-
-    def __init__(self):
-        self.waitNotifs = urwid.Text('')
-        self.message = ClickableText('')
-        urwid.connect_signal(self.message, 'click', lambda wid: self.showNext())
-        self.progress = ClickableText('')
-        self.columns = urwid.Columns([('fixed',6,self.waitNotifs),self.message,('fixed',4,self.progress)])
-        urwid.WidgetWrap.__init__(self, urwid.AttrMap(self.columns,'notifs'))
-        self.notifs = []
-    
-    def __modQueue(self):
-        """must be called each time the notifications queue is changed"""
-        self.waitNotifs.set_text(('notifs',"(%i)" % len(self.notifs) if self.notifs else ''))
-        self._emit('change')
-
-    def setProgress(self,percentage):
-        """Define the progression to show on the right side of the bar"""
-        if percentage == None:
-            self.progress.set_text('')
-        else:
-            self.progress.set_text(('notifs','%02i%%' % percentage))
-        self._emit('change')
-
-    def addPopUp(self, pop_up_widget):
-        """Add a popup to the waiting queue"""
-        self.notifs.append(('popup',pop_up_widget))
-        self.__modQueue()
-
-    def addMessage(self, message):
-        "Add a message to the notificatio bar"
-        if not self.message.get_text():
-            self.message.set_text(('notifs',message))
-            self._invalidate()
-            self._emit('change')
-        else:
-            self.notifs.append(('message',message))
-            self.__modQueue()
-
-    def showNext(self):
-        """Show next message if any, else delete current message"""
-        found = None
-        for notif in self.notifs:
-            if notif[0] == "message":
-                found = notif
-                break
-        if found:
-            self.notifs.remove(found)
-            self.message.set_text(('notifs',found[1]))
-            self.__modQueue()
-        else:
-            self.message.set_text('')
-            self._emit('change')
-
-    def getNextPopup(self):
-        """Return next pop-up and remove it from the queue
-        @return: pop-up or None if there is no more in the queue"""
-        ret = None
-        for notif in self.notifs:
-            if notif[0] == 'popup':
-                ret = notif[1]
-                break
-        if ret:
-            self.notifs.remove(notif)
-            self.__modQueue()
-        return ret
-
-    def isQueueEmpty(self):
-        return not bool(self.notifs)
-
-    def canHide(self):
-        """Return True if there is now important information to show"""
-        return self.isQueueEmpty() and not self.message.get_text() and not self.progress.get_text()
-
-
-class MenuBox(urwid.WidgetWrap):
-    """Show menu items of a category in a box"""
-    signals = ['click']
-    
-    def __init__(self,parent,items):
-        self.parent = parent
-        self.selected = None
-        content = urwid.SimpleListWalker([ClickableText(('menuitem',text)) for text in items])
-        for wid in content:
-            urwid.connect_signal(wid, 'click', self.onClick)
-
-        self.listBox = urwid.ListBox(content)
-        menubox = urwid.LineBox(urwid.BoxAdapter(self.listBox,len(items)))
-        urwid.WidgetWrap.__init__(self,menubox)
-
-    def getValue(self):
-        return self.selected
-   
-    def keypress(self, size, key):
-        if key=='up':
-            if self.listBox.get_focus()[1] == 0:
-                self.parent.keypress(size, key)
-        elif key=='left' or key=='right':
-            self.parent.keypress(size,'up')
-            self.parent.keypress(size,key)
-        return super(MenuBox,self).keypress(size,key)
-    
-    def mouse_event(self, size, event, button, x, y, focus):
-        if button == 3:
-            self.parent.keypress(size,'up')
-            return True
-        return super(MenuBox,self).mouse_event(size, event, button, x, y, focus)
-
-    def onClick(self, wid):
-        self.selected = wid.getValue()
-        self._emit('click')
-
-class Menu(urwid.WidgetWrap):
-
-    def __init__(self,loop, x_orig=0):
-        """Menu widget
-        @param loop: main loop of urwid
-        @param x_orig: absolute start of the abscissa
-        """
-        self.loop = loop
-        self.menu_keys = []
-        self.menu = {}
-        self.x_orig = x_orig
-        self.shortcuts = {} #keyboard shortcuts
-        self.save_bottom = None
-        col_rol = ColumnsRoller()
-        urwid.WidgetWrap.__init__(self, urwid.AttrMap(col_rol,'menubar'))
-    
-    def selectable(self):
-        return True
-
-    def getMenuSize(self):
-        """return the current number of categories in this menu"""
-        return len(self.menu_keys)
-   
-    def setOrigX(self, orig_x):
-        self.x_orig = orig_x
-
-    def __buildOverlay(self,menu_key,columns):
-        """Build the overlay menu which show menuitems
-        @param menu_key: name of the category
-        @colums: column number where the menubox must be displayed"""
-        max_len = 0
-        for item in self.menu[menu_key]:
-            if len(item[0]) > max_len:
-                max_len = len(item[0])
-
-        self.save_bottom = self.loop.widget
-        menu_box = MenuBox(self,[item[0] for item in self.menu[menu_key]])
-        urwid.connect_signal(menu_box, 'click', self.onItemClick)
-        
-        self.loop.widget = urwid.Overlay(urwid.AttrMap(menu_box,'menubar'),self.save_bottom,('fixed left', columns),max_len+2,('fixed top',1),None) 
-
-    def keypress(self, size, key):
-        if key == 'down':
-            key = 'enter'
-        elif key == 'up':
-            if  self.save_bottom:
-                self.loop.widget = self.save_bottom
-                self.save_bottom = None
-            
-        return self._w.base_widget.keypress(size, key)
-    
-    def checkShortcuts(self, key):
-        for shortcut in self.shortcuts.keys():
-            if key == shortcut:
-                category, item, callback = self.shortcuts[shortcut]
-                callback((category, item))
-        return key
-
-    def addMenu(self, category, item, callback, shortcut=None):
-        """Add a menu item, create the category if new
-        @param category: category of the menu (e.g. File/Edit)
-        @param item: menu item (e.g. new/close/about)
-        @callback: method to call when item is selected"""
-        if not category in self.menu.keys():
-            self.menu_keys.append(category)
-            self.menu[category] = []
-            button = CustomButton(('menubar',category), self.onCategoryClick,
-                                   left_border = ('menubar',"[ "),
-                                   right_border = ('menubar'," ]"))
-            self._w.base_widget.addWidget(button,button.getSize())
-        self.menu[category].append((item, callback))
-        if shortcut:
-            assert(shortcut not in self.shortcuts.keys())
-            self.shortcuts[shortcut] = (category, item, callback)
-
-    def onItemClick(self, widget):
-        category = self._w.base_widget.getSelected().get_label()
-        item = widget.getValue()
-        callback = None
-        for menu_item in self.menu[category]:
-            if item == menu_item[0]:
-                callback = menu_item[1]
-                break
-        if callback:
-            self.keypress(None,'up')
-            callback((category, item))
-    
-    def onCategoryClick(self, button):
-        self.__buildOverlay(button.get_label(),
-                            self.x_orig + self._w.base_widget.getStartCol(button)) 
-        
-
-class MenuRoller(urwid.WidgetWrap):
-
-    def __init__(self,menus_list):
-        """Create a MenuRoller
-        @param menus_list: list of tuple with (name, Menu_instance), name can be None
-        """
-        assert (menus_list)
-        self.selected = 0
-        self.name_list = []
-        self.menus = {}
-             
-        self.columns = urwid.Columns([urwid.Text(''),urwid.Text('')]) 
-        urwid.WidgetWrap.__init__(self, self.columns)
-        
-        for menu_tuple in menus_list:
-            name,menu = menu_tuple
-            self.addMenu(name, menu)
-
-    def __showSelected(self):
-        """show menu selected"""
-        name_txt = u'\u21c9 '+self.name_list[self.selected]+u' \u21c7 '
-        current_name = ClickableText(name_txt) 
-        name_len = len(name_txt)
-        current_menu = self.menus[self.name_list[self.selected]]
-        current_menu.setOrigX(name_len)
-        self.columns.widget_list[0] = current_name
-        self.columns.column_types[0]=('fixed', name_len)
-        self.columns.widget_list[1] = current_menu
-
-    def keypress(self, size, key):
-        if key=='up':
-            if self.columns.get_focus_column()==0 and self.selected > 0:
-                self.selected -= 1
-                self.__showSelected()
-        elif key=='down':
-            if self.columns.get_focus_column()==0 and self.selected < len(self.name_list)-1:
-                self.selected += 1
-                self.__showSelected()
-        elif key=='right':
-            if self.columns.get_focus_column()==0 and \
-                (isinstance(self.columns.widget_list[1], urwid.Text) or \
-                self.menus[self.name_list[self.selected]].getMenuSize()==0):
-                return #if we have no menu or the menu is empty, we don't go the right column
-
-        return super(MenuRoller, self).keypress(size, key)
-
-    def addMenu(self, name_param, menu):
-        name = name_param or ''
-        if name not in self.name_list:
-            self.name_list.append(name)
-        self.menus[name] = menu
-        if self.name_list[self.selected] == name:
-            self.__showSelected() #if we are on the menu, we update it
-
-    def removeMenu(self, name):
-        if name in self.name_list:
-            self.name_list.remove(name)
-        if name in self.menus.keys():
-            del self.menus[name]
-        self.selected = 0
-        self.__showSelected()
-
-    def checkShortcuts(self, key):
-        for menu in self.name_list:
-            key = self.menus[menu].checkShortcuts(key)
-        return key
-        
-
-## DIALOGS ##
-
-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:
-            cancel_arg = [kwargs['cancel_value']] if kwargs.has_key('cancel_value') else []
-            ok_arg = [kwargs['ok_value']] if kwargs.has_key('ok_value') else []
-            buttons = [urwid.Button(_("Cancel"), kwargs['cancel_cb'], *cancel_arg),
-                      urwid.Button(_("Ok"), kwargs['ok_cb'], *ok_arg)]
-        elif "YES/NO" in style:
-            yes_arg = [kwargs['yes_value']] if kwargs.has_key('yes_value') else []
-            no_arg = [kwargs['no_value']] if kwargs.has_key('no_value') else []
-            buttons = [urwid.Button(_("Yes"), kwargs['yes_cb'], *yes_arg),
-                      urwid.Button(_("No"), kwargs['no_cb'], *no_arg)]
-        if "OK" in style:
-            ok_arg = [kwargs['ok_value']] if kwargs.has_key('ok_value') else []
-            buttons = [urwid.Button(_("Ok"), kwargs['ok_cb'], *ok_arg)]
-        if buttons:
-            buttons_flow = urwid.GridFlow(buttons, max([len(button.get_label()) for button in buttons])+4, 1, 1, 'center')
-        body_content = urwid.SimpleListWalker(widgets_lst)
-        frame_body = urwid.ListBox(body_content)
-        frame = FocusFrame(frame_body, frame_header, buttons_flow if buttons else None, 'footer' if buttons else 'body')
-        decorated_frame = urwid.LineBox(frame)
-        urwid.WidgetWrap.__init__(self, decorated_frame)
-
-
-
-class InputDialog(GenericDialog):
-    """Dialog with an edit box"""
-
-    def __init__(self, title, instrucions, style=['OK/CANCEL'], default_txt = '', **kwargs):
-        instr_wid = urwid.Text(instrucions+':')
-        edit_box = AdvancedEdit(edit_text=default_txt)
-        GenericDialog.__init__(self, [instr_wid,edit_box], title, style, ok_value=edit_box, **kwargs)
-        self._w.base_widget.set_focus('body')
-
-class ConfirmDialog(GenericDialog):
-    """Dialog with buttons for confirm or cancel an action"""
-
-    def __init__(self, title, style=['YES/NO'], **kwargs):
-        GenericDialog.__init__(self, [], title, style, **kwargs)
-
-class Alert(GenericDialog):
-    """Dialog with just a message and a OK button"""
-
-    def __init__(self, title, message, style=['OK'], **kwargs):
-        GenericDialog.__init__(self, [urwid.Text(message, 'center')], title, style, ok_value=None, **kwargs)
-
-## CONTAINERS ##
-
-class ColumnsRoller(urwid.FlowWidget):
-    
-    def __init__(self, widget_list = None, focus_column=0):
-        self.widget_list = widget_list or []
-        self.focus_column = focus_column
-        self.__start = 0
-        self.__next = False
-
-    def addWidget(self, widget, width):
-        self.widget_list.append((width,widget))
-        if len(self.widget_list) == 1:
-            self.set_focus(0)
-
-    def getStartCol(self, widget):
-        """Return the column of the left corner of the widget"""
-        start_col = 0
-        for wid in self.widget_list[self.__start:]:
-            if wid[1] == widget:
-                return start_col
-            start_col+=wid[0]
-        return None
-
-    def selectable(self):
-        try:
-            return self.widget_list[self.focus_column][1].selectable()
-        except IndexError:
-            return False
-    
-    def keypress(self, size, key):
-        if key=='left':
-            if self.focus_column>0:
-                self.focus_column-=1
-                self._invalidate()
-                return
-        if key=='right':
-            if self.focus_column<len(self.widget_list)-1:
-                self.focus_column+=1
-                self._invalidate()
-                return
-        if self.focus_column<len(self.widget_list):
-            return self.widget_list[self.focus_column][1].keypress(size,key)
-        return key
-
-    def getSelected(self):
-        """Return selected widget"""
-        return self.widget_list[self.focus_column][1]
-
-    def set_focus(self, idx):
-        if idx>len(self.widget_list)-1:
-            idx = len(self.widget_list)-1
-        self.focus_column = idx
-
-    def rows(self,size,focus=False):
-        return 1
-
-    def __calculate_limits(self, size):
-        (maxcol,) = size
-        _prev = _next = False
-        start_wid = 0
-        end_wid = len(self.widget_list)-1
-        
-        total_wid = sum([w[0] for w in self.widget_list])
-        while total_wid > maxcol:
-            if self.focus_column == end_wid:
-                if not _prev:
-                    total_wid+=1
-                    _prev = True
-                total_wid-=self.widget_list[start_wid][0]
-                start_wid+=1
-            else:
-                if not _next:
-                    total_wid+=1
-                    _next = True
-                total_wid-=self.widget_list[end_wid][0]
-                end_wid-=1
-        
-        cols_left = maxcol - total_wid
-        self.__start = start_wid #we need to keep it for getStartCol
-        return _prev,_next,start_wid,end_wid,cols_left
-        
-
-    def mouse_event(self, size, event, button, x, y, focus):
-        (maxcol,)=size
-
-        if urwid.is_mouse_press(event) and button == 1:
-            _prev,_next,start_wid,end_wid,cols_left = self.__calculate_limits(size)
-            if x==0 and _prev:
-                self.keypress(size,'left')
-                return True
-            if x==maxcol-1 and _next:
-                self.keypress(size,'right')
-                return True
-            
-            current_pos = 1 if _prev else 0
-            idx = 0
-            while current_pos<x and idx<len(self.widget_list):
-                width,widget = self.widget_list[idx]
-                if x<=current_pos+width:
-                    self.focus_column = idx
-                    self._invalidate()
-                    if not hasattr(widget,'mouse_event'):
-                        return False
-                    return widget.mouse_event((width,0), event, button, 
-                        x-current_pos, 0, focus)
-
-                current_pos+=self.widget_list[idx][0]
-                idx+=1
-        
-        return False
-    
-    def render(self, size, focus=False):
-        if not self.widget_list:
-            return SolidCanvas(" ", size[0], 1)
-
-        _prev,_next,start_wid,end_wid,cols_left = self.__calculate_limits(size)
-        
-        idx=start_wid
-        render = []
-
-        for width,widget in self.widget_list[start_wid:end_wid+1]:
-            _focus = idx == self.focus_column and focus
-            render.append((widget.render((width,),_focus),False,_focus,width))
-            idx+=1
-        if _prev:
-            render.insert(0,(urwid.Text([u"◀"]).render((1,),False),False,False,1))
-        if _next:
-            render.append((urwid.Text([u"▶"],align='right').render((1+cols_left,),False),False,False,1+cols_left))
-        else:
-            render.append((urwid.SolidCanvas(" "*cols_left, size[0], 1),False,False,cols_left))
-
-        return urwid.CanvasJoin(render)
-
-
-class FocusFrame(urwid.Frame):
-    """Frame which manage 'tab' key"""
-
-    def keypress(self, size, key):
-        ret = urwid.Frame.keypress(self, size, key)
-        if not ret:
-            return
-        
-        if key == 'tab':
-            focus_list = ('header','body','footer')
-            focus_idx = focus_list.index(self.focus_part)
-            for i in range(2):
-                focus_idx = (focus_idx + 1) % len(focus_list)
-                focus_name = focus_list[focus_idx]
-                widget = getattr(self,'_'+focus_name)
-                if widget!=None and widget.selectable():
-                    self.set_focus(focus_name)
-
-        return ret 
-
-class TabsContainer(urwid.WidgetWrap):
-    signals = ['click']
-
-    def __init__(self):
-        self._current_tab = None
-        self._buttons_cont = ColumnsRoller()
-        self.tabs = []
-        self.__frame = FocusFrame(urwid.Filler(urwid.Text('')),urwid.Pile([self._buttons_cont,urwid.Divider(u"─")]))
-        urwid.WidgetWrap.__init__(self, self.__frame)
-
-    def keypress(self, size, key):
-        if key=='tab':
-            self._w.keypress(size,key)
-            return
-        return self._w.keypress(size,key)
-
-    def __buttonClicked(self, button, invisible=False):
-        """Called when a button on the tab is changed,
-        change the page
-        @param button: button clicked
-        @param invisible: emit signal only if False"""
-        tab_name = button.get_label()
-        for tab in self.tabs:
-            if tab[0] == tab_name:
-                break
-        if tab[0] != tab_name:
-            error(_("INTERNAL ERROR: Tab not found"))
-            assert(False)
-        self.__frame.body = tab[1]
-        button.set_label(('title',button.get_label()))
-        if self._current_tab:
-            self._current_tab.set_label(self._current_tab.get_label())
-        self._current_tab = button
-        if not invisible:
-            self._emit('click')
-
-    def __appendButton(self, name):
-        """Append a button to the frame header,
-        and link it to the page change method"""
-        button = CustomButton(name, self.__buttonClicked, left_border = '', right_border=' | ')
-        self._buttons_cont.addWidget(button, button.getSize())
-        if len(self._buttons_cont.widget_list) == 1:
-            #first button: we set the focus and the body
-            self._buttons_cont.set_focus(0)
-            self.__buttonClicked(button,True)
-
-    def addTab(self,name,content=[]):
-        """Add a page to the container
-        @param name: name of the page (what appear on the tab)
-        @param content: content of the page
-        @return: ListBox (content of the page)"""
-        listbox = urwid.ListBox(urwid.SimpleListWalker(content))
-        self.tabs.append([name,listbox])
-        self.__appendButton(name)
-        return listbox
-
-    def addFooter(self, widget):
-        """Add a widget on the bottom of the tab (will be displayed on all pages)
-        @param widget: FlowWidget"""
-        self._w.footer = widget
-    
-
-## DECORATORS ##
-class LabelLine(urwid.LineBox):
-    """Like LineBox, but with a Label centered in the top line"""
-
-    def __init__(self, original_widget, label_widget):
-        urwid.LineBox.__init__(self, original_widget)
-        top_columns = self._w.widget_list[0]
-        top_columns.widget_list[1] = label_widget
-
-class VerticalSeparator(urwid.WidgetDecoration, urwid.WidgetWrap):
-    def __init__(self, original_widget, left_char = u"│", right_char = ''):
-        """Draw a separator on left and/or right of original_widget."""
-        
-        widgets = [original_widget]
-        if left_char:
-            widgets.insert(0, ('fixed', 1, urwid.SolidFill(left_char)))
-        if right_char:
-            widgets.append(('fixed', 1, urwid.SolidFill(right_char)))
-        columns = urwid.Columns(widgets, box_columns = [0,2], focus_column = 1)
-        urwid.WidgetDecoration.__init__(self, original_widget)
-        urwid.WidgetWrap.__init__(self, columns)
-
-        
--- a/frontends/primitivus/files_management.py	Mon Dec 27 21:56:12 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,234 +0,0 @@
-#!/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
-import custom_widgets
-from tools.jid import JID
-import os, os.path
-from xml.dom import minidom
-from logging import debug, info, error
-from time import time
-
-class PathEdit(custom_widgets.AdvancedEdit):
-    """AdvancedEdit with manage file paths"""
-    
-    def keypress(self, size, key):
-        if key == '~' and self.edit_pos==0:
-            expanded = os.path.expanduser('~')
-            self.set_edit_text(os.path.normpath(expanded+'/'+self.edit_text))
-            self.set_edit_pos(len(expanded)+1)
-        elif key == 'ctrl w':
-            if self.edit_pos<2:
-                return
-            before = self.edit_text[:self.edit_pos]
-            pos = (before[:-1] if before.endswith('/') else before).rfind("/")+1
-            self.set_edit_text(before[:pos] + self.edit_text[self.edit_pos:])
-            self.set_edit_pos(pos)
-            return
-        else:
-            return super(PathEdit, self).keypress(size, key) 
-
-class FilesViewer(urwid.WidgetWrap):
-    """List specialised for files"""
-
-    def __init__(self, onPreviousDir, onDirClick, onFileClick):
-        self.path=''
-        self.key_cache = ''
-        self.key_time = time()
-        self.onPreviousDir = onPreviousDir
-        self.onDirClick = onDirClick
-        self.onFileClick = onFileClick
-        self.files_list = urwid.SimpleListWalker([])
-        self.show_hidden = True 
-        listbox = urwid.ListBox(self.files_list)
-        urwid.WidgetWrap.__init__(self, listbox)
-
-    def keypress(self, size, key):
-        if key=='meta h':
-            #(un)hide hidden files
-            self.show_hidden = not self.show_hidden
-            self.showDirectory(self.path)
-        if key=='meta d':
-            #jump to directories
-            if self.files_list:
-                self._w.set_focus(0)
-        elif key=='meta f':
-            for idx in range(len(self.files_list)):
-                if isinstance(self.files_list[idx].base_widget,urwid.Divider):
-                    if idx<len(self.files_list)-1:
-                        self._w.set_focus(idx+1)
-                    break
-        elif len(key) == 1:
-            if time() - self.key_time > 2:
-                self.key_cache=key
-            else:
-                self.key_cache+=key
-            self.key_time = time()
-            for idx in range(len(self.files_list)):
-                if isinstance(self.files_list[idx],custom_widgets.ClickableText) and self.files_list[idx].get_text().lower().startswith(self.key_cache.lower()):
-                    self._w.set_focus(idx)
-                    break
-        else:
-            return self._w.keypress(size, key)
-
-    def showDirectory(self, path):
-        self.path = path
-        del self.files_list[:]
-        directories = []
-        files = []
-        try:
-            for filename in os.listdir(path):
-                fullpath = os.path.join(path,filename)
-                if os.path.isdir(fullpath):
-                    directories.append(filename)
-                else:
-                    files.append(filename)
-        except OSError:
-           self.files_list.append(urwid.Text(("warning",_("Impossible to list directory")),'center')) 
-        directories.sort()
-        files.sort()
-        if os.path.abspath(path)!='/' and os.path.abspath(path) != '//':
-            previous_wid = custom_widgets.ClickableText(('directory','..'))
-            urwid.connect_signal(previous_wid,'click',self.onPreviousDir)
-            self.files_list.append(previous_wid)
-        for directory in directories:
-            if directory.startswith('.') and not self.show_hidden:
-                continue
-            dir_wid = custom_widgets.ClickableText(('directory',directory))
-            urwid.connect_signal(dir_wid,'click',self.onDirClick)
-            self.files_list.append(dir_wid)
-        self.files_list.append(urwid.AttrMap(urwid.Divider('-'),'separator'))
-        for filename in files:
-            if filename.startswith('.') and not self.show_hidden:
-                continue
-            file_wid = custom_widgets.ClickableText(filename)
-            urwid.connect_signal(file_wid,'click',self.onFileClick)
-            self.files_list.append(file_wid)
-
-
-
-class FileDialog(urwid.WidgetWrap):
-
-    def __init__(self, ok_cb, cancel_cb, title=_("Please select a file"), style=[]):
-        """Create file dialog
-        @param title: title of the window/popup
-        @param style: NOT USED YET #FIXME
-        """
-        self.ok_cb = ok_cb
-        self.__home_path = os.path.expanduser('~')
-        self.path_wid = PathEdit(_('Path: '))
-        self.path_wid.setCompletionMethod(self._directory_completion)
-        urwid.connect_signal(self.path_wid, 'change', self.onPathChange)
-        header = urwid.Pile([self.path_wid, urwid.Divider(u'─')])
-        bookm_list = urwid.SimpleListWalker([])
-        self.bookmarks = list(self.getBookmarks())
-        self.bookmarks.sort()
-        for bookmark in self.bookmarks:
-            if bookmark.startswith(self.__home_path):
-                bookmark="~"+bookmark[len(self.__home_path):]
-            book_wid = custom_widgets.ClickableText(bookmark)
-            urwid.connect_signal(book_wid, 'click', self.onBookmarkSelected)
-            bookm_list.append(book_wid)
-        bookm_wid = urwid.Frame(urwid.ListBox(bookm_list), urwid.AttrMap(urwid.Text(_('Bookmarks'),'center'),'title'))
-        self.files_wid = FilesViewer(self.onPreviousDir, self.onDirClick, self.onFileClick)
-        center_row = urwid.Columns([('weight',2,bookm_wid),
-                     ('weight',8,custom_widgets.VerticalSeparator(self.files_wid))])
-
-        buttons = []
-        buttons.append(custom_widgets.CustomButton(_('Cancel'),cancel_cb))
-        max_len = max([button.getSize() for button in buttons])
-        buttons_wid = urwid.GridFlow(buttons,max_len,1,0,'center')
-        main_frame = custom_widgets.FocusFrame(center_row, header, buttons_wid)
-        decorated = custom_widgets.LabelLine(main_frame, custom_widgets.SurroundedText(title))
-        urwid.WidgetWrap.__init__(self, decorated)
-        self.path_wid.set_edit_text(os.getcwdu())
-
-    def _directory_completion(self, path, completion_data):
-        path=os.path.abspath(path)
-        if not os.path.isdir(path):
-            head,dir_start = os.path.split(path)
-        else:
-            head=path
-            dir_start=''
-        try:
-            filenames = os.listdir(head)
-            filenames.sort()
-            try:
-                start_idx=filenames.index(completion_data['last_dir'])+1
-                if start_idx == len(filenames):
-                    start_idx = 0
-            except (KeyError,ValueError):
-                start_idx = 0
-            for idx in range(start_idx,len(filenames)) + range(0,start_idx):
-                full_path = os.path.join(head,filenames[idx])
-                if filenames[idx].lower().startswith(dir_start.lower()) and os.path.isdir(full_path):
-                    completion_data['last_dir'] = filenames[idx]
-                    return full_path 
-        except OSError:
-            pass
-        return path
-
-    def getBookmarks(self):
-        gtk_bookm = os.path.expanduser("~/.gtk-bookmarks")
-        kde_bookm = os.path.expanduser("~/.kde/share/apps/kfileplaces/bookmarks.xml")
-        bookmarks = set()
-        try:
-            with open(gtk_bookm) as gtk_fd:
-                for bm in gtk_fd.readlines():
-                    if bm.startswith("file:///"):
-                        bookmarks.add(bm[7:].replace('\n',''))
-        except IOError:
-            info(_('No GTK bookmarks file found'))
-            pass
-        
-        try:
-            dom = minidom.parse(kde_bookm)
-            for elem in dom.getElementsByTagName('bookmark'):
-                bm = elem.getAttribute("href")
-                if bm.startswith("file:///"):
-                    bookmarks.add(bm[7:])
-        except IOError:
-            info(_('No KDE bookmarks file found'))
-            pass
-            
-        return bookmarks
-
-    def onBookmarkSelected(self, button):
-        self.path_wid.set_edit_text(os.path.expanduser(button.get_text()))
-
-    def onPathChange(self, edit, path):
-        if os.path.isdir(path):
-            self.files_wid.showDirectory(path)
-
-    def onPreviousDir(self, wid):
-        path = os.path.abspath(self.path_wid.get_edit_text())
-        if not os.path.isdir(path):
-            path = dirname(path)
-        self.path_wid.set_edit_text(os.path.split(path)[0])
-
-    def onDirClick(self, wid):
-        path = os.path.abspath(self.path_wid.get_edit_text())
-        if not os.path.isdir(path):
-            path = dirname(path)
-        self.path_wid.set_edit_text(os.path.join(path,wid.get_text()))
-    
-    def onFileClick(self, wid):
-        self.ok_cb(os.path.abspath(os.path.join(self.files_wid.path,wid.get_text())))
--- a/frontends/primitivus/gateways.py	Mon Dec 27 21:56:12 2010 +0100
+++ b/frontends/primitivus/gateways.py	Tue Dec 28 23:10:13 2010 +0100
@@ -20,7 +20,7 @@
 """
 
 import urwid
-import custom_widgets
+from urwid_satext import sat_widgets
 from tools.jid import JID
 from quick_frontend.quick_gateways import QuickGatewaysManager
 
@@ -37,19 +37,19 @@
         for gateway in gateways:
             self.addGateway(widget_list,gateway, gateways[gateway])
         widget_list.append(urwid.Divider())
-        self.ext_serv = custom_widgets.AdvancedEdit(_("Use external XMPP server: "))
-        go_button = custom_widgets.CustomButton( _("GO !"),self.browseExternalServer)
+        self.ext_serv = sat_widgets.AdvancedEdit(_("Use external XMPP server: "))
+        go_button = sat_widgets.CustomButton( _("GO !"),self.browseExternalServer)
         ext_serv_col = urwid.Columns([self.ext_serv,('fixed',go_button.getSize(),go_button)])
         widget_list.append(ext_serv_col)
         list_wid = urwid.ListBox(widget_list)
-        decorated = custom_widgets.LabelLine(list_wid, custom_widgets.SurroundedText(title))
+        decorated = sat_widgets.LabelLine(list_wid, sat_widgets.SurroundedText(title))
         urwid.WidgetWrap.__init__(self, decorated)
     
     def browseExternalServer(self, button):
         """Open the gateway manager on given server"""
         server = self.ext_serv.get_edit_text()
         if not server:
-            popup = custom_widgets.Alert(_("Error"), _("You must enter an external server JID"), ok_cb=self.host.removePopUp)
+            popup = sat_widgets.Alert(_("Error"), _("You must enter an external server JID"), ok_cb=self.host.removePopUp)
             self.host.showPopUp(popup)
             return
         id = self.host.bridge.findGateways(server, self.host.profile)
@@ -67,10 +67,10 @@
 
         #The buttons
         
-        reg_button = custom_widgets.CustomButton( _("Register"), self.onRegister)
+        reg_button = sat_widgets.CustomButton( _("Register"), self.onRegister)
         reg_button.gateway_jid = JID(gateway)
         widget_col.append(('fixed',reg_button.getSize(),reg_button))
-        unreg_button = custom_widgets.CustomButton( _("Unregister"), self.onUnregister)
+        unreg_button = sat_widgets.CustomButton( _("Unregister"), self.onUnregister)
         unreg_button.gateway_jid = JID(gateway)
         widget_col.append(('fixed',unreg_button.getSize(),unreg_button))
         widget_list.append(urwid.Columns(widget_col,1))
--- a/frontends/primitivus/primitivus	Mon Dec 27 21:56:12 2010 +0100
+++ b/frontends/primitivus/primitivus	Tue Dec 28 23:10:13 2010 +0100
@@ -29,7 +29,7 @@
 from contact_list import ContactList
 from chat import Chat
 from gateways import GatewaysManager
-import custom_widgets
+from urwid_satext import sat_widgets
 import logging
 from logging import debug, info, error
 import sys, os
@@ -99,7 +99,7 @@
 
         ##misc setup##
         self.chat_wins=ChatList(self)
-        self.notBar = custom_widgets.NotificationBar()
+        self.notBar = sat_widgets.NotificationBar()
         urwid.connect_signal(self.notBar,'change',self.onNotification)
         self.progress_wid = Progress(self)
         urwid.connect_signal(self.notBar.progress,'click',lambda x:self.addWindow(self.progress_wid))
@@ -196,7 +196,7 @@
             return input
 
     def __buildMenuRoller(self):
-        menu = custom_widgets.Menu(self.loop)
+        menu = sat_widgets.Menu(self.loop)
         general = _("General")
         menu.addMenu(general, _("Connect"), self.onConnectRequest)
         menu.addMenu(general, _("Disconnect"), self.onDisconnectRequest)
@@ -221,18 +221,18 @@
             assert(type=="NORMAL") #TODO: manage other types
             menu.addMenu(unicode(category), unicode(item), add_menu_cb)
             
-        menu_roller = custom_widgets.MenuRoller([(_('Main menu'),menu)])
+        menu_roller = sat_widgets.MenuRoller([(_('Main menu'),menu)])
         return menu_roller 
 
     def __buildMainWidget(self):
         self.contactList = ContactList(self, self.CM, on_click = self.contactSelected, on_change=lambda w: self.redraw())
         #self.center_part = urwid.Columns([('weight',2,self.contactList),('weight',8,Chat('',self))])
         self.center_part = urwid.Columns([('weight',2,self.contactList), ('weight',8,urwid.Filler(urwid.Text('')))])
-        self.editBar = custom_widgets.AdvancedEdit('> ')
+        self.editBar = sat_widgets.AdvancedEdit('> ')
         self.editBar.setCompletionMethod(self._nick_completion)
         urwid.connect_signal(self.editBar,'click',self.onTextEntered)
         self.menu_roller = self.__buildMenuRoller()
-        self.main_widget = custom_widgets.FocusFrame(self.center_part, header=self.menu_roller, footer=self.editBar, focus_part='footer')
+        self.main_widget = sat_widgets.FocusFrame(self.center_part, header=self.menu_roller, footer=self.editBar, focus_part='footer')
         return self.main_widget
 
     def _nick_completion(self, text, completion_data):
@@ -357,25 +357,25 @@
 
     def showDialog(self, message, title="", type="info", answer_cb = None, answer_data = None):
         if type == 'info':
-            popup = custom_widgets.Alert(unicode(title), unicode(message), ok_cb=answer_cb or self.removePopUp) #FIXME: remove unicode here when DBus Bridge will no return dbus.String anymore 
+            popup = sat_widgets.Alert(unicode(title), unicode(message), ok_cb=answer_cb or self.removePopUp) #FIXME: remove unicode here when DBus Bridge will no return dbus.String anymore 
             flags = wx.OK | wx.ICON_INFORMATION
         elif type == 'error':
-            popup = custom_widgets.Alert(unicode(title), unicode(message), ok_cb=answer_cb or self.removePopUp) #FIXME: remove unicode here when DBus Bridge will no return dbus.String anymore 
+            popup = sat_widgets.Alert(unicode(title), unicode(message), ok_cb=answer_cb or self.removePopUp) #FIXME: remove unicode here when DBus Bridge will no return dbus.String anymore 
         elif type == 'yes/no':
-            popup = custom_widgets.ConfirmDialog(unicode(message),
+            popup = sat_widgets.ConfirmDialog(unicode(message),
                     yes_cb=self._dialogOkCb, yes_value = (answer_cb, answer_data),
                     no_cb=self._dialogCancelCb, no_value = (answer_cb, answer_data))
         else:
-            popup = custom_widgets.Alert(unicode(title), unicode(message), ok_cb=answer_cb or self.removePopUp) #FIXME: remove unicode here when DBus Bridge will no return dbus.String anymore 
+            popup = sat_widgets.Alert(unicode(title), unicode(message), ok_cb=answer_cb or self.removePopUp) #FIXME: remove unicode here when DBus Bridge will no return dbus.String anymore 
             error(_('unmanaged dialog type: %s'), type)
         self.showPopUp(popup)
     
     def onNotification(self, notBar):
         """Called when a new notification has been received"""
-        if not isinstance(self.main_widget, custom_widgets.FocusFrame):
+        if not isinstance(self.main_widget, sat_widgets.FocusFrame):
             #if we are not in the main configuration, we ignore the notifications bar
             return
-        if isinstance(self.main_widget.footer,custom_widgets.AdvancedEdit):
+        if isinstance(self.main_widget.footer,sat_widgets.AdvancedEdit):
             if not self.notBar.canHide():
                 #the notification bar is not visible and has usefull informations, we show it
                 pile = urwid.Pile([self.notBar, self.editBar])
@@ -411,7 +411,7 @@
                 ui.show('window')
         elif type == "ERROR":
             self.current_action_ids.remove(id)
-            self.showPopUp(custom_widgets.Alert(_("Error"), unicode(data["message"]), ok_cb=self.removePopUp)) #FIXME: remove unicode here when DBus Bridge will no return dbus.String anymore 
+            self.showPopUp(sat_widgets.Alert(_("Error"), unicode(data["message"]), ok_cb=self.removePopUp)) #FIXME: remove unicode here when DBus Bridge will no return dbus.String anymore 
         elif type == "RESULT":
             self.current_action_ids.remove(id)
             if self.current_action_ids_cb.has_key(id):
@@ -437,7 +437,7 @@
         else:
             message = _("'%s' is an invalid JID !") % room_jid
             error (message)
-            self.showPopUp(custom_widgets.Alert(_("Error"), message, ok_cb=self.removePopUp)) 
+            self.showPopUp(sat_widgets.Alert(_("Error"), message, ok_cb=self.removePopUp)) 
 
     def onAddContact(self, button, edit):
         self.removePopUp()
@@ -447,7 +447,7 @@
         else:
             message = _("'%s' is an invalid JID !") % jid
             error (message)
-            self.showPopUp(custom_widgets.Alert(_("Error"), message, ok_cb=self.removePopUp))
+            self.showPopUp(sat_widgets.Alert(_("Error"), message, ok_cb=self.removePopUp))
 
     def onRemoveContact(self, button):
         self.removePopUp()
@@ -471,7 +471,7 @@
 
     def onJoinRoomRequest(self, menu):
         """User wants to join a MUC room"""
-        pop_up_widget = custom_widgets.InputDialog(_("Entering a MUC room"), _("Please enter MUC's JID"), default_txt = 'room@muc_service.server.tld', cancel_cb=self.removePopUp, ok_cb=self.onJoinRoom)
+        pop_up_widget = sat_widgets.InputDialog(_("Entering a MUC room"), _("Please enter MUC's JID"), default_txt = 'room@muc_service.server.tld', cancel_cb=self.removePopUp, ok_cb=self.onJoinRoom)
         self.showPopUp(pop_up_widget)
 
     def onFindGatewaysRequest(self, e):
@@ -481,19 +481,19 @@
         self.current_action_ids_cb[id] = self.onGatewaysFound
 
     def onAddContactRequest(self, menu):
-        pop_up_widget = custom_widgets.InputDialog(_("Adding a contact"), _("Please enter new contact JID"), default_txt = 'name@server.tld', cancel_cb=self.removePopUp, ok_cb=self.onAddContact)
+        pop_up_widget = sat_widgets.InputDialog(_("Adding a contact"), _("Please enter new contact JID"), default_txt = 'name@server.tld', cancel_cb=self.removePopUp, ok_cb=self.onAddContact)
         self.showPopUp(pop_up_widget)
 
     def onRemoveContactRequest(self, menu):
         contact = self.contactList.get_contact()
         if not contact:
-            self.showPopUp(custom_widgets.Alert(_("Error"), _("You have not selected any contact to delete !"), ok_cb=self.removePopUp))
+            self.showPopUp(sat_widgets.Alert(_("Error"), _("You have not selected any contact to delete !"), ok_cb=self.removePopUp))
         else:
-            pop_up_widget = custom_widgets.ConfirmDialog(_("Are you sure you want to delete the contact [%s] ?" % contact), yes_cb=self.onRemoveContact, no_cb=self.removePopUp)
+            pop_up_widget = sat_widgets.ConfirmDialog(_("Are you sure you want to delete the contact [%s] ?" % contact), yes_cb=self.onRemoveContact, no_cb=self.removePopUp)
             self.showPopUp(pop_up_widget)
 
     def onAboutRequest(self, menu):
-        self.showPopUp(custom_widgets.Alert(_("About"), const_APP_NAME + " v" + self.bridge.getVersion(), ok_cb=self.removePopUp)) 
+        self.showPopUp(sat_widgets.Alert(_("About"), const_APP_NAME + " v" + self.bridge.getVersion(), ok_cb=self.removePopUp)) 
        
     #MISC CALLBACKS#
 
--- a/frontends/primitivus/profile_manager.py	Mon Dec 27 21:56:12 2010 +0100
+++ b/frontends/primitivus/profile_manager.py	Tue Dec 28 23:10:13 2010 +0100
@@ -20,7 +20,7 @@
 """
 
 import urwid
-from custom_widgets import Password,List,InputDialog,ConfirmDialog,Alert,FocusFrame
+from urwid_satext.sat_widgets import Password,List,InputDialog,ConfirmDialog,Alert,FocusFrame
 from tools.jid import JID
 
 
--- a/frontends/primitivus/progress.py	Mon Dec 27 21:56:12 2010 +0100
+++ b/frontends/primitivus/progress.py	Tue Dec 28 23:10:13 2010 +0100
@@ -20,7 +20,7 @@
 """
 
 import urwid
-import custom_widgets
+from urwid_satext import sat_widgets
 from tools.jid import JID
 
 
@@ -32,10 +32,10 @@
         self.progress_dict = {}
         listbox = urwid.ListBox(self.progress_list)
         buttons = []
-        buttons.append(custom_widgets.CustomButton(_('Clear progress list'), self.__onClear))
+        buttons.append(sat_widgets.CustomButton(_('Clear progress list'), self.__onClear))
         max_len = max([button.getSize() for button in buttons])
         buttons_wid = urwid.GridFlow(buttons,max_len,1,0,'center')
-        main_wid = custom_widgets.FocusFrame(listbox, footer=buttons_wid)
+        main_wid = sat_widgets.FocusFrame(listbox, footer=buttons_wid)
         urwid.WidgetWrap.__init__(self, main_wid)
 
     def addProgress(self, id, message):
--- a/frontends/primitivus/xmlui.py	Mon Dec 27 21:56:12 2010 +0100
+++ b/frontends/primitivus/xmlui.py	Tue Dec 28 23:10:13 2010 +0100
@@ -21,7 +21,7 @@
 
 import urwid
 from logging import debug, info, warning, error
-import custom_widgets
+from urwid_satext import sat_widgets
 from xml.dom import minidom
 
 class Pairs(urwid.WidgetWrap):
@@ -82,24 +82,24 @@
             elif type=="label":
                 ctrl = urwid.Text(value+": ")
             elif type=="string":
-                ctrl = custom_widgets.AdvancedEdit(edit_text = value)
+                ctrl = sat_widgets.AdvancedEdit(edit_text = value)
                 self.ctrl_list[name] = ({'type':type, 'control':ctrl})
             elif type=="password":
-                ctrl = custom_widgets.Password(edit_text = value)
+                ctrl = sat_widgets.Password(edit_text = value)
                 self.ctrl_list[name] = ({'type':type, 'control':ctrl})
             elif type=="textbox":
-                ctrl = custom_widgets.AdvancedEdit(edit_text = value, multiline=True)
+                ctrl = sat_widgets.AdvancedEdit(edit_text = value, multiline=True)
                 self.ctrl_list[name] = ({'type':type, 'control':ctrl})
             elif type=="bool":
                 ctrl = urwid.CheckBox('', state = value=="true")
                 self.ctrl_list[name] = ({'type':type, 'control':ctrl})
             elif type=="list":
                 style=[] if elem.getAttribute("multi")=='yes' else ['single']
-                ctrl = custom_widgets.List(options=[option.getAttribute("value") for option in elem.getElementsByTagName("option")], style=style)
+                ctrl = sat_widgets.List(options=[option.getAttribute("value") for option in elem.getElementsByTagName("option")], style=style)
                 self.ctrl_list[name] = ({'type':type, 'control':ctrl})
             elif type=="button":
                 callback_id = elem.getAttribute("callback_id")
-                ctrl = custom_widgets.CustomButton(value, on_press=self.onButtonPress)
+                ctrl = sat_widgets.CustomButton(value, on_press=self.onButtonPress)
                 ctrl.param_id = (callback_id,[field.getAttribute('name') for field in elem.getElementsByTagName("field_back")])
             else:
                 error(_("FIXME FIXME FIXME: type [%s] is not implemented") % type)  #FIXME !
@@ -122,7 +122,7 @@
             if node.nodeName == "layout":
                 type = node.getAttribute('type')
                 if type == "tabs":
-                    tab_cont = custom_widgets.TabsContainer()
+                    tab_cont = sat_widgets.TabsContainer()
                     self.__parseChilds(current, node, ['category'], tab_cont)
                     current.append(tab_cont)
                 elif type == "vertical":
@@ -137,7 +137,7 @@
             elif node.nodeName == "category":
                 name = node.getAttribute('name') 
                 label = node.getAttribute('label') 
-                if not name or not isinstance(data,custom_widgets.TabsContainer):
+                if not name or not isinstance(data,sat_widgets.TabsContainer):
                     raise InvalidXMLUI 
                 if self.type == 'param':
                     self._current_category = name #XXX: awful hack because params need category and we don't keep parent
@@ -167,7 +167,7 @@
 
         assert ret_wid.body
         
-        if isinstance(ret_wid.body[0],custom_widgets.TabsContainer):
+        if isinstance(ret_wid.body[0],sat_widgets.TabsContainer):
             ret_wid = ret_wid.body[0] #xxx: awfull hack cause TabsContainer is a BoxWidget, can't be inside a ListBox
         
         
@@ -180,10 +180,10 @@
             grid_wid = urwid.GridFlow(buttons,max_len+4,1,0,'center')
             ret_wid.body.append(grid_wid)
         elif self.type == 'param':
-            assert(isinstance(ret_wid,custom_widgets.TabsContainer))
+            assert(isinstance(ret_wid,sat_widgets.TabsContainer))
             buttons = []
-            buttons.append(custom_widgets.CustomButton(_('Save'),self.onSaveParams))
-            buttons.append(custom_widgets.CustomButton(_('Cancel'),lambda x:self.host.removeWindow()))
+            buttons.append(sat_widgets.CustomButton(_('Save'),self.onSaveParams))
+            buttons.append(sat_widgets.CustomButton(_('Cancel'),lambda x:self.host.removeWindow()))
             max_len = max([button.getSize() for button in buttons])
             grid_wid = urwid.GridFlow(buttons,max_len,1,0,'center')
             ret_wid.addFooter(grid_wid)
@@ -195,7 +195,7 @@
             - popup
             - window"""
         self.__dest = "popup"
-        decorated = custom_widgets.LabelLine(self, custom_widgets.SurroundedText(self.title or '')) 
+        decorated = sat_widgets.LabelLine(self, sat_widgets.SurroundedText(self.title or '')) 
         if show_type == 'popup':
             self.host.showPopUp(decorated)
         elif show_type == 'window':
@@ -213,7 +213,7 @@
         data = {"callback_id":callback_id}
         for field in fields:
             ctrl = self.ctrl_list[field]
-            if isinstance(ctrl['control'],custom_widgets.List):
+            if isinstance(ctrl['control'],sat_widgets.List):
                 data[field] = '\t'.join(ctrl['control'].getSelectedValues())
             else:
                 data[field] = ctrl['control'].getValue()
@@ -230,7 +230,7 @@
         data = []
         for ctrl_name in self.ctrl_list:
             ctrl = self.ctrl_list[ctrl_name]
-            if isinstance(ctrl['control'], custom_widgets.List):
+            if isinstance(ctrl['control'], sat_widgets.List):
                 data.append((ctrl_name, ctrl['control'].getSelectedValue()))
             elif isinstance(ctrl['control'], urwid.CheckBox):
                 data.append((ctrl_name, "true" if ctrl['control'].get_state() else "false"))