changeset 2669:bdb8276fd2da

frontends (xmlui): class_map is now an arg of create function: class_map was so far used as a global value, but in some cases, several XMLUI managers may be used (it's the case in Cagou's remote controllers plugins, template_xmlui is used to manage remotes). This patch set class_map as a create argument, this way it can be set with partial, and several XMLUI managers can be instanced at the same time.
author Goffi <goffi@goffi.org>
date Fri, 31 Aug 2018 16:03:12 +0200 (2018-08-31)
parents c274201cea94
children ef93fcbaa749
files sat/tools/common/template_xmlui.py sat_frontends/jp/xmlui_manager.py sat_frontends/quick_frontend/quick_app.py sat_frontends/tools/xmlui.py
diffstat 4 files changed, 47 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/sat/tools/common/template_xmlui.py	Fri Aug 31 15:57:11 2018 +0200
+++ b/sat/tools/common/template_xmlui.py	Fri Aug 31 16:03:12 2018 +0200
@@ -26,6 +26,7 @@
 
 log = getLogger(__name__)
 from sat_frontends.tools import xmlui
+from functools import partial
 
 
 ## Widgets ##
@@ -176,6 +177,7 @@
 
 
 class WidgetFactory(object):
+
     def __getattr__(self, attr):
         if attr.startswith("create"):
             cls = globals()[attr[6:]]
@@ -199,6 +201,6 @@
         raise NotImplementedError
 
 
-xmlui.registerClass(xmlui.CLASS_PANEL, XMLUIPanel)
-xmlui.registerClass(xmlui.CLASS_DIALOG, XMLUIDialog)
-create = xmlui.create
+create = partial(xmlui.create, class_map={
+    xmlui.CLASS_PANEL: XMLUIPanel,
+    xmlui.CLASS_DIALOG: XMLUIDialog})
--- a/sat_frontends/jp/xmlui_manager.py	Fri Aug 31 15:57:11 2018 +0200
+++ b/sat_frontends/jp/xmlui_manager.py	Fri Aug 31 16:03:12 2018 +0200
@@ -20,7 +20,7 @@
 from sat.core.log import getLogger
 
 log = getLogger(__name__)
-from sat_frontends.tools import xmlui as xmlui_manager
+from sat_frontends.tools import xmlui as xmlui_base
 from sat_frontends.jp.constants import Const as C
 from sat.tools.common.ansi import ANSI as A
 from sat.core.i18n import _
@@ -50,7 +50,7 @@
         if self._root is not None:
             return self._root
         root = self
-        while not isinstance(root, xmlui_manager.XMLUIBase):
+        while not isinstance(root, xmlui_base.XMLUIBase):
             root = root.xmlui_parent
         self._root = root
         return root
@@ -173,19 +173,19 @@
         return u"noselect" in self.style
 
 
-class EmptyWidget(xmlui_manager.EmptyWidget, Widget):
+class EmptyWidget(xmlui_base.EmptyWidget, Widget):
     def __init__(self, _xmlui_parent):
         Widget.__init__(self)
 
 
-class TextWidget(xmlui_manager.TextWidget, ValueWidget):
+class TextWidget(xmlui_base.TextWidget, ValueWidget):
     type = u"text"
 
     def show(self):
         self.host.disp(self.value)
 
 
-class LabelWidget(xmlui_manager.LabelWidget, ValueWidget):
+class LabelWidget(xmlui_base.LabelWidget, ValueWidget):
     type = u"label"
 
     @property
@@ -204,7 +204,7 @@
         self.disp(A.color(ansi, self.value), no_lf=no_lf)
 
 
-class StringWidget(xmlui_manager.StringWidget, InputWidget):
+class StringWidget(xmlui_base.StringWidget, InputWidget):
     type = u"string"
 
     def show(self):
@@ -223,15 +223,15 @@
                 self.value = value
 
 
-class JidInputWidget(xmlui_manager.JidInputWidget, StringWidget):
+class JidInputWidget(xmlui_base.JidInputWidget, StringWidget):
     type = u"jid_input"
 
 
-class TextBoxWidget(xmlui_manager.TextWidget, StringWidget):
+class TextBoxWidget(xmlui_base.TextWidget, StringWidget):
     type = u"textbox"
 
 
-class ListWidget(xmlui_manager.ListWidget, OptionsWidget):
+class ListWidget(xmlui_base.ListWidget, OptionsWidget):
     type = u"list"
     # TODO: handle flags, notably multi
 
@@ -277,7 +277,7 @@
         self.disp("")
 
 
-class BoolWidget(xmlui_manager.BoolWidget, InputWidget):
+class BoolWidget(xmlui_base.BoolWidget, InputWidget):
     type = u"bool"
 
     def show(self):
@@ -324,15 +324,15 @@
             child.show()
 
 
-class VerticalContainer(xmlui_manager.VerticalContainer, Container):
+class VerticalContainer(xmlui_base.VerticalContainer, Container):
     type = u"vertical"
 
 
-class PairsContainer(xmlui_manager.PairsContainer, Container):
+class PairsContainer(xmlui_base.PairsContainer, Container):
     type = u"pairs"
 
 
-class LabelContainer(xmlui_manager.PairsContainer, Container):
+class LabelContainer(xmlui_base.PairsContainer, Container):
     type = u"label"
 
     def show(self):
@@ -377,14 +377,14 @@
         raise NotImplementedError(self.__class__)
 
 
