diff frontends/src/primitivus/chat.py @ 1388:a025242bebe7

quick_frontend, primitivus: remove QuickChat.updateEntityState and QuickChat.setContactStates, use more general QuickChat.update (also called when joining the room to initialise the occupants list)
author souliane <souliane@mailoo.org>
date Tue, 24 Mar 2015 17:31:08 +0100
parents 1f3513cfb246
children eb907923dce9
line wrap: on
line diff
--- a/frontends/src/primitivus/chat.py	Tue Mar 24 10:46:42 2015 +0100
+++ b/frontends/src/primitivus/chat.py	Tue Mar 24 17:31:08 2015 +0100
@@ -100,6 +100,7 @@
                 self.occupants_list = sat_widgets.GenericList([], option_type=sat_widgets.ClickableText, on_click=self._occupantsClicked)
                 self.occupants_panel = sat_widgets.VerticalSeparator(self.occupants_list)
                 self._appendOccupantsPanel()
+                self.host.addListener('presence', self.presenceListener, [profiles])
 
         self.day_change = time.strptime(time.strftime("%a %b %d 00:00:00  %Y"))  # struct_time of day changing time
         self.show_timestamp = True
@@ -148,24 +149,78 @@
             menu.addMenu(_("Action"), _("Send file"), self.onSendFileRequest)
         return menu
 
-    def setContactStates(self, contact_jid, states):
-        """Set a contact (one2one or MUC occupant) states.
+    def presenceListener(self, entity, show, priority, statuses, profile):
+        """Update entity's presence status
 
-        @param contact_jid (jid.JID): contact
-        @param states (dict{unicode: unicode}): new states
+        @param entity (jid.JID): entity updated
+        @param show: availability
+        @param priority: resource's priority
+        @param statuses: dict of statuses
+        @param profile: %(doc_profile)s
+        """
+        assert self.type == C.CHAT_GROUP
+        if entity.bare != self.target:
+            return
+        self.update(entity)
+
+    def update(self, entity=None):
+        """Update one or all entities.
+
+        @param entity (jid.JID): entity to update
         """
-        if self.type == C.CHAT_GROUP:
-            options = self.occupants_list.getAllValues()
-            for index in xrange(0, len(options)):
-                nick = options[index].value
-                if nick == contact_jid.resource:
-                    options[index] = (nick, "%s %s" % (u''.join(states.values()), nick))
-                    self.occupants_list.changeValues(options)
-                    break
-        else:
+        contact_list = self.host.contact_lists[self.profile]
+
+        if self.type == C.CHAT_ONE2ONE:  # only update the chat title
+            states = self.getEntityStates(self.target)
             self.title_dynamic = ' '.join([u'({})'.format(state) for state in states.values()])
+            self.host.redraw()
+            return
+
+        nicks = list(self.occupants)
+        if entity is None:  # rebuild all the occupants list
+            values = []
+            nicks.sort()
+            for nick in nicks:
+                values.append(self._buildOccupantMarkup(jid.newResource(self.target, nick)))
+            self.occupants_list.changeValues(values)
+        else:  # add, remove or update only one occupant
+            nick = entity.resource
+            show = contact_list.getCache(entity, C.PRESENCE_SHOW)
+            if show == C.PRESENCE_UNAVAILABLE:
+                self.occupants_list.deleteValue(nick)
+            else:
+                values = self.occupants_list.getAllValues()
+                if not values:  # room has just been created
+                    self.occupants_list.changeValues([self._buildOccupantMarkup(entity)])
+                else:  # add or update the occupant, keep the list sorted
+                    index = 0
+                    for entry in values:
+                        order = cmp(entry.value if hasattr(entry, 'value') else entry, nick)
+                        if order < 0:
+                            index += 1
+                            continue
+                        if order > 0:  # insert the occupant the occupant
+                            values.insert(index, self._buildOccupantMarkup(entity))
+                        else:  # update the occupant
+                            values[index] = self._buildOccupantMarkup(entity)
+                        self.occupants_list.changeValues(values)
+                        break
         self.host.redraw()
 
+    def _buildOccupantMarkup(self, entity):
+        """Return the option attributes for a MUC occupant.
+
+        @param nick (unicode): occupant nickname
+        """
+        contact_list = self.host.contact_lists[self.profile]
+        show = contact_list.getCache(entity, C.PRESENCE_SHOW)
+        states = self.getEntityStates(entity)
+        nick = entity.resource
+        # TODO: use entity_attr and return (nick, markup), but ListOption is unicode and not urwid.Text
+        show_icon, entity_attr = C.PRESENCE.get(show, (u'', u'default'))
+        text = "%s%s %s" % (u''.join(states.values()), show_icon, nick)
+        return (nick, text)
+
     def _occupantsClicked(self, list_wid, clicked_wid):
         assert self.type == C.CHAT_GROUP
         nick = clicked_wid.getValue().value
@@ -218,24 +273,6 @@
         self.chat_widget.header = urwid.AttrMap(self.subj_wid, 'title')
         self.host.redraw()
 
-    def addUser(self, param_nick):
-        """Add user if it is not in the group list"""
-        nick = unicode(param_nick)  # FIXME: should be done in DBus bridge
-        QuickChat.addUser(self, nick)
-        occupants = self.occupants_list.getAllValues()
-        if nick not in [occupants.value for occupants in occupants]:
-            occupants.append(nick)
-            occupants.sort(cmp=lambda a, b: cmp(a.value if hasattr(a, 'value') else a, b.value if hasattr(b, 'value') else b))
-            self.occupants_list.changeValues(occupants)
-        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.occupants_list.deleteValue(nick)
-        self.host.redraw()
-
     def clearHistory(self):
         """Clear the content of this chat."""
         del self.content[:]
@@ -356,6 +393,11 @@
         self.host.addProgress(progress_id, filepath)
         self.host.showDialog(_(u"You file request has been sent, we are waiting for your contact answer"), title=_("File request sent"))
 
+    def onDelete(self):
+        QuickChat.onDelete(self)
+        if self.type == C.CHAT_GROUP:
+            self.host.removeListener('presence', self.presenceListener)
+
 
 quick_widgets.register(QuickChat, Chat)
 quick_widgets.register(quick_games.Tarot, game_tarot.TarotGame)