comparison frontends/src/tools/xmlui.py @ 1265:e3a9ea76de35 frontends_multi_profiles

quick_frontend, primitivus: multi-profiles refactoring part 1 (big commit, sorry :p): This refactoring allow primitivus to manage correctly several profiles at once, with various other improvments: - profile_manager can now plug several profiles at once, requesting password when needed. No more profile plug specific method is used anymore in backend, instead a "validated" key is used in actions - Primitivus widget are now based on a common "PrimitivusWidget" classe which mainly manage the decoration so far - all widgets are treated in the same way (contactList, Chat, Progress, etc), no more chat_wins specific behaviour - widgets are created in a dedicated manager, with facilities to react on new widget creation or other events - quick_frontend introduce a new QuickWidget class, which aims to be as generic and flexible as possible. It can manage several targets (jids or something else), and several profiles - each widget class return a Hash according to its target. For example if given a target jid and a profile, a widget class return a hash like (target.bare, profile), the same widget will be used for all resources of the same jid - better management of CHAT_GROUP mode for Chat widgets - some code moved from Primitivus to QuickFrontend, the final goal is to have most non backend code in QuickFrontend, and just graphic code in subclasses - no more (un)escapePrivate/PRIVATE_PREFIX - contactList improved a lot: entities not in roster and special entities (private MUC conversations) are better managed - resources can be displayed in Primitivus, and their status messages - profiles are managed in QuickFrontend with dedicated managers This is work in progress, other frontends are broken. Urwid SàText need to be updated. Most of features of Primitivus should work as before (or in a better way ;))
author Goffi <goffi@goffi.org>
date Wed, 10 Dec 2014 19:00:09 +0100
parents f91e7028e2c3
children faa1129559b8
comparison
equal deleted inserted replaced
1264:60dfa2f5d61f 1265:e3a9ea76de35
200 """Base class to construct SàT XML User Interface 200 """Base class to construct SàT XML User Interface
201 201
202 This class must not be instancied directly 202 This class must not be instancied directly
203 """ 203 """
204 204
205 def __init__(self, host, parsed_dom, title = None, flags = None): 205 def __init__(self, host, parsed_dom, title=None, flags=None, callback=None, profile=C.PROF_KEY_NONE):
206 """Initialise the XMLUI instance 206 """Initialise the XMLUI instance
207 207
208 @param host: %(doc_host)s 208 @param host: %(doc_host)s
209 @param parsed_dom: main parsed dom 209 @param parsed_dom: main parsed dom
210 @param title: force the title, or use XMLUI one if None 210 @param title: force the title, or use XMLUI one if None
211 @param flags: list of string which can be: 211 @param flags: list of string which can be:
212 - NO_CANCEL: the UI can't be cancelled 212 - NO_CANCEL: the UI can't be cancelled
213 @param callback: if present, will be use with launchAction
213 """ 214 """
214 self.host = host 215 self.host = host
215 top=parsed_dom.documentElement 216 top=parsed_dom.documentElement
216 self.session_id = top.getAttribute("session_id") or None 217 self.session_id = top.getAttribute("session_id") or None
217 self.submit_id = top.getAttribute("submit") or None 218 self.submit_id = top.getAttribute("submit") or None
218 self.title = title or top.getAttribute("title") or u"" 219 self.xmlui_title = title or top.getAttribute("title") or u""
219 if flags is None: 220 if flags is None:
220 flags = [] 221 flags = []
221 self.flags = flags 222 self.flags = flags
223 self.callback = callback
224 self.profile = profile
222 225
223 def _isAttrSet(self, name, node): 226 def _isAttrSet(self, name, node):
224 """Returnw widget boolean attribute status 227 """Returnw widget boolean attribute status
225 228
226 @param name: name of the attribute (e.g. "read_only") 229 @param name: name of the attribute (e.g. "read_only")
251 if self.session_id is not None: 254 if self.session_id is not None:
252 data["session_id"] = self.session_id 255 data["session_id"] = self.session_id
253 self._xmluiLaunchAction(self.submit_id, data) 256 self._xmluiLaunchAction(self.submit_id, data)
254 257
255 def _xmluiLaunchAction(self, action_id, data): 258 def _xmluiLaunchAction(self, action_id, data):
256 self.host.launchAction(action_id, data, profile_key = self.host.profile) 259 self.host.launchAction(action_id, data, callback=self.callback, profile=self.profile)
257 260
258 261
259 class XMLUIPanel(XMLUIBase): 262 class XMLUIPanel(XMLUIBase):
260 """XMLUI Panel 263 """XMLUI Panel
261 264
263 @property widget_factory: factory to create frontend-specific widgets 266 @property widget_factory: factory to create frontend-specific widgets
264 @proporety dialog_factory: factory to create frontend-specific dialogs 267 @proporety dialog_factory: factory to create frontend-specific dialogs
265 """ 268 """
266 widget_factory = None 269 widget_factory = None
267 270
268 def __init__(self, host, parsed_dom, title = None, flags = None): 271 def __init__(self, host, parsed_dom, title=None, flags=None, callback=None, profile=C.PROF_KEY_NONE):
269 super(XMLUIPanel, self).__init__(host, parsed_dom, title = None, flags = None) 272 super(XMLUIPanel, self).__init__(host, parsed_dom, title=title, flags=flags, callback=callback, profile=profile)
270 self.ctrl_list = {} # usefull to access ctrl 273 self.ctrl_list = {} # usefull to access ctrl
271 self._main_cont = None 274 self._main_cont = None
272 self.constructUI(parsed_dom) 275 self.constructUI(parsed_dom)
273 276
274 def escape(self, name): 277 def escape(self, name):
460 this method must be overrided 463 this method must be overrided
461 """ 464 """
462 raise NotImplementedError 465 raise NotImplementedError
463 466
464 def _xmluiSetParam(self, name, value, category): 467 def _xmluiSetParam(self, name, value, category):
465 self.host.bridge.setParam(name, value, category, profile_key=self.host.profile) 468 self.host.bridge.setParam(name, value, category, profile=self.profile)
466 469
467 ##EVENTS## 470 ##EVENTS##
468 471
469 def onParamChange(self, ctrl): 472 def onParamChange(self, ctrl):
470 """Called when type is param and a widget to save is modified 473 """Called when type is param and a widget to save is modified
637 640
638 641
639 class XMLUIDialog(XMLUIBase): 642 class XMLUIDialog(XMLUIBase):
640 dialog_factory = None 643 dialog_factory = None
641 644
642 def __init__(self, host, parsed_dom, title = None, flags = None): 645 def __init__(self, host, parsed_dom, title=None, flags=None, callback=None, profile=C.PROF_KEY_NONE):
643 super(XMLUIDialog, self).__init__(host, parsed_dom, title = None, flags = None) 646 super(XMLUIDialog, self).__init__(host, parsed_dom, title=None, flags=None, callback=callback, profile=C.PROF_KEY_NONE)
644 top=parsed_dom.documentElement 647 top=parsed_dom.documentElement
645 dlg_elt = self._getChildNode(top, "dialog") 648 dlg_elt = self._getChildNode(top, "dialog")
646 if dlg_elt is None: 649 if dlg_elt is None:
647 raise ValueError("Invalid XMLUI: no Dialog element found !") 650 raise ValueError("Invalid XMLUI: no Dialog element found !")
648 dlg_type = dlg_elt.getAttribute("type") or C.XMLUI_DIALOG_MESSAGE 651 dlg_type = dlg_elt.getAttribute("type") or C.XMLUI_DIALOG_MESSAGE
652 except (TypeError, AttributeError): # XXX: TypeError is here because pyjamas raise a TypeError instead of an AttributeError 655 except (TypeError, AttributeError): # XXX: TypeError is here because pyjamas raise a TypeError instead of an AttributeError
653 message = "" 656 message = ""
654 level = dlg_elt.getAttribute(C.XMLUI_DATA_LVL) or C.XMLUI_DATA_LVL_INFO 657 level = dlg_elt.getAttribute(C.XMLUI_DATA_LVL) or C.XMLUI_DATA_LVL_INFO
655 658
656 if dlg_type == C.XMLUI_DIALOG_MESSAGE: 659 if dlg_type == C.XMLUI_DIALOG_MESSAGE:
657 self.dlg = self.dialog_factory.createMessageDialog(self, self.title, message, level) 660 self.dlg = self.dialog_factory.createMessageDialog(self, self.xmlui_title, message, level)
658 elif dlg_type == C.XMLUI_DIALOG_NOTE: 661 elif dlg_type == C.XMLUI_DIALOG_NOTE:
659 self.dlg = self.dialog_factory.createNoteDialog(self, self.title, message, level) 662 self.dlg = self.dialog_factory.createNoteDialog(self, self.xmlui_title, message, level)
660 elif dlg_type == C.XMLUI_DIALOG_CONFIRM: 663 elif dlg_type == C.XMLUI_DIALOG_CONFIRM:
661 try: 664 try:
662 buttons_elt = self._getChildNode(dlg_elt, "buttons") 665 buttons_elt = self._getChildNode(dlg_elt, "buttons")
663 buttons_set = buttons_elt.getAttribute("set") or C.XMLUI_DATA_BTNS_SET_DEFAULT 666 buttons_set = buttons_elt.getAttribute("set") or C.XMLUI_DATA_BTNS_SET_DEFAULT
664 except (TypeError, AttributeError): # XXX: TypeError is here because pyjamas raise a TypeError instead of an AttributeError 667 except (TypeError, AttributeError): # XXX: TypeError is here because pyjamas raise a TypeError instead of an AttributeError
665 buttons_set = C.XMLUI_DATA_BTNS_SET_DEFAULT 668 buttons_set = C.XMLUI_DATA_BTNS_SET_DEFAULT
666 self.dlg = self.dialog_factory.createConfirmDialog(self, self.title, message, level, buttons_set) 669 self.dlg = self.dialog_factory.createConfirmDialog(self, self.xmlui_title, message, level, buttons_set)
667 elif dlg_type == C.XMLUI_DIALOG_FILE: 670 elif dlg_type == C.XMLUI_DIALOG_FILE:
668 try: 671 try:
669 file_elt = self._getChildNode(dlg_elt, "file") 672 file_elt = self._getChildNode(dlg_elt, "file")
670 filetype = file_elt.getAttribute("type") or C.XMLUI_DATA_FILETYPE_DEFAULT 673 filetype = file_elt.getAttribute("type") or C.XMLUI_DATA_FILETYPE_DEFAULT
671 except (TypeError, AttributeError): # XXX: TypeError is here because pyjamas raise a TypeError instead of an AttributeError 674 except (TypeError, AttributeError): # XXX: TypeError is here because pyjamas raise a TypeError instead of an AttributeError
672 filetype = C.XMLUI_DATA_FILETYPE_DEFAULT 675 filetype = C.XMLUI_DATA_FILETYPE_DEFAULT
673 self.dlg = self.dialog_factory.createFileDialog(self, self.title, message, level, filetype) 676 self.dlg = self.dialog_factory.createFileDialog(self, self.xmlui_title, message, level, filetype)
674 else: 677 else:
675 raise ValueError("Unknown dialog type [%s]" % dlg_type) 678 raise ValueError("Unknown dialog type [%s]" % dlg_type)
676 679
677 def show(self): 680 def show(self):
678 self.dlg._xmluiShow() 681 self.dlg._xmluiShow()
688 """ 691 """
689 assert type_ in (CLASS_PANEL, CLASS_DIALOG) 692 assert type_ in (CLASS_PANEL, CLASS_DIALOG)
690 class_map[type_] = class_ 693 class_map[type_] = class_
691 694
692 695
693 def create(host, xml_data, title = None, flags = None, dom_parse=None, dom_free=None): 696 def create(host, xml_data, title=None, flags=None, dom_parse=None, dom_free=None, callback=None, profile=C.PROF_KEY_NONE):
694 """ 697 """
695 @param dom_parse: methode equivalent to minidom.parseString (but which must manage unicode), or None to use default one 698 @param dom_parse: methode equivalent to minidom.parseString (but which must manage unicode), or None to use default one
696 @param dom_free: method used to free the parsed DOM 699 @param dom_free: method used to free the parsed DOM
697 """ 700 """
698 if dom_parse is None: 701 if dom_parse is None:
711 else: 714 else:
712 cls = class_map[CLASS_DIALOG] 715 cls = class_map[CLASS_DIALOG]
713 except KeyError: 716 except KeyError:
714 raise ClassNotRegistedError(_("You must register classes with registerClass before creating a XMLUI")) 717 raise ClassNotRegistedError(_("You must register classes with registerClass before creating a XMLUI"))
715 718
716 xmlui = cls(host, parsed_dom, title, flags) 719 xmlui = cls(host, parsed_dom, title, flags, callback, profile)
717 dom_free(parsed_dom) 720 dom_free(parsed_dom)
718 return xmlui 721 return xmlui