core: dynamics menus refactoring:
- menu now use generic callback system, with extra data
- asyncMenuCall is removed in favor of launchAction
- menu_id (== callback_id) is used to identify menu instead of category/name/type tuple
- i18n is managed throught deferred translation, and returned with _i18n suffix
e.g.: menu (D_('File'), D_('Open')): (u'File', u'Open') is menu_path, (u'Fichier', u'Ouvrir') is french menu_path_i18n.
- type actually can have the following values:
- NORMAL: classical menu
- JID_CONTEXT: contextual menu, used with any jid
- ROSTER_JID_CONTEXT: like JID_CONTEXT, but restricted to jids in roster.
- ROSTER_GROUP_CONTEXT: contextual menu, use with groups
- security_limit is used, in the same way as for parameters
- when using importMenu, callback can be an actual callback, or one already registered with registerCallback
This commit is contained in:
parent
f46a7bf23d
commit
b7bf434cd2
8 changed files with 129 additions and 132 deletions
|
|
@ -98,9 +98,6 @@ class DBusBridgeFrontend(BridgeFrontend):
|
||||||
def addContact(self, entity_jid, profile_key="@DEFAULT@"):
|
def addContact(self, entity_jid, profile_key="@DEFAULT@"):
|
||||||
return self.db_core_iface.addContact(entity_jid, profile_key)
|
return self.db_core_iface.addContact(entity_jid, profile_key)
|
||||||
|
|
||||||
def asyncCallMenu(self, category, name, menu_type, profile_key, callback=None, errback=None):
|
|
||||||
return unicode(self.db_core_iface.asyncCallMenu(category, name, menu_type, profile_key, reply_handler=callback, error_handler=lambda err:errback(err._dbus_error_name[len(const_ERROR_PREFIX)+1:])))
|
|
||||||
|
|
||||||
def asyncConnect(self, profile_key="@DEFAULT@", callback=None, errback=None):
|
def asyncConnect(self, profile_key="@DEFAULT@", callback=None, errback=None):
|
||||||
return self.db_core_iface.asyncConnect(profile_key, reply_handler=callback, error_handler=lambda err:errback(err._dbus_error_name[len(const_ERROR_PREFIX)+1:]))
|
return self.db_core_iface.asyncConnect(profile_key, reply_handler=callback, error_handler=lambda err:errback(err._dbus_error_name[len(const_ERROR_PREFIX)+1:]))
|
||||||
|
|
||||||
|
|
@ -146,11 +143,11 @@ class DBusBridgeFrontend(BridgeFrontend):
|
||||||
def getLastResource(self, contact_jid, profile_key="@DEFAULT@"):
|
def getLastResource(self, contact_jid, profile_key="@DEFAULT@"):
|
||||||
return unicode(self.db_core_iface.getLastResource(contact_jid, profile_key))
|
return unicode(self.db_core_iface.getLastResource(contact_jid, profile_key))
|
||||||
|
|
||||||
def getMenuHelp(self, category, name, menu_type):
|
def getMenuHelp(self, menu_id, language):
|
||||||
return unicode(self.db_core_iface.getMenuHelp(category, name, menu_type))
|
return unicode(self.db_core_iface.getMenuHelp(menu_id, language))
|
||||||
|
|
||||||
def getMenus(self, ):
|
def getMenus(self, language, security_limit):
|
||||||
return self.db_core_iface.getMenus()
|
return self.db_core_iface.getMenus(language, security_limit)
|
||||||
|
|
||||||
def getParamA(self, name, category, attribute="value", profile_key="@DEFAULT@"):
|
def getParamA(self, name, category, attribute="value", profile_key="@DEFAULT@"):
|
||||||
return unicode(self.db_core_iface.getParamA(name, category, attribute, profile_key))
|
return unicode(self.db_core_iface.getParamA(name, category, attribute, profile_key))
|
||||||
|
|
|
||||||
|
|
@ -58,3 +58,5 @@ class Const(object):
|
||||||
# from plugin_misc_text_syntaxes
|
# from plugin_misc_text_syntaxes
|
||||||
_SYNTAX_XHTML = "XHTML"
|
_SYNTAX_XHTML = "XHTML"
|
||||||
_SYNTAX_CURRENT = "@CURRENT@"
|
_SYNTAX_CURRENT = "@CURRENT@"
|
||||||
|
|
||||||
|
NO_SECURITY_LIMIT = -1
|
||||||
|
|
|
||||||
|
|
@ -282,13 +282,6 @@ class PrimitivusApp(QuickApp, InputHistory):
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return input
|
return input
|
||||||
|
|
||||||
def _dynamicMenuCb(self, xmlui):
|
|
||||||
ui = XMLUI(self, xml_data = xmlui)
|
|
||||||
ui.show('popup')
|
|
||||||
|
|
||||||
def _dynamicMenuEb(self, failure):
|
|
||||||
self.showDialog(_(u"Error while calling menu"), type="error")
|
|
||||||
|
|
||||||
def _buildMenuRoller(self):
|
def _buildMenuRoller(self):
|
||||||
menu = sat_widgets.Menu(self.loop)
|
menu = sat_widgets.Menu(self.loop)
|
||||||
general = _("General")
|
general = _("General")
|
||||||
|
|
@ -306,14 +299,14 @@ class PrimitivusApp(QuickApp, InputHistory):
|
||||||
menu.addMenu(communication, _("Search directory"), self.onSearchDirectory)
|
menu.addMenu(communication, _("Search directory"), self.onSearchDirectory)
|
||||||
#additionals menus
|
#additionals menus
|
||||||
#FIXME: do this in a more generic way (in quickapp)
|
#FIXME: do this in a more generic way (in quickapp)
|
||||||
add_menus = self.bridge.getMenus()
|
add_menus = self.bridge.getMenus('', Const.NO_SECURITY_LIMIT)
|
||||||
def add_menu_cb(menu):
|
def add_menu_cb(callback_id):
|
||||||
category, name = menu
|
self.launchAction(callback_id, None, profile_key = self.profile)
|
||||||
self.bridge.asyncCallMenu(category, name, Const.MENU_NORMAL, self.profile, callback=self._dynamicMenuCb, errback=self._dynamicMenuEb)
|
for id_, type_, path, path_i18n in add_menus:
|
||||||
for new_menu in add_menus:
|
|
||||||
type_, category, name = new_menu
|
|
||||||
assert(type_=="NORMAL") #TODO: manage other types
|
assert(type_=="NORMAL") #TODO: manage other types
|
||||||
menu.addMenu(unicode(category), unicode(name), add_menu_cb)
|
if len(path) != 2:
|
||||||
|
raise NotImplementedError("Menu with a path != 2 are not implemented yet")
|
||||||
|
menu.addMenu(path_i18n[0], path_i18n[1], lambda menu: add_menu_cb(id_))
|
||||||
|
|
||||||
menu_roller = sat_widgets.MenuRoller([(_('Main menu'),menu)])
|
menu_roller = sat_widgets.MenuRoller([(_('Main menu'),menu)])
|
||||||
return menu_roller
|
return menu_roller
|
||||||
|
|
|
||||||
|
|
@ -116,17 +116,6 @@ class MainWindow(wx.Frame, QuickApp):
|
||||||
self.menuBar.EnableTop(i, True)
|
self.menuBar.EnableTop(i, True)
|
||||||
super(MainWindow, self).plug_profile(profile_key)
|
super(MainWindow, self).plug_profile(profile_key)
|
||||||
|
|
||||||
def _dynamicMenuCb(self, xmlui):
|
|
||||||
XMLUI(self, xml_data = xmlui)
|
|
||||||
|
|
||||||
def _dynamicMenuEb(self, failure):
|
|
||||||
dlg = wx.MessageDialog(self, _(u"Error while calling menu"),
|
|
||||||
_('Error'),
|
|
||||||
wx.OK | wx.ICON_ERROR
|
|
||||||
)
|
|
||||||
dlg.ShowModal()
|
|
||||||
dlg.Destroy()
|
|
||||||
|
|
||||||
def createMenus(self):
|
def createMenus(self):
|
||||||
info(_("Creating menus"))
|
info(_("Creating menus"))
|
||||||
connectMenu = wx.Menu()
|
connectMenu = wx.Menu()
|
||||||
|
|
@ -152,10 +141,13 @@ class MainWindow(wx.Frame, QuickApp):
|
||||||
|
|
||||||
#additionals menus
|
#additionals menus
|
||||||
#FIXME: do this in a more generic way (in quickapp)
|
#FIXME: do this in a more generic way (in quickapp)
|
||||||
add_menus = self.bridge.getMenus()
|
add_menus = self.bridge.getMenus('', Const.NO_SECURITY_LIMIT)
|
||||||
for menu in add_menus:
|
for id_, type_, path, path_i18n in add_menus:
|
||||||
type_,category,name = menu
|
|
||||||
assert(type_=="NORMAL") #TODO: manage other types
|
assert(type_=="NORMAL") #TODO: manage other types
|
||||||
|
if len(path) != 2:
|
||||||
|
raise NotImplementedError("Menu with a path != 2 are not implemented yet")
|
||||||
|
category = path_i18n[0] # TODO: manage path with more than 2 levels
|
||||||
|
name = path_i18n[1]
|
||||||
menu_idx = self.menuBar.FindMenu(category)
|
menu_idx = self.menuBar.FindMenu(category)
|
||||||
current_menu = None
|
current_menu = None
|
||||||
if menu_idx == wx.NOT_FOUND:
|
if menu_idx == wx.NOT_FOUND:
|
||||||
|
|
@ -166,11 +158,12 @@ class MainWindow(wx.Frame, QuickApp):
|
||||||
current_menu = self.menuBar.GetMenu(menu_idx)
|
current_menu = self.menuBar.GetMenu(menu_idx)
|
||||||
assert(current_menu != None)
|
assert(current_menu != None)
|
||||||
item_id = wx.NewId()
|
item_id = wx.NewId()
|
||||||
help_string = self.bridge.getMenuHelp(category, name, type_)
|
help_string = self.bridge.getMenuHelp(id_, '')
|
||||||
current_menu.Append(item_id, name, help = help_string)
|
current_menu.Append(item_id, name, help=help_string)
|
||||||
#now we register the event
|
#now we register the event
|
||||||
def event_answer(e):
|
def event_answer(e):
|
||||||
self.bridge.asyncCallMenu(category, name, Const.MENU_NORMAL, self.profile, callback=self._dynamicMenuCb, errback=self._dynamicMenuEb)
|
self.launchAction(id_, None, profile_key = self.profile)
|
||||||
|
|
||||||
wx.EVT_MENU(self, item_id, event_answer)
|
wx.EVT_MENU(self, item_id, event_answer)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -191,12 +191,6 @@ class DbusObject(dbus.service.Object):
|
||||||
def addContact(self, entity_jid, profile_key="@DEFAULT@"):
|
def addContact(self, entity_jid, profile_key="@DEFAULT@"):
|
||||||
return self._callback("addContact", unicode(entity_jid), unicode(profile_key))
|
return self._callback("addContact", unicode(entity_jid), unicode(profile_key))
|
||||||
|
|
||||||
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
|
||||||
in_signature='ssss', out_signature='s',
|
|
||||||
async_callbacks=('callback', 'errback'))
|
|
||||||
def asyncCallMenu(self, category, name, menu_type, profile_key, callback=None, errback=None):
|
|
||||||
return self._callback("asyncCallMenu", unicode(category), unicode(name), unicode(menu_type), unicode(profile_key), callback=callback, errback=errback)
|
|
||||||
|
|
||||||
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
||||||
in_signature='s', out_signature='',
|
in_signature='s', out_signature='',
|
||||||
async_callbacks=('callback', 'errback'))
|
async_callbacks=('callback', 'errback'))
|
||||||
|
|
@ -288,16 +282,16 @@ class DbusObject(dbus.service.Object):
|
||||||
return self._callback("getLastResource", unicode(contact_jid), unicode(profile_key))
|
return self._callback("getLastResource", unicode(contact_jid), unicode(profile_key))
|
||||||
|
|
||||||
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
||||||
in_signature='sss', out_signature='s',
|
in_signature='ss', out_signature='s',
|
||||||
async_callbacks=None)
|
async_callbacks=None)
|
||||||
def getMenuHelp(self, category, name, menu_type):
|
def getMenuHelp(self, menu_id, language):
|
||||||
return self._callback("getMenuHelp", unicode(category), unicode(name), unicode(menu_type))
|
return self._callback("getMenuHelp", unicode(menu_id), unicode(language))
|
||||||
|
|
||||||
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
||||||
in_signature='', out_signature='a(sss)',
|
in_signature='si', out_signature='a(ssasas)',
|
||||||
async_callbacks=None)
|
async_callbacks=None)
|
||||||
def getMenus(self, ):
|
def getMenus(self, language, security_limit):
|
||||||
return self._callback("getMenus", )
|
return self._callback("getMenus", unicode(language), security_limit)
|
||||||
|
|
||||||
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
||||||
in_signature='ssss', out_signature='s',
|
in_signature='ssss', out_signature='s',
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
doc_profile=profile: Name of the profile.
|
doc_profile=profile: Name of the profile.
|
||||||
doc_profile_key=profile_key: Profile key which can be either a magic (eg: @DEFAULT@) or the name of an existing profile.
|
doc_profile_key=profile_key: Profile key which can be either a magic (eg: @DEFAULT@) or the name of an existing profile.
|
||||||
|
doc_security_limit=security_limit: -1 means no security then the higher the most secure
|
||||||
|
|
||||||
;signals
|
;signals
|
||||||
|
|
||||||
|
|
@ -410,7 +411,7 @@ doc=Change a parameter
|
||||||
doc_param_0=name: Name of the parameter to change
|
doc_param_0=name: Name of the parameter to change
|
||||||
doc_param_1=value: New Value of the parameter
|
doc_param_1=value: New Value of the parameter
|
||||||
doc_param_2=category: Category of the parameter to change
|
doc_param_2=category: Category of the parameter to change
|
||||||
doc_param_3=security_limit: -1 means no security then the higher the most secure
|
doc_param_3=%(doc_security_limit)s
|
||||||
doc_param_4=%(doc_profile_key)s
|
doc_param_4=%(doc_profile_key)s
|
||||||
|
|
||||||
[getParamA]
|
[getParamA]
|
||||||
|
|
@ -439,7 +440,7 @@ doc=Helper method to get a parameter's attribute
|
||||||
doc_param_0=name: as for [setParam]
|
doc_param_0=name: as for [setParam]
|
||||||
doc_param_1=category: as for [setParam]
|
doc_param_1=category: as for [setParam]
|
||||||
doc_param_2=attribute: Name of the attribute
|
doc_param_2=attribute: Name of the attribute
|
||||||
doc_param_3=security_limit: -1 means no security then the higher the most secure
|
doc_param_3=%(doc_security_limit)s
|
||||||
doc_param_4=%(doc_profile_key)s
|
doc_param_4=%(doc_profile_key)s
|
||||||
|
|
||||||
[getParamsUI]
|
[getParamsUI]
|
||||||
|
|
@ -451,7 +452,7 @@ sig_out=s
|
||||||
param_0_default=-1
|
param_0_default=-1
|
||||||
param_1_default="@DEFAULT@"
|
param_1_default="@DEFAULT@"
|
||||||
doc=Return a SàT XMLUI for parameters
|
doc=Return a SàT XMLUI for parameters
|
||||||
doc_param_0=security_limit: -1 means no security then the higher the most secure
|
doc_param_0=%(doc_security_limit)s
|
||||||
doc_param_1=%(doc_profile_key)s
|
doc_param_1=%(doc_profile_key)s
|
||||||
|
|
||||||
[getParams]
|
[getParams]
|
||||||
|
|
@ -463,7 +464,7 @@ sig_out=s
|
||||||
param_0_default=-1
|
param_0_default=-1
|
||||||
param_1_default="@DEFAULT@"
|
param_1_default="@DEFAULT@"
|
||||||
doc=Return XML of parameters
|
doc=Return XML of parameters
|
||||||
doc_param_0=security_limit: -1 means no security then the higher the most secure
|
doc_param_0=%(doc_security_limit)s
|
||||||
doc_param_1=%(doc_profile_key)s
|
doc_param_1=%(doc_profile_key)s
|
||||||
|
|
||||||
[getParamsForCategory]
|
[getParamsForCategory]
|
||||||
|
|
@ -476,7 +477,7 @@ param_1_default=-1
|
||||||
param_2_default="@DEFAULT@"
|
param_2_default="@DEFAULT@"
|
||||||
doc=Return a xml of all params in a category
|
doc=Return a xml of all params in a category
|
||||||
doc_param_0=category: Category to get
|
doc_param_0=category: Category to get
|
||||||
doc_param_1=security_limit: -1 means no security then the higher the most secure
|
doc_param_1=%(doc_security_limit)s
|
||||||
doc_param_2=%(doc_profile_key)s
|
doc_param_2=%(doc_profile_key)s
|
||||||
|
|
||||||
[getParamsCategories]
|
[getParamsCategories]
|
||||||
|
|
@ -576,36 +577,26 @@ doc_return=dict with progress information:
|
||||||
[getMenus]
|
[getMenus]
|
||||||
type=method
|
type=method
|
||||||
category=core
|
category=core
|
||||||
sig_in=
|
sig_in= si
|
||||||
sig_out=a(sss)
|
sig_out=a(ssasas)
|
||||||
doc=Get all additional menus
|
doc=Get all additional menus
|
||||||
|
doc_param_0=language: language in which the menu should be translated (empty string for default)
|
||||||
|
doc_param_1=security_limit: %(doc_security_limit)s
|
||||||
doc_return=list of tuple with the following value:
|
doc_return=list of tuple with the following value:
|
||||||
|
- menu_id: menu id (same as callback id)
|
||||||
- menu_type: Type which can be:
|
- menu_type: Type which can be:
|
||||||
* NORMAL: Classical application menu
|
* NORMAL: Classical application menu
|
||||||
- category: Category of the menu
|
- menu_path: raw path of the menu
|
||||||
- name: Name of the menu
|
- menu_path_i18n: translated path of the menu
|
||||||
|
|
||||||
[getMenuHelp]
|
[getMenuHelp]
|
||||||
type=method
|
type=method
|
||||||
category=core
|
category=core
|
||||||
sig_in=sss
|
sig_in=ss
|
||||||
sig_out=s
|
sig_out=s
|
||||||
param_2="NORMAL"
|
param_2="NORMAL"
|
||||||
doc=Get help information for a menu
|
doc=Get help information for a menu
|
||||||
doc_param_0=category: Category of the menu
|
doc_param_0=menu_id: id of the menu (same as callback_id)
|
||||||
doc_param_1=name: Name of the menu
|
doc_param_1=language: language in which the menu should be translated (empty string for default)
|
||||||
doc_param_2=menu_type: Type of the menu as in [getMenus] return value
|
doc_return=Translated help string
|
||||||
doc_return=Help string
|
|
||||||
|
|
||||||
[asyncCallMenu]
|
|
||||||
async=
|
|
||||||
type=method
|
|
||||||
category=core
|
|
||||||
sig_in=ssss
|
|
||||||
sig_out=s
|
|
||||||
doc=Execute action associated with a menu
|
|
||||||
doc_param_0=category: as in [getMenuHelp]
|
|
||||||
doc_param_1=name: as in [getMenuHelp]
|
|
||||||
doc_param_2=menu_type: as in [getMenuHelp]
|
|
||||||
doc_param_3=%(doc_profile_key)s
|
|
||||||
doc_return=return a XMLUI or empty string if it is a one shot action
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from sat.core.i18n import _
|
from sat.core.i18n import _, languageSwitch
|
||||||
from twisted.application import service
|
from twisted.application import service
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
|
|
||||||
|
|
@ -39,7 +39,7 @@ import os.path
|
||||||
from sat.core.default_config import CONST
|
from sat.core.default_config import CONST
|
||||||
from sat.core import xmpp
|
from sat.core import xmpp
|
||||||
from sat.core import exceptions
|
from sat.core import exceptions
|
||||||
from sat.memory.memory import Memory
|
from sat.memory.memory import Memory, NO_SECURITY_LIMIT
|
||||||
from sat.tools.xml_tools import tupleList2dataForm
|
from sat.tools.xml_tools import tupleList2dataForm
|
||||||
from sat.tools.misc import TriggerManager
|
from sat.tools.misc import TriggerManager
|
||||||
from glob import glob
|
from glob import glob
|
||||||
|
|
@ -106,10 +106,10 @@ class SAT(service.Service):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._cb_map = {} # map from callback_id to callbacks
|
self._cb_map = {} # map from callback_id to callbacks
|
||||||
|
self._menus = {} # dynamic menus. key: callback_id, value: menu data (dictionnary)
|
||||||
self.__private_data = {} # used for internal callbacks (key = id) FIXME: to be removed
|
self.__private_data = {} # used for internal callbacks (key = id) FIXME: to be removed
|
||||||
self.profiles = {}
|
self.profiles = {}
|
||||||
self.plugins = {}
|
self.plugins = {}
|
||||||
self.menus = {} # dynamic menus. key: (type, category, name), value: menu data (dictionnary)
|
|
||||||
|
|
||||||
self.memory = Memory(self)
|
self.memory = Memory(self)
|
||||||
|
|
||||||
|
|
@ -162,7 +162,6 @@ class SAT(service.Service):
|
||||||
self.bridge.register("getProgress", self.getProgress)
|
self.bridge.register("getProgress", self.getProgress)
|
||||||
self.bridge.register("getMenus", self.getMenus)
|
self.bridge.register("getMenus", self.getMenus)
|
||||||
self.bridge.register("getMenuHelp", self.getMenuHelp)
|
self.bridge.register("getMenuHelp", self.getMenuHelp)
|
||||||
self.bridge.register("asyncCallMenu", self.callMenu)
|
|
||||||
|
|
||||||
self.memory.initialized.addCallback(self._postMemoryInit)
|
self.memory.initialized.addCallback(self._postMemoryInit)
|
||||||
|
|
||||||
|
|
@ -891,57 +890,85 @@ class SAT(service.Service):
|
||||||
|
|
||||||
#Menus management
|
#Menus management
|
||||||
|
|
||||||
def importMenu(self, category, name, callback, callback_args=None, callback_kwargs=None, help_string="", type_="NORMAL"):
|
def importMenu(self, path, callback, security_limit=NO_SECURITY_LIMIT, help_string="", type_="NORMAL"):
|
||||||
"""register a new menu for frontends
|
"""register a new menu for frontends
|
||||||
@param category: category of the menu
|
@param path: path to go to the menu (category/subcategory/.../item), must be an iterable (e.g.: ("File", "Open"))
|
||||||
@param name: menu item entry
|
/!\ use D_() instead of _() for translations (e.g. (D_("File"), D_("Open")))
|
||||||
@param callback: method to be called when menuitem is selected
|
@param callback: method to be called when menuitem is selected, callable or a callback id (string) as returned by [registerCallback]
|
||||||
@param callback_args: optional arguments to forward to callback
|
@param security_limit: %(doc_security_limit)s
|
||||||
@param callback_kwargs: optional keywords arguments to forward to callback
|
/!\ security_limit MUST be added to data in launchCallback if used
|
||||||
|
@param help_string: string used to indicate what the menu do (can be show as a tooltip).
|
||||||
|
/!\ use D_() instead of _() for translations
|
||||||
|
@param type: one of:
|
||||||
|
- NORMAL: classical menu, can be shown in a menubar on top (e.g. something like File/Open)
|
||||||
|
- JID_CONTEXT: contextual menu, used with any jid (e.g.: ad hoc commands, jid is already filled)
|
||||||
|
- ROSTER_JID_CONTEXT: like JID_CONTEXT, but restricted to jids in roster.
|
||||||
|
- ROSTER_GROUP_CONTEXT: contextual menu, used with group (e.g.: publish microblog, group is already filled)
|
||||||
|
@return: menu_id (same as callback_id)
|
||||||
"""
|
"""
|
||||||
# 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):
|
if callable(callback):
|
||||||
"""Return all menus registered"""
|
callback_id = self.registerCallback(callback, with_data=True)
|
||||||
# TODO: manage translations
|
elif isinstance(callback, basestring):
|
||||||
return self.menus.keys()
|
# The callback is already registered
|
||||||
|
callback_id = callback
|
||||||
|
try:
|
||||||
|
callback, args, kwargs = self._cb_map[callback_id]
|
||||||
|
except KeyError:
|
||||||
|
raise exceptions.DataError("Unknown callback id")
|
||||||
|
kwargs["with_data"] = True # we have to be sure that we use extra data
|
||||||
|
else:
|
||||||
|
raise exceptions.DataError("Unknown callback type")
|
||||||
|
|
||||||
def getMenuHelp(self, category, name, type_="NORMAL"):
|
for menu_data in self._menus.itervalues():
|
||||||
"""return the help string of the menu"""
|
if menu_data['path'] == path and menu_data['type'] == type_:
|
||||||
# TODO: manage translations
|
raise exceptions.ConflictError(_("A menu with the same path and type already exists"))
|
||||||
|
|
||||||
|
menu_data = {'path': path,
|
||||||
|
'security_limit': security_limit,
|
||||||
|
'help_string': help_string,
|
||||||
|
'type': type_
|
||||||
|
}
|
||||||
|
|
||||||
|
self._menus[callback_id] = menu_data
|
||||||
|
|
||||||
|
return callback_id
|
||||||
|
|
||||||
|
def getMenus(self, language='', security_limit = NO_SECURITY_LIMIT):
|
||||||
|
"""Return all menus registered
|
||||||
|
@param language: language used for translation, or empty string for default
|
||||||
|
@param security_limit: %(doc_security_limit)s
|
||||||
|
@return: array of tuple with:
|
||||||
|
- menu id (same as callback_id)
|
||||||
|
- menu type
|
||||||
|
- raw menu path (array of strings)
|
||||||
|
- translated menu path
|
||||||
|
|
||||||
|
"""
|
||||||
|
ret = []
|
||||||
|
for menu_id, menu_data in self._menus.iteritems():
|
||||||
|
type_ = menu_data['type']
|
||||||
|
path = menu_data['path']
|
||||||
|
languageSwitch(language)
|
||||||
|
path_i18n = [_(elt) for elt in path]
|
||||||
|
languageSwitch()
|
||||||
|
ret.append((menu_id, type_, path, path_i18n))
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def getMenuHelp(self, menu_id, language=''):
|
||||||
|
"""
|
||||||
|
return the help string of the menu
|
||||||
|
@param menu_id: id of the menu (same as callback_id)
|
||||||
|
@param language: language used for translation, or empty string for default
|
||||||
|
@param return: translated help
|
||||||
|
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
return self.menus[(type_, category, name)]['help_string']
|
menu_data = self._menus[menu_id]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise exceptions.DataError("Trying to access an unknown menu")
|
raise exceptions.DataError("Trying to access an unknown menu")
|
||||||
|
languageSwitch(language)
|
||||||
def callMenu(self, category, name, type_="NORMAL", profile_key='@NONE@'):
|
help_string = _(menu_data['help_string'])
|
||||||
""" Call a dynamic menu
|
languageSwitch()
|
||||||
@param category: category of the menu to call
|
return help_string
|
||||||
@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
|
|
||||||
"""
|
|
||||||
# TODO: menus should use launchCallback
|
|
||||||
profile = self.memory.getProfileName(profile_key)
|
|
||||||
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})
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from sat.core.i18n import _
|
from sat.core.i18n import _, D_
|
||||||
from logging import debug, info, warning, error
|
from logging import debug, info, warning, error
|
||||||
from twisted.words.protocols.jabber import jid
|
from twisted.words.protocols.jabber import jid
|
||||||
from twisted.words.protocols.jabber import error as xmpp_error
|
from twisted.words.protocols.jabber import error as xmpp_error
|
||||||
|
|
@ -212,7 +212,7 @@ class XEP_0050(object):
|
||||||
method=self._requestCommandsList,
|
method=self._requestCommandsList,
|
||||||
async=True)
|
async=True)
|
||||||
self.__requesting_id = host.registerCallback(self._requestingEntity, with_data=True)
|
self.__requesting_id = host.registerCallback(self._requestingEntity, with_data=True)
|
||||||
host.importMenu("Service", "commands", self._commandsMenu, help_string=_("Execute ad-hoc commands"))
|
host.importMenu((D_("Service"), D_("commands")), self._commandsMenu, help_string=D_("Execute ad-hoc commands"))
|
||||||
|
|
||||||
def getHandler(self, profile):
|
def getHandler(self, profile):
|
||||||
return XEP_0050_handler(self)
|
return XEP_0050_handler(self)
|
||||||
|
|
@ -322,7 +322,7 @@ class XEP_0050(object):
|
||||||
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def _commandsMenu(self, profile):
|
def _commandsMenu(self, menu_data, profile):
|
||||||
""" First XMLUI activated by menu: ask for target jid
|
""" First XMLUI activated by menu: ask for target jid
|
||||||
@param profile: %(doc_profile)s
|
@param profile: %(doc_profile)s
|
||||||
|
|
||||||
|
|
@ -332,7 +332,7 @@ class XEP_0050(object):
|
||||||
form_ui.changeLayout("pairs")
|
form_ui.changeLayout("pairs")
|
||||||
form_ui.addLabel("jid")
|
form_ui.addLabel("jid")
|
||||||
form_ui.addString("jid")
|
form_ui.addString("jid")
|
||||||
return form_ui.toXml()
|
return {'xmlui': form_ui.toXml()}
|
||||||
|
|
||||||
def _statusCallback(self, command_elt, session_data, action, node, profile):
|
def _statusCallback(self, command_elt, session_data, action, node, profile):
|
||||||
""" Ad-hoc command used to change the "show" part of status """
|
""" Ad-hoc command used to change the "show" part of status """
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue