comparison frontends/src/quick_frontend/quick_widgets.py @ 1290:faa1129559b8 frontends_multi_profiles

core, frontends: refactoring to base Libervia on QuickFrontend (big mixed commit): /!\ not finished, everything is still instable ! - bridge: DBus bridge has been modified to allow blocking call to be called in the same way as asynchronous calls - bridge: calls with a callback and no errback are now possible, default errback log the error - constants: removed hack to manage presence without OrderedDict, as an OrderedDict like class has been implemented in Libervia - core: getLastResource has been removed and replaced by getMainResource (there is a global better management of resources) - various style improvments: use of constants when possible, fixed variable overlaps, import of module instead of direct class import - frontends: printInfo and printMessage methods in (Quick)Chat are more generic (use of extra instead of timestamp) - frontends: bridge creation and option parsing (command line arguments) are now specified by the frontend in QuickApp __init__ - frontends: ProfileManager manage a more complete plug sequence (some stuff formerly manage in contact_list have moved to ProfileManager) - quick_frontend (quick_widgets): QuickWidgetsManager is now iterable (all widgets are then returned), or can return an iterator on a specific class (return all widgets of this class) with getWidgets - frontends: tools.jid can now be used in Pyjamas, with some care - frontends (XMLUI): profile is now managed - core (memory): big improvment on entities cache management (and specially resource management) - core (params/exceptions): added PermissionError - various fixes and improvments, check diff for more details
author Goffi <goffi@goffi.org>
date Sat, 24 Jan 2015 01:00:29 +0100
parents e3a9ea76de35
children afc57b34c0a3
comparison
equal deleted inserted replaced
1289:653f2e2eea31 1290:faa1129559b8
21 log = getLogger(__name__) 21 log = getLogger(__name__)
22 from sat.core import exceptions 22 from sat.core import exceptions
23 23
24 24
25 classes_map = {} 25 classes_map = {}
26
27
28 try:
29 # FIXME: to be removed when an acceptable solution is here
30 unicode('') # XXX: unicode doesn't exist in pyjamas
31 except (TypeError, AttributeError): # Error raised is not the same depending on pyjsbuild options
32 unicode = str
26 33
27 34
28 def register(base_cls, child_cls=None): 35 def register(base_cls, child_cls=None):
29 """Register a child class to use by default when a base class is needed 36 """Register a child class to use by default when a base class is needed
30 37
40 A widget can be a window, a graphical thing, or someting else depending of the frontend""" 47 A widget can be a window, a graphical thing, or someting else depending of the frontend"""
41 48
42 def __init__(self, host): 49 def __init__(self, host):
43 self.host = host 50 self.host = host
44 self._widgets = {} 51 self._widgets = {}
52
53 def __iter__(self):
54 """Iterate throught all widgets"""
55 for widget_map in self._widgets.itervalues():
56 for widget in widget_map.itervalues():
57 yield widget
58
59 def getRealClass(self, class_):
60 """Return class registered for given class_
61
62 @param class_: subclass of QuickWidget
63 @return: class actually used to create widget
64 """
65 try:
66 cls = classes_map[class_]
67 except KeyError:
68 cls = class_
69 if cls is None:
70 raise exceptions.InternalError("There is not class registered for {}".format(class_))
71 return cls
72
73 def getWidgets(self, class_):
74 """Get all subclassed widgets
75
76 @param class_: subclass of QuickWidget, same parameter as used in [getOrCreateWidget]
77 @return: iterator on widgets
78 """
79 class_ = self.getRealClass(class_)
80 try:
81 widgets_map = self._widgets[class_]
82 except KeyError:
83 return iter([])
84 else:
85 return widgets_map.itervalues()
45 86
46 def getOrCreateWidget(self, class_, target, *args, **kwargs): 87 def getOrCreateWidget(self, class_, target, *args, **kwargs):
47 """Get an existing widget or create a new one when necessary 88 """Get an existing widget or create a new one when necessary
48 89
49 If the widget is new, self.host.newWidget will be called with it. 90 If the widget is new, self.host.newWidget will be called with it.
58 [callable]: this method will be called instead of self.host.newWidget 99 [callable]: this method will be called instead of self.host.newWidget
59 None: do nothing 100 None: do nothing
60 if 'force_hash' is present, the hash given in value will be used instead of the one returned by class_.getWidgetHash 101 if 'force_hash' is present, the hash given in value will be used instead of the one returned by class_.getWidgetHash
61 @return: a class_ instance, either new or already existing 102 @return: a class_ instance, either new or already existing
62 """ 103 """
63 # class management 104 cls = self.getRealClass(class_)
64 try:
65 cls = classes_map[class_]
66 except KeyError:
67 cls = class_
68 if cls is None:
69 raise exceptions.InternalError("There is not class registered for {}".format(class_))
70 105
71 # arguments management 106 # arguments management
72 _args = [self.host, target] + list(args) or [] # FIXME: check if it's really necessary to use optional args 107 _args = [self.host, target] + list(args) or [] # FIXME: check if it's really necessary to use optional args
73 _kwargs = kwargs or {} 108 _kwargs = kwargs or {}
74 if 'profiles' in _kwargs and 'profile' in _kwargs: 109 if 'profiles' in _kwargs and 'profile' in _kwargs:
84 hash_ = _kwargs.pop('force_hash') 119 hash_ = _kwargs.pop('force_hash')
85 except KeyError: 120 except KeyError:
86 hash_ = cls.getWidgetHash(target, _kwargs['profiles']) 121 hash_ = cls.getWidgetHash(target, _kwargs['profiles'])
87 122
88 # widget creation or retrieval 123 # widget creation or retrieval
89 widgets_list = self._widgets.setdefault(cls, {}) # we sorts widgets by classes 124 widgets_map = self._widgets.setdefault(cls, {}) # we sorts widgets by classes
90 if not cls.SINGLE: 125 if not cls.SINGLE:
91 widget = None # if the class is not SINGLE, we always create a new widget 126 widget = None # if the class is not SINGLE, we always create a new widget
92 else: 127 else:
93 try: 128 try:
94 widget = widgets_list[hash_] 129 widget = widgets_map[hash_]
95 widget.addTarget(target) 130 widget.addTarget(target)
96 except KeyError: 131 except KeyError:
97 widget = None 132 widget = None
98 133
99 if widget is None: 134 if widget is None:
104 except KeyError: 139 except KeyError:
105 on_new_widget = 'NEW_WIDGET' 140 on_new_widget = 'NEW_WIDGET'
106 141
107 log.debug(u"Creating new widget for target {} {}".format(target, cls)) 142 log.debug(u"Creating new widget for target {} {}".format(target, cls))
108 widget = cls(*_args, **_kwargs) 143 widget = cls(*_args, **_kwargs)
109 widgets_list[hash_] = widget 144 widgets_map[hash_] = widget
110 145
111 if on_new_widget == 'NEW_WIDGET': 146 if on_new_widget == 'NEW_WIDGET':
112 self.host.newWidget(widget) 147 self.host.newWidget(widget)
113 elif callable(on_new_widget): 148 elif callable(on_new_widget):
114 on_new_widget(widget) 149 on_new_widget(widget)