changeset 777:5642939d254e

core, bridge: new method paramsRegisterApp to register frontend's specific parameters
author souliane <souliane@mailoo.org>
date Fri, 27 Dec 2013 13:28:26 +0100
parents f89173f44850
children bfafed251b40
files frontends/src/bridge/DBus.py frontends/src/constants.py frontends/src/primitivus/primitivus frontends/src/wix/main_window.py frontends/src/wix/param.py src/bridge/DBus.py src/bridge/bridge.py src/bridge/bridge_constructor/bridge_template.ini src/core/sat_main.py src/memory/memory.py
diffstat 10 files changed, 175 insertions(+), 59 deletions(-) [+]
line wrap: on
line diff
--- a/frontends/src/bridge/DBus.py	Fri Jan 03 21:25:07 2014 +0100
+++ b/frontends/src/bridge/DBus.py	Fri Dec 27 13:28:26 2013 +0100
@@ -152,17 +152,17 @@
     def getParamA(self, name, category, attribute="value", profile_key="@DEFAULT@"):
         return unicode(self.db_core_iface.getParamA(name, category, attribute, profile_key))
 
-    def getParams(self, security_limit=-1, profile_key="@DEFAULT@", callback=None, errback=None):
-        return unicode(self.db_core_iface.getParams(security_limit, profile_key, reply_handler=callback, error_handler=lambda err:errback(err._dbus_error_name[len(const_ERROR_PREFIX)+1:])))
+    def getParams(self, security_limit=-1, app='', profile_key="@DEFAULT@", callback=None, errback=None):
+        return unicode(self.db_core_iface.getParams(security_limit, app, profile_key, reply_handler=callback, error_handler=lambda err:errback(err._dbus_error_name[len(const_ERROR_PREFIX)+1:])))
 
     def getParamsCategories(self, ):
         return self.db_core_iface.getParamsCategories()
 
-    def getParamsForCategory(self, category, security_limit=-1, profile_key="@DEFAULT@", callback=None, errback=None):
-        return unicode(self.db_core_iface.getParamsForCategory(category, security_limit, profile_key, reply_handler=callback, error_handler=lambda err:errback(err._dbus_error_name[len(const_ERROR_PREFIX)+1:])))
+    def getParamsForCategory(self, category, security_limit=-1, app='', profile_key="@DEFAULT@", callback=None, errback=None):
+        return unicode(self.db_core_iface.getParamsForCategory(category, security_limit, app, profile_key, reply_handler=callback, error_handler=lambda err:errback(err._dbus_error_name[len(const_ERROR_PREFIX)+1:])))
 
-    def getParamsUI(self, security_limit=-1, profile_key="@DEFAULT@", callback=None, errback=None):
-        return unicode(self.db_core_iface.getParamsUI(security_limit, profile_key, reply_handler=callback, error_handler=lambda err:errback(err._dbus_error_name[len(const_ERROR_PREFIX)+1:])))
+    def getParamsUI(self, security_limit=-1, app='', profile_key="@DEFAULT@", callback=None, errback=None):
+        return unicode(self.db_core_iface.getParamsUI(security_limit, app, profile_key, reply_handler=callback, error_handler=lambda err:errback(err._dbus_error_name[len(const_ERROR_PREFIX)+1:])))
 
     def getPresenceStatus(self, profile_key="@DEFAULT@"):
         return self.db_core_iface.getPresenceStatus(profile_key)
@@ -191,6 +191,9 @@
     def launchAction(self, callback_id, data, profile_key="@DEFAULT@", callback=None, errback=None):
         return self.db_core_iface.launchAction(callback_id, data, profile_key, reply_handler=callback, error_handler=lambda err:errback(err._dbus_error_name[len(const_ERROR_PREFIX)+1:]))
 
+    def paramsRegisterApp(self, xml, security_limit=-1, app=''):
+        return self.db_core_iface.paramsRegisterApp(xml, security_limit, app)
+
     def registerNewAccount(self, login, password, email, host, port=5222):
         return unicode(self.db_core_iface.registerNewAccount(login, password, email, host, port))
 
--- a/frontends/src/constants.py	Fri Jan 03 21:25:07 2014 +0100
+++ b/frontends/src/constants.py	Fri Dec 27 13:28:26 2013 +0100
@@ -18,7 +18,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
-from sat.core.i18n import _
+from sat.core.i18n import _, D_
 
 try:
     from collections import OrderedDict  # only available from python 2.7
@@ -56,7 +56,7 @@
     MENU_NORMAL = "NORMAL"
 
     # from plugin_misc_text_syntaxes
-    _SYNTAX_XHTML = "XHTML"
-    _SYNTAX_CURRENT = "@CURRENT@"
+    SYNTAX_XHTML = "XHTML"
+    SYNTAX_CURRENT = "@CURRENT@"
 
     NO_SECURITY_LIMIT = -1
--- a/frontends/src/primitivus/primitivus	Fri Jan 03 21:25:07 2014 +0100
+++ b/frontends/src/primitivus/primitivus	Fri Dec 27 13:28:26 2013 +0100
@@ -574,11 +574,11 @@
 
     def onParam(self, menu):
         def success(params):
-            self.addWindow(XMLUI(self,xml_data=params))
+            self.addWindow(XMLUI(self, xml_data=params))
+
         def failure(error):
             self.showPopUp(sat_widgets.Alert(_("Error"), _("Can't get parameters"), ok_cb=self.removePopUp))
-        self.bridge.getParamsUI(profile_key=self.profile, callback=success, errback=failure)
-
+        self.bridge.getParamsUI(app=Const.APP_NAME, profile_key=self.profile, callback=success, errback=failure)
 
     def onExitRequest(self, menu):
         QuickApp.onExit(self)
--- a/frontends/src/wix/main_window.py	Fri Jan 03 21:25:07 2014 +0100
+++ b/frontends/src/wix/main_window.py	Fri Dec 27 13:28:26 2013 +0100
@@ -407,9 +407,7 @@
 
     def onParam(self, e):
         debug(_("Param request"))
-        #xmlui = self.bridge.getParamsUI(profile_key=self.profile)
-        #XMLUI(self, xml_data = xmlui)
-        param=Param(self)
+        param = Param(self)
 
     def onAbout(self, e):
         about = wx.AboutDialogInfo()
--- a/frontends/src/wix/param.py	Fri Jan 03 21:25:07 2014 +0100
+++ b/frontends/src/wix/param.py	Fri Dec 27 13:28:26 2013 +0100
@@ -25,6 +25,7 @@
 from xml.dom import minidom
 from logging import debug, info, error
 from sat.tools.jid  import JID
+from sat_frontends.wix.constants import Const
 
 
 class Param(wx.Frame):
@@ -104,6 +105,7 @@
             cat_dom.unlink()
 
         self.host.bridge.getParamsForCategory(category,
+                                              app=Const.APP_NAME,
                                               profile_key=self.host.profile,
                                               callback=gotParams,
                                               errback=errorGettingParams)
--- a/src/bridge/DBus.py	Fri Jan 03 21:25:07 2014 +0100
+++ b/src/bridge/DBus.py	Fri Dec 27 13:28:26 2013 +0100
@@ -300,10 +300,10 @@
         return self._callback("getParamA", unicode(name), unicode(category), unicode(attribute), unicode(profile_key))
 
     @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
-                         in_signature='is', out_signature='s',
+                         in_signature='iss', out_signature='s',
                          async_callbacks=('callback', 'errback'))
-    def getParams(self, security_limit=-1, profile_key="@DEFAULT@", callback=None, errback=None):
-        return self._callback("getParams", security_limit, unicode(profile_key), callback=callback, errback=errback)
+    def getParams(self, security_limit=-1, app='', profile_key="@DEFAULT@", callback=None, errback=None):
+        return self._callback("getParams", security_limit, unicode(app), unicode(profile_key), callback=callback, errback=errback)
 
     @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
                          in_signature='', out_signature='as',
@@ -312,16 +312,16 @@
         return self._callback("getParamsCategories", )
 
     @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
-                         in_signature='sis', out_signature='s',
+                         in_signature='siss', out_signature='s',
                          async_callbacks=('callback', 'errback'))
-    def getParamsForCategory(self, category, security_limit=-1, profile_key="@DEFAULT@", callback=None, errback=None):
-        return self._callback("getParamsForCategory", unicode(category), security_limit, unicode(profile_key), callback=callback, errback=errback)
+    def getParamsForCategory(self, category, security_limit=-1, app='', profile_key="@DEFAULT@", callback=None, errback=None):
+        return self._callback("getParamsForCategory", unicode(category), security_limit, unicode(app), unicode(profile_key), callback=callback, errback=errback)
 
     @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
-                         in_signature='is', out_signature='s',
+                         in_signature='iss', out_signature='s',
                          async_callbacks=('callback', 'errback'))
-    def getParamsUI(self, security_limit=-1, profile_key="@DEFAULT@", callback=None, errback=None):
-        return self._callback("getParamsUI", security_limit, unicode(profile_key), callback=callback, errback=errback)
+    def getParamsUI(self, security_limit=-1, app='', profile_key="@DEFAULT@", callback=None, errback=None):
+        return self._callback("getParamsUI", security_limit, unicode(app), unicode(profile_key), callback=callback, errback=errback)
 
     @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
                          in_signature='s', out_signature='a{sa{s(sia{ss})}}',
@@ -378,6 +378,12 @@
         return self._callback("launchAction", unicode(callback_id), data, unicode(profile_key), callback=callback, errback=errback)
 
     @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
+                         in_signature='sis', out_signature='',
+                         async_callbacks=None)
+    def paramsRegisterApp(self, xml, security_limit=-1, app=''):
+        return self._callback("paramsRegisterApp", unicode(xml), security_limit, unicode(app))
+
+    @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
                          in_signature='ssssi', out_signature='s',
                          async_callbacks=None)
     def registerNewAccount(self, login, password, email, host, port=5222):
--- a/src/bridge/bridge.py	Fri Jan 03 21:25:07 2014 +0100
+++ b/src/bridge/bridge.py	Fri Dec 27 13:28:26 2013 +0100
@@ -59,7 +59,7 @@
     def getParam(self, name, namespace):
         raise NotImplementedError
 
-    def getParams(self, security_limit, namespace):
+    def getParams(self, security_limit, app, namespace):
         raise NotImplementedError
 
     def getHistory(self, from_jid, to_jid, size):
--- a/src/bridge/bridge_constructor/bridge_template.ini	Fri Jan 03 21:25:07 2014 +0100
+++ b/src/bridge/bridge_constructor/bridge_template.ini	Fri Dec 27 13:28:26 2013 +0100
@@ -447,38 +447,44 @@
 async=
 type=method
 category=core
-sig_in=is
+sig_in=iss
 sig_out=s
 param_0_default=-1
-param_1_default="@DEFAULT@"
-doc=Return a SàT XMLUI for parameters
+param_1_default=''
+param_2_default="@DEFAULT@"
+doc=Return a SàT XMLUI for parameters, eventually restrict the result to the parameters concerning a given frontend
 doc_param_0=%(doc_security_limit)s
-doc_param_1=%(doc_profile_key)s
+doc_param_1=app: name of the frontend requesting the parameters, or '' to get all parameters
+doc_param_2=%(doc_profile_key)s
 
 [getParams]
 async=
 type=method
 category=core
-sig_in=is
+sig_in=iss
 sig_out=s
 param_0_default=-1
-param_1_default="@DEFAULT@"
-doc=Return XML of parameters
+param_1_default=''
+param_2_default="@DEFAULT@"
+doc=Return XML of parameters, eventually restrict the result to the parameters concerning a given frontend
 doc_param_0=%(doc_security_limit)s
-doc_param_1=%(doc_profile_key)s
+doc_param_1=app: name of the frontend requesting the parameters, or '' to get all parameters
+doc_param_2=%(doc_profile_key)s
 
 [getParamsForCategory]
 async=
 type=method
 category=core
-sig_in=sis
+sig_in=siss
 sig_out=s
 param_1_default=-1
-param_2_default="@DEFAULT@"
-doc=Return a xml of all params in a category
+param_2_default=''
+param_3_default="@DEFAULT@"
+doc=Return a xml of all params in a category, eventually restrict the result to the parameters concerning a given frontend
 doc_param_0=category: Category to get
 doc_param_1=%(doc_security_limit)s
-doc_param_2=%(doc_profile_key)s
+doc_param_2=app: name of the frontend requesting the parameters, or '' to get all parameters
+doc_param_3=%(doc_profile_key)s
 
 [getParamsCategories]
 type=method
@@ -488,6 +494,18 @@
 doc=Get all categories currently existing in parameters
 doc_return=list of categories
 
+[paramsRegisterApp]
+type=method
+category=core
+sig_in=sis
+sig_out=
+param_1_default=-1
+param_2_default=''
+doc=Register frontend's specific parameters
+doc_param_0=xml: XML definition of the parameters to be added
+doc_param_1=%(doc_security_limit)s
+doc_param_2=app: name of the frontend registering the parameters
+
 [getHistory]
 async=
 type=method
--- a/src/core/sat_main.py	Fri Jan 03 21:25:07 2014 +0100
+++ b/src/core/sat_main.py	Fri Dec 27 13:28:26 2013 +0100
@@ -150,6 +150,7 @@
         self.bridge.register("getParams", self.memory.getParams)
         self.bridge.register("getParamsForCategory", self.memory.getParamsForCategory)
         self.bridge.register("getParamsCategories", self.memory.getParamsCategories)
+        self.bridge.register("paramsRegisterApp", self.memory.paramsRegisterApp)
         self.bridge.register("getHistory", self.memory.getHistory)
         self.bridge.register("setPresence", self.setPresence)
         self.bridge.register("subscription", self.subscription)
--- a/src/memory/memory.py	Fri Jan 03 21:25:07 2014 +0100
+++ b/src/memory/memory.py	Fri Dec 27 13:28:26 2013 +0100
@@ -295,10 +295,40 @@
         #the node is new
         return None
 
-    def updateParams(self, xml):
+    def updateParams(self, xml, security_limit=NO_SECURITY_LIMIT, app=''):
         """import xml in parameters, do nothing if the param already exist
-        @param xml: parameters in xml form"""
-        src_dom = minidom.parseString(xml.encode('utf-8'))
+        If security_limit is specified and greater than -1, the parameters
+        that have a security level lower than security_limit are skipped.
+        @param xml: parameters in xml form
+        @param security_limit: -1 means no security then the higher the most secure
+        @param app: name of the frontend registering the parameters or empty value
+        """
+        src_parent = minidom.parseString(xml.encode('utf-8')).documentElement
+
+        def pre_process_app_node(src_parent, security_limit, app):
+            """Parameters that are registered from a frontend must be checked"""
+            to_remove = []
+            for type_node in src_parent.childNodes:
+                if type_node.nodeName != INDIVIDUAL:
+                    to_remove.append(type_node)  # accept individual parameters only
+                    continue
+                for cat_node in type_node.childNodes:
+                    if cat_node.nodeName != 'category':
+                        to_remove.append(cat_node)
+                        continue
+                    to_remove_count = 0  # count the params to be removed from current category
+                    for node in cat_node.childNodes:
+                        if node.nodeName != "param" or not self.checkSecurityLimit(node, security_limit):
+                            to_remove.append(node)
+                            to_remove_count += 1
+                            continue
+                        node.setAttribute('app', app)
+                    if len(cat_node.childNodes) == to_remove_count:  # remove empty category
+                        for dummy in xrange(0, to_remove_count):
+                            to_remove.pop()
+                        to_remove.append(cat_node)
+            for node in to_remove:
+                node.parentNode.removeChild(node)
 
         def import_node(tgt_parent, src_parent):
             for child in src_parent.childNodes:
@@ -315,7 +345,28 @@
                         # the node already exists, we recurse 1 more level
                         import_node(node, child)
 
-        import_node(self.dom.documentElement, src_dom.documentElement)
+        if app:
+            pre_process_app_node(src_parent, security_limit, app)
+        import_node(self.dom.documentElement, src_parent)
+
+    def paramsRegisterApp(self, xml, security_limit, app):
+        """Register frontend's specific parameters
+        If security_limit is specified and greater than -1, the parameters
+        that have a security level lower than security_limit are skipped.
+        @param xml: XML definition of the parameters to be added
+        @param security_limit: -1 means no security then the higher the most secure
+        @param app: name of the frontend registering the parameters
+        """
+        if not app:
+            warning(_("Trying to register frontends parameters with no specified app: aborted"))
+            return
+        if not hasattr(self, "frontends_cache"):
+            self.frontends_cache = {}
+        if app in self.frontends_cache:
+            warning(_("Trying to register twice frontends parameters for %(app)s: aborted" % {"app": app}))
+            return
+        self.updateParams(xml, security_limit, app)
+        debug("Frontends parameters registered for %(app)s" % {'app': app})
 
     def __default_ok(self, value, name, category):
         #FIXME: will not work with individual parameters
@@ -471,12 +522,13 @@
             return None
         return cache[(category, name)]
 
-    def __constructProfileXml(self, security_limit, profile):
+    def __constructProfileXml(self, security_limit, app, profile):
         """Construct xml for asked profile, filling values when needed
         /!\ as noticed in doc, don't forget to unlink the minidom.Document
-        @security_limit: NO_SECURITY_LIMIT (-1) to return all the params.
+        @param security_limit: NO_SECURITY_LIMIT (-1) to return all the params.
         Otherwise sole the params which have a security level defined *and*
         lower or equal to the specified value are returned.
+        @param app: name of the frontend requesting the parameters, or '' to get all parameters
         @param profile: profile name (not key !)
         @return: a deferred that fire a minidom.Document of the profile xml (cf warning above)
         """
@@ -518,6 +570,8 @@
                         name = param_node.getAttribute('name')
                         if not self.checkSecurityLimit(param_node, security_limit):
                             continue
+                        if not self.checkApp(param_node, app):
+                            continue
                         if name not in dest_params:
                             # this is reached when a previous category exists
                             dest_params[name] = param_node.cloneNode(True)
@@ -551,18 +605,31 @@
 
         return d.addCallback(constructProfile, profile_cache)
 
-    def getParamsUI(self, security_limit, profile_key):
-        """Return a SàT XMLUI for parameters, with given profile"""
+    def getParamsUI(self, security_limit, app, profile_key):
+        """
+        @param security_limit: NO_SECURITY_LIMIT (-1) to return all the params.
+        Otherwise sole the params which have a security level defined *and*
+        lower or equal to the specified value are returned.
+        @param app: name of the frontend requesting the parameters, or '' to get all parameters
+        @param profile_key: Profile key which can be either a magic (eg: @DEFAULT@) or the name of an existing profile.
+        @return: a SàT XMLUI for parameters
+        """
         profile = self.getProfileName(profile_key)
         if not profile:
             error(_("Asking params for inexistant profile"))
             return ""
-        d = self.getParams(security_limit, profile)
+        d = self.getParams(security_limit, app, profile)
         return d.addCallback(lambda param_xml: paramsXml2xmlUI(param_xml))
 
-    def getParams(self, security_limit, profile_key):
-        """Construct xml for asked profile
-        Take params xml as skeleton"""
+    def getParams(self, security_limit, app, profile_key):
+        """Construct xml for asked profile, take params xml as skeleton
+        @param security_limit: NO_SECURITY_LIMIT (-1) to return all the params.
+        Otherwise sole the params which have a security level defined *and*
+        lower or equal to the specified value are returned.
+        @param app: name of the frontend requesting the parameters, or '' to get all parameters
+        @param profile_key: Profile key which can be either a magic (eg: @DEFAULT@) or the name of an existing profile.
+        @return: XML of parameters
+        """
         profile = self.getProfileName(profile_key)
         if not profile:
             error(_("Asking params for inexistant profile"))
@@ -573,10 +640,18 @@
             prof_xml.unlink()
             return '\n'.join((line for line in return_xml.split('\n') if line))
 
-        return self.__constructProfileXml(security_limit, profile).addCallback(returnXML)
+        return self.__constructProfileXml(security_limit, app, profile).addCallback(returnXML)
 
-    def getParamsForCategory(self, category, security_limit, profile_key):
-        """Return node's xml for selected category"""
+    def getParamsForCategory(self, category, security_limit, app, profile_key):
+        """
+        @param category: the desired category
+        @param security_limit: NO_SECURITY_LIMIT (-1) to return all the params.
+        Otherwise sole the params which have a security level defined *and*
+        lower or equal to the specified value are returned.
+        @param app: name of the frontend requesting the parameters, or '' to get all parameters
+        @param profile_key: Profile key which can be either a magic (eg: @DEFAULT@) or the name of an existing profile.
+        @return: node's xml for selected category
+        """
         #TODO: manage category of general type (without existant profile)
         profile = self.getProfileName(profile_key)
         if not profile:
@@ -593,7 +668,7 @@
             prof_xml.unlink()
             return "<category />"
 
-        d = self.__constructProfileXml(security_limit, profile)
+        d = self.__constructProfileXml(security_limit, app, profile)
         return d.addCallback(returnCategoryXml)
 
     def _getParamNode(self, name, category, type_="@ALL@"):  # FIXME: is type_ useful ?
@@ -680,6 +755,16 @@
                 return True
         return False
 
+    def checkApp(self, node, app):
+        """Check the given node against the given app.
+        @param node: parameter node
+        @param app: name of the frontend requesting the parameters, or '' to get all parameters
+        @return: True if this node concerns the given app.
+        """
+        if not app or not node.hasAttribute("app"):
+            return True
+        return node.getAttribute("app") == app
+
 
 class Memory(object):
     """This class manage all persistent informations"""
@@ -1063,14 +1148,14 @@
     def asyncGetStringParamA(self, name, category, attr="value", security_limit=NO_SECURITY_LIMIT, profile_key='@NONE@'):
         return self.params.asyncGetStringParamA(name, category, attr, security_limit, profile_key)
 
-    def getParamsUI(self, security_limit=NO_SECURITY_LIMIT, profile_key='@NONE@'):
-        return self.params.getParamsUI(security_limit, profile_key)
+    def getParamsUI(self, security_limit=NO_SECURITY_LIMIT, app='', profile_key='@NONE@'):
+        return self.params.getParamsUI(security_limit, app, profile_key)
 
-    def getParams(self, security_limit=NO_SECURITY_LIMIT, profile_key='@NONE@'):
-        return self.params.getParams(security_limit, profile_key)
+    def getParams(self, security_limit=NO_SECURITY_LIMIT, app='', profile_key='@NONE@'):
+        return self.params.getParams(security_limit, app, profile_key)
 
-    def getParamsForCategory(self, category, security_limit=NO_SECURITY_LIMIT, profile_key='@NONE@'):
-        return self.params.getParamsForCategory(category, security_limit, profile_key)
+    def getParamsForCategory(self, category, security_limit=NO_SECURITY_LIMIT, app='', profile_key='@NONE@'):
+        return self.params.getParamsForCategory(category, security_limit, app, profile_key)
 
     def getParamsCategories(self):
         return self.params.getParamsCategories()
@@ -1081,5 +1166,8 @@
     def updateParams(self, xml):
         return self.params.updateParams(xml)
 
+    def paramsRegisterApp(self, xml, security_limit=NO_SECURITY_LIMIT, app=''):
+        return self.params.paramsRegisterApp(xml, security_limit, app)
+
     def setDefault(self, name, category, callback, errback=None):
         return self.params.setDefault(name, category, callback, errback)