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