Mercurial > libervia-backend
comparison sat_frontends/quick_frontend/quick_menus.py @ 2624:56f94936df1e
code style reformatting using black
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 27 Jun 2018 20:14:46 +0200 |
parents | 26edcf3a30eb |
children | 003b8b4b56a7 |
comparison
equal
deleted
inserted
replaced
2623:49533de4540b | 2624:56f94936df1e |
---|---|
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 try: | 20 try: |
21 # FIXME: to be removed when an acceptable solution is here | 21 # FIXME: to be removed when an acceptable solution is here |
22 unicode('') # XXX: unicode doesn't exist in pyjamas | 22 unicode("") # XXX: unicode doesn't exist in pyjamas |
23 except (TypeError, AttributeError): # Error raised is not the same depending on pyjsbuild options | 23 except ( |
24 TypeError, | |
25 AttributeError, | |
26 ): # Error raised is not the same depending on pyjsbuild options | |
24 unicode = str | 27 unicode = str |
25 | 28 |
26 from sat.core.log import getLogger | 29 from sat.core.log import getLogger |
27 from sat.core.i18n import _, languageSwitch | 30 from sat.core.i18n import _, languageSwitch |
31 | |
28 log = getLogger(__name__) | 32 log = getLogger(__name__) |
29 from sat_frontends.quick_frontend.constants import Const as C | 33 from sat_frontends.quick_frontend.constants import Const as C |
30 from collections import OrderedDict | 34 from collections import OrderedDict |
31 | 35 |
32 | 36 |
33 ## items ## | 37 ## items ## |
34 | 38 |
39 | |
35 class MenuBase(object): | 40 class MenuBase(object): |
36 ACTIVE=True | 41 ACTIVE = True |
37 | 42 |
38 def __init__(self, name, extra=None): | 43 def __init__(self, name, extra=None): |
39 """ | 44 """ |
40 @param name(unicode): canonical name of the item | 45 @param name(unicode): canonical name of the item |
41 @param extra(dict[unicode, unicode], None): same as in [addMenus] | 46 @param extra(dict[unicode, unicode], None): same as in [addMenus] |
59 self.icon = extra.get("icon") | 64 self.icon = extra.get("icon") |
60 | 65 |
61 | 66 |
62 class MenuItem(MenuBase): | 67 class MenuItem(MenuBase): |
63 """A callable item in the menu""" | 68 """A callable item in the menu""" |
64 CALLABLE=False | 69 |
70 CALLABLE = False | |
65 | 71 |
66 def __init__(self, name, name_i18n, extra=None, type_=None): | 72 def __init__(self, name, name_i18n, extra=None, type_=None): |
67 """ | 73 """ |
68 @param name(unicode): canonical name of the item | 74 @param name(unicode): canonical name of the item |
69 @param name_i18n(unicode): translated name of the item | 75 @param name_i18n(unicode): translated name of the item |
81 def collectData(self, caller): | 87 def collectData(self, caller): |
82 """Get data according to data_collector | 88 """Get data according to data_collector |
83 | 89 |
84 @param caller: Menu caller | 90 @param caller: Menu caller |
85 """ | 91 """ |
86 assert self.type is not None # if data collector are used, type must be set | 92 assert self.type is not None # if data collector are used, type must be set |
87 data_collector = QuickMenusManager.getDataCollector(self.type) | 93 data_collector = QuickMenusManager.getDataCollector(self.type) |
88 | 94 |
89 if data_collector is None: | 95 if data_collector is None: |
90 return {} | 96 return {} |
91 | 97 |
99 data = {} | 105 data = {} |
100 for data_key, caller_attr in data_collector.iteritems(): | 106 for data_key, caller_attr in data_collector.iteritems(): |
101 data[data_key] = unicode(getattr(caller, caller_attr)) | 107 data[data_key] = unicode(getattr(caller, caller_attr)) |
102 return data | 108 return data |
103 | 109 |
104 | |
105 def call(self, caller, profile=C.PROF_KEY_NONE): | 110 def call(self, caller, profile=C.PROF_KEY_NONE): |
106 """Execute the menu item | 111 """Execute the menu item |
107 | 112 |
108 @param caller: instance linked to the menu | 113 @param caller: instance linked to the menu |
109 @param profile: %(doc_profile)s | 114 @param profile: %(doc_profile)s |
111 raise NotImplementedError | 116 raise NotImplementedError |
112 | 117 |
113 | 118 |
114 class MenuItemDistant(MenuItem): | 119 class MenuItemDistant(MenuItem): |
115 """A MenuItem with a distant callback""" | 120 """A MenuItem with a distant callback""" |
116 CALLABLE=True | 121 |
122 CALLABLE = True | |
117 | 123 |
118 def __init__(self, host, type_, name, name_i18n, id_, extra=None): | 124 def __init__(self, host, type_, name, name_i18n, id_, extra=None): |
119 """ | 125 """ |
120 @param host: %(doc_host)s | 126 @param host: %(doc_host)s |
121 @param type_(unicode): same as in [sat.core.sat_main.SAT.importMenu] | 127 @param type_(unicode): same as in [sat.core.sat_main.SAT.importMenu] |
127 MenuItem.__init__(self, name, name_i18n, extra, type_) | 133 MenuItem.__init__(self, name, name_i18n, extra, type_) |
128 self.host = host | 134 self.host = host |
129 self.id = id_ | 135 self.id = id_ |
130 | 136 |
131 def call(self, caller, profile=C.PROF_KEY_NONE): | 137 def call(self, caller, profile=C.PROF_KEY_NONE): |
132 data = self.collectData(caller) | 138 data = self.collectData(caller) |
133 log.debug("data collected: %s" % data) | 139 log.debug("data collected: %s" % data) |
134 self.host.launchAction(self.id, data, profile=profile) | 140 self.host.launchAction(self.id, data, profile=profile) |
135 | 141 |
136 | 142 |
137 class MenuItemLocal(MenuItem): | 143 class MenuItemLocal(MenuItem): |
138 """A MenuItem with a local callback""" | 144 """A MenuItem with a local callback""" |
139 CALLABLE=True | 145 |
146 CALLABLE = True | |
140 | 147 |
141 def __init__(self, type_, name, name_i18n, callback, extra=None): | 148 def __init__(self, type_, name, name_i18n, callback, extra=None): |
142 """ | 149 """ |
143 @param type_(unicode): same as in [sat.core.sat_main.SAT.importMenu] | 150 @param type_(unicode): same as in [sat.core.sat_main.SAT.importMenu] |
144 @param name(unicode): canonical name of the item | 151 @param name(unicode): canonical name of the item |
160 self.callback(caller, self.collectData(caller), profile) | 167 self.callback(caller, self.collectData(caller), profile) |
161 | 168 |
162 | 169 |
163 class MenuHook(MenuItemLocal): | 170 class MenuHook(MenuItemLocal): |
164 """A MenuItem which replace an expected item from backend""" | 171 """A MenuItem which replace an expected item from backend""" |
172 | |
165 pass | 173 pass |
166 | 174 |
167 | 175 |
168 class MenuPlaceHolder(MenuItem): | 176 class MenuPlaceHolder(MenuItem): |
169 """A non existant menu which is used to keep a position""" | 177 """A non existant menu which is used to keep a position""" |
170 ACTIVE=False | 178 |
179 ACTIVE = False | |
171 | 180 |
172 def __init__(self, name): | 181 def __init__(self, name): |
173 MenuItem.__init__(self, name, name) | 182 MenuItem.__init__(self, name, name) |
174 | 183 |
175 | 184 |
176 class MenuSeparator(MenuItem): | 185 class MenuSeparator(MenuItem): |
177 """A separation between items/categories""" | 186 """A separation between items/categories""" |
178 SEP_IDX=0 | 187 |
188 SEP_IDX = 0 | |
179 | 189 |
180 def __init__(self): | 190 def __init__(self): |
181 MenuSeparator.SEP_IDX +=1 | 191 MenuSeparator.SEP_IDX += 1 |
182 name = u"___separator_{}".format(MenuSeparator.SEP_IDX) | 192 name = u"___separator_{}".format(MenuSeparator.SEP_IDX) |
183 MenuItem.__init__(self, name, name) | 193 MenuItem.__init__(self, name, name) |
184 | 194 |
185 | 195 |
186 ## containers ## | 196 ## containers ## |
187 | 197 |
188 | 198 |
189 class MenuContainer(MenuBase): | 199 class MenuContainer(MenuBase): |
190 | |
191 def __init__(self, name, extra=None): | 200 def __init__(self, name, extra=None): |
192 MenuBase.__init__(self, name, extra) | 201 MenuBase.__init__(self, name, extra) |
193 self._items = OrderedDict() | 202 self._items = OrderedDict() |
194 | 203 |
195 def __len__(self): | 204 def __len__(self): |
206 return self._items[item.canonical] | 215 return self._items[item.canonical] |
207 except KeyError: | 216 except KeyError: |
208 raise KeyError(item) | 217 raise KeyError(item) |
209 | 218 |
210 def getOrCreate(self, item): | 219 def getOrCreate(self, item): |
211 log.debug(u"MenuContainer getOrCreate: item=%s name=%s\nlist=%s" % (item, item.canonical, self._items.keys())) | 220 log.debug( |
221 u"MenuContainer getOrCreate: item=%s name=%s\nlist=%s" | |
222 % (item, item.canonical, self._items.keys()) | |
223 ) | |
212 try: | 224 try: |
213 return self[item] | 225 return self[item] |
214 except KeyError: | 226 except KeyError: |
215 self.append(item) | 227 self.append(item) |
216 return item | 228 return item |
253 return self._name_i18n | 265 return self._name_i18n |
254 | 266 |
255 | 267 |
256 class MenuType(MenuContainer): | 268 class MenuType(MenuContainer): |
257 """A type which can hold other menus or categories""" | 269 """A type which can hold other menus or categories""" |
270 | |
258 pass | 271 pass |
259 | 272 |
260 | 273 |
261 ## manager ## | 274 ## manager ## |
262 | 275 |
263 | 276 |
264 class QuickMenusManager(object): | 277 class QuickMenusManager(object): |
265 """Manage all the menus""" | 278 """Manage all the menus""" |
266 _data_collectors={C.MENU_GLOBAL: None} # No data is associated with C.MENU_GLOBAL items | 279 |
280 _data_collectors = { | |
281 C.MENU_GLOBAL: None | |
282 } # No data is associated with C.MENU_GLOBAL items | |
267 | 283 |
268 def __init__(self, host, menus=None, language=None): | 284 def __init__(self, host, menus=None, language=None): |
269 """ | 285 """ |
270 @param host: %(doc_host)s | 286 @param host: %(doc_host)s |
271 @param menus(iterable): menus as in [addMenus] | 287 @param menus(iterable): menus as in [addMenus] |
356 container_item = menu_container[item] | 372 container_item = menu_container[item] |
357 if isinstance(container_item, MenuPlaceHolder): | 373 if isinstance(container_item, MenuPlaceHolder): |
358 menu_container.replace(item) | 374 menu_container.replace(item) |
359 elif isinstance(container_item, MenuHook): | 375 elif isinstance(container_item, MenuHook): |
360 # MenuHook must not be replaced | 376 # MenuHook must not be replaced |
361 log.debug(u"ignoring menu at path [{}] because a hook is already in place".format(path)) | 377 log.debug( |
378 u"ignoring menu at path [{}] because a hook is already in place".format( | |
379 path | |
380 ) | |
381 ) | |
362 else: | 382 else: |
363 log.error(u"Conflicting menus at path [{}]".format(path)) | 383 log.error(u"Conflicting menus at path [{}]".format(path)) |
364 else: | 384 else: |
365 log.debug(u"Adding menu [{type_}] {path}".format(type_=type_, path=path)) | 385 log.debug(u"Adding menu [{type_}] {path}".format(type_=type_, path=path)) |
366 menu_container.append(item) | 386 menu_container.append(item) |
367 self.host.callListeners('menu', type_, path, path_i18n, item) | 387 self.host.callListeners("menu", type_, path, path_i18n, item) |
368 | 388 |
369 def addMenu(self, type_, path, path_i18n=None, extra=None, top_extra=None, id_=None, callback=None): | 389 def addMenu( |
390 self, | |
391 type_, | |
392 path, | |
393 path_i18n=None, | |
394 extra=None, | |
395 top_extra=None, | |
396 id_=None, | |
397 callback=None, | |
398 ): | |
370 """Add a menu item | 399 """Add a menu item |
371 | 400 |
372 @param type_(unicode): same as in [sat.core.sat_main.SAT.importMenu] | 401 @param type_(unicode): same as in [sat.core.sat_main.SAT.importMenu] |
373 @param path(list[unicode]): same as in [sat.core.sat_main.SAT.importMenu] | 402 @param path(list[unicode]): same as in [sat.core.sat_main.SAT.importMenu] |
374 @param path_i18n(list[unicode], None): translated menu path (same lenght as path), or None to get deferred translation | 403 @param path_i18n(list[unicode], None): translated menu path (same lenght as path), or None to get deferred translation |
377 @param id_(unicode): callback id (mutually exclusive with callback) | 406 @param id_(unicode): callback id (mutually exclusive with callback) |
378 @param callback(callable): local callback (mutually exclusive with id_) | 407 @param callback(callable): local callback (mutually exclusive with id_) |
379 """ | 408 """ |
380 if path_i18n is None: | 409 if path_i18n is None: |
381 path_i18n = self._getPathI18n(path) | 410 path_i18n = self._getPathI18n(path) |
382 assert bool(id_) ^ bool(callback) # we must have id_ xor callback defined | 411 assert bool(id_) ^ bool(callback) # we must have id_ xor callback defined |
383 if id_: | 412 if id_: |
384 menu_item = MenuItemDistant(self.host, type_, path[-1], path_i18n[-1], id_=id_, extra=extra) | 413 menu_item = MenuItemDistant( |
414 self.host, type_, path[-1], path_i18n[-1], id_=id_, extra=extra | |
415 ) | |
385 else: | 416 else: |
386 menu_item = MenuItemLocal(type_, path[-1], path_i18n[-1], callback=callback, extra=extra) | 417 menu_item = MenuItemLocal( |
418 type_, path[-1], path_i18n[-1], callback=callback, extra=extra | |
419 ) | |
387 self.addMenuItem(type_, path[:-1], menu_item, path_i18n[:-1], top_extra) | 420 self.addMenuItem(type_, path[:-1], menu_item, path_i18n[:-1], top_extra) |
388 | 421 |
389 def addMenus(self, menus, top_extra=None): | 422 def addMenus(self, menus, top_extra=None): |
390 """Add several menus at once | 423 """Add several menus at once |
391 | 424 |
399 @param top_extra: same as in [_createCategories] | 432 @param top_extra: same as in [_createCategories] |
400 """ | 433 """ |
401 # TODO: manage icons | 434 # TODO: manage icons |
402 for id_, type_, path, path_i18n, extra in menus: | 435 for id_, type_, path, path_i18n, extra in menus: |
403 if callable(id_): | 436 if callable(id_): |
404 self.addMenu(type_, path, path_i18n, callback=id_, extra=extra, top_extra=top_extra) | 437 self.addMenu( |
438 type_, path, path_i18n, callback=id_, extra=extra, top_extra=top_extra | |
439 ) | |
405 else: | 440 else: |
406 self.addMenu(type_, path, path_i18n, id_=id_, extra=extra, top_extra=top_extra) | 441 self.addMenu( |
407 | 442 type_, path, path_i18n, id_=id_, extra=extra, top_extra=top_extra |
408 def addMenuHook(self, type_, path, path_i18n=None, extra=None, top_extra=None, callback=None): | 443 ) |
444 | |
445 def addMenuHook( | |
446 self, type_, path, path_i18n=None, extra=None, top_extra=None, callback=None | |
447 ): | |
409 """Helper method to add a menu hook | 448 """Helper method to add a menu hook |
410 | 449 |
411 Menu hooks are local menus which override menu given by backend | 450 Menu hooks are local menus which override menu given by backend |
412 @param type_(unicode): same as in [sat.core.sat_main.SAT.importMenu] | 451 @param type_(unicode): same as in [sat.core.sat_main.SAT.importMenu] |
413 @param path(list[unicode]): same as in [sat.core.sat_main.SAT.importMenu] | 452 @param path(list[unicode]): same as in [sat.core.sat_main.SAT.importMenu] |
416 @param top_extra: same as in [_createCategories] | 455 @param top_extra: same as in [_createCategories] |
417 @param callback(callable): local callback (mutually exclusive with id_) | 456 @param callback(callable): local callback (mutually exclusive with id_) |
418 """ | 457 """ |
419 if path_i18n is None: | 458 if path_i18n is None: |
420 path_i18n = self._getPathI18n(path) | 459 path_i18n = self._getPathI18n(path) |
421 menu_item = MenuHook(type_, path[-1], path_i18n[-1], callback=callback, extra=extra) | 460 menu_item = MenuHook( |
461 type_, path[-1], path_i18n[-1], callback=callback, extra=extra | |
462 ) | |
422 self.addMenuItem(type_, path[:-1], menu_item, path_i18n[:-1], top_extra) | 463 self.addMenuItem(type_, path[:-1], menu_item, path_i18n[:-1], top_extra) |
423 log.info(u"Menu hook set on {path} ({type_})".format(path=path, type_=type_)) | 464 log.info(u"Menu hook set on {path} ({type_})".format(path=path, type_=type_)) |
424 | 465 |
425 def addCategory(self, type_, path, path_i18n=None, extra=None, top_extra=None): | 466 def addCategory(self, type_, path, path_i18n=None, extra=None, top_extra=None): |
426 """Create a category with all parents, and set extra on the last one | 467 """Create a category with all parents, and set extra on the last one |
432 @param top_extra: same as in [_createCategories] | 473 @param top_extra: same as in [_createCategories] |
433 @return (MenuCategory): last category add | 474 @return (MenuCategory): last category add |
434 """ | 475 """ |
435 if path_i18n is None: | 476 if path_i18n is None: |
436 path_i18n = self._getPathI18n(path) | 477 path_i18n = self._getPathI18n(path) |
437 last_container = self._createCategories(type_, path, path_i18n, top_extra=top_extra) | 478 last_container = self._createCategories( |
479 type_, path, path_i18n, top_extra=top_extra | |
480 ) | |
438 last_container.setExtra(extra) | 481 last_container.setExtra(extra) |
439 return last_container | 482 return last_container |
440 | 483 |
441 def getMainContainer(self, type_): | 484 def getMainContainer(self, type_): |
442 """Get a main MenuType container | 485 """Get a main MenuType container |