# HG changeset patch # User Goffi # Date 1423245666 -3600 # Node ID afc57b34c0a308e0376b112beb8ec8958ccd6319 # Parent ba73798317a753b15896105be0e77d1a8afc7f87 Quick Frontend (quick_widgets): added on_existing_widget in getOrCreateWidget (see docstring for more infos) + use of constants diff -r ba73798317a7 -r afc57b34c0a3 frontends/src/constants.py --- a/frontends/src/constants.py Fri Feb 06 18:54:44 2015 +0100 +++ b/frontends/src/constants.py Fri Feb 06 19:01:06 2015 +0100 @@ -62,6 +62,14 @@ # Roster GROUP_NOT_IN_ROSTER = D_('Not in roster') - #Chats + # Chats CHAT_ONE2ONE = 'one2one' CHAT_GROUP = 'group' + + # Widgets management + # FIXME: should be in quick_frontend.constant, but Libervia doesn't inherit from it + WIDGET_NEW = 'NEW' + WIDGET_KEEP = 'KEEP' + WIDGET_RAISE = 'RAISE' + WIDGET_RECREATE = 'RECREATE' + diff -r ba73798317a7 -r afc57b34c0a3 frontends/src/quick_frontend/quick_widgets.py --- a/frontends/src/quick_frontend/quick_widgets.py Fri Feb 06 18:54:44 2015 +0100 +++ b/frontends/src/quick_frontend/quick_widgets.py Fri Feb 06 19:01:06 2015 +0100 @@ -21,6 +21,7 @@ log = getLogger(__name__) from sat.core import exceptions +from sat_frontends.quick_frontend.constants import Const as C classes_map = {} @@ -40,6 +41,8 @@ Can be None if it's the base_cls itself which register """ classes_map[base_cls] = child_cls +class WidgetAlreadyExistsError(Exception): + pass class QuickWidgetsManager(object): @@ -95,15 +98,19 @@ if 'profile' key is present, it will be popped and put in 'profiles' if there is neither 'profile' nor 'profiles', None will be used for 'profiles' if 'on_new_widget' is present it can have the following values: - 'NEW_WIDGET' [default]: self.host.newWidget will be called on widget creation + C.WIDGET_NEW [default]: self.host.newWidget will be called on widget creation [callable]: this method will be called instead of self.host.newWidget None: do nothing + if 'on_existing_widget' is present it can have the following values: + C.WIDGET_KEEP [default]: return the existing widget + C.WIDGET_RAISE: raise WidgetAlreadyExistsError + C.WIDGET_RECREATE: create a new widget *WITH A NEW HASH* if 'force_hash' is present, the hash given in value will be used instead of the one returned by class_.getWidgetHash @return: a class_ instance, either new or already existing """ cls = self.getRealClass(class_) - # arguments management + ## arguments management ## _args = [self.host, target] + list(args) or [] # FIXME: check if it's really necessary to use optional args _kwargs = kwargs or {} if 'profiles' in _kwargs and 'profile' in _kwargs: @@ -114,7 +121,19 @@ if not 'profiles' in _kwargs: _kwargs['profiles'] = None - # we get the hash + #on_new_widget tell what to do for the new widget creation + try: + on_new_widget = _kwargs.pop('on_new_widget') + except KeyError: + on_new_widget = C.WIDGET_NEW + + #on_existing_widget tell what to do when the widget already exists + try: + on_existing_widget = _kwargs.pop('on_existing_widget') + except KeyError: + on_existing_widget = C.WIDGET_KEEP + + ## we get the hash ## try: hash_ = _kwargs.pop('force_hash') except KeyError: @@ -133,23 +152,45 @@ if widget is None: # we need to create a new widget - try: - #on_new_widget tell what to do for the new widget creation - on_new_widget = _kwargs.pop('on_new_widget') - except KeyError: - on_new_widget = 'NEW_WIDGET' - log.debug(u"Creating new widget for target {} {}".format(target, cls)) widget = cls(*_args, **_kwargs) widgets_map[hash_] = widget - if on_new_widget == 'NEW_WIDGET': + if on_new_widget == C.WIDGET_NEW: self.host.newWidget(widget) elif callable(on_new_widget): on_new_widget(widget) else: assert on_new_widget is None + else: + # the widget already exists + if on_existing_widget == C.WIDGET_RAISE: + raise WidgetAlreadyExistsError(hash_) + elif on_existing_widget == C.WIDGET_RECREATE: + # we use getOrCreateWidget to recreate the new widget + # /!\ we use args and kwargs and not _args and _kwargs because we need the original args + # we need to get rid of kwargs special options + new_kwargs = kwargs.copy() + try: + new_kwargs.pop('force_hash') # FIXME: we use pop instead of del here because pyjamas doesn't raise error on del + except KeyError: + pass + else: + raise ValueError("force_hash option can't be used with on_existing_widget=RECREATE") + # XXX: keep up-to-date if new special kwargs are added (i.e.: delete these keys here) + new_kwargs['on_new_widget'] = None + new_kwargs['on_existing_widget'] = C.WIDGET_RAISE + hash_idx = 1 + while True: + new_kwargs['force_hash'] = hash_ + "_new_instance_{}".format(hash_idx) + try: + widget = self.getOrCreateWidget(class_, target, *args, **new_kwargs) + except WidgetAlreadyExistsError: + hash_idx += 1 + else: + log.debug(u"Widget already exists, a new one has been recreated with hash {}".format(new_kwargs['force_hash'])) + break return widget