diff frontends/primitivus/chat.py @ 124:961e0898271f

primitivus chat window - management of one 2 one / group chat - timestamp displayed - added shortcuts for showing/hiding panels - color used - fixed vcard bug (contact displayed even if not from current profile if vcard changed/not in cache) - added VerticalSeparator widget - *List widgets can now use an other widget than SelectableText - new UnselectableText widget
author Goffi <goffi@goffi.org>
date Thu, 08 Jul 2010 19:47:54 +0800
parents 1ca5f254ce41
children 8d611eb9ae48
line wrap: on
line diff
--- a/frontends/primitivus/chat.py	Thu Jul 08 18:29:44 2010 +0800
+++ b/frontends/primitivus/chat.py	Thu Jul 08 19:47:54 2010 +0800
@@ -22,33 +22,169 @@
 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,LabelLine,SurroundedText
+import custom_widgets
+import time
+from tools.jid  import JID
+
+
+class ChatText(urwid.FlowWidget):
+    """Manage the printing of chat message"""
+    
+    def __init__(self, parent, timestamp, my_jid, from_jid, message, align='left'):
+        self.parent = parent
+        self.timestamp = time.localtime(timestamp)
+        self.my_jid = my_jid
+        self.from_jid = from_jid
+        self.message = unicode(message)
+        self.align = align
+
+    def selectable(self):
+        return True
 
+    def keypress(self, size, key):
+        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):
+        my_mess = (self.from_jid.resource == self.parent.nick) if self.parent.type == "group" else (self.from_jid.short == self.my_jid.short) #mymess = True if message comes from local user
+        render_txt = []
+        if self.parent.show_timestamp:
+            time_format = "%c" if self.timestamp < self.parent.day_change else "%H:%M" #if the message was sent before today, we print the full date
+            render_txt.append(('date',"[%s]" % time.strftime(time_format, self.timestamp)))
+        if self.parent.show_short_nick:
+            render_txt.append(('my_nick' if my_mess else 'other_nick',"**" if my_mess else "*"))
+        else:
+            render_txt.append(('my_nick' if my_mess else 'other_nick',"[%s] " % self.from_jid))
+        render_txt.append(self.message)
+        return urwid.Text(render_txt, align=self.align)
 
 class Chat(urwid.WidgetWrap, QuickChat):
 
     def __init__(self, target, host, type='one2one'):
+        self.target = target
         QuickChat.__init__(self, target, host, type)
         self.content = urwid.SimpleListWalker([])
         self.text_list = urwid.ListBox(self.content)
-        main_widget = LabelLine(
-                      urwid.Frame(self.text_list), SurroundedText(str(target))
-                      )
-        urwid.WidgetWrap.__init__(self, main_widget)
+        self.chat_widget = urwid.Frame(self.text_list)
+        self.columns = urwid.Columns([('weight', 8, self.chat_widget)])
+        urwid.WidgetWrap.__init__(self, self.__getDecoration(self.columns))
         self.setType(type)
-    
+        self.day_change = time.strptime(time.strftime("%a %b %d 00:00:00  %Y")) #struct_time of day changing time
+        self.show_timestamp = True
+        self.show_short_nick = False
+        self.show_title = True
+        self.subject = None
+
+    def keypress(self, size, key):
+        if key == "meta p": #user wants to (un)hide the presents panel
+            if self.type == 'group':
+                widgets = self.columns.widget_list
+                if self.present_panel in widgets:
+                    self.__removePresentPanel()
+                else:
+                    self.__appendPresentPanel()
+        elif key == "meta t": #user wants to (un)hide timestamp
+            self.show_timestamp = not self.show_timestamp
+            for wid in self.content:
+                wid._invalidate()
+        elif key == "meta n": #user wants to (not) use short nick
+            self.show_short_nick = not self.show_short_nick
+            for wid in self.content:
+                wid._invalidate()
+        elif key == "meta l": #user wants to (un)hide widget decoration
+            show = not self._w.__class__ == custom_widgets.LabelLine
+            self.showDecoration(show)
+            self._invalidate()
+        elif key == "meta s": #user wants to (un)hide group's subject
+            if self.subject:
+                self.show_title = not self.show_title
+                if self.show_title:
+                    self.setSubject(self.subject)
+                else:
+                    self.chat_widget.header = None
+                self._invalidate()
+
+
+        return super(Chat, self).keypress(size, key) 
+
     def setType(self, type):
         QuickChat.setType(self, type)
         if type == 'one2one':
             self.historyPrint(profile=self.host.profile)
-    
+        elif type == 'group':
+            if len(self.columns.widget_list) == 1:
+                present_widget = self.__buildPresentList()
+                self.present_panel = custom_widgets.VerticalSeparator(present_widget)
+                self.__appendPresentPanel()
+          
+    def __getDecoration(self, widget):
+        return custom_widgets.LabelLine(widget, custom_widgets.SurroundedText(unicode(self.target)))
+
+    def showDecoration(self, show=True):
+        if show:
+            main_widget = self.__getDecoration(self.columns)
+        else:
+            main_widget = self.columns
+        self._w = main_widget
+
+
+    def __buildPresentList(self):
+        self.present_wid = custom_widgets.GenericList([],option_type = custom_widgets.UnselectableText)
+        return self.present_wid
+   
+    def __appendPresentPanel(self):
+        self.columns.widget_list.append(self.present_panel) 
+        self.columns.column_types.append(('weight', 2))
+
+    def __removePresentPanel(self):
+        self.columns.set_focus(0) #necessary as the focus change to the next object, we can go out of range if we are on the last object of self.columns
+        self.columns.widget_list.remove(self.present_panel)
+        del self.columns.column_types[-1]
+
     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')
+        self.subject = subject
+        self.chat_widget.header = urwid.AttrMap(urwid.Text(unicode(subject),align='center'),'title')
+
+    def setPresents(self, param_nicks):
+        """Set the users presents in the contact list for a group chat
+        @param nicks: list of nicknames
+        """
+        nicks = [unicode(nick) for nick in param_nicks] #FIXME: should be done in DBus bridge
+        nicks.sort()
+        QuickChat.setPresents(self, nicks)
+        self.present_wid.changeValues(nicks)
+        self.host.redraw()
 
+    def replaceUser(self, param_nick):
+        """Add user if it is not in the group list"""
+        nick = unicode(param_nick) #FIXME: should be done in DBus bridge
+        if "facebook" in nick:
+            self.host.debug()
+        QuickChat.replaceUser(self, nick)
+        presents = self.present_wid.getAllValues()
+        if nick not in presents:
+            presents.append(nick)
+            presents.sort()
+            self.present_wid.changeValues(presents)
+        self.host.redraw()
+
+    def removeUser(self, param_nick):
+        """Remove a user from the group list"""
+        nick = unicode(param_nick) #FIXME: should be done in DBus bridge
+        QuickChat.removeUser(self, nick)
+        self.present_wid.deleteValue(nick)
+        self.host.redraw()
 
     def printMessage(self, from_jid, msg, profile, timestamp=""):
-        self.content.append(SelectableText("[%s] " % from_jid + msg))
+        assert (from_jid.__class__ == JID)
+        my_jid = self.host.profiles[profile]['whoami']
+        self.content.append(ChatText(self, timestamp or None, my_jid, from_jid, msg))
         self.text_list.set_focus(len(self.content)-1)
         self.host.redraw()