comparison frontends/src/quick_frontend/quick_app.py @ 1331:7fa07c7b0761 frontends_multi_profiles

quick_frontend (quick_app): addListener takes a profiles_filter argument to check the profile before calling a listener (profile must be passed right after the event type in callListeners)
author souliane <souliane@mailoo.org>
date Sun, 22 Feb 2015 20:39:33 +0100
parents f8bd40509a2d
children 0f92b6a150ff
comparison
equal deleted inserted replaced
1330:22fce2e51c70 1331:7fa07c7b0761
15 # GNU Affero General Public License for more details. 15 # GNU Affero General Public License for more details.
16 16
17 # You should have received a copy of the GNU Affero General Public License 17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 19
20 from sat.core.i18n import _
21 import sys
22 from sat.core.log import getLogger 20 from sat.core.log import getLogger
23 log = getLogger(__name__) 21 log = getLogger(__name__)
22
23 from sat.core.i18n import _
24 from sat.core import exceptions 24 from sat.core import exceptions
25
25 from sat_frontends.tools import jid 26 from sat_frontends.tools import jid
26 from sat_frontends.quick_frontend.quick_widgets import QuickWidgetsManager 27 from sat_frontends.quick_frontend.quick_widgets import QuickWidgetsManager
27 from sat_frontends.quick_frontend import quick_chat 28 from sat_frontends.quick_frontend import quick_chat
28
29 from sat_frontends.quick_frontend.constants import Const as C 29 from sat_frontends.quick_frontend.constants import Const as C
30 30
31 import sys
32 from collections import OrderedDict
31 33
32 try: 34 try:
33 # FIXME: to be removed when an acceptable solution is here 35 # FIXME: to be removed when an acceptable solution is here
34 unicode('') # XXX: unicode doesn't exist in pyjamas 36 unicode('') # XXX: unicode doesn't exist in pyjamas
35 except (TypeError, AttributeError): # Error raised is not the same depending on pyjsbuild options 37 except (TypeError, AttributeError): # Error raised is not the same depending on pyjsbuild options
292 if profile is not None and not self.check_profile(profile): 294 if profile is not None and not self.check_profile(profile):
293 return # we ignore signal for profiles we don't manage 295 return # we ignore signal for profiles we don't manage
294 handler(*args, **kwargs) 296 handler(*args, **kwargs)
295 self.bridge.register(functionName, signalReceived, iface) 297 self.bridge.register(functionName, signalReceived, iface)
296 298
297 def addListener(self, type_, callback): 299 def addListener(self, type_, callback, profiles_filter=None):
298 """Add a listener for an event 300 """Add a listener for an event
299 301
300 /!\ don't forget to remove listener when not used anymore (e.g. if you delete a widget) 302 /!\ don't forget to remove listener when not used anymore (e.g. if you delete a widget)
301 @param type_: type of event, can be: 303 @param type_: type of event, can be:
302 - avatar: called when avatar data is updated 304 - avatar: called when avatar data is updated
303 args: (entity, avatar file, profile) 305 args: (entity, avatar file)
306 - presence: called when a presence is received
307 args: (entity, show, priority, statuses)
304 @param callback: method to call on event 308 @param callback: method to call on event
309 @param profiles_filter (set[unicode]): if set and not empty, the
310 listener will be callable only by one of the given profiles.
305 """ 311 """
306 assert type_ in C.LISTENERS 312 assert type_ in C.LISTENERS
307 self._listeners.setdefault(type_, []).append(callback) 313 self._listeners.setdefault(type_, OrderedDict())[callback] = profiles_filter
308 314
309 def removeListener(self, type_, callback): 315 def removeListener(self, type_, callback):
310 """Remove a callback from listeners 316 """Remove a callback from listeners
311 317
312 @param type_: same as for [addListener] 318 @param type_: same as for [addListener]
313 @param callback: callback to remove 319 @param callback: callback to remove
314 """ 320 """
315 assert type_ in C.LISTENERS 321 assert type_ in C.LISTENERS
316 self._listeners[type_].remove(callback) 322 self._listeners[type_].pop(callback)
317 323
318 def callListeners(self, type_, *args): 324 def callListeners(self, type_, profile, *args):
319 """Call all methods which listen of type_ event 325 """Call the methods which listen type_ event. If a profiles filter has
326 been register with a listener and profile argument is not None, the
327 listener will be called only if profile is in the profiles filter list.
320 328
321 @param type_: same as for [addListener] 329 @param type_: same as for [addListener]
330 @param profile (unicode): %(doc_profile)s
322 @param *args: arguments sent to callback 331 @param *args: arguments sent to callback
323 """ 332 """
324 assert type_ in C.LISTENERS 333 assert type_ in C.LISTENERS
325 try: 334 try:
326 listeners = self._listeners[type_] 335 listeners = self._listeners[type_]
327 except KeyError: 336 except KeyError:
328 pass 337 pass
329 else: 338 else:
330 for listener in listeners: 339 for listener, profiles_filter in listeners.iteritems():
331 listener(*args) 340 if profile is None or not profiles_filter or profile in profiles_filter:
341 listener(*args)
332 342
333 def check_profile(self, profile): 343 def check_profile(self, profile):
334 """Tell if the profile is currently followed by the application""" 344 """Tell if the profile is currently followed by the application"""
335 return profile in self.profiles 345 return profile in self.profiles
336 346
461 # #FIXME: must be moved in a plugin 471 # #FIXME: must be moved in a plugin
462 # if entity.bare in self.profiles[profile].data.get('watched',[]) and not entity.bare in self.profiles[profile]['onlineContact']: 472 # if entity.bare in self.profiles[profile].data.get('watched',[]) and not entity.bare in self.profiles[profile]['onlineContact']:
463 # self.showAlert(_("Watched jid [%s] is connected !") % entity.bare) 473 # self.showAlert(_("Watched jid [%s] is connected !") % entity.bare)
464 474
465 self.contact_lists[profile].updatePresence(entity, show, priority, statuses) 475 self.contact_lists[profile].updatePresence(entity, show, priority, statuses)
466 self.callListeners('presence', entity, show, priority, statuses, profile) 476 self.callListeners('presence', profile, entity, show, priority, statuses)
467 477
468 def roomJoinedHandler(self, room_jid_s, room_nicks, user_nick, profile): 478 def roomJoinedHandler(self, room_jid_s, room_nicks, user_nick, profile):
469 """Called when a MUC room is joined""" 479 """Called when a MUC room is joined"""
470 log.debug("Room [%(room_jid)s] joined by %(profile)s, users presents:%(users)s" % {'room_jid': room_jid_s, 'profile': profile, 'users': room_nicks}) 480 log.debug("Room [%(room_jid)s] joined by %(profile)s, users presents:%(users)s" % {'room_jid': room_jid_s, 'profile': profile, 'users': room_nicks})
471 room_jid = jid.JID(room_jid_s) 481 room_jid = jid.JID(room_jid_s)
654 self.contact_lists[profile].setCache(entity, 'nick', value) 664 self.contact_lists[profile].setCache(entity, 'nick', value)
655 elif key == "avatar": 665 elif key == "avatar":
656 if entity in self.contact_lists[profile]: 666 if entity in self.contact_lists[profile]:
657 def gotFilename(filename): 667 def gotFilename(filename):
658 self.contact_lists[profile].setCache(entity, 'avatar', filename) 668 self.contact_lists[profile].setCache(entity, 'avatar', filename)
659 self.callListeners('avatar', entity, filename, profile) 669 self.callListeners('avatar', profile, entity, filename)
660 self.bridge.getAvatarFile(value, callback=gotFilename) 670 self.bridge.getAvatarFile(value, callback=gotFilename)
661 671
662 def askConfirmationHandler(self, confirm_id, confirm_type, data, profile): 672 def askConfirmationHandler(self, confirm_id, confirm_type, data, profile):
663 raise NotImplementedError 673 raise NotImplementedError
664 674