changeset 120:1ca5f254ce41

primitivus group chat & misc primitivus: new widget: SurroundedText (text with a character repeated around it) primitivus: new decorator LabelLine (like lineBox, but with a label on the top line) wix & primitivus & quick_app: group chat method move to quick_chat wix: when new message, window is not raised anymore, but RequestUserAttention is called instead
author Goffi <goffi@goffi.org>
date Thu, 08 Jul 2010 14:12:18 +0800
parents ded2431cea5a
children 03d8bcc67182
files frontends/primitivus/chat.py frontends/primitivus/contact_list.py frontends/primitivus/custom_widgets.py frontends/primitivus/primitivus frontends/quick_frontend/quick_chat.py frontends/wix/chat.py frontends/wix/main_window.py
diffstat 7 files changed, 113 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/frontends/primitivus/chat.py	Mon Jul 05 19:13:36 2010 +0800
+++ b/frontends/primitivus/chat.py	Thu Jul 08 14:12:18 2010 +0800
@@ -22,7 +22,7 @@
 import urwid
 from quick_frontend.quick_contact_list import QuickContactList
 from quick_frontend.quick_chat import QuickChat
-from custom_widgets import Password,List,InputDialog,ConfirmDialog,Alert,SelectableText
+from custom_widgets import Password,List,InputDialog,ConfirmDialog,Alert,SelectableText,LabelLine,SurroundedText
 
 
 class Chat(urwid.WidgetWrap, QuickChat):
@@ -31,8 +31,8 @@
         QuickChat.__init__(self, target, host, type)
         self.content = urwid.SimpleListWalker([])
         self.text_list = urwid.ListBox(self.content)
