changeset 2668:c274201cea94

core, frontends (xmlui): added "hidden" widget, to specify a value to be returned unmodified
author Goffi <goffi@goffi.org>
date Fri, 31 Aug 2018 15:57:11 +0200
parents 8dd9db785ac8
children bdb8276fd2da
files sat/tools/xml_tools.py sat_frontends/tools/xmlui.py
diffstat 2 files changed, 57 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/sat/tools/xml_tools.py	Fri Aug 31 15:47:00 2018 +0200
+++ b/sat/tools/xml_tools.py	Fri Aug 31 15:57:11 2018 +0200
@@ -78,6 +78,8 @@
         widget_type = "textbox"
         widget_args[0] = u"\n".join(field.values)
         widget_kwargs["read_only"] = read_only
+    elif field.fieldType == "hidden":
+        widget_type = "hidden"
     elif field.fieldType == "text-private":
         widget_type = "password"
         widget_kwargs["read_only"] = read_only
@@ -148,11 +150,12 @@
             widget_type, widget_args, widget_kwargs = widget_filter(
                 form_ui, widget_type, widget_args, widget_kwargs
             )
-        label = field.label or field.var
-        if label:
-            form_ui.addLabel(label)
-        else:
-            form_ui.addEmpty()
+        if widget_type != "hidden":
+            label = field.label or field.var
+            if label:
+                form_ui.addLabel(label)
+            else:
+                form_ui.addEmpty()
 
         form_ui.addWidget(widget_type, *widget_args, **widget_kwargs)
 
@@ -902,7 +905,6 @@
 
     used most of time to display the desciption or name of the next widget
     """
-
     type = "label"
 
     def __init__(self, xmlui, label, name=None, parent=None):
@@ -910,6 +912,22 @@
         self.elem.setAttribute("value", label)
 
 
+class HiddenWidget(Widget):
+    """Not displayed widget, frontends will just copy the value(s)"""
+    type = "hidden"
+
+    def __init__(self, xmlui, value, name, parent=None):
+        super(HiddenWidget, self).__init__(xmlui, name, parent)
+        value_elt = self.xmlui.doc.createElement("value")
+        text = self.xmlui.doc.createTextNode(value)
+        value_elt.appendChild(text)
+        self.elem.appendChild(value_elt)
+
+    @property
+    def value(self):
+        return self.elem.firstChild.firstChild.wholeText
+
+
 class JidWidget(Widget):
     """Used to display a Jabber ID, some specific methods can be added"""
 
--- a/sat_frontends/tools/xmlui.py	Fri Aug 31 15:47:00 2018 +0200
+++ b/sat_frontends/tools/xmlui.py	Fri Aug 31 15:57:11 2018 +0200
@@ -29,6 +29,7 @@
 CLASS_PANEL = "panel"
 CLASS_DIALOG = "dialog"
 CURRENT_LABEL = "current_label"
+HIDDEN = "hidden"
 
 
 class InvalidXMLUI(Exception):
@@ -261,15 +262,8 @@
     This class must not be instancied directly
     """
 
-    def __init__(
-        self,
-        host,
-        parsed_dom,
-        title=None,
-        flags=None,
-        callback=None,
-        profile=C.PROF_KEY_NONE,
-    ):
+    def __init__(self, host, parsed_dom, title=None, flags=None, callback=None,
+                 profile=C.PROF_KEY_NONE):
         """Initialise the XMLUI instance
 
         @param host: %(doc_host)s
@@ -277,17 +271,22 @@
         @param title: force the title, or use XMLUI one if None
         @param flags: list of string which can be:
             - NO_CANCEL: the UI can't be cancelled
-            - FROM_BACKEND: the UI come from backend (i.e. it's not the direct result of user operation)
+            - FROM_BACKEND: the UI come from backend (i.e. it's not the direct result of
+                            user operation)
         @param callback(callable, None): if not None, will be used with launchAction:
-            - if None is used, default behaviour will be used (closing the dialog and calling host.actionManager)
+            - if None is used, default behaviour will be used (closing the dialog and
+              calling host.actionManager)
             - if a callback is provided, it will be used instead, so you'll have to manage
-                dialog closing or new xmlui to display, or other action (you can call host.actionManager)
+                dialog closing or new xmlui to display, or other action (you can call
+                host.actionManager)
+                The callback will have data, callback_id and profile as arguments
         """
         self.host = host
         top = parsed_dom.documentElement
         self.session_id = top.getAttribute("session_id") or None
         self.submit_id = top.getAttribute("submit") or None
         self.xmlui_title = title or top.getAttribute("title") or u""
