diff src/core/sat_main.py @ 755:e3ad48a2aab2

core, frontends: callMenu is now async and don't use callback_id anymore
author Goffi <goffi@goffi.org>
date Tue, 24 Dec 2013 15:18:31 +0100
parents f49945d728de
children 93bd868b8fb6
line wrap: on
line diff
--- a/src/core/sat_main.py	Tue Dec 24 01:31:18 2013 +0100
+++ b/src/core/sat_main.py	Tue Dec 24 15:18:31 2013 +0100
@@ -109,7 +109,7 @@
         self.__private_data = {}  # used for internal callbacks (key = id)
         self.profiles = {}
         self.plugins = {}
-        self.menus = {}  # used to know which new menus are wanted by plugins
+        self.menus = {}  # dynamic menus. key: (type, category, name), value: menu data (dictionnary)
 
         self.memory = Memory(self)
 
@@ -162,7 +162,7 @@
         self.bridge.register("getProgress", self.getProgress)
         self.bridge.register("getMenus", self.getMenus)
         self.bridge.register("getMenuHelp", self.getMenuHelp)
-        self.bridge.register("callMenu", self.callMenu)
+        self.bridge.register("asyncCallMenu", self.callMenu)
 
         self.memory.initialized.addCallback(self._postMemoryInit)
 
@@ -213,11 +213,11 @@
             self.plugins[import_name].is_handler = False
         #TODO: test xmppclient presence and register handler parent
 
-    def connect(self, profile_key='@DEFAULT@'):
+    def connect(self, profile_key='@NONE@'):
         """Connect to jabber server"""
         self.asyncConnect(profile_key)
 
-    def asyncConnect(self, profile_key='@DEFAULT@'):
+    def asyncConnect(self, profile_key='@NONE@'):
         """Connect to jabber server with asynchronous reply
         @param profile_key: %(doc_profile)s
         """
@@ -376,7 +376,7 @@
             return None
         return self.profiles[profile].getHostJid()
 
-    def registerNewAccount(self, login, password, email, server, port=5222, id=None, profile_key='@DEFAULT@'):
+    def registerNewAccount(self, login, password, email, server, port=5222, id=None, profile_key='@NONE@'):
         """Connect to a server and create a new account using in-band registration"""
         profile = self.memory.getProfileName(profile_key)
         assert(profile)
@@ -884,38 +884,56 @@
 
     #Menus management
 
-    def importMenu(self, category, name, callback, help_string="", type="NORMAL"):
+    def importMenu(self, category, name, callback, callback_args=None, callback_kwargs=None, help_string="", type_="NORMAL"):
         """register a new menu for frontends
         @param category: category of the menu
         @param name: menu item entry
-        @param callback: method to be called when menuitem is selected"""
-        if (category, name) in self.menus:
-            error("Want to register a menu which already existe")
-            return
-        self.menus[(category, name, type)] = {'callback': callback, 'help_string': help_string, 'type': type}
+        @param callback: method to be called when menuitem is selected
+        @param callback_args: optional arguments to forward to callback
+        @param callback_kwargs: optional keywords arguments to forward to callback
+        """
+        # TODO: manage translations
+        if (type_, category, name) in self.menus:
+            raise exceptions.ConflictError("Menu already exists")
+        menu_data = {'callback': callback, 'help_string': help_string}
+        if callback_args is not None:
+            assert(isinstance(callback_args, list))
+            menu_data['callback_args'] = callback_args
+        if callback_kwargs is not None:
+            assert(isinstance(callback_kwargs, dict))
+            menu_data['callback_kwargs'] = callback_kwargs
+        self.menus[(type_, category, name)] = menu_data
 
     def getMenus(self):
         """Return all menus registered"""
+        # TODO: manage translations
         return self.menus.keys()
 
-    def getMenuHelp(self, category, name, type="NORMAL"):
+    def getMenuHelp(self, category, name, type_="NORMAL"):
         """return the help string of the menu"""
+        # TODO: manage translations
         try:
-            return self.menus[(category, name, type)]['help_string']
+            return self.menus[(type_, category, name)]['help_string']
         except KeyError:
-            error(_("Trying to access an unknown menu"))
-            return ""
+            raise exceptions.DataError("Trying to access an unknown menu")
 
-    def callMenu(self, category, name, type="NORMAL", profile_key='@DEFAULT@'):
-        """return the id of the action"""
+    def callMenu(self, category, name, type_="NORMAL", profile_key='@NONE@'):
+        """ Call a dynamic menu
+        @param category: category of the menu to call
+        @param name: name of the menu to call
+        @param type_: type of the menu to call
+        @param profile_key: %(doc_profile_key)s
+        @return: XMLUI or empty string if it's a one shot menu
+        """
         profile = self.memory.getProfileName(profile_key)
-        if not profile_key:
-            error(_('Non-exsitant profile'))
-            return ""
-        if (category, name, type) in self.menus:
-            id = self.get_next_id()
-            self.menus[(category, name, type)]['callback'](id, profile)
-            return id
-        else:
-            error(_("Trying to access an unknown menu (%(category)s/%(name)s/%(type)s)") % {'category': category, 'name': name, 'type': type})
-            return ""
+        if not profile:
+            raise exceptions.ProfileUnknownError
+        menu_data = self.menus[(type_, category, name)]
+        callback = menu_data['callback']
+        args = menu_data.get('callback_args', ())
+        kwargs = menu_data.get('callback_kwargs', {}).copy()
+        kwargs["profile"] = profile
+        try:
+            return defer.maybeDeferred(callback, *args, **kwargs)
+        except KeyError:
+            raise exceptions.DataError("Trying to access an unknown menu (%(type)s/%(category)s/%(name)s)" % {'type': type_, 'category': category, 'name': name})