-        main_widget = urwid.LineBox(
-                      urwid.Frame(self.text_list, urwid.AttrMap(urwid.Text(str(target),'center'),'title'))
+        main_widget = LabelLine(
+                      urwid.Frame(self.text_list), SurroundedText(str(target))
                       )
         urwid.WidgetWrap.__init__(self, main_widget)
         self.setType(type)
@@ -41,6 +41,12 @@
         QuickChat.setType(self, type)
         if type == 'one2one':
             self.historyPrint(profile=self.host.profile)
+    
+    def setSubject(self, subject):
+        """Set title for a group chat"""
+        QuickChat.setSubject(self, subject)
+        self._w.base_widget.header = urwid.AttrMap(urwid.Text(unicode(subject),align='center'),'title')
+
 
     def printMessage(self, from_jid, msg, profile, timestamp=""):
         self.content.append(SelectableText("[%s] " % from_jid + msg))
--- a/frontends/primitivus/contact_list.py	Mon Jul 05 19:13:36 2010 +0800
+++ b/frontends/primitivus/contact_list.py	Thu Jul 08 14:12:18 2010 +0800
@@ -21,7 +21,7 @@
 
 import urwid
 from quick_frontend.quick_contact_list import QuickContactList
-from custom_widgets import Password,List,InputDialog,ConfirmDialog,Alert
+from custom_widgets import Password,List,InputDialog,ConfirmDialog,Alert,LabelLine,SurroundedText
 
 
 class ContactList(urwid.WidgetWrap, QuickContactList):
@@ -35,8 +35,8 @@
         #we now build the widget
         body_content = urwid.SimpleListWalker([self.list_wid])
         frame_body = urwid.ListBox(body_content)
-        frame = urwid.Frame(frame_body,urwid.AttrMap(urwid.Text(_("Contacts"),align='center'),'title'))
-        self.main_widget = urwid.LineBox(frame)
+        frame = urwid.Frame(frame_body) #,urwid.AttrMap(urwid.Text(_("Contacts"),align='center'),'title'))
+        self.main_widget = LabelLine(frame,SurroundedText(_("Contacts")))
         urwid.WidgetWrap.__init__(self, self.main_widget)
         if on_click:
             urwid.connect_signal(self, 'click', on_click, user_data)
--- a/frontends/primitivus/custom_widgets.py	Mon Jul 05 19:13:36 2010 +0800
+++ b/frontends/primitivus/custom_widgets.py	Thu Jul 08 14:12:18 2010 +0800
@@ -20,6 +20,7 @@
 """
 
 import urwid
+from urwid.escape import utf8decode
 
 class Password(urwid.Edit):
 
@@ -59,7 +60,28 @@
         return super(AdvancedEdit, self).keypress(size, key) 
        
 
+class SurroundedText(urwid.FlowWidget):
+
+    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.FlowWidget):
+    """Text which can be selected with space"""
     signals = ['change']
     
     def __init__(self, text, align='left'):
@@ -255,9 +277,11 @@
 
     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) 
+        height = min(list_size,self.max_height) or 1 
         return urwid.BoxAdapter(self.genericList, height)
 
+## DIALOGS ##
+
 class GenericDialog(urwid.WidgetWrap):
 
     def __init__(self, widgets_lst, title, style=[], **kwargs):
@@ -286,9 +310,9 @@
 
 class InputDialog(GenericDialog):
 
-    def __init__(self, title, instrucions, style=['OK/CANCEL'], **kwargs):
+    def __init__(self, title, instrucions, style=['OK/CANCEL'], default_txt = '', **kwargs):
         instr_wid = urwid.Text(instrucions+':')
-        edit_box = urwid.Edit()
+        edit_box = urwid.Edit(edit_text=default_txt)
         GenericDialog.__init__(self, [instr_wid,edit_box], title, style, ok_value=edit_box, **kwargs)
 
 class ConfirmDialog(GenericDialog):
@@ -301,6 +325,8 @@
     def __init__(self, title, message, style=['OK'], **kwargs):
         GenericDialog.__init__(self, [urwid.Text(message, 'center')], title, style, ok_value=None, **kwargs)
 
+## CONTAINERS ##
+
 class FocusFrame(urwid.Frame):
     """Frame which manage "tab" key"""
 
@@ -316,3 +342,12 @@
                     self.set_focus(focus_name)
 
         return urwid.Frame.keypress(self, size, key)
+
+## DECORATORS ##
+class LabelLine(urwid.LineBox):
+
+    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
+        
--- a/frontends/primitivus/primitivus	Mon Jul 05 19:13:36 2010 +0800
+++ b/frontends/primitivus/primitivus	Thu Jul 08 14:12:18 2010 +0800
@@ -28,7 +28,7 @@
 from profile_manager import ProfileManager
 from contact_list import ContactList
 from chat import Chat
-from custom_widgets import AdvancedEdit,FocusFrame
+from custom_widgets import AdvancedEdit,FocusFrame,InputDialog,Alert
 import pdb
 """from window import Window
 from editbox import EditBox
@@ -39,6 +39,7 @@
 from logging import debug, info, error
 #import locale
 import sys, os
+from tools.jid  import JID
 #from curses import ascii
 #import locale
 #from signal import signal, SIGWINCH 
@@ -104,6 +105,9 @@
             raise urwid.ExitMainLoop()
         elif input == 'ctrl d' and 'D' in self.bridge.getVersion(): #Debug only for dev versions
             self.debug()
+        elif input == 'meta j': #user wants to join a room
+            pop_up_widget = InputDialog(_("Entering a MUC room"), _("Please enter MUC's JID"), default_txt = 'test@conference.necton2.int', cancel_cb=self.removePopUp, ok_cb=self.onJoinRoom)
+            self.showPopUp(pop_up_widget)
   
     def __buildMainWidget(self):
         self.contactList = ContactList(self, self.CM, on_click = self.contactSelected, on_change=lambda w: self.redraw())
@@ -118,7 +122,7 @@
         self.loop.widget = self.__buildMainWidget() 
         QuickApp.plug_profile(self, profile_key)
     
-    def removePopUp(self):
+    def removePopUp(self, widget=None):
         self.loop.widget = self.main_widget
 
     def showPopUp(self, pop_up_widget):
@@ -134,11 +138,26 @@
             self.center_part.widget_list[1] = self.chat_wins[contact]
 
     def onTextEntered(self, editBar):
-        contact = self.contactList.get_contact()
+        """Called when text is entered in the main edit bar"""
+        contact = self.contactList.get_contact() ###Based on the fact that there is currently only one contact selectableat once
         if contact:
-            self.bridge.sendMessage(contact, editBar.get_edit_text(), profile_key=self.profile)
+            chat = self.chat_wins[contact]
+            self.bridge.sendMessage(contact,
+                                    editBar.get_edit_text(),
+                                    type = "groupchat" if chat.type == 'group' else "chat",
+                                    profile_key=self.profile)
             editBar.set_edit_text('')
 
+    def onJoinRoom(self, button, edit):
+        self.removePopUp()
+        room_jid = JID(edit.get_edit_text())
+        if room_jid.is_valid():
+            self.bridge.joinMUC(room_jid.domain, room_jid.node, self.profiles[self.profile]['whoami'].node, self.profile)
+        else:
+            message = _("'%s' is an invalid JID !") % room_jid
+            error (message)
+            Alert(_("Error"), message, ok_cb=self.removePopUp)        
+
 sat = PrimitivusApp()
 sat.start()
 
--- a/frontends/quick_frontend/quick_chat.py	Mon Jul 05 19:13:36 2010 +0800
+++ b/frontends/quick_frontend/quick_chat.py	Thu Jul 08 14:12:18 2010 +0800
@@ -40,10 +40,40 @@
         """
         self.type = type
 
+    def setPresents(self, nicks):
+        """Set the users presents in the contact list for a group chat
+        @param nicks: list of nicknames
+        """
+        debug (_("Adding users %s to room") % nicks)
+        if self.type != "group":
+            error (_("[INTERNAL] trying to set presents nicks for a non group chat window"))
+            raise Exception("INTERNAL ERROR") #TODO: raise proper Exception here
+    
+    def replaceUser(self, nick):
+        """Add user if it is not in the group list"""
+        debug (_("Replacing user %s") % nick)
+        if self.type != "group":
+            error (_("[INTERNAL] trying to replace user for a non group chat window"))
+            raise Exception("INTERNAL ERROR") #TODO: raise proper Exception here
+    
     def setUserNick(self, nick):
         """Set the nick of the user, usefull for e.g. change the color of the user"""
         self.nick = nick
 
+    def removeUser(self, nick):
+        """Remove a user from the group list"""
+        debug(_("Removing user %s") % nick)
+        if self.type != "group":
+            error (_("[INTERNAL] trying to remove user for a non group chat window"))
+            raise Exception("INTERNAL ERROR") #TODO: raise proper Exception here
+
+    def setSubject(self, subject):
+        """Set title for a group chat"""
+        debug(_("Setting subject to %s") % subject)
+        if self.type != "group":
+            error (_("[INTERNAL] trying to set subject for a non group chat window"))
+            raise Exception("INTERNAL ERROR") #TODO: raise proper Exception here
+
     def historyPrint(self, size=20, keep_last=False, profile='@NONE@'):
         """Print the initial history"""
         debug (_("now we print history"))
--- a/frontends/wix/chat.py	Mon Jul 05 19:13:36 2010 +0800
+++ b/frontends/wix/chat.py	Thu Jul 08 14:12:18 2010 +0800
@@ -128,10 +128,7 @@
         """Set the users presents in the contact list for a group chat
         @param nicks: list of nicknames
         """
-        debug (_("Adding users %s to room") % nicks)
-        if self.type != "group":
-            error (_("[INTERNAL] trying to set presents nicks for a non group chat window"))
-            return
+        QuickChat.setPresents(self, nicks)
         for nick in nicks:
             self.present_panel.presents.replace(nick)
             self.occupants.add(nick)
@@ -143,27 +140,19 @@
         if self.type != "group":
             error (_("[INTERNAL] trying to replace user for a non group chat window"))
             return
-        self.present_panel.presents.replace(nick)
-        self.occupants.add(nick)
-      
+        QuickChat.replaceUser(self, nick)
+
     def removeUser(self, nick):
         """Remove a user from the group list"""
-        debug(_("Removing user %s") % nick)
-        if self.type != "group":
-            error (_("[INTERNAL] trying to remove user for a non group chat window"))
-            return
+        QuickChat.removeUser(self, nick)
         self.present_panel.presents.remove(nick)
         self.occupants.remove(nick)
 
     def setSubject(self, subject):
         """Set title for a group chat"""
-        debug(_("Setting subject to %s") % subject)
-        if self.type != "group":
-            error (_("[INTERNAL] trying to set subject for a non group chat window"))
-            return
+        QuickChat.setSubject(self, subject)
         self.subjectBox.SetValue(subject)
 
-
     def __eraseMenus(self):
         """erase all menus"""
         menuBar = self.GetMenuBar()
@@ -228,7 +217,10 @@
         self.chatWindow.SetDefaultStyle(wx.TextAttr("BLACK", font=_font))
         self.chatWindow.AppendText("%s\n" % msg)
         if not mymess:
-            self.Raise()  #FIXME: too intrusive
+            #TODO: use notification system
+            self.RequestUserAttention() #FIXME: do this only if in background.
+            self.Show() #gof: FIXME: to check
+            #self.Raise()  #FIXME: too intrusive
 
     ### events ###
 
--- a/frontends/wix/main_window.py	Mon Jul 05 19:13:36 2010 +0800
+++ b/frontends/wix/main_window.py	Thu Jul 08 14:12:18 2010 +0800
@@ -442,7 +442,7 @@
         #TODO: a proper MUC room joining dialog with nickname etc
         dlg = wx.TextEntryDialog(
                 self, _("Please enter MUC's JID"),
-                _('Entering a MUC room'), _('test@conference.necton2.int'))
+                _('Entering a MUC room'), 'test@conference.necton2.int')
                 #_('Entering a MUC room'), _('room@muc_service.server.tld'))
         if dlg.ShowModal() == wx.ID_OK:
             room_jid=JID(dlg.GetValue())