# HG changeset patch # User souliane # Date 1426865299 -3600 # Node ID 3dae6964c0715e77df2b958878715afd009e88ba # Parent 017270e6eea4039f361d9fe4ef4163e90ae89c23 quick_frontends, primitivus: move the chat states logic to quick_frontend diff -r 017270e6eea4 -r 3dae6964c071 frontends/src/primitivus/chat.py --- a/frontends/src/primitivus/chat.py Fri Mar 20 16:25:38 2015 +0100 +++ b/frontends/src/primitivus/chat.py Fri Mar 20 16:28:19 2015 +0100 @@ -150,25 +150,29 @@ menu.addMenu(_("Action"), _("Send file"), self.onSendFileRequest) return menu - def updateChatState(self, from_jid, state): - if self.type == C.CHAT_GROUP: - if from_jid == C.ENTITY_ALL: - occupants = self.occupants - else: - nick = from_jid.resource - if not nick: - log.debug("no nick found for chatstate") - return - occupants = [nick] - options = self.present_wid.getAllValues() - for index in xrange(0, len(options)): - nick = options[index].value - if nick in occupants: - options[index] = (nick, '%s %s' % (C.MUC_USER_STATES[state], nick)) - self.present_wid.changeValues(options) - self.host.redraw() - else: - self.title_dynamic = '({})'.format(state) + def setOccupantStates(self, occupant_jid, states): + """Set a MUC occupant's states. + + @param occupant_jid (jid.JID): occupant to update + @param states (dict{unicode: unicode}): new states + """ + options = self.present_wid.getAllValues() + for index in xrange(0, len(options)): + nick = options[index].value + if nick == occupant_jid.resource: + options[index] = (nick, "%s %s" % (u''.join(states.values()), nick)) + self.present_wid.changeValues(options) + break + self.host.redraw() + + def setContactStates(self, contact_jid, states): + """Set a one2one contact's states. + + @param contact_jid (jid.JID): contact + @param states (dict{unicode: unicode}): new states + """ + self.title_dynamic = ' '.join([u'({})'.format(state) for state in states.values()]) + self.host.redraw() def _presentClicked(self, list_wid, clicked_wid): assert self.type == C.CHAT_GROUP diff -r 017270e6eea4 -r 3dae6964c071 frontends/src/quick_frontend/constants.py --- a/frontends/src/quick_frontend/constants.py Fri Mar 20 16:25:38 2015 +0100 +++ b/frontends/src/quick_frontend/constants.py Fri Mar 20 16:28:19 2015 +0100 @@ -42,8 +42,7 @@ XMLUI_STATUS_CANCELLED = constants.Const.XMLUI_DATA_CANCELLED # MUC - ALL_OCCUPANTS = 1 - MUC_USER_STATES = { + USER_CHAT_STATES = { "active": u'✔', "inactive": u'☄', "gone": u'✈', diff -r 017270e6eea4 -r 3dae6964c071 frontends/src/quick_frontend/quick_app.py --- a/frontends/src/quick_frontend/quick_app.py Fri Mar 20 16:25:38 2015 +0100 +++ b/frontends/src/quick_frontend/quick_app.py Fri Mar 20 16:28:19 2015 +0100 @@ -574,16 +574,22 @@ log.debug("new subject for room [%(room_jid)s]: %(subject)s" % {'room_jid': room_jid, "subject": subject}) def chatStateReceivedHandler(self, from_jid_s, state, profile): - """Called when a new chat state is received. + """Called when a new chat state (XEP-0085) is received. - @param from_jid_s: JID of the contact who sent his state, or '@ALL@' - @param state: new state (string) - @profile: current profile + @param from_jid_s (unicode): JID of a contact or C.ENTITY_ALL + @param state (unicode): new state + @param profile (unicode): current profile """ from_jid = jid.JID(from_jid_s) if from_jid_s != C.ENTITY_ALL else C.ENTITY_ALL for widget in self.widgets.getWidgets(quick_chat.QuickChat): - if from_jid == C.ENTITY_ALL or from_jid.bare == widget.target.bare: - widget.updateChatState(from_jid, state) + 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(self.target, nick) for nick in widget.occupants]: + widget.updateEntityState(occupant, 'chat_state', to_display) + elif from_jid.bare == widget.target.bare: # roster contact or MUC occupant + widget.updateEntityState(from_jid, 'chat_state', to_display) def personalEventHandler(self, sender, event_type, data): """Called when a PEP event is received. diff -r 017270e6eea4 -r 3dae6964c071 frontends/src/quick_frontend/quick_chat.py --- a/frontends/src/quick_frontend/quick_chat.py Fri Mar 20 16:25:38 2015 +0100 +++ b/frontends/src/quick_frontend/quick_chat.py Fri Mar 20 16:28:19 2015 +0100 @@ -23,7 +23,7 @@ from sat_frontends.tools import jid from sat_frontends.quick_frontend import quick_widgets from sat_frontends.quick_frontend.constants import Const as C - +from collections import OrderedDict try: # FIXME: to be removed when an acceptable solution is here @@ -34,6 +34,8 @@ class QuickChat(quick_widgets.QuickWidget): + visible_states = ['chat_state'] + def __init__(self, host, target, type_=C.CHAT_ONE2ONE, profiles=None): """ @param type_: can be C.CHAT_ONE2ONE for single conversation or C.CHAT_GROUP for chat à la IRC @@ -207,12 +209,25 @@ """ raise NotImplementedError - def updateChatState(self, from_jid, state): - """Set the chat state (XEP-0085) of the contact. + def updateEntityState(self, entity, type_, value): + """Update a state value for the given entity. - @param state: the new chat state + @param entity (jid.JID): entity to update + @param type_ (unicode): type of state (e.g. 'chat_state') + @param value (unicode): new value """ - raise NotImplementedError + contact_list = self.host.contact_lists[self.profile] + contact_list.setCache(entity, type_, value) + 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 + if self.type == C.CHAT_GROUP: + self.setOccupantStates(entity, states) + else: + self.setContactStates(entity, states) def addGamePanel(self, widget): """Insert a game panel to this Chat dialog. diff -r 017270e6eea4 -r 3dae6964c071 frontends/src/tools/jid.py --- a/frontends/src/tools/jid.py Fri Mar 20 16:25:38 2015 +0100 +++ b/frontends/src/tools/jid.py Fri Mar 20 16:28:19 2015 +0100 @@ -20,7 +20,7 @@ # hack to use this module with pyjamas try: - unicode('') # XXX: unicode doesn't exist in pyjamas + unicode('') # XXX: unicode doesn't exist in pyjamas # normal version class BaseJID(unicode): @@ -38,14 +38,15 @@ node_end = 0 domain_end = self.find('/') if domain_end == 0: - raise ValueError("a jid can't start with '/'") + raise ValueError("a jid can't start with '/'") if domain_end == -1: domain_end = len(self) self.node = self[:node_end] or None self.domain = self[(node_end + 1) if node_end else 0:domain_end] self.resource = self[domain_end + 1:] or None -except (TypeError, AttributeError): # Error raised is not the same depending on pyjsbuild options +except (TypeError, AttributeError): # Error raised is not the same depending on pyjsbuild options + # pyjamas version class BaseJID(object): def __init__(self, jid_str): @@ -113,3 +114,13 @@ """ # TODO: implement real check, according to the RFC http://tools.ietf.org/html/rfc6122 return self.domain != "" + + +def newResource(entity, resource): + """Build a new JID from the given entity and resource. + + @param entity (JID): original JID + @param resource (unicode): new resource + @return: a new JID instance + """ + return JID(u"%s/%s" % (entity.bare, resource))