Mercurial > libervia-backend
comparison frontends/src/quick_frontend/quick_widgets.py @ 1301:afc57b34c0a3 frontends_multi_profiles
Quick Frontend (quick_widgets): added on_existing_widget in getOrCreateWidget (see docstring for more infos) + use of constants
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 06 Feb 2015 19:01:06 +0100 |
parents | faa1129559b8 |
children | d3ef3894254d |
comparison
equal
deleted
inserted
replaced
1300:ba73798317a7 | 1301:afc57b34c0a3 |
---|---|
19 | 19 |
20 from sat.core.log import getLogger | 20 from sat.core.log import getLogger |
21 log = getLogger(__name__) | 21 log = getLogger(__name__) |
22 from sat.core import exceptions | 22 from sat.core import exceptions |
23 | 23 |
24 from sat_frontends.quick_frontend.constants import Const as C | |
24 | 25 |
25 classes_map = {} | 26 classes_map = {} |
26 | 27 |
27 | 28 |
28 try: | 29 try: |
38 @param base_cls: "Quick..." base class (like QuickChat or QuickContact), must inherit from QuickWidget | 39 @param base_cls: "Quick..." base class (like QuickChat or QuickContact), must inherit from QuickWidget |
39 @param child_cls: inherited class to use when Quick... class is requested, must inherit from base_cls. | 40 @param child_cls: inherited class to use when Quick... class is requested, must inherit from base_cls. |
40 Can be None if it's the base_cls itself which register | 41 Can be None if it's the base_cls itself which register |
41 """ | 42 """ |
42 classes_map[base_cls] = child_cls | 43 classes_map[base_cls] = child_cls |
44 class WidgetAlreadyExistsError(Exception): | |
45 pass | |
43 | 46 |
44 | 47 |
45 class QuickWidgetsManager(object): | 48 class QuickWidgetsManager(object): |
46 """This class is used to manage all the widgets of a frontend | 49 """This class is used to manage all the widgets of a frontend |
47 A widget can be a window, a graphical thing, or someting else depending of the frontend""" | 50 A widget can be a window, a graphical thing, or someting else depending of the frontend""" |
93 @param args(list): optional args to create a new instance of class_ | 96 @param args(list): optional args to create a new instance of class_ |
94 @param kwargs(list): optional kwargs to create anew instance of class_ | 97 @param kwargs(list): optional kwargs to create anew instance of class_ |
95 if 'profile' key is present, it will be popped and put in 'profiles' | 98 if 'profile' key is present, it will be popped and put in 'profiles' |
96 if there is neither 'profile' nor 'profiles', None will be used for 'profiles' | 99 if there is neither 'profile' nor 'profiles', None will be used for 'profiles' |
97 if 'on_new_widget' is present it can have the following values: | 100 if 'on_new_widget' is present it can have the following values: |
98 'NEW_WIDGET' [default]: self.host.newWidget will be called on widget creation | 101 C.WIDGET_NEW [default]: self.host.newWidget will be called on widget creation |
99 [callable]: this method will be called instead of self.host.newWidget | 102 [callable]: this method will be called instead of self.host.newWidget |
100 None: do nothing | 103 None: do nothing |
104 if 'on_existing_widget' is present it can have the following values: | |
105 C.WIDGET_KEEP [default]: return the existing widget | |
106 C.WIDGET_RAISE: raise WidgetAlreadyExistsError | |
107 C.WIDGET_RECREATE: create a new widget *WITH A NEW HASH* | |
101 if 'force_hash' is present, the hash given in value will be used instead of the one returned by class_.getWidgetHash | 108 if 'force_hash' is present, the hash given in value will be used instead of the one returned by class_.getWidgetHash |
102 @return: a class_ instance, either new or already existing | 109 @return: a class_ instance, either new or already existing |
103 """ | 110 """ |
104 cls = self.getRealClass(class_) | 111 cls = self.getRealClass(class_) |
105 | 112 |
106 # arguments management | 113 ## arguments management ## |
107 _args = [self.host, target] + list(args) or [] # FIXME: check if it's really necessary to use optional args | 114 _args = [self.host, target] + list(args) or [] # FIXME: check if it's really necessary to use optional args |
108 _kwargs = kwargs or {} | 115 _kwargs = kwargs or {} |
109 if 'profiles' in _kwargs and 'profile' in _kwargs: | 116 if 'profiles' in _kwargs and 'profile' in _kwargs: |
110 raise ValueError("You can't have 'profile' and 'profiles' keys at the same time") | 117 raise ValueError("You can't have 'profile' and 'profiles' keys at the same time") |
111 try: | 118 try: |
112 _kwargs['profiles'] = _kwargs.pop('profile') | 119 _kwargs['profiles'] = _kwargs.pop('profile') |
113 except KeyError: | 120 except KeyError: |
114 if not 'profiles' in _kwargs: | 121 if not 'profiles' in _kwargs: |
115 _kwargs['profiles'] = None | 122 _kwargs['profiles'] = None |
116 | 123 |
117 # we get the hash | 124 #on_new_widget tell what to do for the new widget creation |
125 try: | |
126 on_new_widget = _kwargs.pop('on_new_widget') | |
127 except KeyError: | |
128 on_new_widget = C.WIDGET_NEW | |
129 | |
130 #on_existing_widget tell what to do when the widget already exists | |
131 try: | |
132 on_existing_widget = _kwargs.pop('on_existing_widget') | |
133 except KeyError: | |
134 on_existing_widget = C.WIDGET_KEEP | |
135 | |
136 ## we get the hash ## | |
118 try: | 137 try: |
119 hash_ = _kwargs.pop('force_hash') | 138 hash_ = _kwargs.pop('force_hash') |
120 except KeyError: | 139 except KeyError: |
121 hash_ = cls.getWidgetHash(target, _kwargs['profiles']) | 140 hash_ = cls.getWidgetHash(target, _kwargs['profiles']) |
122 | 141 |
131 except KeyError: | 150 except KeyError: |
132 widget = None | 151 widget = None |
133 | 152 |
134 if widget is None: | 153 if widget is None: |
135 # we need to create a new widget | 154 # we need to create a new widget |
136 try: | |
137 #on_new_widget tell what to do for the new widget creation | |
138 on_new_widget = _kwargs.pop('on_new_widget') | |
139 except KeyError: | |
140 on_new_widget = 'NEW_WIDGET' | |
141 | |
142 log.debug(u"Creating new widget for target {} {}".format(target, cls)) | 155 log.debug(u"Creating new widget for target {} {}".format(target, cls)) |
143 widget = cls(*_args, **_kwargs) | 156 widget = cls(*_args, **_kwargs) |
144 widgets_map[hash_] = widget | 157 widgets_map[hash_] = widget |
145 | 158 |
146 if on_new_widget == 'NEW_WIDGET': | 159 if on_new_widget == C.WIDGET_NEW: |
147 self.host.newWidget(widget) | 160 self.host.newWidget(widget) |
148 elif callable(on_new_widget): | 161 elif callable(on_new_widget): |
149 on_new_widget(widget) | 162 on_new_widget(widget) |
150 else: | 163 else: |
151 assert on_new_widget is None | 164 assert on_new_widget is None |
152 | 165 else: |
166 # the widget already exists | |
167 if on_existing_widget == C.WIDGET_RAISE: | |
168 raise WidgetAlreadyExistsError(hash_) | |
169 elif on_existing_widget == C.WIDGET_RECREATE: | |
170 # we use getOrCreateWidget to recreate the new widget | |
171 # /!\ we use args and kwargs and not _args and _kwargs because we need the original args | |
172 # we need to get rid of kwargs special options | |
173 new_kwargs = kwargs.copy() | |
174 try: | |
175 new_kwargs.pop('force_hash') # FIXME: we use pop instead of del here because pyjamas doesn't raise error on del | |
176 except KeyError: | |
177 pass | |
178 else: | |
179 raise ValueError("force_hash option can't be used with on_existing_widget=RECREATE") | |
180 | |
181 # XXX: keep up-to-date if new special kwargs are added (i.e.: delete these keys here) | |
182 new_kwargs['on_new_widget'] = None | |
183 new_kwargs['on_existing_widget'] = C.WIDGET_RAISE | |
184 hash_idx = 1 | |
185 while True: | |
186 new_kwargs['force_hash'] = hash_ + "_new_instance_{}".format(hash_idx) | |
187 try: | |
188 widget = self.getOrCreateWidget(class_, target, *args, **new_kwargs) | |
189 except WidgetAlreadyExistsError: | |
190 hash_idx += 1 | |
191 else: | |
192 log.debug(u"Widget already exists, a new one has been recreated with hash {}".format(new_kwargs['force_hash'])) | |
193 break | |
153 return widget | 194 return widget |
154 | 195 |
155 | 196 |
156 class QuickWidget(object): | 197 class QuickWidget(object): |
157 """generic widget base""" | 198 """generic widget base""" |