quick frontends: signal cache: if a signal arrives between the beginning of profile plugging, and the when the profile is actually ready, it is cached and replayed when the profile is ready.

This commit is contained in:
Goffi 2015-02-24 20:29:57 +01:00
commit 3ed295e7b1

View file

@ -204,6 +204,8 @@ class QuickApp(object):
"""
ProfileManager.host = self
self.profiles = ProfilesManager()
self.ready_profiles = set() # profiles which are connected and ready
self.signals_cache = {} # used to keep signal received between start of plug_profile and when the profile is actualy ready
self.contact_lists = {}
self.widgets = QuickWidgetsManager(self)
if check_options is not None:
@ -281,18 +283,18 @@ class QuickApp(object):
"""widgets currently visible (must be implemented by frontend)"""
raise NotImplementedError
def registerSignal(self, functionName, handler=None, iface="core", with_profile=True):
def registerSignal(self, function_name, handler=None, iface="core", with_profile=True):
"""Register a handler for a signal
@param functionName (str): name of the signal to handle
@param handler (instancemethod): method to call when the signal arrive, None for calling an automatically named handler (functionName + 'Handler')
@param function_name (str): name of the signal to handle
@param handler (instancemethod): method to call when the signal arrive, None for calling an automatically named handler (function_name + 'Handler')
@param iface (str): interface of the bridge to use ('core' or 'plugin')
@param with_profile (boolean): True if the signal concerns a specific profile, in that case the profile name has to be passed by the caller
"""
if handler is None:
handler = getattr(self, "{}{}".format(functionName, 'Handler'))
handler = getattr(self, "{}{}".format(function_name, 'Handler'))
if not with_profile:
self.bridge.register(functionName, handler, iface)
self.bridge.register(function_name, handler, iface)
return
def signalReceived(*args, **kwargs):
@ -301,10 +303,14 @@ class QuickApp(object):
if not args:
raise exceptions.ProfileNotSetError
profile = args[-1]
if profile is not None and not self.check_profile(profile):
return # we ignore signal for profiles we don't manage
if profile is not None:
if not self.check_profile(profile):
if profile in self.profiles:
# profile is not ready but is in self.profiles, that's mean that it's being connecting and we need to cache the signal
self.signals_cache.setdefault(profile, []).append((function_name, handler, args, kwargs))
return # we ignore signal for profiles we don't manage
handler(*args, **kwargs)
self.bridge.register(functionName, signalReceived, iface)
self.bridge.register(function_name, signalReceived, iface)
def addListener(self, type_, callback, profiles_filter=None):
"""Add a listener for an event
@ -354,8 +360,8 @@ class QuickApp(object):
listener(*args, **kwargs)
def check_profile(self, profile):
"""Tell if the profile is currently followed by the application"""
return profile in self.profiles
"""Tell if the profile is currently followed by the application, and ready"""
return profile in self.ready_profiles
def postInit(self, profile_manager):
"""Must be called after initialization is done, do all automatic task (auto plug profile)
@ -368,9 +374,17 @@ class QuickApp(object):
def profilePlugged(self, profile):
"""Method called when the profile is fully plugged, to launch frontend specific workflow
/!\ if you override the method and don't call the parent, be sure to add the profile to ready_profiles !
if you don't, all signals will stay in cache
@param profile(unicode): %(doc_profile)s
"""
pass
self.ready_profiles.add(profile)
# profile is ready, we can call send signals that where is cache
cached_signals = self.signals_cache.pop(profile, [])
for function_name, handler, args, kwargs in cached_signals:
log.debug(u"Calling cached signal [%s] with args %s and kwargs %s" % (function_name, args, kwargs))
def asyncConnect(self, profile, callback=None, errback=None):
if not callback: