From ac5d0f24da2eb854492d8634896114193638088d Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Sat, 14 Nov 2009 19:54:33 +0100 Subject: [PATCH 01/20] Fix error in the documentation of our xmpp dispatcher fork. Raise NodeProcessed if the stanza should NOT be handled by other user handlers. --- src/common/xmpp/dispatcher_nb.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/common/xmpp/dispatcher_nb.py b/src/common/xmpp/dispatcher_nb.py index 8f4746f68..477d3e6c4 100644 --- a/src/common/xmpp/dispatcher_nb.py +++ b/src/common/xmpp/dispatcher_nb.py @@ -247,25 +247,23 @@ class XMPPDispatcher(PlugIn): ''' Register user callback as stanzas handler of declared type. - Callback must take (if chained, see later) arguments: + Callback arguments: dispatcher instance (for replying), incoming return of previous handlers. The callback must raise xmpp.NodeProcessed just before return if it wants - other callbacks to be called with the same stanza as argument _and_, more - importantly library from returning stanza to sender with error set. + to prevent other callbacks to be called with the same stanza as argument + _and_, more importantly library from returning stanza to sender with error set. :param name: name of stanza. F.e. "iq". :param handler: user callback. :param typ: value of stanza's "type" attribute. If not specified any value will match :param ns: namespace of child that stanza must contain. - :param chained: chain together output of several handlers. - :param makefirst: insert handler in the beginning of handlers list instea + :param makefirst: insert handler in the beginning of handlers list instead of adding it to the end. Note that more common handlers i.e. w/o "typ" and " will be called first nevertheless. :param system: call handler even if NodeProcessed Exception were raised already. ''' - # FIXME: What does chain mean and where is it handled? if not xmlns: xmlns=self._owner.defaultNamespace log.debug('Registering handler %s for "%s" type->%s ns->%s(%s)' % From 30580702d54b92cf3f177ca62dd8171e17a7c6f1 Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Sat, 14 Nov 2009 19:56:15 +0100 Subject: [PATCH 02/20] Create a ConnectionPEP class and directly register its callback to handle pep events. --- src/common/connection_handlers.py | 51 +++---------------------------- src/common/pep.py | 50 ++++++++++++++++++++++++++++++ src/common/xmpp/protocol.py | 1 + 3 files changed, 55 insertions(+), 47 deletions(-) diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py index e134aa003..cb9197d5e 100644 --- a/src/common/connection_handlers.py +++ b/src/common/connection_handlers.py @@ -46,11 +46,10 @@ import common.xmpp from common import helpers from common import gajim -from common import atom -from common import pep from common import exceptions from common.commands import ConnectionCommands from common.pubsub import ConnectionPubSub +from common.pep import ConnectionPEP from common.caps import ConnectionCaps if gajim.HAVE_FARSIGHT: from common.jingle import ConnectionJingle @@ -1453,7 +1452,7 @@ sent a message to.''' return sess -class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, ConnectionCommands, ConnectionPubSub, ConnectionCaps, ConnectionHandlersBase, ConnectionJingle): +class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, ConnectionCommands, ConnectionPubSub, ConnectionPEP, ConnectionCaps, ConnectionHandlersBase, ConnectionJingle): def __init__(self): ConnectionVcard.__init__(self) ConnectionBytestream.__init__(self) @@ -1874,15 +1873,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, def _messageCB(self, con, msg): '''Called when we receive a message''' log.debug('MessageCB') - mtype = msg.getType() - # check if the message is pubsub#event - if msg.getTag('event') is not None: - if mtype == 'groupchat': - return - if msg.getTag('error') is None: - self._pubsubEventCB(con, msg) - return # check if the message is a roster item exchange (XEP-0144) if msg.getTag('x', namespace=common.xmpp.NS_ROSTERX): @@ -2148,42 +2139,6 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, self.dispatch('GC_INVITATION',(frm, jid_from, reason, password, is_continued)) - def _pubsubEventCB(self, con, msg): - ''' Called when we receive with pubsub event. ''' - # TODO: Logging? (actually services where logging would be useful, should - # TODO: allow to access archives remotely...) - jid = helpers.get_full_jid_from_iq(msg) - event = msg.getTag('event') - - # XEP-0107: User Mood - items = event.getTag('items', {'node': common.xmpp.NS_MOOD}) - if items: pep.user_mood(items, self.name, jid) - # XEP-0118: User Tune - items = event.getTag('items', {'node': common.xmpp.NS_TUNE}) - if items: pep.user_tune(items, self.name, jid) - # XEP-0080: User Geolocation - items = event.getTag('items', {'node': common.xmpp.NS_GEOLOC}) - if items: pep.user_geoloc(items, self.name, jid) - # XEP-0108: User Activity - items = event.getTag('items', {'node': common.xmpp.NS_ACTIVITY}) - if items: pep.user_activity(items, self.name, jid) - # XEP-0172: User Nickname - items = event.getTag('items', {'node': common.xmpp.NS_NICK}) - if items: pep.user_nickname(items, self.name, jid) - - items = event.getTag('items') - if items is None: return - - for item in items.getTags('item'): - entry = item.getTag('entry') - if entry is not None: - # for each entry in feed (there shouldn't be more than one, - # but to be sure... - self.dispatch('ATOM_ENTRY', (atom.OldEntry(node=entry),)) - continue - # unknown type... probably user has another client who understands that event - raise common.xmpp.NodeProcessed - def _presenceCB(self, con, prs): '''Called when we receive a presence''' ptype = prs.getType() @@ -2751,6 +2706,8 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, con.RegisterHandler('message', self._messageCB) con.RegisterHandler('presence', self._presenceCB) con.RegisterHandler('presence', self._capsPresenceCB) + con.RegisterHandler('message', self._pubsubEventCB, + ns=common.xmpp.NS_PUBSUB_EVENT) con.RegisterHandler('iq', self._vCardCB, 'result', common.xmpp.NS_VCARD) con.RegisterHandler('iq', self._rosterSetCB, 'set', diff --git a/src/common/pep.py b/src/common/pep.py index 54012514f..fe67d578a 100644 --- a/src/common/pep.py +++ b/src/common/pep.py @@ -192,6 +192,56 @@ ACTIVITIES = { 'studying': _('Studying'), 'writing': _('Writing')}} +import logging +log = logging.getLogger('gajim.c.pep') + +import helpers +import atom + +class ConnectionPEP: + + def _pubsubEventCB(self, xmpp_dispatcher, msg): + ''' Called when we receive with pubsub event. ''' + + if msg.getTag('error'): + log.warning('Pep Error CB') + return + + # TODO: Logging? (actually services where logging would be useful, should + # TODO: allow to access archives remotely...) + jid = helpers.get_full_jid_from_iq(msg) + event = msg.getTag('event') + + # XEP-0107: User Mood + items = event.getTag('items', {'node': common.xmpp.NS_MOOD}) + if items: user_mood(items, self.name, jid) + # XEP-0118: User Tune + items = event.getTag('items', {'node': common.xmpp.NS_TUNE}) + if items: user_tune(items, self.name, jid) + # XEP-0080: User Geolocation + items = event.getTag('items', {'node': common.xmpp.NS_GEOLOC}) + if items: user_geoloc(items, self.name, jid) + # XEP-0108: User Activity + items = event.getTag('items', {'node': common.xmpp.NS_ACTIVITY}) + if items: user_activity(items, self.name, jid) + # XEP-0172: User Nickname + items = event.getTag('items', {'node': common.xmpp.NS_NICK}) + if items: user_nickname(items, self.name, jid) + + items = event.getTag('items') + if items is None: return + + for item in items.getTags('item'): + entry = item.getTag('entry') + if entry is not None: + # for each entry in feed (there shouldn't be more than one, + # but to be sure... + self.dispatch('ATOM_ENTRY', (atom.OldEntry(node=entry),)) + continue + # unknown type... probably user has another client who understands that event + + raise common.xmpp.NodeProcessed + def user_mood(items, name, jid): has_child = False retract = False diff --git a/src/common/xmpp/protocol.py b/src/common/xmpp/protocol.py index 619771409..5eb31b7d3 100644 --- a/src/common/xmpp/protocol.py +++ b/src/common/xmpp/protocol.py @@ -88,6 +88,7 @@ NS_PRIVACY ='jabber:iq:privacy' NS_PRIVATE ='jabber:iq:private' NS_PROFILE ='http://jabber.org/protocol/profile' # XEP-0154 NS_PUBSUB ='http://jabber.org/protocol/pubsub' # XEP-0060 +NS_PUBSUB_EVENT = 'http://jabber.org/protocol/pubsub#event' NS_PUBSUB_PUBLISH_OPTIONS = NS_PUBSUB + '#publish-options' # XEP-0060 NS_PUBSUB_OWNER ='http://jabber.org/protocol/pubsub#owner' # JEP-0060 NS_REGISTER ='jabber:iq:register' From 85b7b89b49a7db6b077e1c01a3811d92556e3092 Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Sat, 14 Nov 2009 20:48:33 +0100 Subject: [PATCH 03/20] Create a class for each PEP XEP that we support. Dispatch an event to the Interface() handlers when we have have received a PEP event. --- src/common/pep.py | 100 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 79 insertions(+), 21 deletions(-) diff --git a/src/common/pep.py b/src/common/pep.py index fe67d578a..03f262ce3 100644 --- a/src/common/pep.py +++ b/src/common/pep.py @@ -198,37 +198,94 @@ log = logging.getLogger('gajim.c.pep') import helpers import atom + +class AbstractPEP(object): + + type = '' + namespace = '' + + @classmethod + def get_tag_as_PEP(cls, jid, account, event_tag): + items = event_tag.getTag('items', {'node': cls.namespace}) + if items: + log.debug("Received PEP 'user %s' from %s" % (cls.type, jid)) + return cls(jid, account, items) + else: + return None + + +class UserMoodPEP(AbstractPEP): + '''XEP-0107: User Mood''' + + type = 'mood' + namespace = common.xmpp.NS_MOOD + + def __init__(self, jid, account, items): + user_mood(items, account, jid) + + +class UserTunePEP(AbstractPEP): + '''XEP-0118: User Tune''' + + type = 'tune' + namespace = common.xmpp.NS_TUNE + + def __init__(self, jid, account, items): + user_tune(items, account, jid) + + +class UserGeolocationPEP(AbstractPEP): + '''XEP-0080: User Geolocation''' + + type = 'geolocation' + namespace = common.xmpp.NS_GEOLOC + + def __init__(self, jid, account, items): + user_geoloc(items, account, jid) + + +class UserActivityPEP(AbstractPEP): + '''XEP-0108: User Activity''' + + type = 'activity' + namespace = common.xmpp.NS_ACTIVITY + + def __init__(self, jid, account, items): + user_activity(items, account, jid) + + +class UserNicknamePEP(AbstractPEP): + '''XEP-0172: User Nickname''' + + type = 'activity' + namespace = common.xmpp.NS_NICK + + def __init__(self, jid, account, items): + user_nickname(items, self.name, jid) + + +SUPPORTED_PERSONAL_USER_EVENTS = [UserMoodPEP, UserTunePEP, UserGeolocationPEP, + UserActivityPEP, UserNicknamePEP] + class ConnectionPEP: def _pubsubEventCB(self, xmpp_dispatcher, msg): ''' Called when we receive with pubsub event. ''' - if msg.getTag('error'): - log.warning('Pep Error CB') + log.warning('PubsubEventCB received error stanza') return - + # TODO: Logging? (actually services where logging would be useful, should # TODO: allow to access archives remotely...) jid = helpers.get_full_jid_from_iq(msg) - event = msg.getTag('event') + event_tag = msg.getTag('event') - # XEP-0107: User Mood - items = event.getTag('items', {'node': common.xmpp.NS_MOOD}) - if items: user_mood(items, self.name, jid) - # XEP-0118: User Tune - items = event.getTag('items', {'node': common.xmpp.NS_TUNE}) - if items: user_tune(items, self.name, jid) - # XEP-0080: User Geolocation - items = event.getTag('items', {'node': common.xmpp.NS_GEOLOC}) - if items: user_geoloc(items, self.name, jid) - # XEP-0108: User Activity - items = event.getTag('items', {'node': common.xmpp.NS_ACTIVITY}) - if items: user_activity(items, self.name, jid) - # XEP-0172: User Nickname - items = event.getTag('items', {'node': common.xmpp.NS_NICK}) - if items: user_nickname(items, self.name, jid) - - items = event.getTag('items') + for pep_class in SUPPORTED_PERSONAL_USER_EVENTS: + pep = pep_class.get_tag_as_PEP(jid, self.name, event_tag) + if pep: + self.dispatch('PEP_RECEIVED', (pep.type, pep)) + + items = event_tag.getTag('items') if items is None: return for item in items.getTags('item'): @@ -242,6 +299,7 @@ class ConnectionPEP: raise common.xmpp.NodeProcessed + def user_mood(items, name, jid): has_child = False retract = False From 7c6dc424afc4039ee92c0314c7008ae87928ed35 Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Sat, 14 Nov 2009 20:54:42 +0100 Subject: [PATCH 04/20] Make user_tune a instance method, not a function. --- src/common/pep.py | 119 +++++++++++++++++++++++----------------------- 1 file changed, 60 insertions(+), 59 deletions(-) diff --git a/src/common/pep.py b/src/common/pep.py index 03f262ce3..7f04f4139 100644 --- a/src/common/pep.py +++ b/src/common/pep.py @@ -221,7 +221,66 @@ class UserMoodPEP(AbstractPEP): namespace = common.xmpp.NS_MOOD def __init__(self, jid, account, items): - user_mood(items, account, jid) + self.user_mood(items, account, jid) + + + def user_mood(self, items, name, jid): + has_child = False + retract = False + mood = None + text = None + for item in items.getTags('item'): + child = item.getTag('mood') + if child is not None: + has_child = True + for ch in child.getChildren(): + if ch.getName() != 'text': + mood = ch.getName() + else: + text = ch.getData() + if items.getTag('retract') is not None: + retract = True + + if jid == common.gajim.get_jid_from_account(name): + acc = common.gajim.connections[name] + if has_child: + if 'mood' in acc.mood: + del acc.mood['mood'] + if 'text' in acc.mood: + del acc.mood['text'] + if mood is not None: + acc.mood['mood'] = mood + if text is not None: + acc.mood['text'] = text + elif retract: + if 'mood' in acc.mood: + del acc.mood['mood'] + if 'text' in acc.mood: + del acc.mood['text'] + + (user, resource) = common.gajim.get_room_and_nick_from_fjid(jid) + for contact in common.gajim.contacts.get_contacts(name, user): + if has_child: + if 'mood' in contact.mood: + del contact.mood['mood'] + if 'text' in contact.mood: + del contact.mood['text'] + if mood is not None: + contact.mood['mood'] = mood + if text is not None: + contact.mood['text'] = text + elif retract: + if 'mood' in contact.mood: + del contact.mood['mood'] + if 'text' in contact.mood: + del contact.mood['text'] + + if jid == common.gajim.get_jid_from_account(name): + common.gajim.interface.roster.draw_account(name) + common.gajim.interface.roster.draw_mood(user, name) + ctrl = common.gajim.interface.msg_win_mgr.get_control(user, name) + if ctrl: + ctrl.update_mood() class UserTunePEP(AbstractPEP): @@ -300,64 +359,6 @@ class ConnectionPEP: raise common.xmpp.NodeProcessed -def user_mood(items, name, jid): - has_child = False - retract = False - mood = None - text = None - for item in items.getTags('item'): - child = item.getTag('mood') - if child is not None: - has_child = True - for ch in child.getChildren(): - if ch.getName() != 'text': - mood = ch.getName() - else: - text = ch.getData() - if items.getTag('retract') is not None: - retract = True - - if jid == common.gajim.get_jid_from_account(name): - acc = common.gajim.connections[name] - if has_child: - if 'mood' in acc.mood: - del acc.mood['mood'] - if 'text' in acc.mood: - del acc.mood['text'] - if mood is not None: - acc.mood['mood'] = mood - if text is not None: - acc.mood['text'] = text - elif retract: - if 'mood' in acc.mood: - del acc.mood['mood'] - if 'text' in acc.mood: - del acc.mood['text'] - - (user, resource) = common.gajim.get_room_and_nick_from_fjid(jid) - for contact in common.gajim.contacts.get_contacts(name, user): - if has_child: - if 'mood' in contact.mood: - del contact.mood['mood'] - if 'text' in contact.mood: - del contact.mood['text'] - if mood is not None: - contact.mood['mood'] = mood - if text is not None: - contact.mood['text'] = text - elif retract: - if 'mood' in contact.mood: - del contact.mood['mood'] - if 'text' in contact.mood: - del contact.mood['text'] - - if jid == common.gajim.get_jid_from_account(name): - common.gajim.interface.roster.draw_account(name) - common.gajim.interface.roster.draw_mood(user, name) - ctrl = common.gajim.interface.msg_win_mgr.get_control(user, name) - if ctrl: - ctrl.update_mood() - def user_tune(items, name, jid): has_child = False retract = False From 99e718583aaedebe03bbd0e8efd6a87f605d860f Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Sat, 14 Nov 2009 22:31:27 +0100 Subject: [PATCH 05/20] Initial simplification of PEP data extraction by moving the extraction methods to the newly created PEP classess. If-else-retract complexity is substituted by dictionaries. --- src/common/pep.py | 407 +++++++++++++++------------------------------- 1 file changed, 131 insertions(+), 276 deletions(-) diff --git a/src/common/pep.py b/src/common/pep.py index 7f04f4139..9e99a5a24 100644 --- a/src/common/pep.py +++ b/src/common/pep.py @@ -192,6 +192,8 @@ ACTIVITIES = { 'studying': _('Studying'), 'writing': _('Writing')}} +TUNE_DATA = ['artist', 'title', 'source', 'track', 'length'] + import logging log = logging.getLogger('gajim.c.pep') @@ -221,59 +223,36 @@ class UserMoodPEP(AbstractPEP): namespace = common.xmpp.NS_MOOD def __init__(self, jid, account, items): + self._mood_dict, self._retracted = self._extract_info(items) + self.user_mood(items, account, jid) + def _extract_info(self, items): + mood_dict = {} - def user_mood(self, items, name, jid): - has_child = False - retract = False - mood = None - text = None for item in items.getTags('item'): - child = item.getTag('mood') - if child is not None: - has_child = True - for ch in child.getChildren(): - if ch.getName() != 'text': - mood = ch.getName() - else: - text = ch.getData() - if items.getTag('retract') is not None: - retract = True + mood_tag = item.getTag('mood') + if mood_tag: + for child in mood_tag.getChildren(): + if child.getName() == 'text': + mood_dict['text'] = child.getData() + elif child.getName() in MOODS : + mood_dict['mood'] = child.getName() + + retracted = items.getTag('retract') or not mood_dict + return (mood_dict, retracted) + + def user_mood(self, items, name, jid): + + mood_dict = {} if self._retracted else self._mood_dict if jid == common.gajim.get_jid_from_account(name): acc = common.gajim.connections[name] - if has_child: - if 'mood' in acc.mood: - del acc.mood['mood'] - if 'text' in acc.mood: - del acc.mood['text'] - if mood is not None: - acc.mood['mood'] = mood - if text is not None: - acc.mood['text'] = text - elif retract: - if 'mood' in acc.mood: - del acc.mood['mood'] - if 'text' in acc.mood: - del acc.mood['text'] + acc.mood = mood_dict - (user, resource) = common.gajim.get_room_and_nick_from_fjid(jid) + user = common.gajim.get_room_and_nick_from_fjid(jid)[0] for contact in common.gajim.contacts.get_contacts(name, user): - if has_child: - if 'mood' in contact.mood: - del contact.mood['mood'] - if 'text' in contact.mood: - del contact.mood['text'] - if mood is not None: - contact.mood['mood'] = mood - if text is not None: - contact.mood['text'] = text - elif retract: - if 'mood' in contact.mood: - del contact.mood['mood'] - if 'text' in contact.mood: - del contact.mood['text'] + contact.mood = mood_dict if jid == common.gajim.get_jid_from_account(name): common.gajim.interface.roster.draw_account(name) @@ -290,18 +269,42 @@ class UserTunePEP(AbstractPEP): namespace = common.xmpp.NS_TUNE def __init__(self, jid, account, items): - user_tune(items, account, jid) - + self._tune_dict, self._retracted = self._extract_info(items) -class UserGeolocationPEP(AbstractPEP): - '''XEP-0080: User Geolocation''' + self.user_tune(items, account, jid) + + def _extract_info(self, items): + tune_dict = {} - type = 'geolocation' - namespace = common.xmpp.NS_GEOLOC - - def __init__(self, jid, account, items): - user_geoloc(items, account, jid) + for item in items.getTags('item'): + tune_tag = item.getTag('tune') + if tune_tag: + for child in tune_tag.getChildren(): + if child.getName() in TUNE_DATA: + tune_dict[child.getName()] = child.getData() + + retracted = items.getTag('retract') or not tune_dict + return (tune_dict, retracted) + + + def user_tune(self, items, name, jid): + tune_dict = {} if self._retracted else self._tune_dict + if jid == common.gajim.get_jid_from_account(name): + acc = common.gajim.connections[name] + acc.tune = tune_dict + + user = common.gajim.get_room_and_nick_from_fjid(jid)[0] + for contact in common.gajim.contacts.get_contacts(name, user): + contact.tune = tune_dict + + if jid == common.gajim.get_jid_from_account(name): + common.gajim.interface.roster.draw_account(name) + common.gajim.interface.roster.draw_tune(user, name) + ctrl = common.gajim.interface.msg_win_mgr.get_control(user, name) + if ctrl: + ctrl.update_tune() + class UserActivityPEP(AbstractPEP): '''XEP-0108: User Activity''' @@ -310,7 +313,45 @@ class UserActivityPEP(AbstractPEP): namespace = common.xmpp.NS_ACTIVITY def __init__(self, jid, account, items): - user_activity(items, account, jid) + self._activity_dict, self._retracted = self._extract_info(items) + + self.user_activity(items, account, jid) + + def _extract_info(self, items): + activity_dict = {} + + for item in items.getTags('item'): + activity_tag = item.getTag('activity') + if activity_tag: + for child in child.getChildren(): + if child.getName() == 'text': + activity_dict['text'] = child.getData() + elif child.getName() in ACTIVITIES: + activity_dict['activity'] = child.getName() + for subactivity in child.getChildren(): + if subactivity.getName() in ACTIVITIES[child.getName()]: + activity_dict['subactivity'] = subactivity.getName() + + retracted = items.getTag('retract') or not activity_dict + return (activity_dict, retracted) + + def user_activity(self, items, name, jid): + activity_dict = {} if self._retracted else self._activity_dict + + if jid == common.gajim.get_jid_from_account(name): + acc = common.gajim.connections[name] + acc.activity = activity_dict + + user = common.gajim.get_room_and_nick_from_fjid(jid)[0] + for contact in common.gajim.contacts.get_contacts(name, user): + contact.activity = activity_dict + + if jid == common.gajim.get_jid_from_account(name): + common.gajim.interface.roster.draw_account(name) + common.gajim.interface.roster.draw_activity(user, name) + ctrl = common.gajim.interface.msg_win_mgr.get_control(user, name) + if ctrl: + ctrl.update_activity() class UserNicknamePEP(AbstractPEP): @@ -320,11 +361,44 @@ class UserNicknamePEP(AbstractPEP): namespace = common.xmpp.NS_NICK def __init__(self, jid, account, items): - user_nickname(items, self.name, jid) + self._nick, self._retracted = self._extract_info(items) + self.user_nickname(items, account, jid) + + def _extract_info(self, items): + nick = '' + for item in items.getTags('item'): + child = item.getTag('nick') + if child: + nick = child.getData() + break + + retracted = items.getTag('retract') or not nick + return (nick, retracted) + + def user_nickname(self, items, name, jid): + if jid == common.gajim.get_jid_from_account(name): + if self._retracted: + common.gajim.nicks[name] = common.gajim.config.get_per('accounts', + name, 'name') + else: + common.gajim.nicks[name] = self._nick + + nick = '' if self._retracted else self._nick + + user = common.gajim.get_room_and_nick_from_fjid(jid)[0] + for contact in common.gajim.contacts.get_contacts(name, user): + contact.contact_name = nick + common.gajim.interface.roster.draw_contact(user, name) + + ctrl = common.gajim.interface.msg_win_mgr.get_control(user, name) + if ctrl: + ctrl.update_ui() + win = ctrl.parent_win + win.redraw_tab(ctrl) + win.show_title() -SUPPORTED_PERSONAL_USER_EVENTS = [UserMoodPEP, UserTunePEP, UserGeolocationPEP, - UserActivityPEP, UserNicknamePEP] +SUPPORTED_PERSONAL_USER_EVENTS = [UserMoodPEP, UserTunePEP, UserActivityPEP, UserNicknamePEP] class ConnectionPEP: @@ -359,225 +433,6 @@ class ConnectionPEP: raise common.xmpp.NodeProcessed -def user_tune(items, name, jid): - has_child = False - retract = False - artist = None - title = None - source = None - track = None - length = None - - for item in items.getTags('item'): - child = item.getTag('tune') - if child is not None: - has_child = True - for ch in child.getChildren(): - if ch.getName() == 'artist': - artist = ch.getData() - elif ch.getName() == 'title': - title = ch.getData() - elif ch.getName() == 'source': - source = ch.getData() - elif ch.getName() == 'track': - track = ch.getData() - elif ch.getName() == 'length': - length = ch.getData() - if items.getTag('retract') is not None: - retract = True - - if jid == common.gajim.get_jid_from_account(name): - acc = common.gajim.connections[name] - if has_child: - if 'artist' in acc.tune: - del acc.tune['artist'] - if 'title' in acc.tune: - del acc.tune['title'] - if 'source' in acc.tune: - del acc.tune['source'] - if 'track' in acc.tune: - del acc.tune['track'] - if 'length' in acc.tune: - del acc.tune['length'] - if artist is not None: - acc.tune['artist'] = artist - if title is not None: - acc.tune['title'] = title - if source is not None: - acc.tune['source'] = source - if track is not None: - acc.tune['track'] = track - if length is not None: - acc.tune['length'] = length - elif retract: - if 'artist' in acc.tune: - del acc.tune['artist'] - if 'title' in acc.tune: - del acc.tune['title'] - if 'source' in acc.tune: - del acc.tune['source'] - if 'track' in acc.tune: - del acc.tune['track'] - if 'length' in acc.tune: - del acc.tune['length'] - - user = common.gajim.get_room_and_nick_from_fjid(jid)[0] - for contact in common.gajim.contacts.get_contacts(name, user): - if has_child: - if 'artist' in contact.tune: - del contact.tune['artist'] - if 'title' in contact.tune: - del contact.tune['title'] - if 'source' in contact.tune: - del contact.tune['source'] - if 'track' in contact.tune: - del contact.tune['track'] - if 'length' in contact.tune: - del contact.tune['length'] - if artist is not None: - contact.tune['artist'] = artist - if title is not None: - contact.tune['title'] = title - if source is not None: - contact.tune['source'] = source - if track is not None: - contact.tune['track'] = track - if length is not None: - contact.tune['length'] = length - elif retract: - if 'artist' in contact.tune: - del contact.tune['artist'] - if 'title' in contact.tune: - del contact.tune['title'] - if 'source' in contact.tune: - del contact.tune['source'] - if 'track' in contact.tune: - del contact.tune['track'] - if 'length' in contact.tune: - del contact.tune['length'] - - if jid == common.gajim.get_jid_from_account(name): - common.gajim.interface.roster.draw_account(name) - common.gajim.interface.roster.draw_tune(user, name) - ctrl = common.gajim.interface.msg_win_mgr.get_control(user, name) - if ctrl: - ctrl.update_tune() - -def user_geoloc(items, name, jid): - pass - -def user_activity(items, name, jid): - has_child = False - retract = False - activity = None - subactivity = None - text = None - - for item in items.getTags('item'): - child = item.getTag('activity') - if child is not None: - has_child = True - for ch in child.getChildren(): - if ch.getName() != 'text': - activity = ch.getName() - for chi in ch.getChildren(): - subactivity = chi.getName() - else: - text = ch.getData() - if items.getTag('retract') is not None: - retract = True - - if jid == common.gajim.get_jid_from_account(name): - acc = common.gajim.connections[name] - if has_child: - if 'activity' in acc.activity: - del acc.activity['activity'] - if 'subactivity' in acc.activity: - del acc.activity['subactivity'] - if 'text' in acc.activity: - del acc.activity['text'] - if activity is not None: - acc.activity['activity'] = activity - if subactivity is not None and subactivity != 'other': - acc.activity['subactivity'] = subactivity - if text is not None: - acc.activity['text'] = text - elif retract: - if 'activity' in acc.activity: - del acc.activity['activity'] - if 'subactivity' in acc.activity: - del acc.activity['subactivity'] - if 'text' in acc.activity: - del acc.activity['text'] - - user = common.gajim.get_room_and_nick_from_fjid(jid)[0] - for contact in common.gajim.contacts.get_contacts(name, user): - if has_child: - if 'activity' in contact.activity: - del contact.activity['activity'] - if 'subactivity' in contact.activity: - del contact.activity['subactivity'] - if 'text' in contact.activity: - del contact.activity['text'] - if activity is not None: - contact.activity['activity'] = activity - if subactivity is not None and subactivity != 'other': - contact.activity['subactivity'] = subactivity - if text is not None: - contact.activity['text'] = text - elif retract: - if 'activity' in contact.activity: - del contact.activity['activity'] - if 'subactivity' in contact.activity: - del contact.activity['subactivity'] - if 'text' in contact.activity: - del contact.activity['text'] - - if jid == common.gajim.get_jid_from_account(name): - common.gajim.interface.roster.draw_account(name) - common.gajim.interface.roster.draw_activity(user, name) - ctrl = common.gajim.interface.msg_win_mgr.get_control(user, name) - if ctrl: - ctrl.update_activity() - -def user_nickname(items, name, jid): - has_child = False - retract = False - nick = None - - for item in items.getTags('item'): - child = item.getTag('nick') - if child is not None: - has_child = True - nick = child.getData() - break - - if items.getTag('retract') is not None: - retract = True - - if jid == common.gajim.get_jid_from_account(name): - if has_child: - common.gajim.nicks[name] = nick - if retract: - common.gajim.nicks[name] = common.gajim.config.get_per('accounts', - name, 'name') - - user = common.gajim.get_room_and_nick_from_fjid(jid)[0] - if has_child: - if nick is not None: - for contact in common.gajim.contacts.get_contacts(name, user): - contact.contact_name = nick - common.gajim.interface.roster.draw_contact(user, name) - - ctrl = common.gajim.interface.msg_win_mgr.get_control(user, name) - if ctrl: - ctrl.update_ui() - win = ctrl.parent_win - win.redraw_tab(ctrl) - win.show_title() - elif retract: - contact.contact_name = '' - def user_send_mood(account, mood, message=''): if not common.gajim.connections[account].pep_supported: return From 3d5e8cc42737418a237d3f5812834d2b9ef9acce Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Sat, 14 Nov 2009 22:47:21 +0100 Subject: [PATCH 06/20] Move common pep constructor logic to base class. --- src/common/pep.py | 55 ++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 34 deletions(-) diff --git a/src/common/pep.py b/src/common/pep.py index 9e99a5a24..4b31fb58e 100644 --- a/src/common/pep.py +++ b/src/common/pep.py @@ -205,7 +205,7 @@ class AbstractPEP(object): type = '' namespace = '' - + @classmethod def get_tag_as_PEP(cls, jid, account, event_tag): items = event_tag.getTag('items', {'node': cls.namespace}) @@ -215,17 +215,19 @@ class AbstractPEP(object): else: return None + def __init__(self, jid, account, items): + self._pep_specific_data, self._retracted = self._extract_info(items) + self.do(jid, account) + + def _extract_info(self, items): + '''To be implemented by subclasses''' + raise NotImplementedError class UserMoodPEP(AbstractPEP): '''XEP-0107: User Mood''' type = 'mood' namespace = common.xmpp.NS_MOOD - - def __init__(self, jid, account, items): - self._mood_dict, self._retracted = self._extract_info(items) - - self.user_mood(items, account, jid) def _extract_info(self, items): mood_dict = {} @@ -242,9 +244,8 @@ class UserMoodPEP(AbstractPEP): retracted = items.getTag('retract') or not mood_dict return (mood_dict, retracted) - def user_mood(self, items, name, jid): - - mood_dict = {} if self._retracted else self._mood_dict + def do(self, jid, name): + mood_dict = {} if self._retracted else self._pep_specific_data if jid == common.gajim.get_jid_from_account(name): acc = common.gajim.connections[name] @@ -267,12 +268,7 @@ class UserTunePEP(AbstractPEP): type = 'tune' namespace = common.xmpp.NS_TUNE - - def __init__(self, jid, account, items): - self._tune_dict, self._retracted = self._extract_info(items) - - self.user_tune(items, account, jid) - + def _extract_info(self, items): tune_dict = {} @@ -287,8 +283,8 @@ class UserTunePEP(AbstractPEP): return (tune_dict, retracted) - def user_tune(self, items, name, jid): - tune_dict = {} if self._retracted else self._tune_dict + def do(self, jid, name): + tune_dict = {} if self._retracted else self._pep_specific_data if jid == common.gajim.get_jid_from_account(name): acc = common.gajim.connections[name] @@ -311,19 +307,14 @@ class UserActivityPEP(AbstractPEP): type = 'activity' namespace = common.xmpp.NS_ACTIVITY - - def __init__(self, jid, account, items): - self._activity_dict, self._retracted = self._extract_info(items) - - self.user_activity(items, account, jid) - + def _extract_info(self, items): activity_dict = {} for item in items.getTags('item'): activity_tag = item.getTag('activity') if activity_tag: - for child in child.getChildren(): + for child in activity_tag.getChildren(): if child.getName() == 'text': activity_dict['text'] = child.getData() elif child.getName() in ACTIVITIES: @@ -335,8 +326,8 @@ class UserActivityPEP(AbstractPEP): retracted = items.getTag('retract') or not activity_dict return (activity_dict, retracted) - def user_activity(self, items, name, jid): - activity_dict = {} if self._retracted else self._activity_dict + def do(self, jid, name): + activity_dict = {} if self._retracted else self._pep_specific_data if jid == common.gajim.get_jid_from_account(name): acc = common.gajim.connections[name] @@ -359,11 +350,7 @@ class UserNicknamePEP(AbstractPEP): type = 'activity' namespace = common.xmpp.NS_NICK - - def __init__(self, jid, account, items): - self._nick, self._retracted = self._extract_info(items) - self.user_nickname(items, account, jid) - + def _extract_info(self, items): nick = '' for item in items.getTags('item'): @@ -375,15 +362,15 @@ class UserNicknamePEP(AbstractPEP): retracted = items.getTag('retract') or not nick return (nick, retracted) - def user_nickname(self, items, name, jid): + def do(self, jid, name): if jid == common.gajim.get_jid_from_account(name): if self._retracted: common.gajim.nicks[name] = common.gajim.config.get_per('accounts', name, 'name') else: - common.gajim.nicks[name] = self._nick + common.gajim.nicks[name] = self._pep_specific_data - nick = '' if self._retracted else self._nick + nick = '' if self._retracted else self._pep_specific_data user = common.gajim.get_room_and_nick_from_fjid(jid)[0] for contact in common.gajim.contacts.get_contacts(name, user): From 088916f4e7709133023cd308972c938787376ace Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Sat, 14 Nov 2009 23:07:22 +0100 Subject: [PATCH 07/20] Strip PEP info at the network level. (Currently it is done at the UI level in many, many different places) --- src/common/pep.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/common/pep.py b/src/common/pep.py index 4b31fb58e..bd17e46ba 100644 --- a/src/common/pep.py +++ b/src/common/pep.py @@ -236,10 +236,11 @@ class UserMoodPEP(AbstractPEP): mood_tag = item.getTag('mood') if mood_tag: for child in mood_tag.getChildren(): - if child.getName() == 'text': + name = child.getName().strip() + if name == 'text': mood_dict['text'] = child.getData() - elif child.getName() in MOODS : - mood_dict['mood'] = child.getName() + elif name in MOODS : + mood_dict['mood'] = name retracted = items.getTag('retract') or not mood_dict return (mood_dict, retracted) @@ -276,8 +277,10 @@ class UserTunePEP(AbstractPEP): tune_tag = item.getTag('tune') if tune_tag: for child in tune_tag.getChildren(): + name = child.getName().strip() + data = child.getData().strip() if child.getName() in TUNE_DATA: - tune_dict[child.getName()] = child.getData() + tune_dict[name] = data retracted = items.getTag('retract') or not tune_dict return (tune_dict, retracted) @@ -315,13 +318,16 @@ class UserActivityPEP(AbstractPEP): activity_tag = item.getTag('activity') if activity_tag: for child in activity_tag.getChildren(): - if child.getName() == 'text': - activity_dict['text'] = child.getData() - elif child.getName() in ACTIVITIES: - activity_dict['activity'] = child.getName() + name = child.getName().strip() + data = child.getData().strip() + if name == 'text': + activity_dict['text'] = data + elif name in ACTIVITIES: + activity_dict['activity'] = name for subactivity in child.getChildren(): - if subactivity.getName() in ACTIVITIES[child.getName()]: - activity_dict['subactivity'] = subactivity.getName() + subactivity_name = subactivity.getName().strip() + if subactivity_name in ACTIVITIES[name]: + activity_dict['subactivity'] = subactivity_name retracted = items.getTag('retract') or not activity_dict return (activity_dict, retracted) From e41e4848559c0446107cc378d15d8887daaea129 Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Sun, 15 Nov 2009 00:12:15 +0100 Subject: [PATCH 08/20] Proof of concept: Move markup / pixbuf determination logic from the UI to the different PEP classes. Currently this is only done for UserMood. We can decide later on (if needed), to move the asPixbufIcon and asMarkupText methods to a more appropriate place. Goal is to remove as much redundant code as possible. --- src/chat_control.py | 31 +++++-------------------------- src/common/contacts.py | 1 + src/common/pep.py | 36 ++++++++++++++++++++++++++++++++---- 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/src/chat_control.py b/src/chat_control.py index 04d6abc00..fc59c2444 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -1432,34 +1432,13 @@ class ChatControl(ChatControlBase): self._convert_to_gc_button.set_sensitive(False) def update_mood(self): - mood = None - text = None - if isinstance(self.contact, GC_Contact): return - - if 'mood' in self.contact.mood: - mood = self.contact.mood['mood'].strip() - if 'text' in self.contact.mood: - text = self.contact.mood['text'].strip() - - if mood is not None: - if mood in MOODS: - self._mood_image.set_from_pixbuf(gtkgui_helpers.load_mood_icon( - mood).get_pixbuf()) - # Translate standard moods - mood = MOODS[mood] - else: - self._mood_image.set_from_pixbuf(gtkgui_helpers.load_mood_icon( - 'unknown').get_pixbuf()) - - mood = gobject.markup_escape_text(mood) - - tooltip = '%s' % mood - if text: - text = gobject.markup_escape_text(text) - tooltip += '\n' + text - self._mood_image.set_tooltip_markup(tooltip) + + pep = self.contact.pep + if 'mood' in pep and not pep['mood'].was_retracted(): + self._mood_image.set_from_pixbuf(pep['mood'].asPixbufIcon()) + self._mood_image.set_tooltip_markup(pep['mood'].asMarkup()) self._mood_image.show() else: self._mood_image.hide() diff --git a/src/common/contacts.py b/src/common/contacts.py index a4a64a0dd..b8b039288 100644 --- a/src/common/contacts.py +++ b/src/common/contacts.py @@ -110,6 +110,7 @@ class Contact(CommonContact): self.msg_id = msg_id self.last_status_time = last_status_time + self.pep = {} self.mood = mood.copy() self.tune = tune.copy() self.activity = activity.copy() diff --git a/src/common/pep.py b/src/common/pep.py index bd17e46ba..f11021ec7 100644 --- a/src/common/pep.py +++ b/src/common/pep.py @@ -197,8 +197,10 @@ TUNE_DATA = ['artist', 'title', 'source', 'track', 'length'] import logging log = logging.getLogger('gajim.c.pep') -import helpers -import atom +import common.helpers +import common.atom +import gtkgui_helpers +import gobject class AbstractPEP(object): @@ -223,6 +225,9 @@ class AbstractPEP(object): '''To be implemented by subclasses''' raise NotImplementedError + def was_rectacted(self): + return self._retracted + class UserMoodPEP(AbstractPEP): '''XEP-0107: User Mood''' @@ -239,10 +244,10 @@ class UserMoodPEP(AbstractPEP): name = child.getName().strip() if name == 'text': mood_dict['text'] = child.getData() - elif name in MOODS : + else: mood_dict['mood'] = name - retracted = items.getTag('retract') or not mood_dict + retracted = items.getTag('retract') or not 'mood' in mood_dict return (mood_dict, retracted) def do(self, jid, name): @@ -255,6 +260,7 @@ class UserMoodPEP(AbstractPEP): user = common.gajim.get_room_and_nick_from_fjid(jid)[0] for contact in common.gajim.contacts.get_contacts(name, user): contact.mood = mood_dict + contact.pep['mood'] = self if jid == common.gajim.get_jid_from_account(name): common.gajim.interface.roster.draw_account(name) @@ -262,7 +268,29 @@ class UserMoodPEP(AbstractPEP): ctrl = common.gajim.interface.msg_win_mgr.get_control(user, name) if ctrl: ctrl.update_mood() + + + def asPixbufIcon(self): + if self._retracted: + return None + else: + received_mood = self._pep_specific_data['mood'] + mood = received_mood if received_mood in MOODS else 'unknown' + pixbuf = gtkgui_helpers.load_mood_icon(mood).get_pixbuf() + return pixbuf + def asMarkupText(self): + if self._retracted: + return None + else: + untranslated_mood = self._pep_specific_data['mood'] + mood = MOODS[untranslated_mood] if untranslated_mood in MOODS else untranslated_mood + markuptext = '%s' % gobject.markup_escape_text(mood) + if 'text' in self._pep_specific_data: + text = self._pep_specific_data['text'] + markuptext += '(%s)' + gobject.markup_escape_text(text) + return markuptext + class UserTunePEP(AbstractPEP): '''XEP-0118: User Tune''' From 234a6520dd4a2639a3fdada45d9d9fe911a1fb5e Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Sun, 15 Nov 2009 00:15:31 +0100 Subject: [PATCH 09/20] Removed unused code. --- src/common/helpers.py | 49 ------------------------------------------- src/common/pep.py | 4 ++-- 2 files changed, 2 insertions(+), 51 deletions(-) diff --git a/src/common/helpers.py b/src/common/helpers.py index 70bdfc9fe..341ebb15f 100644 --- a/src/common/helpers.py +++ b/src/common/helpers.py @@ -569,8 +569,6 @@ def datetime_tuple(timestamp): # import gajim only when needed (after decode_string is defined) see #4764 import gajim -import pep - def convert_bytes(string): suffix = '' @@ -777,53 +775,6 @@ def get_global_status(): status = gajim.connections[account].status return status -def get_pep_dict(account): - pep_dict = {} - con = gajim.connections[account] - # activity - if 'activity' in con.activity and con.activity['activity'] in pep.ACTIVITIES: - activity = con.activity['activity'] - if 'subactivity' in con.activity and con.activity['subactivity'] in \ - pep.ACTIVITIES[activity]: - subactivity = con.activity['subactivity'] - else: - subactivity = 'other' - else: - activity = '' - subactivity = '' - if 'text' in con.activity: - text = con.activity['text'] - else: - text = '' - pep_dict['activity'] = activity - pep_dict['subactivity'] = subactivity - pep_dict['activity_text'] = text - - # mood - if 'mood' in con.mood and con.mood['mood'] in pep.MOODS: - mood = con.mood['mood'] - else: - mood = '' - if 'text' in con.mood: - text = con.mood['text'] - else: - text = '' - pep_dict['mood'] = mood - pep_dict['mood_text'] = text - return pep_dict - -def get_global_pep(): - maxi = 0 - pep_dict = {'activity': '', 'mood': ''} - for account in gajim.connections: - if not gajim.config.get_per('accounts', account, - 'sync_with_global_status'): - continue - connected = gajim.connections[account].connected - if connected > maxi: - maxi = connected - pep_dict = get_pep_dict(account) - return pep_dict def statuses_unified(): '''testing if all statuses are the same.''' diff --git a/src/common/pep.py b/src/common/pep.py index f11021ec7..e32c2c444 100644 --- a/src/common/pep.py +++ b/src/common/pep.py @@ -197,8 +197,8 @@ TUNE_DATA = ['artist', 'title', 'source', 'track', 'length'] import logging log = logging.getLogger('gajim.c.pep') -import common.helpers -import common.atom +import helpers +import atom import gtkgui_helpers import gobject From 5f4db2eed9c93e378317479cf3f2b28e6758017d Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Sun, 15 Nov 2009 10:55:31 +0100 Subject: [PATCH 10/20] Unify updating of accounts and contact pep information. Implement and use asMarkupText() for tunes. --- src/chat_control.py | 36 ++-------- src/common/connection.py | 1 + src/common/pep.py | 144 +++++++++++++++++++++++---------------- src/roster_window.py | 11 +-- src/tooltips.py | 36 ++-------- 5 files changed, 101 insertions(+), 127 deletions(-) diff --git a/src/chat_control.py b/src/chat_control.py index fc59c2444..ab6f10213 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -1434,11 +1434,10 @@ class ChatControl(ChatControlBase): def update_mood(self): if isinstance(self.contact, GC_Contact): return - pep = self.contact.pep - if 'mood' in pep and not pep['mood'].was_retracted(): + if 'mood' in pep: self._mood_image.set_from_pixbuf(pep['mood'].asPixbufIcon()) - self._mood_image.set_tooltip_markup(pep['mood'].asMarkup()) + self._mood_image.set_tooltip_markup(pep['mood'].asMarkupText()) self._mood_image.show() else: self._mood_image.hide() @@ -1489,35 +1488,12 @@ class ChatControl(ChatControlBase): self._activity_image.hide() def update_tune(self): - artist = None - title = None - source = None - if isinstance(self.contact, GC_Contact): return - - if 'artist' in self.contact.tune: - artist = self.contact.tune['artist'].strip() - artist = gobject.markup_escape_text(artist) - if 'title' in self.contact.tune: - title = self.contact.tune['title'].strip() - title = gobject.markup_escape_text(title) - if 'source' in self.contact.tune: - source = self.contact.tune['source'].strip() - source = gobject.markup_escape_text(source) - - if artist or title: - if not artist: - artist = _('Unknown Artist') - if not title: - title = _('Unknown Title') - if not source: - source = _('Unknown Source') - - self._tune_image.set_tooltip_markup( - _('"%(title)s" by %(artist)s\n' - 'from %(source)s') % {'title': title, 'artist': artist, - 'source': source}) + + pep = self.contact.pep + if 'tune' in pep: + self._tune_image.set_tooltip_markup(pep['tune'].asMarkupText()) self._tune_image.show() else: self._tune_image.hide() diff --git a/src/common/connection.py b/src/common/connection.py index 717684a6b..90df73d08 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -171,6 +171,7 @@ class Connection(ConnectionHandlers): self.mood = {} self.tune = {} self.activity = {} + self.pep = {} # Do we continue connection when we get roster (send presence,get vcard..) self.continue_connect_info = None # Do we auto accept insecure connection diff --git a/src/common/pep.py b/src/common/pep.py index e32c2c444..bbc388f2a 100644 --- a/src/common/pep.py +++ b/src/common/pep.py @@ -203,6 +203,13 @@ import gtkgui_helpers import gobject +def translate_mood(mood): + if mood in MOODS: + return MOODS[mood] + else: + return mood + + class AbstractPEP(object): type = '' @@ -219,14 +226,49 @@ class AbstractPEP(object): def __init__(self, jid, account, items): self._pep_specific_data, self._retracted = self._extract_info(items) + + self._update_contacts(jid, account) + if jid == common.gajim.get_jid_from_account(account): + self._update_account(account) + self.do(jid, account) def _extract_info(self, items): '''To be implemented by subclasses''' raise NotImplementedError - def was_rectacted(self): - return self._retracted + def _update_contacts(self, jid, account): + dict = {} if self._retracted else self._pep_specific_data + + for contact in common.gajim.contacts.get_contacts(account, jid): + setattr(contact, self.type, dict) + + if self._retracted: + if self.type in contact.pep: + del contact.pep[self.type] + else: + contact.pep[self.type] = self + + def _update_account(self, account): + dict = {} if self._retracted else self._pep_specific_data + + acc = common.gajim.connections[account] + setattr(acc, self.type, dict) + + if self._retracted: + if self.type in acc.pep: + del acc.pep[self.type] + else: + acc.pep[self.type] = self + + def asPixbufIcon(self): + '''To be implemented by subclasses''' + raise NotImplementedError + + def asMarkupText(self): + '''To be implemented by subclasses''' + raise NotImplementedError + class UserMoodPEP(AbstractPEP): '''XEP-0107: User Mood''' @@ -251,45 +293,31 @@ class UserMoodPEP(AbstractPEP): return (mood_dict, retracted) def do(self, jid, name): - mood_dict = {} if self._retracted else self._pep_specific_data - - if jid == common.gajim.get_jid_from_account(name): - acc = common.gajim.connections[name] - acc.mood = mood_dict - - user = common.gajim.get_room_and_nick_from_fjid(jid)[0] - for contact in common.gajim.contacts.get_contacts(name, user): - contact.mood = mood_dict - contact.pep['mood'] = self - + if jid == common.gajim.get_jid_from_account(name): common.gajim.interface.roster.draw_account(name) - common.gajim.interface.roster.draw_mood(user, name) - ctrl = common.gajim.interface.msg_win_mgr.get_control(user, name) + common.gajim.interface.roster.draw_mood(jid, name) + ctrl = common.gajim.interface.msg_win_mgr.get_control(jid, name) if ctrl: ctrl.update_mood() def asPixbufIcon(self): - if self._retracted: - return None - else: - received_mood = self._pep_specific_data['mood'] - mood = received_mood if received_mood in MOODS else 'unknown' - pixbuf = gtkgui_helpers.load_mood_icon(mood).get_pixbuf() - return pixbuf + assert not self._retracted + received_mood = self._pep_specific_data['mood'] + mood = received_mood if received_mood in MOODS else 'unknown' + pixbuf = gtkgui_helpers.load_mood_icon(mood).get_pixbuf() + return pixbuf def asMarkupText(self): - if self._retracted: - return None - else: - untranslated_mood = self._pep_specific_data['mood'] - mood = MOODS[untranslated_mood] if untranslated_mood in MOODS else untranslated_mood - markuptext = '%s' % gobject.markup_escape_text(mood) - if 'text' in self._pep_specific_data: - text = self._pep_specific_data['text'] - markuptext += '(%s)' + gobject.markup_escape_text(text) - return markuptext + assert not self._retracted + untranslated_mood = self._pep_specific_data['mood'] + mood = translate_mood(untranslated_mood) + markuptext = '%s' % gobject.markup_escape_text(mood) + if 'text' in self._pep_specific_data: + text = self._pep_specific_data['text'] + markuptext += ' (%s)' % gobject.markup_escape_text(text) + return markuptext class UserTunePEP(AbstractPEP): @@ -310,27 +338,36 @@ class UserTunePEP(AbstractPEP): if child.getName() in TUNE_DATA: tune_dict[name] = data - retracted = items.getTag('retract') or not tune_dict + retracted = items.getTag('retract') or not ('artist' in tune_dict or + 'title' in tune_dict) return (tune_dict, retracted) - def do(self, jid, name): - tune_dict = {} if self._retracted else self._pep_specific_data - - if jid == common.gajim.get_jid_from_account(name): - acc = common.gajim.connections[name] - acc.tune = tune_dict - - user = common.gajim.get_room_and_nick_from_fjid(jid)[0] - for contact in common.gajim.contacts.get_contacts(name, user): - contact.tune = tune_dict - + def do(self, jid, name): if jid == common.gajim.get_jid_from_account(name): common.gajim.interface.roster.draw_account(name) - common.gajim.interface.roster.draw_tune(user, name) - ctrl = common.gajim.interface.msg_win_mgr.get_control(user, name) + common.gajim.interface.roster.draw_tune(jid, name) + ctrl = common.gajim.interface.msg_win_mgr.get_control(jid, name) if ctrl: ctrl.update_tune() + + def asMarkupText(self): + assert not self._retracted + tune = self._pep_specific_data + + artist = tune.get('artist', _('Unknown Artist')) + artist = gobject.markup_escape_text(artist) + + title = tune.get('title', _('Unknown Title')) + title = gobject.markup_escape_text(title) + + source = tune.get('source', _('Unknown Source')) + source = gobject.markup_escape_text(source) + + tune_string = _('"%(title)s" by %(artist)s\n' + 'from %(source)s') % {'title': title, + 'artist': artist, 'source': source} + return tune_string class UserActivityPEP(AbstractPEP): @@ -361,20 +398,11 @@ class UserActivityPEP(AbstractPEP): return (activity_dict, retracted) def do(self, jid, name): - activity_dict = {} if self._retracted else self._pep_specific_data - - if jid == common.gajim.get_jid_from_account(name): - acc = common.gajim.connections[name] - acc.activity = activity_dict - - user = common.gajim.get_room_and_nick_from_fjid(jid)[0] - for contact in common.gajim.contacts.get_contacts(name, user): - contact.activity = activity_dict if jid == common.gajim.get_jid_from_account(name): common.gajim.interface.roster.draw_account(name) - common.gajim.interface.roster.draw_activity(user, name) - ctrl = common.gajim.interface.msg_win_mgr.get_control(user, name) + common.gajim.interface.roster.draw_activity(jid, name) + ctrl = common.gajim.interface.msg_win_mgr.get_control(jid, name) if ctrl: ctrl.update_activity() @@ -437,7 +465,7 @@ class ConnectionPEP: for pep_class in SUPPORTED_PERSONAL_USER_EVENTS: pep = pep_class.get_tag_as_PEP(jid, self.name, event_tag) if pep: - self.dispatch('PEP_RECEIVED', (pep.type, pep)) + self.dispatch('PEP_RECEIVED', (jid, pep.type)) items = event_tag.getTag('items') if items is None: return diff --git a/src/roster_window.py b/src/roster_window.py index 4ea9d884a..93bdef75a 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -1281,15 +1281,10 @@ class RosterWindow: iters = self._get_contact_iter(jid, account, model=self.model) if not iters or not gajim.config.get('show_mood_in_roster'): return - jid = self.model[iters[0]][C_JID] - jid = jid.decode('utf-8') + jid = self.model[iters[0]][C_JID].decode('utf-8') contact = gajim.contacts.get_contact(account, jid) - if 'mood' in contact.mood and contact.mood['mood'].strip() in MOODS: - pixbuf = gtkgui_helpers.load_mood_icon( - contact.mood['mood'].strip()).get_pixbuf() - elif 'mood' in contact.mood: - pixbuf = gtkgui_helpers.load_mood_icon( - 'unknown').get_pixbuf() + if 'mood' in contact.pep: + pixbuf = contact.pep['mood'].asPixbufIcon() else: pixbuf = None for child_iter in iters: diff --git a/src/tooltips.py b/src/tooltips.py index fa96cbd8c..47f44b1ff 100644 --- a/src/tooltips.py +++ b/src/tooltips.py @@ -579,17 +579,9 @@ class RosterTooltip(NotificationAreaTooltip): Append Tune, Mood, Activity information of the specified contact to the given property list. ''' - if 'mood' in contact.mood: - mood = contact.mood['mood'].strip() - mood = MOODS.get(mood, mood) - mood = gobject.markup_escape_text(mood) + if 'mood' in contact.pep: + mood = contact.pep['mood'].asMarkupText() mood_string = _('Mood:') + ' %s' % mood - if 'text' in contact.mood \ - and contact.mood['text'] != '': - mood_text = contact.mood['text'].strip() - mood_text = \ - gobject.markup_escape_text(mood_text) - mood_string += ' (%s)' % mood_text properties.append((mood_string, None)) if 'activity' in contact.activity: @@ -617,27 +609,9 @@ class RosterTooltip(NotificationAreaTooltip): activity_string += ' (%s)' % activity_text properties.append((activity_string, None)) - if 'artist' in contact.tune \ - or 'title' in contact.tune: - if 'artist' in contact.tune: - artist = contact.tune['artist'].strip() - artist = gobject.markup_escape_text(artist) - else: - artist = _('Unknown Artist') - if 'title' in contact.tune: - title = contact.tune['title'].strip() - title = gobject.markup_escape_text(title) - else: - title = _('Unknown Title') - if 'source' in contact.tune: - source = contact.tune['source'].strip() - source = gobject.markup_escape_text(source) - else: - source = _('Unknown Source') - tune_string = _('Tune:') + ' ' + \ - _('"%(title)s" by %(artist)s\n' - 'from %(source)s') % {'title': title, - 'artist': artist, 'source': source} + if 'tune' in contact.pep: + tune = contact.pep['tune'].asMarkupText() + tune_string = _('Tune:') + ' %s' % tune properties.append((tune_string, None)) From 6c0fb26e58ecd746a799a4998e7fa4b6d8c45f83 Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Sun, 15 Nov 2009 11:11:51 +0100 Subject: [PATCH 11/20] Use central event_handler in Interface() instead of updating the GUI directly from XMPP callbacks. --- src/common/pep.py | 70 ++++++++++---------------------------------- src/gui_interface.py | 30 +++++++++++++++++++ 2 files changed, 46 insertions(+), 54 deletions(-) diff --git a/src/common/pep.py b/src/common/pep.py index bbc388f2a..ad4d3f815 100644 --- a/src/common/pep.py +++ b/src/common/pep.py @@ -230,8 +230,6 @@ class AbstractPEP(object): self._update_contacts(jid, account) if jid == common.gajim.get_jid_from_account(account): self._update_account(account) - - self.do(jid, account) def _extract_info(self, items): '''To be implemented by subclasses''' @@ -291,16 +289,6 @@ class UserMoodPEP(AbstractPEP): retracted = items.getTag('retract') or not 'mood' in mood_dict return (mood_dict, retracted) - - def do(self, jid, name): - - if jid == common.gajim.get_jid_from_account(name): - common.gajim.interface.roster.draw_account(name) - common.gajim.interface.roster.draw_mood(jid, name) - ctrl = common.gajim.interface.msg_win_mgr.get_control(jid, name) - if ctrl: - ctrl.update_mood() - def asPixbufIcon(self): assert not self._retracted @@ -341,16 +329,7 @@ class UserTunePEP(AbstractPEP): retracted = items.getTag('retract') or not ('artist' in tune_dict or 'title' in tune_dict) return (tune_dict, retracted) - - - def do(self, jid, name): - if jid == common.gajim.get_jid_from_account(name): - common.gajim.interface.roster.draw_account(name) - common.gajim.interface.roster.draw_tune(jid, name) - ctrl = common.gajim.interface.msg_win_mgr.get_control(jid, name) - if ctrl: - ctrl.update_tune() - + def asMarkupText(self): assert not self._retracted tune = self._pep_specific_data @@ -397,20 +376,11 @@ class UserActivityPEP(AbstractPEP): retracted = items.getTag('retract') or not activity_dict return (activity_dict, retracted) - def do(self, jid, name): - - if jid == common.gajim.get_jid_from_account(name): - common.gajim.interface.roster.draw_account(name) - common.gajim.interface.roster.draw_activity(jid, name) - ctrl = common.gajim.interface.msg_win_mgr.get_control(jid, name) - if ctrl: - ctrl.update_activity() - - + class UserNicknamePEP(AbstractPEP): '''XEP-0172: User Nickname''' - type = 'activity' + type = 'nickname' namespace = common.xmpp.NS_NICK def _extract_info(self, items): @@ -423,29 +393,21 @@ class UserNicknamePEP(AbstractPEP): retracted = items.getTag('retract') or not nick return (nick, retracted) - - def do(self, jid, name): - if jid == common.gajim.get_jid_from_account(name): - if self._retracted: - common.gajim.nicks[name] = common.gajim.config.get_per('accounts', - name, 'name') - else: - common.gajim.nicks[name] = self._pep_specific_data - + + def _update_contacts(self, jid, account): + # TODO: use dict instead nick = '' if self._retracted else self._pep_specific_data - - user = common.gajim.get_room_and_nick_from_fjid(jid)[0] - for contact in common.gajim.contacts.get_contacts(name, user): + for contact in common.gajim.contacts.get_contacts(account, jid): contact.contact_name = nick - common.gajim.interface.roster.draw_contact(user, name) - - ctrl = common.gajim.interface.msg_win_mgr.get_control(user, name) - if ctrl: - ctrl.update_ui() - win = ctrl.parent_win - win.redraw_tab(ctrl) - win.show_title() - + + def _update_account(self, account): + # TODO: use dict instead + if self._retracted: + common.gajim.nicks[account] = common.gajim.config.get_per('accounts', + account, 'name') + else: + common.gajim.nicks[account] = self._pep_specific_data + SUPPORTED_PERSONAL_USER_EVENTS = [UserMoodPEP, UserTunePEP, UserActivityPEP, UserNicknamePEP] diff --git a/src/gui_interface.py b/src/gui_interface.py index 812aba08a..8aec6f993 100644 --- a/src/gui_interface.py +++ b/src/gui_interface.py @@ -1989,6 +1989,35 @@ class Interface: _('PEP node %(node)s was not removed: %(message)s') % { 'node': data[1], 'message': data[2]}) + def handle_event_pep_received(self, account, data): + # ('PEP_RECEIVED', account, (jid, pep_type)) + jid = data[0] + pep_type = data[1] + ctrl = common.gajim.interface.msg_win_mgr.get_control(jid, account) + + if jid == common.gajim.get_jid_from_account(account): + self.roster.draw_account(account) + + if pep_type == 'mood': + self.roster.draw_mood(jid, account) + if ctrl: + ctrl.update_mood() + elif pep_type == 'tune': + self.roster.draw_tune(jid, account) + if ctrl: + ctrl.update_tune() + elif pep_type == 'activity': + self.roster.draw_activity(jid, account) + if ctrl: + ctrl.update_activity() + elif pep_type == 'nickname': + self.roster.draw_contact(jid, account) + if ctrl: + ctrl.update_ui() + win = ctrl.parent_win + win.redraw_tab(ctrl) + win.show_title() + def register_handler(self, event, handler): if event not in self.handlers: self.handlers[event] = [] @@ -2088,6 +2117,7 @@ class Interface: 'JINGLE_CONNECTED': [self.handle_event_jingle_connected], 'JINGLE_DISCONNECTED': [self.handle_event_jingle_disconnected], 'JINGLE_ERROR': [self.handle_event_jingle_error], + 'PEP_RECEIVED': [self.handle_event_pep_received] } def dispatch(self, event, account, data): From 30191888bab4132556fd4a368271a3fa7026a4f1 Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Sun, 15 Nov 2009 16:52:19 +0100 Subject: [PATCH 12/20] Create asPixbufIcon and asMarkupText functions on the UserActivity class. --- src/chat_control.py | 43 ++++------------------------------ src/common/pep.py | 55 ++++++++++++++++++++++++++++++++++++++++---- src/roster_window.py | 21 ++++------------- src/tooltips.py | 28 ++++------------------ 4 files changed, 62 insertions(+), 85 deletions(-) diff --git a/src/chat_control.py b/src/chat_control.py index ab6f10213..b71033da5 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -1443,46 +1443,12 @@ class ChatControl(ChatControlBase): self._mood_image.hide() def update_activity(self): - activity = None - subactivity = None - text = None - if isinstance(self.contact, GC_Contact): return - - if 'activity' in self.contact.activity: - activity = self.contact.activity['activity'].strip() - if 'subactivity' in self.contact.activity: - subactivity = self.contact.activity['subactivity'].strip() - if 'text' in self.contact.activity: - text = self.contact.activity['text'].strip() - - if activity is not None: - if activity in ACTIVITIES: - # Translate standard activities - if subactivity in ACTIVITIES[activity]: - self._activity_image.set_from_pixbuf( - gtkgui_helpers.load_activity_icon(activity, subactivity). \ - get_pixbuf()) - subactivity = ACTIVITIES[activity][subactivity] - else: - self._activity_image.set_from_pixbuf( - gtkgui_helpers.load_activity_icon(activity).get_pixbuf()) - activity = ACTIVITIES[activity]['category'] - else: - self._activity_image.set_from_pixbuf( - gtkgui_helpers.load_activity_icon('unknown').get_pixbuf()) - - # Translate standard subactivities - - tooltip = '' + gobject.markup_escape_text(activity) - if subactivity: - tooltip += ': ' + gobject.markup_escape_text(subactivity) - tooltip += '' - if text: - tooltip += '\n' + gobject.markup_escape_text(text) - self._activity_image.set_tooltip_markup(tooltip) - + pep = self.contact.pep + if 'activity' in pep: + self._activity_image.set_from_pixbuf(pep['activity'].asPixbufIcon()) + self._activity_image.set_tooltip_markup(pep['activity'].asMarkupText()) self._activity_image.show() else: self._activity_image.hide() @@ -1490,7 +1456,6 @@ class ChatControl(ChatControlBase): def update_tune(self): if isinstance(self.contact, GC_Contact): return - pep = self.contact.pep if 'tune' in pep: self._tune_image.set_tooltip_markup(pep['tune'].asMarkupText()) diff --git a/src/common/pep.py b/src/common/pep.py index ad4d3f815..13a774a1b 100644 --- a/src/common/pep.py +++ b/src/common/pep.py @@ -201,6 +201,8 @@ import helpers import atom import gtkgui_helpers import gobject +import gajim +import gtk def translate_mood(mood): @@ -329,6 +331,11 @@ class UserTunePEP(AbstractPEP): retracted = items.getTag('retract') or not ('artist' in tune_dict or 'title' in tune_dict) return (tune_dict, retracted) + + def asPixbufIcon(self): + import os + path = os.path.join(gajim.DATA_DIR, 'emoticons', 'static', 'music.png') + return gtk.gdk.pixbuf_new_from_file(path) def asMarkupText(self): assert not self._retracted @@ -366,16 +373,54 @@ class UserActivityPEP(AbstractPEP): data = child.getData().strip() if name == 'text': activity_dict['text'] = data - elif name in ACTIVITIES: + else: activity_dict['activity'] = name for subactivity in child.getChildren(): subactivity_name = subactivity.getName().strip() - if subactivity_name in ACTIVITIES[name]: - activity_dict['subactivity'] = subactivity_name + activity_dict['subactivity'] = subactivity_name - retracted = items.getTag('retract') or not activity_dict + retracted = items.getTag('retract') or not 'activity' in activity_dict return (activity_dict, retracted) + + def asPixbufIcon(self): + assert not self._retracted + pep = self._pep_specific_data + activity = pep['activity'] + has_known_activity = activity in ACTIVITIES + has_known_subactivity = (has_known_activity and ('subactivity' in pep) + and (pep['subactivity'] in ACTIVITIES[activity])) + + if has_known_activity: + if has_known_subactivity: + subactivity = pep['subactivity'] + return gtkgui_helpers.load_activity_icon(activity, subactivity).get_pixbuf() + else: + return gtkgui_helpers.load_activity_icon(activity).get_pixbuf() + else: + return gtkgui_helpers.load_activity_icon('unknown').get_pixbuf() + + def asMarkupText(self): + assert not self._retracted + pep = self._pep_specific_data + activity = pep['activity'] + subactivity = pep['subactivity'] if 'subactivity' in pep else None + text = pep['text'] if 'text' in pep else None + + if activity in ACTIVITIES: + # Translate standard activities + if subactivity in ACTIVITIES[activity]: + subactivity = ACTIVITIES[activity][subactivity] + activity = ACTIVITIES[activity]['category'] + + markuptext = '' + gobject.markup_escape_text(activity) + if subactivity: + markuptext += ': ' + gobject.markup_escape_text(subactivity) + markuptext += '' + if text: + markuptext += ' (%s)' + gobject.markup_escape_text(text) + return markuptext + class UserNicknamePEP(AbstractPEP): '''XEP-0172: User Nickname''' @@ -404,7 +449,7 @@ class UserNicknamePEP(AbstractPEP): # TODO: use dict instead if self._retracted: common.gajim.nicks[account] = common.gajim.config.get_per('accounts', - account, 'name') + account, 'name') else: common.gajim.nicks[account] = self._pep_specific_data diff --git a/src/roster_window.py b/src/roster_window.py index 93bdef75a..4206a2844 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -1299,20 +1299,8 @@ class RosterWindow: jid = self.model[iters[0]][C_JID] jid = jid.decode('utf-8') contact = gajim.contacts.get_contact(account, jid) - if 'activity' in contact.activity \ - and contact.activity['activity'].strip() in ACTIVITIES: - if 'subactivity' in contact.activity \ - and contact.activity['subactivity'].strip() in \ - ACTIVITIES[contact.activity['activity'].strip()]: - pixbuf = gtkgui_helpers.load_activity_icon( - contact.activity['activity'].strip(), - contact.activity['subactivity'].strip()).get_pixbuf() - else: - pixbuf = gtkgui_helpers.load_activity_icon( - contact.activity['activity'].strip()).get_pixbuf() - elif 'activity' in contact.activity: - pixbuf = gtkgui_helpers.load_activity_icon( - 'unknown').get_pixbuf() + if 'activity' in contact.pep: + pixbuf = contact.pep['activity'].asPixbufIcon() else: pixbuf = None for child_iter in iters: @@ -1327,9 +1315,8 @@ class RosterWindow: jid = self.model[iters[0]][C_JID] jid = jid.decode('utf-8') contact = gajim.contacts.get_contact(account, jid) - if 'artist' in contact.tune or 'title' in contact.tune: - path = os.path.join(gajim.DATA_DIR, 'emoticons', 'static', 'music.png') - pixbuf = gtk.gdk.pixbuf_new_from_file(path) + if 'tune' in contact.pep: + pixbuf = contact.pep['tune'].asPixbufIcon() else: pixbuf = None for child_iter in iters: diff --git a/src/tooltips.py b/src/tooltips.py index 47f44b1ff..847e6a17a 100644 --- a/src/tooltips.py +++ b/src/tooltips.py @@ -581,32 +581,12 @@ class RosterTooltip(NotificationAreaTooltip): ''' if 'mood' in contact.pep: mood = contact.pep['mood'].asMarkupText() - mood_string = _('Mood:') + ' %s' % mood + mood_string = _('Mood:') + ' %s' % mood properties.append((mood_string, None)) - if 'activity' in contact.activity: - activity = act_plain = \ - contact.activity['activity'].strip() - activity = gobject.markup_escape_text(activity) - if act_plain in ACTIVITIES: - activity = ACTIVITIES[activity]['category'] - activity_string = _('Activity:') + ' %s' % activity - if 'subactivity' in contact.activity: - activity_sub = \ - contact.activity['subactivity'].strip() - if act_plain in ACTIVITIES and activity_sub in \ - ACTIVITIES[act_plain]: - activity_sub = ACTIVITIES[act_plain][activity_sub] - activity_sub = \ - gobject.markup_escape_text(activity_sub) - activity_string += ': %s' % activity_sub - else: - activity_string += '' - if 'text' in contact.activity: - activity_text = contact.activity['text'].strip() - activity_text = gobject.markup_escape_text( - activity_text) - activity_string += ' (%s)' % activity_text + if 'activity' in contact.pep: + activity = contact.pep['activity'].asMarkupText() + activity_string = _('Activity:') + ' %s' % activity properties.append((activity_string, None)) if 'tune' in contact.pep: From b7c7beafd96de0665581a7f4814c63468b24b482 Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Sun, 15 Nov 2009 17:00:39 +0100 Subject: [PATCH 13/20] Unify the PEP drawing methods in the RosterWindow. --- src/roster_window.py | 46 ++++++++++++-------------------------------- 1 file changed, 12 insertions(+), 34 deletions(-) diff --git a/src/roster_window.py b/src/roster_window.py index 4206a2844..01be6b2cc 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -1276,53 +1276,31 @@ class RosterWindow: return False - def draw_mood(self, jid, account): - iters = self._get_contact_iter(jid, account, model=self.model) - if not iters or not gajim.config.get('show_mood_in_roster'): - return - jid = self.model[iters[0]][C_JID].decode('utf-8') - contact = gajim.contacts.get_contact(account, jid) - if 'mood' in contact.pep: - pixbuf = contact.pep['mood'].asPixbufIcon() - else: - pixbuf = None - for child_iter in iters: - self.model[child_iter][C_MOOD_PIXBUF] = pixbuf - return False - + if gajim.config.get('show_mood_in_roster'): + self._draw_pep(jid, account, 'tune', C_MOOD_PIXBUF) def draw_activity(self, jid, account): - iters = self._get_contact_iter(jid, account, model=self.model) - if not iters or not gajim.config.get('show_activity_in_roster'): - return - jid = self.model[iters[0]][C_JID] - jid = jid.decode('utf-8') - contact = gajim.contacts.get_contact(account, jid) - if 'activity' in contact.pep: - pixbuf = contact.pep['activity'].asPixbufIcon() - else: - pixbuf = None - for child_iter in iters: - self.model[child_iter][C_ACTIVITY_PIXBUF] = pixbuf - return False - + if gajim.config.get('show_activity_in_roster'): + self._draw_pep(jid, account, 'tune', C_ACTIVITY_PIXBUF) def draw_tune(self, jid, account): + if gajim.config.get('show_tunes_in_roster'): + self._draw_pep(jid, account, 'tune', C_TUNE_PIXBUF) + + def _draw_pep(self, jid, account, pep_type, model_column): iters = self._get_contact_iter(jid, account, model=self.model) - if not iters or not gajim.config.get('show_tunes_in_roster'): + if not iters: return jid = self.model[iters[0]][C_JID] jid = jid.decode('utf-8') contact = gajim.contacts.get_contact(account, jid) - if 'tune' in contact.pep: - pixbuf = contact.pep['tune'].asPixbufIcon() + if pep_type in contact.pep: + pixbuf = contact.pep[pep_type].asPixbufIcon() else: pixbuf = None for child_iter in iters: - self.model[child_iter][C_TUNE_PIXBUF] = pixbuf - return False - + self.model[child_iter][model_column] = pixbuf def draw_avatar(self, jid, account): iters = self._get_contact_iter(jid, account, model=self.model) From 3b15d70782290a67bb32ef79bea1d2abb3ad48a5 Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Sun, 15 Nov 2009 17:11:06 +0100 Subject: [PATCH 14/20] Unify PEP cell_data_functions. --- src/roster_window.py | 150 +++++-------------------------------------- 1 file changed, 16 insertions(+), 134 deletions(-) diff --git a/src/roster_window.py b/src/roster_window.py index 01be6b2cc..6d06388f8 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -1278,11 +1278,11 @@ class RosterWindow: def draw_mood(self, jid, account): if gajim.config.get('show_mood_in_roster'): - self._draw_pep(jid, account, 'tune', C_MOOD_PIXBUF) + self._draw_pep(jid, account, 'mood', C_MOOD_PIXBUF) def draw_activity(self, jid, account): if gajim.config.get('show_activity_in_roster'): - self._draw_pep(jid, account, 'tune', C_ACTIVITY_PIXBUF) + self._draw_pep(jid, account, 'activity', C_ACTIVITY_PIXBUF) def draw_tune(self, jid, account): if gajim.config.get('show_tunes_in_roster'): @@ -4441,9 +4441,9 @@ class RosterWindow: renderer.set_property('xpad', 8) - def _fill_mood_pixbuf_renderer(self, column, renderer, model, titer, - data = None): - '''When a row is added, set properties for avatar renderer''' + def _fill_pep_pixbuf_renderer(self, column, renderer, model, titer, + data=None): + '''When a row is added, draw the respective pep icon''' theme = gajim.config.get('roster_theme') type_ = model[titer][C_TYPE] if type_ == 'group': @@ -4451,155 +4451,37 @@ class RosterWindow: return # allocate space for the icon only if needed - if model[titer][C_MOOD_PIXBUF]: + if model[titer][data]: renderer.set_property('visible', True) else: renderer.set_property('visible', False) if type_ == 'account': - color = gajim.config.get_per('themes', theme, - 'accountbgcolor') + color = gajim.config.get_per('themes', theme, 'accountbgcolor') if color: renderer.set_property('cell-background', color) else: - self.set_renderer_color(renderer, - gtk.STATE_ACTIVE) + self.set_renderer_color(renderer, gtk.STATE_ACTIVE) # align pixbuf to the right) renderer.set_property('xalign', 1) # prevent type_ = None, see http://trac.gajim.org/ticket/2534 elif type_: - if not model[titer][C_JID] \ - or not model[titer][C_ACCOUNT]: + if not model[titer][C_JID] or not model[titer][C_ACCOUNT]: # This can append at the moment we add the row return jid = model[titer][C_JID].decode('utf-8') account = model[titer][C_ACCOUNT].decode('utf-8') if jid in gajim.newly_added[account]: - renderer.set_property('cell-background', - gajim.config.get( + renderer.set_property('cell-background', gajim.config.get( 'just_connected_bg_color')) elif jid in gajim.to_be_removed[account]: - renderer.set_property('cell-background', - gajim.config.get( + renderer.set_property('cell-background', gajim.config.get( 'just_disconnected_bg_color')) else: - color = gajim.config.get_per('themes', - theme, 'contactbgcolor') - if color: - renderer.set_property( - 'cell-background', color) - else: - renderer.set_property( - 'cell-background', None) + color = gajim.config.get_per('themes', theme, 'contactbgcolor') + renderer.set_property('cell-background', color if color else None) # align pixbuf to the right renderer.set_property('xalign', 1) - - def _fill_activity_pixbuf_renderer(self, column, renderer, model, titer, - data = None): - '''When a row is added, set properties for avatar renderer''' - theme = gajim.config.get('roster_theme') - type_ = model[titer][C_TYPE] - if type_ == 'group': - renderer.set_property('visible', False) - return - - # allocate space for the icon only if needed - if model[titer][C_ACTIVITY_PIXBUF]: - renderer.set_property('visible', True) - else: - renderer.set_property('visible', False) - if type_ == 'account': - color = gajim.config.get_per('themes', theme, - 'accountbgcolor') - if color: - renderer.set_property('cell-background', color) - else: - self.set_renderer_color(renderer, - gtk.STATE_ACTIVE) - # align pixbuf to the right) - renderer.set_property('xalign', 1) - # prevent type_ = None, see http://trac.gajim.org/ticket/2534 - elif type_: - if not model[titer][C_JID] \ - or not model[titer][C_ACCOUNT]: - # This can append at the moment we add the row - return - jid = model[titer][C_JID].decode('utf-8') - account = model[titer][C_ACCOUNT].decode('utf-8') - if jid in gajim.newly_added[account]: - renderer.set_property('cell-background', - gajim.config.get( - 'just_connected_bg_color')) - elif jid in gajim.to_be_removed[account]: - renderer.set_property('cell-background', - gajim.config.get( - 'just_disconnected_bg_color')) - else: - color = gajim.config.get_per('themes', - theme, 'contactbgcolor') - if color: - renderer.set_property( - 'cell-background', color) - else: - renderer.set_property( - 'cell-background', None) - # align pixbuf to the right - renderer.set_property('xalign', 1) - - - def _fill_tune_pixbuf_renderer(self, column, renderer, model, titer, - data = None): - '''When a row is added, set properties for avatar renderer''' - theme = gajim.config.get('roster_theme') - type_ = model[titer][C_TYPE] - if type_ == 'group': - renderer.set_property('visible', False) - return - - # allocate space for the icon only if needed - if model[titer][C_TUNE_PIXBUF]: - renderer.set_property('visible', True) - else: - renderer.set_property('visible', False) - if type_ == 'account': - color = gajim.config.get_per('themes', theme, - 'accountbgcolor') - if color: - renderer.set_property('cell-background', color) - else: - self.set_renderer_color(renderer, - gtk.STATE_ACTIVE) - # align pixbuf to the right) - renderer.set_property('xalign', 1) - # prevent type_ = None, see http://trac.gajim.org/ticket/2534 - elif type_: - if not model[titer][C_JID] \ - or not model[titer][C_ACCOUNT]: - # This can append at the moment we add the row - return - jid = model[titer][C_JID].decode('utf-8') - account = model[titer][C_ACCOUNT].decode('utf-8') - if jid in gajim.newly_added[account]: - renderer.set_property('cell-background', - gajim.config.get( - 'just_connected_bg_color')) - elif jid in gajim.to_be_removed[account]: - renderer.set_property('cell-background', - gajim.config.get( - 'just_disconnected_bg_color')) - else: - color = gajim.config.get_per('themes', - theme, 'contactbgcolor') - if color: - renderer.set_property( - 'cell-background', color) - else: - renderer.set_property( - 'cell-background', None) - # align pixbuf to the right - renderer.set_property('xalign', 1) - - def _fill_avatar_pixbuf_renderer(self, column, renderer, model, titer, data = None): '''When a row is added, set properties for avatar renderer''' @@ -5893,19 +5775,19 @@ class RosterWindow: col.pack_start(render_pixbuf, expand=False) col.add_attribute(render_pixbuf, 'pixbuf', C_MOOD_PIXBUF) col.set_cell_data_func(render_pixbuf, - self._fill_mood_pixbuf_renderer, None) + self._fill_pep_pixbuf_renderer, C_MOOD_PIXBUF) render_pixbuf = gtk.CellRendererPixbuf() col.pack_start(render_pixbuf, expand=False) col.add_attribute(render_pixbuf, 'pixbuf', C_ACTIVITY_PIXBUF) col.set_cell_data_func(render_pixbuf, - self._fill_activity_pixbuf_renderer, None) + self._fill_pep_pixbuf_renderer, C_ACTIVITY_PIXBUF) render_pixbuf = gtk.CellRendererPixbuf() col.pack_start(render_pixbuf, expand=False) col.add_attribute(render_pixbuf, 'pixbuf', C_TUNE_PIXBUF) col.set_cell_data_func(render_pixbuf, - self._fill_tune_pixbuf_renderer, None) + self._fill_pep_pixbuf_renderer, C_TUNE_PIXBUF) if gajim.config.get('avatar_position_in_roster') == 'right': add_avatar_renderer() From 4c03c1ab85297f2c25aea8bc1521504a63c8bfe9 Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Sun, 15 Nov 2009 22:41:17 +0100 Subject: [PATCH 15/20] Remove duplicated Icon determination logic used when drawing accounts. --- src/roster_window.py | 48 +++++++------------------------------------- 1 file changed, 7 insertions(+), 41 deletions(-) diff --git a/src/roster_window.py b/src/roster_window.py index 6d06388f8..e425c9cb3 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -1022,55 +1022,21 @@ class RosterWindow: self.model[child_iter][C_NAME] = account_name - if gajim.config.get('show_mood_in_roster') \ - and 'mood' in gajim.connections[account].mood \ - and gajim.connections[account].mood['mood'].strip() in MOODS: - - self.model[child_iter][C_MOOD_PIXBUF] = gtkgui_helpers.load_mood_icon( - gajim.connections[account].mood['mood'].strip()).get_pixbuf() - - elif gajim.config.get('show_mood_in_roster') \ - and 'mood' in gajim.connections[account].mood: - self.model[child_iter][C_MOOD_PIXBUF] = \ - gtkgui_helpers.load_mood_icon('unknown'). \ - get_pixbuf() + pep = gajim.connections[account].pep + if gajim.config.get('show_mood_in_roster') and 'mood' in pep: + self.model[child_iter][C_MOOD_PIXBUF] = pep['mood'].asPixbufIcon() else: self.model[child_iter][C_MOOD_PIXBUF] = None - if gajim.config.get('show_activity_in_roster') \ - and 'activity' in gajim.connections[account].activity \ - and gajim.connections[account].activity['activity'].strip() \ - in ACTIVITIES: - if 'subactivity' in gajim.connections[account].activity \ - and gajim.connections[account].activity['subactivity'].strip() \ - in ACTIVITIES[gajim.connections[account].activity['activity'].strip()]: - self.model[child_iter][C_ACTIVITY_PIXBUF] = \ - gtkgui_helpers.load_activity_icon( - gajim.connections[account].activity['activity'].strip(), - gajim.connections[account].activity['subactivity'].strip()). \ - get_pixbuf() - else: - self.model[child_iter][C_ACTIVITY_PIXBUF] = \ - gtkgui_helpers.load_activity_icon( - gajim.connections[account].activity['activity'].strip()). \ - get_pixbuf() - elif gajim.config.get('show_activity_in_roster') \ - and 'activity' in gajim.connections[account].activity: - self.model[child_iter][C_ACTIVITY_PIXBUF] = \ - gtkgui_helpers.load_activity_icon('unknown'). \ - get_pixbuf() + if gajim.config.get('show_activity_in_roster') and 'activity' in pep: + self.model[child_iter][C_ACTIVITY_PIXBUF] = pep['activity'].asPixbufIcon() else: self.model[child_iter][C_ACTIVITY_PIXBUF] = None - if gajim.config.get('show_tunes_in_roster') \ - and ('artist' in gajim.connections[account].tune \ - or 'title' in gajim.connections[account].tune): - path = os.path.join(gajim.DATA_DIR, 'emoticons', 'static', 'music.png') - self.model[child_iter][C_TUNE_PIXBUF] = \ - gtk.gdk.pixbuf_new_from_file(path) + if gajim.config.get('show_tunes_in_roster') and 'tune' in pep: + self.model[child_iter][C_TUNE_PIXBUF] = pep['tune'].asPixbufIcon() else: self.model[child_iter][C_TUNE_PIXBUF] = None - return False def draw_group(self, group, account): From 338cb11dcce2218978f7e56bb45094c049431d57 Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Sun, 15 Nov 2009 22:54:20 +0100 Subject: [PATCH 16/20] Unify update_mood, update_tune, update_activity by using a single update_pep(pep_type) method. --- src/chat_control.py | 52 +++++++++++++++----------------------------- src/common/pep.py | 5 ++--- src/gui_interface.py | 6 ++--- 3 files changed, 22 insertions(+), 41 deletions(-) diff --git a/src/chat_control.py b/src/chat_control.py index b71033da5..d9607c4b5 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -1279,14 +1279,12 @@ class ChatControl(ChatControlBase): self.video_state = self.JINGLE_STATE_NOT_AVAILABLE self.update_toolbar() - - self._mood_image = self.xml.get_widget('mood_image') - self._activity_image = self.xml.get_widget('activity_image') - self._tune_image = self.xml.get_widget('tune_image') - - self.update_mood() - self.update_activity() - self.update_tune() + + self._pep_images = {} + self._pep_images['mood'] = self.xml.get_widget('mood_image') + self._pep_images['activity'] = self.xml.get_widget('activity_image') + self._pep_images['tune'] = self.xml.get_widget('tune_image') + self.update_all_pep_types() # keep timeout id and window obj for possible big avatar # it is on enter-notify and leave-notify so no need to be @@ -1430,38 +1428,22 @@ class ChatControl(ChatControlBase): self._convert_to_gc_button.set_sensitive(True) else: self._convert_to_gc_button.set_sensitive(False) + + def update_all_pep_types(self): + for pep_type in ('tune', 'mood', 'activity'): + self.update_pep(pep_type) - def update_mood(self): + def update_pep(self, pep_type): if isinstance(self.contact, GC_Contact): return pep = self.contact.pep - if 'mood' in pep: - self._mood_image.set_from_pixbuf(pep['mood'].asPixbufIcon()) - self._mood_image.set_tooltip_markup(pep['mood'].asMarkupText()) - self._mood_image.show() + img = self._pep_images[pep_type] + if pep_type in pep: + img.set_from_pixbuf(pep[pep_type].asPixbufIcon()) + img.set_tooltip_markup(pep[pep_type].asMarkupText()) + img.show() else: - self._mood_image.hide() - - def update_activity(self): - if isinstance(self.contact, GC_Contact): - return - pep = self.contact.pep - if 'activity' in pep: - self._activity_image.set_from_pixbuf(pep['activity'].asPixbufIcon()) - self._activity_image.set_tooltip_markup(pep['activity'].asMarkupText()) - self._activity_image.show() - else: - self._activity_image.hide() - - def update_tune(self): - if isinstance(self.contact, GC_Contact): - return - pep = self.contact.pep - if 'tune' in pep: - self._tune_image.set_tooltip_markup(pep['tune'].asMarkupText()) - self._tune_image.show() - else: - self._tune_image.hide() + img.hide() def _update_jingle(self, jingle_type): if jingle_type not in ('audio', 'video'): diff --git a/src/common/pep.py b/src/common/pep.py index 13a774a1b..18a27364a 100644 --- a/src/common/pep.py +++ b/src/common/pep.py @@ -594,8 +594,7 @@ def delete_pep(jid, name): common.gajim.interface.roster.draw_mood(user, name) ctrl = common.gajim.interface.msg_win_mgr.get_control(user, name) if ctrl: - ctrl.update_activity() - ctrl.update_tune() - ctrl.update_mood() + ctrl.update_all_pep_types() + # vim: se ts=3: diff --git a/src/gui_interface.py b/src/gui_interface.py index 8aec6f993..ec093b03b 100644 --- a/src/gui_interface.py +++ b/src/gui_interface.py @@ -2001,15 +2001,15 @@ class Interface: if pep_type == 'mood': self.roster.draw_mood(jid, account) if ctrl: - ctrl.update_mood() + ctrl.update_pep(pep_type) elif pep_type == 'tune': self.roster.draw_tune(jid, account) if ctrl: - ctrl.update_tune() + ctrl.update_pep(pep_type) elif pep_type == 'activity': self.roster.draw_activity(jid, account) if ctrl: - ctrl.update_activity() + ctrl.update_pep(pep_type) elif pep_type == 'nickname': self.roster.draw_contact(jid, account) if ctrl: From 28161dc33c2d0f0da693d37baea6980013d6ee2e Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Sun, 15 Nov 2009 22:59:43 +0100 Subject: [PATCH 17/20] Apply coding standards. --- src/common/pep.py | 33 ++++++++++++++------------------- src/roster_window.py | 3 +-- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/common/pep.py b/src/common/pep.py index 18a27364a..e0394ce61 100644 --- a/src/common/pep.py +++ b/src/common/pep.py @@ -475,11 +475,12 @@ class ConnectionPEP: self.dispatch('PEP_RECEIVED', (jid, pep.type)) items = event_tag.getTag('items') - if items is None: return + if items is None: + return for item in items.getTags('item'): entry = item.getTag('entry') - if entry is not None: + if entry: # for each entry in feed (there shouldn't be more than one, # but to be sure... self.dispatch('ATOM_ENTRY', (atom.OldEntry(node=entry),)) @@ -493,9 +494,9 @@ def user_send_mood(account, mood, message=''): if not common.gajim.connections[account].pep_supported: return item = xmpp.Node('mood', {'xmlns': xmpp.NS_MOOD}) - if mood != '': + if mood: item.addChild(mood) - if message != '': + if message: i = item.addChild('text') i.addData(message) @@ -506,11 +507,11 @@ def user_send_activity(account, activity, subactivity='', message=''): if not common.gajim.connections[account].pep_supported: return item = xmpp.Node('activity', {'xmlns': xmpp.NS_ACTIVITY}) - if activity != '': + if activity: i = item.addChild(activity) - if subactivity != '': + if subactivity: i.addChild(subactivity) - if message != '': + if message: i = item.addChild('text') i.addData(message) @@ -523,22 +524,22 @@ items=None): common.gajim.connections[account].pep_supported): return item = xmpp.Node('tune', {'xmlns': xmpp.NS_TUNE}) - if artist != '': + if artist: i = item.addChild('artist') i.addData(artist) - if title != '': + if title: i = item.addChild('title') i.addData(title) - if source != '': + if source: i = item.addChild('source') i.addData(source) - if track != 0: + if track: i = item.addChild('track') i.addData(track) - if length != 0: + if length: i = item.addChild('length') i.addData(length) - if items is not None: + if items: item.addChild(payload=items) common.gajim.connections[account].send_pb_publish('', xmpp.NS_TUNE, item, @@ -570,20 +571,14 @@ def delete_pep(jid, name): if jid == common.gajim.get_jid_from_account(name): acc = common.gajim.connections[name] - del acc.activity acc.activity = {} user_send_tune(name) - del acc.tune acc.tune = {} - del acc.mood acc.mood = {} for contact in common.gajim.contacts.get_contacts(name, user): - del contact.activity contact.activity = {} - del contact.tune contact.tune = {} - del contact.mood contact.mood = {} if jid == common.gajim.get_jid_from_account(name): diff --git a/src/roster_window.py b/src/roster_window.py index e425c9cb3..046684b57 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -1934,8 +1934,7 @@ class RosterWindow: gajim.connections[account].send_custom_status(status, txt, to) else: if status in ('invisible', 'offline'): - pep.delete_pep(gajim.get_jid_from_account(account), \ - account) + pep.delete_pep(gajim.get_jid_from_account(account), account) was_invisible = gajim.connections[account].connected == \ gajim.SHOW_LIST.index('invisible') gajim.connections[account].change_status(status, txt, auto) From aa53988fd18d1f7f2b8d58bd5dd88c895c40331d Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Sun, 15 Nov 2009 23:23:56 +0100 Subject: [PATCH 18/20] Similar to update_pep, unify towards draw_pep of the RosterWindow. --- src/chat_control.py | 4 +++- src/common/pep.py | 4 +--- src/gui_interface.py | 18 +++++------------- src/roster_window.py | 40 +++++++++++++++++++++++++--------------- 4 files changed, 34 insertions(+), 32 deletions(-) diff --git a/src/chat_control.py b/src/chat_control.py index d9607c4b5..9c491b9e1 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -1430,12 +1430,14 @@ class ChatControl(ChatControlBase): self._convert_to_gc_button.set_sensitive(False) def update_all_pep_types(self): - for pep_type in ('tune', 'mood', 'activity'): + for pep_type in self._pep_images: self.update_pep(pep_type) def update_pep(self, pep_type): if isinstance(self.contact, GC_Contact): return + if pep_type not in self._pep_images: + return pep = self.contact.pep img = self._pep_images[pep_type] if pep_type in pep: diff --git a/src/common/pep.py b/src/common/pep.py index e0394ce61..85e72d8ea 100644 --- a/src/common/pep.py +++ b/src/common/pep.py @@ -584,9 +584,7 @@ def delete_pep(jid, name): if jid == common.gajim.get_jid_from_account(name): common.gajim.interface.roster.draw_account(name) - common.gajim.interface.roster.draw_activity(user, name) - common.gajim.interface.roster.draw_tune(user, name) - common.gajim.interface.roster.draw_mood(user, name) + common.gajim.interface.roster.draw_all_pep_types(jid, name) ctrl = common.gajim.interface.msg_win_mgr.get_control(user, name) if ctrl: ctrl.update_all_pep_types() diff --git a/src/gui_interface.py b/src/gui_interface.py index ec093b03b..f33e769e3 100644 --- a/src/gui_interface.py +++ b/src/gui_interface.py @@ -1998,25 +1998,17 @@ class Interface: if jid == common.gajim.get_jid_from_account(account): self.roster.draw_account(account) - if pep_type == 'mood': - self.roster.draw_mood(jid, account) - if ctrl: - ctrl.update_pep(pep_type) - elif pep_type == 'tune': - self.roster.draw_tune(jid, account) - if ctrl: - ctrl.update_pep(pep_type) - elif pep_type == 'activity': - self.roster.draw_activity(jid, account) - if ctrl: - ctrl.update_pep(pep_type) - elif pep_type == 'nickname': + if pep_type == 'nickname': self.roster.draw_contact(jid, account) if ctrl: ctrl.update_ui() win = ctrl.parent_win win.redraw_tab(ctrl) win.show_title() + else: + self.roster.draw_pep(jid, account, pep_type) + if ctrl: + ctrl.update_pep(pep_type) def register_handler(self, event, handler): if event not in self.handlers: diff --git a/src/roster_window.py b/src/roster_window.py index 046684b57..2745a3365 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -1242,19 +1242,27 @@ class RosterWindow: return False - def draw_mood(self, jid, account): - if gajim.config.get('show_mood_in_roster'): - self._draw_pep(jid, account, 'mood', C_MOOD_PIXBUF) - - def draw_activity(self, jid, account): - if gajim.config.get('show_activity_in_roster'): - self._draw_pep(jid, account, 'activity', C_ACTIVITY_PIXBUF) - - def draw_tune(self, jid, account): - if gajim.config.get('show_tunes_in_roster'): - self._draw_pep(jid, account, 'tune', C_TUNE_PIXBUF) + def _is_pep_shown_in_roster(self, pep_type): + if pep_type == 'mood': + return gajim.config.get('show_mood_in_roster') + elif pep_type == 'activity': + return gajim.config.get('show_activity_in_roster') + elif pep_type == 'tune': + return gajim.config.get('show_tunes_in_roster') + else: + return False + + def draw_all_pep_types(self, jid, account): + for pep_type in self._pep_type_to_model_column: + self.draw_pep(jid, account, pep_type) - def _draw_pep(self, jid, account, pep_type, model_column): + def draw_pep(self, jid, account, pep_type): + if pep_type not in self._pep_type_to_model_column: + return + if not self._is_pep_shown_in_roster(pep_type): + return + + model_column = self._pep_type_to_model_column[pep_type] iters = self._get_contact_iter(jid, account, model=self.model) if not iters: return @@ -1285,9 +1293,7 @@ class RosterWindow: def draw_completely(self, jid, account): self.draw_contact(jid, account) - self.draw_mood(jid, account) - self.draw_activity(jid, account) - self.draw_tune(jid, account) + self.draw_all_pep_types(jid, account) self.draw_avatar(jid, account) def adjust_and_draw_contact_context(self, jid, account): @@ -5753,6 +5759,10 @@ class RosterWindow: col.add_attribute(render_pixbuf, 'pixbuf', C_TUNE_PIXBUF) col.set_cell_data_func(render_pixbuf, self._fill_pep_pixbuf_renderer, C_TUNE_PIXBUF) + + self._pep_type_to_model_column = {'mood': C_MOOD_PIXBUF, + 'activity': C_ACTIVITY_PIXBUF, + 'tune': C_ACTIVITY_PIXBUF} if gajim.config.get('avatar_position_in_roster') == 'right': add_avatar_renderer() From a3ea00f4ea349b51b172a9f187842e3a3b6d4f4c Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Sun, 15 Nov 2009 23:52:43 +0100 Subject: [PATCH 19/20] Remove different dicts for tune, activity and mood and from now on only use the common 'pep' dict. The pep dict contacts the different UserPEP classes. --- src/common/connection.py | 3 --- src/common/contacts.py | 21 +++++++++--------- src/common/pep.py | 25 ++++++---------------- src/common/zeroconf/connection_zeroconf.py | 4 +--- src/roster_window.py | 9 ++++---- test/lib/gajim_mocks.py | 4 +--- 6 files changed, 22 insertions(+), 44 deletions(-) diff --git a/src/common/connection.py b/src/common/connection.py index 90df73d08..e2b6d2166 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -168,9 +168,6 @@ class Connection(ConnectionHandlers): self.pubsub_supported = False self.pubsub_publish_options_supported = False self.pep_supported = False - self.mood = {} - self.tune = {} - self.activity = {} self.pep = {} # Do we continue connection when we get roster (send presence,get vcard..) self.continue_connect_info = None diff --git a/src/common/contacts.py b/src/common/contacts.py index b8b039288..d012558bf 100644 --- a/src/common/contacts.py +++ b/src/common/contacts.py @@ -94,7 +94,7 @@ class Contact(CommonContact): def __init__(self, jid, account, name='', groups=[], show='', status='', sub='', ask='', resource='', priority=0, keyID='', client_caps=None, our_chatstate=None, chatstate=None, last_status_time=None, msg_id = None, - composing_xep=None, mood={}, tune={}, activity={}): + composing_xep=None): CommonContact.__init__(self, jid, account, resource, show, status, name, our_chatstate, composing_xep, chatstate, client_caps=client_caps) @@ -111,9 +111,6 @@ class Contact(CommonContact): self.last_status_time = last_status_time self.pep = {} - self.mood = mood.copy() - self.tune = tune.copy() - self.activity = activity.copy() def get_full_jid(self): if self.resource: @@ -229,23 +226,25 @@ class Contacts: def create_contact(self, jid, account, name='', groups=[], show='', status='', sub='', ask='', resource='', priority=0, keyID='', client_caps=None, our_chatstate=None, chatstate=None, last_status_time=None, - composing_xep=None, mood={}, tune={}, activity={}): + composing_xep=None): account = self._accounts.get(account, account) # Use Account object if available return Contact(jid=jid, account=account, name=name, groups=groups, show=show, status=status, sub=sub, ask=ask, resource=resource, priority=priority, keyID=keyID, client_caps=client_caps, our_chatstate=our_chatstate, chatstate=chatstate, last_status_time=last_status_time, - composing_xep=composing_xep, mood=mood, tune=tune, activity=activity) + composing_xep=composing_xep) - def create_self_contact(self, jid, account, resource, show, status, priority, keyID=''): + def create_self_contact(self, jid, account, resource, show, status, priority, + name='', keyID=''): conn = common.gajim.connections[account] - nick = common.gajim.nicks[account] + nick = name or common.gajim.nicks[account] account = self._accounts.get(account, account) # Use Account object if available - return self.create_contact(jid=jid, account=account, + self_contact = self.create_contact(jid=jid, account=account, name=nick, groups=['self_contact'], show=show, status=status, sub='both', ask='none', priority=priority, keyID=keyID, - resource=resource, mood=conn.mood, tune=conn.tune, - activity=conn.activity) + resource=resource) + self_contact.pep = conn.pep + return self_contact def create_not_in_roster_contact(self, jid, account, resource='', name='', keyID=''): account = self._accounts.get(account, account) # Use Account object if available diff --git a/src/common/pep.py b/src/common/pep.py index 85e72d8ea..fa4a31a3a 100644 --- a/src/common/pep.py +++ b/src/common/pep.py @@ -237,24 +237,16 @@ class AbstractPEP(object): '''To be implemented by subclasses''' raise NotImplementedError - def _update_contacts(self, jid, account): - dict = {} if self._retracted else self._pep_specific_data - - for contact in common.gajim.contacts.get_contacts(account, jid): - setattr(contact, self.type, dict) - + def _update_contacts(self, jid, account): + for contact in common.gajim.contacts.get_contacts(account, jid): if self._retracted: if self.type in contact.pep: del contact.pep[self.type] else: contact.pep[self.type] = self - def _update_account(self, account): - dict = {} if self._retracted else self._pep_specific_data - - acc = common.gajim.connections[account] - setattr(acc, self.type, dict) - + def _update_account(self, account): + acc = common.gajim.connections[account] if self._retracted: if self.type in acc.pep: del acc.pep[self.type] @@ -571,15 +563,10 @@ def delete_pep(jid, name): if jid == common.gajim.get_jid_from_account(name): acc = common.gajim.connections[name] - acc.activity = {} - user_send_tune(name) - acc.tune = {} - acc.mood = {} + acc.pep = {} for contact in common.gajim.contacts.get_contacts(name, user): - contact.activity = {} - contact.tune = {} - contact.mood = {} + contact.pep = {} if jid == common.gajim.get_jid_from_account(name): common.gajim.interface.roster.draw_account(name) diff --git a/src/common/zeroconf/connection_zeroconf.py b/src/common/zeroconf/connection_zeroconf.py index c5a93b4b8..26725f5f0 100644 --- a/src/common/zeroconf/connection_zeroconf.py +++ b/src/common/zeroconf/connection_zeroconf.py @@ -88,9 +88,7 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): self.no_log_for = False self.pep_supported = False - self.mood = {} - self.tune = {} - self.activity = {} + self.pep = {} # Do we continue connection when we get roster (send presence,get vcard...) self.continue_connect_info = None if gajim.HAVE_GPG: diff --git a/src/roster_window.py b/src/roster_window.py index 2745a3365..17697b3dd 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -2432,11 +2432,10 @@ class RosterWindow: account_name = account if gajim.account_is_connected(account): account_name += ' (%s/%s)' % (repr(nbr_on), repr(nbr_total)) - contact = gajim.contacts.create_contact(jid=jid, account=account, name=account_name, - show=connection.get_status(), sub='', status=connection.status, - resource=connection.server_resource, - priority=connection.priority, mood=connection.mood, - tune=connection.tune, activity=connection.activity) + contact = gajim.contacts.create_self_contact(jid=jid, account=account, + name=account_name, show=connection.get_status(), + status=connection.status, resource=connection.server_resource, + priority=connection.priority) if gajim.connections[account].gpg: contact.keyID = gajim.config.get_per('accounts', connection.name, 'keyid') diff --git a/test/lib/gajim_mocks.py b/test/lib/gajim_mocks.py index d45e488e6..9607a77c9 100644 --- a/test/lib/gajim_mocks.py +++ b/test/lib/gajim_mocks.py @@ -14,9 +14,7 @@ class MockConnection(Mock, ConnectionHandlersBase): self.name = account self.connected = 2 - self.mood = {} - self.activity = {} - self.tune = {} + self.pep = {} self.blocked_contacts = {} self.blocked_groups = {} self.sessions = {} From 10428555aa87d512def8274bc06abb1de87f2ce7 Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Mon, 16 Nov 2009 19:31:17 +0100 Subject: [PATCH 20/20] Various pep-related cleanups. Most important change is that pep send/retract functions no reside on the ConnectionPEP object. --- src/common/pep.py | 208 +++++++++++++++++++----------------------- src/gui_interface.py | 22 ++--- src/profile_window.py | 3 +- src/roster_window.py | 74 +++++++-------- 4 files changed, 139 insertions(+), 168 deletions(-) diff --git a/src/common/pep.py b/src/common/pep.py index fa4a31a3a..21861c5e2 100644 --- a/src/common/pep.py +++ b/src/common/pep.py @@ -400,17 +400,17 @@ class UserActivityPEP(AbstractPEP): text = pep['text'] if 'text' in pep else None if activity in ACTIVITIES: - # Translate standard activities - if subactivity in ACTIVITIES[activity]: - subactivity = ACTIVITIES[activity][subactivity] - activity = ACTIVITIES[activity]['category'] + # Translate standard activities + if subactivity in ACTIVITIES[activity]: + subactivity = ACTIVITIES[activity][subactivity] + activity = ACTIVITIES[activity]['category'] markuptext = '' + gobject.markup_escape_text(activity) if subactivity: markuptext += ': ' + gobject.markup_escape_text(subactivity) markuptext += '' if text: - markuptext += ' (%s)' + gobject.markup_escape_text(text) + markuptext += ' (%s)' % gobject.markup_escape_text(text) return markuptext @@ -446,18 +446,17 @@ class UserNicknamePEP(AbstractPEP): common.gajim.nicks[account] = self._pep_specific_data -SUPPORTED_PERSONAL_USER_EVENTS = [UserMoodPEP, UserTunePEP, UserActivityPEP, UserNicknamePEP] +SUPPORTED_PERSONAL_USER_EVENTS = [UserMoodPEP, UserTunePEP, UserActivityPEP, + UserNicknamePEP] -class ConnectionPEP: - +class ConnectionPEP(object): + def _pubsubEventCB(self, xmpp_dispatcher, msg): ''' Called when we receive with pubsub event. ''' if msg.getTag('error'): log.warning('PubsubEventCB received error stanza') return - - # TODO: Logging? (actually services where logging would be useful, should - # TODO: allow to access archives remotely...) + jid = helpers.get_full_jid_from_iq(msg) event_tag = msg.getTag('event') @@ -467,114 +466,97 @@ class ConnectionPEP: self.dispatch('PEP_RECEIVED', (jid, pep.type)) items = event_tag.getTag('items') - if items is None: - return - - for item in items.getTags('item'): - entry = item.getTag('entry') - if entry: - # for each entry in feed (there shouldn't be more than one, - # but to be sure... - self.dispatch('ATOM_ENTRY', (atom.OldEntry(node=entry),)) - continue - # unknown type... probably user has another client who understands that event + if items: + for item in items.getTags('item'): + entry = item.getTag('entry') + if entry: + # for each entry in feed (there shouldn't be more than one, + # but to be sure... + self.dispatch('ATOM_ENTRY', (atom.OldEntry(node=entry),)) raise common.xmpp.NodeProcessed + + def send_activity(self, activity, subactivity=None, message=None): + if not self.pep_supported: + return + item = xmpp.Node('activity', {'xmlns': xmpp.NS_ACTIVITY}) + if activity: + i = item.addChild(activity) + if subactivity: + i.addChild(subactivity) + if message: + i = item.addChild('text') + i.addData(message) + self.send_pb_publish('', xmpp.NS_ACTIVITY, item, '0') + + def retract_activity(self): + if not self.pep_supported: + return + # not all server support retract, so send empty pep first + self.send_activity(None) + self.send_pb_retract('', xmpp.NS_ACTIVITY, '0') + def send_mood(self, mood, message=None): + if not self.pep_supported: + return + item = xmpp.Node('mood', {'xmlns': xmpp.NS_MOOD}) + if mood: + item.addChild(mood) + if message: + i = item.addChild('text') + i.addData(message) + self.send_pb_publish('', xmpp.NS_MOOD, item, '0') + + def retract_mood(self): + if not self.pep_supported: + return + self.send_mood(None) + self.send_pb_retract('', xmpp.NS_MOOD, '0') + + def send_tune(self, artist='', title='', source='', track=0, length=0, + items=None): + if not self.pep_supported: + return + item = xmpp.Node('tune', {'xmlns': xmpp.NS_TUNE}) + if artist: + i = item.addChild('artist') + i.addData(artist) + if title: + i = item.addChild('title') + i.addData(title) + if source: + i = item.addChild('source') + i.addData(source) + if track: + i = item.addChild('track') + i.addData(track) + if length: + i = item.addChild('length') + i.addData(length) + if items: + item.addChild(payload=items) + self.send_pb_publish('', xmpp.NS_TUNE, item, '0') -def user_send_mood(account, mood, message=''): - if not common.gajim.connections[account].pep_supported: - return - item = xmpp.Node('mood', {'xmlns': xmpp.NS_MOOD}) - if mood: - item.addChild(mood) - if message: - i = item.addChild('text') - i.addData(message) + def retract_tune(self): + if not self.pep_supported: + return + # not all server support retract, so send empty pep first + self.send_tune(None) + self.send_pb_retract('', xmpp.NS_TUNE, '0') - common.gajim.connections[account].send_pb_publish('', xmpp.NS_MOOD, item, - '0') + def send_nickname(self, nick): + if not self.pep_supported: + return + item = xmpp.Node('nick', {'xmlns': xmpp.NS_NICK}) + item.addData(nick) + self.send_pb_publish('', xmpp.NS_NICK, item, '0') -def user_send_activity(account, activity, subactivity='', message=''): - if not common.gajim.connections[account].pep_supported: - return - item = xmpp.Node('activity', {'xmlns': xmpp.NS_ACTIVITY}) - if activity: - i = item.addChild(activity) - if subactivity: - i.addChild(subactivity) - if message: - i = item.addChild('text') - i.addData(message) - - common.gajim.connections[account].send_pb_publish('', xmpp.NS_ACTIVITY, item, - '0') - -def user_send_tune(account, artist='', title='', source='', track=0, length=0, -items=None): - if not (common.gajim.config.get_per('accounts', account, 'publish_tune') and\ - common.gajim.connections[account].pep_supported): - return - item = xmpp.Node('tune', {'xmlns': xmpp.NS_TUNE}) - if artist: - i = item.addChild('artist') - i.addData(artist) - if title: - i = item.addChild('title') - i.addData(title) - if source: - i = item.addChild('source') - i.addData(source) - if track: - i = item.addChild('track') - i.addData(track) - if length: - i = item.addChild('length') - i.addData(length) - if items: - item.addChild(payload=items) - - common.gajim.connections[account].send_pb_publish('', xmpp.NS_TUNE, item, - '0') - -def user_send_nickname(account, nick): - if not common.gajim.connections[account].pep_supported: - return - item = xmpp.Node('nick', {'xmlns': xmpp.NS_NICK}) - item.addData(nick) - - common.gajim.connections[account].send_pb_publish('', xmpp.NS_NICK, item, - '0') - -def user_retract_mood(account): - common.gajim.connections[account].send_pb_retract('', xmpp.NS_MOOD, '0') - -def user_retract_activity(account): - common.gajim.connections[account].send_pb_retract('', xmpp.NS_ACTIVITY, '0') - -def user_retract_tune(account): - common.gajim.connections[account].send_pb_retract('', xmpp.NS_TUNE, '0') - -def user_retract_nickname(account): - common.gajim.connections[account].send_pb_retract('', xmpp.NS_NICK, '0') - -def delete_pep(jid, name): - user = common.gajim.get_room_and_nick_from_fjid(jid)[0] - - if jid == common.gajim.get_jid_from_account(name): - acc = common.gajim.connections[name] - acc.pep = {} - - for contact in common.gajim.contacts.get_contacts(name, user): - contact.pep = {} - - if jid == common.gajim.get_jid_from_account(name): - common.gajim.interface.roster.draw_account(name) - - common.gajim.interface.roster.draw_all_pep_types(jid, name) - ctrl = common.gajim.interface.msg_win_mgr.get_control(user, name) - if ctrl: - ctrl.update_all_pep_types() + def retract_nickname(self): + if not self.pep_supported: + return + # not all server support retract, so send empty pep first + self.send_tune(None) + self.send_pb_retract('', xmpp.NS_NICK, '0') # vim: se ts=3: diff --git a/src/gui_interface.py b/src/gui_interface.py index f33e769e3..98c1f3298 100644 --- a/src/gui_interface.py +++ b/src/gui_interface.py @@ -2796,33 +2796,27 @@ class Interface: listener.disconnect(self.music_track_changed_signal) self.music_track_changed_signal = None - def music_track_changed(self, unused_listener, music_track_info, account=''): - if account == '': + def music_track_changed(self, unused_listener, music_track_info, account=None): + if not account: accounts = gajim.connections.keys() else: accounts = [account] - if music_track_info is None: - artist = '' - title = '' - source = '' - elif hasattr(music_track_info, 'paused') and music_track_info.paused == 0: - artist = '' - title = '' - source = '' + + is_paused = hasattr(music_track_info, 'paused') and music_track_info.paused == 0 + if not music_track_info or is_paused: + artist = title = source = '' else: artist = music_track_info.artist title = music_track_info.title source = music_track_info.album for acct in accounts: - if acct not in gajim.connections: - continue if not gajim.account_is_connected(acct): continue - if not gajim.connections[acct].pep_supported: + if not gajim.config.get_per('accounts', acct, 'publish_tune'): continue if gajim.connections[acct].music_track_info == music_track_info: continue - pep.user_send_tune(acct, artist, title, source) + gajim.connections[acct].send_tune(artist, title, source) gajim.connections[acct].music_track_info = music_track_info def get_bg_fg_colors(self): diff --git a/src/profile_window.py b/src/profile_window.py index a417ede08..f3fe1faa4 100644 --- a/src/profile_window.py +++ b/src/profile_window.py @@ -322,8 +322,7 @@ class ProfileWindow: nick = '' if 'NICKNAME' in vcard_: nick = vcard_['NICKNAME'] - from common import pep - pep.user_send_nickname(self.account, nick) + gajim.connections[self.account].send_nickname(self.account, nick) if nick == '': nick = gajim.config.get_per('accounts', self.account, 'name') gajim.nicks[self.account] = nick diff --git a/src/roster_window.py b/src/roster_window.py index 17697b3dd..6cef52f35 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -1896,36 +1896,36 @@ class RosterWindow: self.send_status_continue(account, status, txt, auto, to) - def send_pep(self, account, pep_dict=None): - '''Sends pep information (activity, mood)''' - if not pep_dict: - return - # activity - if 'activity' in pep_dict and pep_dict['activity'] in pep.ACTIVITIES: + def send_pep(self, account, pep_dict): + connection = gajim.connections[account] + + if 'activity' in pep_dict: activity = pep_dict['activity'] - if 'subactivity' in pep_dict and \ - pep_dict['subactivity'] in pep.ACTIVITIES[activity]: - subactivity = pep_dict['subactivity'] - else: - subactivity = 'other' - if 'activity_text' in pep_dict: - activity_text = pep_dict['activity_text'] - else: - activity_text = '' - pep.user_send_activity(account, activity, subactivity, activity_text) + subactivity = pep_dict.get('subactivity', None) + activity_text = pep_dict.get('activity_text', None) + connection.send_activity(activity, subactivity, activity_text) else: - pep.user_send_activity(account, '') + connection.retract_activity() - # mood - if 'mood' in pep_dict and pep_dict['mood'] in pep.MOODS: + if 'mood' in pep_dict: mood = pep_dict['mood'] - if 'mood_text' in pep_dict: - mood_text = pep_dict['mood_text'] - else: - mood_text = '' - pep.user_send_mood(account, mood, mood_text) + mood_text = pep_dict.get('mood_text', None) + connection.send_mood(mood, mood_text) else: - pep.user_send_mood(account, '') + connection.retract_mood() + + def delete_pep(self, jid, account): + if jid == gajim.get_jid_from_account(account): + gajim.connections[account].pep = {} + self.draw_account(account) + + for contact in gajim.contacts.get_contacts(account, jid): + contact.pep = {} + + self.draw_all_pep_types(jid, account) + ctrl = gajim.interface.msg_win_mgr.get_control(jid, account) + if ctrl: + ctrl.update_all_pep_types() def send_status_continue(self, account, status, txt, auto, to): if gajim.account_is_connected(account) and not to: @@ -1940,7 +1940,7 @@ class RosterWindow: gajim.connections[account].send_custom_status(status, txt, to) else: if status in ('invisible', 'offline'): - pep.delete_pep(gajim.get_jid_from_account(account), account) + self.delete_pep(gajim.get_jid_from_account(account), account) was_invisible = gajim.connections[account].connected == \ gajim.SHOW_LIST.index('invisible') gajim.connections[account].change_status(status, txt, auto) @@ -2018,7 +2018,7 @@ class RosterWindow: contact_instances) if not keep_pep and contact.jid != gajim.get_jid_from_account(account) \ and not contact.is_groupchat(): - pep.delete_pep(contact.jid, account) + self.delete_pep(contact.jid, account) # Redraw everything and select the sender self.adjust_and_draw_contact_context(contact.jid, account) @@ -3318,23 +3318,19 @@ class RosterWindow: gajim.interface.instances['preferences'] = config.PreferencesWindow() def on_publish_tune_toggled(self, widget, account): - act = widget.get_active() - gajim.config.set_per('accounts', account, 'publish_tune', act) - if act: + active = widget.get_active() + gajim.config.set_per('accounts', account, 'publish_tune', active) + if active: gajim.interface.enable_music_listener() else: - # disable it only if no other account use it - for acct in gajim.connections: - if gajim.config.get_per('accounts', acct, 'publish_tune'): + gajim.connections[account].retract_tune() + # disable music listener only if no other account uses it + for acc in gajim.connections: + if gajim.config.get_per('accounts', acc, 'publish_tune'): break else: gajim.interface.disable_music_listener() - if gajim.connections[account].pep_supported: - # As many implementations don't support retracting items, we send a - # "Stopped" event first - pep.user_send_tune(account, '') - pep.user_retract_tune(account) helpers.update_optional_features(account) def on_pep_services_menuitem_activate(self, widget, account): @@ -5761,7 +5757,7 @@ class RosterWindow: self._pep_type_to_model_column = {'mood': C_MOOD_PIXBUF, 'activity': C_ACTIVITY_PIXBUF, - 'tune': C_ACTIVITY_PIXBUF} + 'tune': C_TUNE_PIXBUF} if gajim.config.get('avatar_position_in_roster') == 'right': add_avatar_renderer()