+        self.hidden = {}
         if flags is None:
             flags = []
         self.flags = flags
@@ -333,7 +332,8 @@
             raise ValueError("Can't submit is self.submit_id is not set")
         if "session_id" in data:
             raise ValueError(
-                "session_id must no be used in data, it is automaticaly filled with self.session_id if present"
+                u"session_id must no be used in data, it is automaticaly filled with "
+                u"self.session_id if present"
             )
         if self.session_id is not None:
             data["session_id"] = self.session_id
@@ -379,17 +379,8 @@
 
     widget_factory = None
 
-    def __init__(
-        self,
-        host,
-        parsed_dom,
-        title=None,
-        flags=None,
-        callback=None,
-        ignore=None,
-        whitelist=None,
-        profile=C.PROF_KEY_NONE,
-    ):
+    def __init__(self, host, parsed_dom, title=None, flags=None, callback=None,
+                 ignore=None, whitelist=None, profile=C.PROF_KEY_NONE):
         """
 
         @param title(unicode, None): title of the
@@ -416,7 +407,8 @@
             self._whitelist = None
         self.constructUI(parsed_dom)
 
-    def escape(self, name):
+    @staticmethod
+    def escape(name):
         """Return escaped name for forms"""
         return u"%s%s" % (C.SAT_FORM_PREFIX, name)
 
@@ -435,7 +427,8 @@
 
         @param _xmlui_parent: widget container with '_xmluiAppend' method
         @param current_node: element from which childs will be parsed
-        @param wanted: list of tag names that can be present in the childs to be SàT XMLUI compliant
+        @param wanted: list of tag names that can be present in the childs to be SàT XMLUI
+                       compliant
         @param data(None, dict): additionnal data which are needed in some cases
         """
         for node in current_node.childNodes:
@@ -447,7 +440,8 @@
             if node.nodeName == "container":
                 type_ = node.getAttribute("type")
                 if _xmlui_parent is self and type_ != "vertical":
-                    # main container is not a VerticalContainer and we want one, so we create one to wrap it
+                    # main container is not a VerticalContainer and we want one,
+                    # so we create one to wrap it
                     _xmlui_parent = self.widget_factory.createVerticalContainer(self)
                     self.main_cont = _xmlui_parent
                 if type_ == "tabs":
@@ -557,6 +551,12 @@
                 elif type_ == "label":
                     ctrl = self.widget_factory.createLabelWidget(_xmlui_parent, value)
                     data[CURRENT_LABEL] = ctrl
+                elif type_ == "hidden":
+                    if name in self.hidden:
+                        raise exceptions.ConflictError(u"Conflict on hidden value with "
+                                                       u"name {name}".format(name=name))
+                    self.hidden[name] = value
+                    continue
                 elif type_ == "jid":
                     ctrl = self.widget_factory.createJidWidget(_xmlui_parent, value)
                 elif type_ == "divider":
@@ -650,7 +650,8 @@
                     except (
                         AttributeError,
                         TypeError,
-                    ):  # XXX: TypeError is here because pyjamas raise a TypeError instead of an AttributeError
+                    ):  # XXX: TypeError is here because pyjamas raise a TypeError instead
+                        #      of an AttributeError
                         if not isinstance(
                             ctrl, (EmptyWidget, TextWidget, LabelWidget, JidWidget)
                         ):
@@ -857,8 +858,11 @@
                 )
             else:
                 selected_values.append((escaped, ctrl["control"]._xmluiGetValue()))
+        data = dict(selected_values)
+        for key, value in self.hidden.iteritems():
+            data[self.escape(key)] = value
+
         if self.submit_id is not None:
-            data = dict(selected_values)
             self.submit(data)
         else:
             log.warning(