# HG changeset patch # User souliane # Date 1427214668 -3600 # Node ID a025242bebe71a7ba59edfafa5cb90affeadb896 # Parent 3511ff4b40a0d33e6f8f6e527cfb59fc932d76c1 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) diff -r 3511ff4b40a0 -r a025242bebe7 frontends/src/primitivus/chat.py --- 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) diff -r 3511ff4b40a0 -r a025242bebe7 frontends/src/quick_frontend/quick_app.py --- a/frontends/src/quick_frontend/quick_app.py Tue Mar 24 10:46:42 2015 +0100 +++ b/frontends/src/quick_frontend/quick_app.py Tue Mar 24 17:31:08 2015 +0100 @@ -534,6 +534,7 @@ chat_widget = self.widgets.getOrCreateWidget(quick_chat.QuickChat, room_jid, type_=C.CHAT_GROUP, profile=profile) chat_widget.setUserNick(unicode(user_nick)) self.contact_lists[profile].setSpecial(room_jid, C.CONTACT_SPECIAL_GROUP) + chat_widget.update() def roomLeftHandler(self, room_jid_s, profile): """Called when a MUC room is left""" @@ -579,16 +580,20 @@ @param state (unicode): new state @param profile (unicode): current profile """ + log.debug(_(u"Received new chat state {} from {} [{}]").format(state, from_jid_s, profile)) from_jid = jid.JID(from_jid_s) if from_jid_s != C.ENTITY_ALL else C.ENTITY_ALL + contact_list = self.contact_lists[profile] for widget in self.widgets.getWidgets(quick_chat.QuickChat): if profile != widget.profile: continue to_display = C.USER_CHAT_STATES[state] if (state and widget.type == C.CHAT_GROUP) else state if widget.type == C.CHAT_GROUP and from_jid_s == C.ENTITY_ALL: for occupant in [jid.newResource(widget.target, nick) for nick in widget.occupants]: - widget.updateEntityState(occupant, 'chat_state', to_display) + contact_list.setCache(occupant, 'chat_state', to_display) + widget.update(occupant) elif from_jid.bare == widget.target.bare: # roster contact or MUC occupant - widget.updateEntityState(from_jid, 'chat_state', to_display) + contact_list.setCache(from_jid, 'chat_state', to_display) + widget.update(from_jid) def personalEventHandler(self, sender, event_type, data): """Called when a PEP event is received. diff -r 3511ff4b40a0 -r a025242bebe7 frontends/src/quick_frontend/quick_chat.py --- a/frontends/src/quick_frontend/quick_chat.py Tue Mar 24 10:46:42 2015 +0100 +++ b/frontends/src/quick_frontend/quick_chat.py Tue Mar 24 17:31:08 2015 +0100 @@ -206,30 +206,19 @@ """ raise NotImplementedError - def updateEntityState(self, entity, type_, value): - """Update a state value for the given entity. + def getEntityStates(self, entity): + """Retrieve states for an entity. - @param entity (jid.JID): entity to update - @param type_ (unicode): type of state (e.g. 'chat_state') - @param value (unicode): new value + @param entity (jid.JID): entity + @return: OrderedDict{unicode: unicode} """ - contact_list = self.host.contact_lists[self.profile] - contact_list.setCache(entity, type_, value) + states = OrderedDict() clist = self.host.contact_lists[self.profile] - states = OrderedDict() for key in self.visible_states: value = clist.getCache(entity, key) if value: states[key] = value - self.setContactStates(entity, states) - - def setContactStates(self, contact_jid, states): - """Set a contact (one2one or MUC occupant) states. - - @param contact_jid (jid.JID): contact - @param states (dict{unicode: unicode}): new states - """ - raise NotImplementedError + return states def addGamePanel(self, widget): """Insert a game panel to this Chat dialog. @@ -245,5 +234,12 @@ """ raise NotImplementedError + def update(self, entity=None): + """Update one or all entities. + + @param entity (jid.JID): entity to update + """ + raise NotImplementedError + quick_widgets.register(QuickChat) diff -r 3511ff4b40a0 -r a025242bebe7 frontends/src/quick_frontend/quick_games.py --- a/frontends/src/quick_frontend/quick_games.py Tue Mar 24 10:46:42 2015 +0100 +++ b/frontends/src/quick_frontend/quick_games.py Tue Mar 24 17:31:08 2015 +0100 @@ -59,12 +59,11 @@ chat_widget.visible_states.append(cls._game_name) symbols = games.SYMBOLS[cls._game_name] index = 0 + contact_list = host.contact_lists[profile] for occupant in chat_widget.occupants: occupant_jid = jid.newResource(room_jid, occupant) - if occupant in players: - chat_widget.updateEntityState(occupant_jid, cls._game_name, symbols[index % len(symbols)]) - else: - chat_widget.updateEntityState(occupant_jid, cls._game_name, None) + contact_list.setCache(occupant_jid, cls._game_name, symbols[index % len(symbols)] if occupant in players else None) + chat_widget.update(occupant_jid) if suffix == "Players" or chat_widget.nick not in players: return # waiting for other players to join, or not playing