-class NoteDialog(xmlui_manager.NoteDialog, Dialog):
+class NoteDialog(xmlui_base.NoteDialog, Dialog):
     def show(self):
         # TODO: handle title and level
         self.disp(self.message)
 
     def __init__(self, _xmlui_parent, title, message, level):
         Dialog.__init__(self, _xmlui_parent)
-        xmlui_manager.NoteDialog.__init__(self, _xmlui_parent)
+        xmlui_base.NoteDialog.__init__(self, _xmlui_parent)
         self.title, self.message, self.level = title, message, level
 
 
@@ -398,7 +398,7 @@
             return cls
 
 
-class XMLUIPanel(xmlui_manager.XMLUIPanel):
+class XMLUIPanel(xmlui_base.XMLUIPanel):
     widget_factory = WidgetFactory()
     _actions = 0  # use to keep track of bridge's launchAction calls
     read_only = False
@@ -406,18 +406,9 @@
     workflow = None
     _submit_cb = None
 
-    def __init__(
-        self,
-        host,
-        parsed_dom,
-        title=None,
-        flags=None,
-        callback=None,
-        ignore=None,
-        whitelist=None,
-        profile=None,
-    ):
-        xmlui_manager.XMLUIPanel.__init__(
+    def __init__(self, host, parsed_dom, title=None, flags=None, callback=None,
+                 ignore=None, whitelist=None, profile=None):
+        xmlui_base.XMLUIPanel.__init__(
             self,
             host,
             parsed_dom,
@@ -500,7 +491,7 @@
         assert XMLUIPanel._actions >= 0
         if u"xmlui" in data:
             xmlui_raw = data["xmlui"]
-            xmlui = xmlui_manager.create(self.host, xmlui_raw)
+            xmlui = create(self.host, xmlui_raw)
             xmlui.show()
             if xmlui.submit_id:
                 xmlui.onFormSubmitted()
@@ -526,7 +517,7 @@
         )
 
 
-class XMLUIDialog(xmlui_manager.XMLUIDialog):
+class XMLUIDialog(xmlui_base.XMLUIDialog):
     type = "dialog"
     dialog_factory = WidgetFactory()
     read_only = False
@@ -538,6 +529,6 @@
         pass
 
 
-xmlui_manager.registerClass(xmlui_manager.CLASS_PANEL, XMLUIPanel)
-xmlui_manager.registerClass(xmlui_manager.CLASS_DIALOG, XMLUIDialog)
-create = xmlui_manager.create
+create = partial(xmlui_base.create, class_map={
+    xmlui_base.CLASS_PANEL: XMLUIPanel,
+    xmlui_base.CLASS_DIALOG: XMLUIDialog})
--- a/sat_frontends/quick_frontend/quick_app.py	Fri Aug 31 15:57:11 2018 +0200
+++ b/sat_frontends/quick_frontend/quick_app.py	Fri Aug 31 16:03:12 2018 +0200
@@ -1121,14 +1121,8 @@
             if value and entity in self.contact_lists[profile]:
                 self.getAvatar(entity, ignore_cache=True, profile=profile)
 
-    def actionManager(
-        self,
-        action_data,
-        callback=None,
-        ui_show_cb=None,
-        user_action=True,
-        profile=C.PROF_KEY_NONE,
-    ):
+    def actionManager(self, action_data, callback=None, ui_show_cb=None, user_action=True,
+                      profile=C.PROF_KEY_NONE):
         """Handle backend action
 
         @param action_data(dict): action dict as sent by launchAction or returned by an
--- a/sat_frontends/tools/xmlui.py	Fri Aug 31 15:57:11 2018 +0200
+++ b/sat_frontends/tools/xmlui.py	Fri Aug 31 16:03:12 2018 +0200
@@ -25,7 +25,7 @@
 from sat.core import exceptions
 
 
-class_map = {}
+_class_map = {}
 CLASS_PANEL = "panel"
 CLASS_DIALOG = "dialog"
 CURRENT_LABEL = "current_label"
@@ -986,22 +986,22 @@
         CLASS_DIALOG: XMLUI dialog
     @param class_: the class to use to instanciate given type
     """
+    # TODO: remove this method, as there are seme use cases where different XMLUI
+    #       classes can be used in the same frontend, so a global value is not good
     assert type_ in (CLASS_PANEL, CLASS_DIALOG)
-    class_map[type_] = class_
+    log.warning(u"registerClass for XMLUI is deprecated, please use partial with "
+                u"xmlui.create and class_map instead")
+    if type_ in _class_map:
+        log.debug(_(u"XMLUI class already registered for {type_}, ignoring").format(
+            type_=type_))
+        return
+
+    _class_map[type_] = class_
 
 
-def create(
-    host,
-    xml_data,
-    title=None,
-    flags=None,
-    dom_parse=None,
-    dom_free=None,
-    callback=None,
-    ignore=None,
-    whitelist=None,
-    profile=C.PROF_KEY_NONE,
-):
+def create(host, xml_data, title=None, flags=None, dom_parse=None, dom_free=None,
+           callback=None, ignore=None, whitelist=None, class_map=None,
+           profile=C.PROF_KEY_NONE):
     """
         @param dom_parse: methode equivalent to minidom.parseString (but which must manage unicode), or None to use default one
         @param dom_free: method used to free the parsed DOM
@@ -1011,6 +1011,8 @@
             when not None, only widgets in this list and their label will be kept
             mutually exclusive with ignore
     """
+    if class_map is None:
+        class_map = _class_map
     if dom_parse is None:
         from xml.dom import minidom