core, frontends: callMenu is now async and don't use callback_id anymore
This commit is contained in:
parent
5723ee2ef2
commit
71c1def32a
7 changed files with 93 additions and 56 deletions
|
|
@ -97,6 +97,9 @@ class DBusBridgeFrontend(BridgeFrontend):
|
|||
def addContact(self, entity_jid, profile_key="@DEFAULT@"):
|
||||
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):
|
||||
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:]))
|
||||
|
||||
|
|
@ -106,9 +109,6 @@ class DBusBridgeFrontend(BridgeFrontend):
|
|||
def asyncGetParamA(self, name, category, attribute="value", security_limit=-1, profile_key="@DEFAULT@", callback=None, errback=None):
|
||||
return unicode(self.db_core_iface.asyncGetParamA(name, category, attribute, security_limit, profile_key, reply_handler=callback, error_handler=lambda err:errback(err._dbus_error_name[len(const_ERROR_PREFIX)+1:])))
|
||||
|
||||
def callMenu(self, category, name, menu_type, profile_key):
|
||||
return unicode(self.db_core_iface.callMenu(category, name, menu_type, profile_key))
|
||||
|
||||
def confirmationAnswer(self, id, accepted, data, profile):
|
||||
return self.db_core_iface.confirmationAnswer(id, accepted, data, profile)
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@ def getPresence():
|
|||
class Const(object):
|
||||
PRESENCE = getPresence()
|
||||
|
||||
MENU_NORMAL = "NORMAL"
|
||||
|
||||
# from plugin_misc_text_syntaxes
|
||||
_SYNTAX_XHTML = "XHTML"
|
||||
_SYNTAX_CURRENT = "@CURRENT@"
|
||||
|
|
|
|||
|
|
@ -281,8 +281,15 @@ class PrimitivusApp(QuickApp, InputHistory):
|
|||
except AttributeError:
|
||||
return input
|
||||
|
||||
def _dynamicMenuCb(self, xmlui):
|
||||
misc = {}
|
||||
ui = XMLUI(self, xml_data = xmlui)
|
||||
ui.show('popup')
|
||||
|
||||
def __buildMenuRoller(self):
|
||||
def _dynamicMenuEb(self, failure):
|
||||
self.showDialog(_(u"Error while calling menu"), type="error")
|
||||
|
||||
def _buildMenuRoller(self):
|
||||
menu = sat_widgets.Menu(self.loop)
|
||||
general = _("General")
|
||||
menu.addMenu(general, _("Connect"), self.onConnectRequest)
|
||||
|
|
@ -301,29 +308,28 @@ class PrimitivusApp(QuickApp, InputHistory):
|
|||
#FIXME: do this in a more generic way (in quickapp)
|
||||
add_menus = self.bridge.getMenus()
|
||||
def add_menu_cb(menu):
|
||||
category, item = menu
|
||||
id = self.bridge.callMenu(category, item, "NORMAL", self.profile)
|
||||
self.current_action_ids.add(id)
|
||||
category, name = menu
|
||||
self.bridge.asyncCallMenu(category, name, Const.MENU_NORMAL, self.profile, callback=self._dynamicMenuCb, errback=self._dynamicMenuEb)
|
||||
for new_menu in add_menus:
|
||||
category,item,type = new_menu
|
||||
assert(type=="NORMAL") #TODO: manage other types
|
||||
menu.addMenu(unicode(category), unicode(item), add_menu_cb)
|
||||
type_, category, name = new_menu
|
||||
assert(type_=="NORMAL") #TODO: manage other types
|
||||
menu.addMenu(unicode(category), unicode(name), add_menu_cb)
|
||||
|
||||
menu_roller = sat_widgets.MenuRoller([(_('Main menu'),menu)])
|
||||
return menu_roller
|
||||
|
||||
def __buildMainWidget(self):
|
||||
def _buildMainWidget(self):
|
||||
self.contact_list = ContactList(self, on_click=self.contactSelected, on_change=lambda w: self.redraw())
|
||||
#self.center_part = urwid.Columns([('weight',2,self.contact_list),('weight',8,Chat('',self))])
|
||||
self.center_part = urwid.Columns([('weight', 2, self.contact_list), ('weight', 8, urwid.Filler(urwid.Text('')))])
|
||||
|
||||
self.editBar = EditBar(self)
|
||||
self.menu_roller = self.__buildMenuRoller()
|
||||
self.menu_roller = self._buildMenuRoller()
|
||||
self.main_widget = sat_widgets.FocusFrame(self.center_part, header=self.menu_roller, footer=self.editBar, focus_part='footer')
|
||||
return self.main_widget
|
||||
|
||||
def plug_profile(self, profile_key='@DEFAULT@'):
|
||||
self.loop.widget = self.__buildMainWidget()
|
||||
self.loop.widget = self._buildMainWidget()
|
||||
self.redraw()
|
||||
QuickApp.plug_profile(self, profile_key)
|
||||
|
||||
|
|
|
|||
|
|
@ -115,6 +115,17 @@ class MainWindow(wx.Frame, QuickApp):
|
|||
self.menuBar.EnableTop(i, True)
|
||||
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):
|
||||
info(_("Creating menus"))
|
||||
connectMenu = wx.Menu()
|
||||
|
|
@ -142,8 +153,8 @@ class MainWindow(wx.Frame, QuickApp):
|
|||
#FIXME: do this in a more generic way (in quickapp)
|
||||
add_menus = self.bridge.getMenus()
|
||||
for menu in add_menus:
|
||||
category,item,type = menu
|
||||
assert(type=="NORMAL") #TODO: manage other types
|
||||
type_,category,name = menu
|
||||
assert(type_=="NORMAL") #TODO: manage other types
|
||||
menu_idx = self.menuBar.FindMenu(category)
|
||||
current_menu = None
|
||||
if menu_idx == wx.NOT_FOUND:
|
||||
|
|
@ -154,12 +165,11 @@ class MainWindow(wx.Frame, QuickApp):
|
|||
current_menu = self.menuBar.GetMenu(menu_idx)
|
||||
assert(current_menu != None)
|
||||
item_id = wx.NewId()
|
||||
help_string = self.bridge.getMenuHelp(category, item, type)
|
||||
current_menu.Append(item_id, item, help = help_string)
|
||||
help_string = self.bridge.getMenuHelp(category, name, type_)
|
||||
current_menu.Append(item_id, name, help = help_string)
|
||||
#now we register the event
|
||||
def event_answer(e):
|
||||
id = self.bridge.callMenu(category, item, type, self.profile)
|
||||
self.current_action_ids.add(id)
|
||||
self.bridge.asyncCallMenu(category, name, Const.MENU_NORMAL, self.profile, callback=self._dynamicMenuCb, errback=self._dynamicMenuEb)
|
||||
wx.EVT_MENU(self, item_id, event_answer)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -191,6 +191,12 @@ class DbusObject(dbus.service.Object):
|
|||
def addContact(self, entity_jid, profile_key="@DEFAULT@"):
|
||||
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,
|
||||
in_signature='s', out_signature='',
|
||||
async_callbacks=('callback', 'errback'))
|
||||
|
|
@ -209,12 +215,6 @@ class DbusObject(dbus.service.Object):
|
|||
def asyncGetParamA(self, name, category, attribute="value", security_limit=-1, profile_key="@DEFAULT@", callback=None, errback=None):
|
||||
return self._callback("asyncGetParamA", unicode(name), unicode(category), unicode(attribute), security_limit, unicode(profile_key), callback=callback, errback=errback)
|
||||
|
||||
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
||||
in_signature='ssss', out_signature='s',
|
||||
async_callbacks=None)
|
||||
def callMenu(self, category, name, menu_type, profile_key):
|
||||
return self._callback("callMenu", unicode(category), unicode(name), unicode(menu_type), unicode(profile_key))
|
||||
|
||||
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
||||
in_signature='sba{ss}s', out_signature='',
|
||||
async_callbacks=None)
|
||||
|
|
|
|||
|
|
@ -574,10 +574,10 @@ sig_in=
|
|||
sig_out=a(sss)
|
||||
doc=Get all additional menus
|
||||
doc_return=list of tuple with the following value:
|
||||
- category: Category of the menu
|
||||
- name: Name of the menu
|
||||
- menu_type: Type which can be:
|
||||
* NORMAL: Classical application menu
|
||||
- category: Category of the menu
|
||||
- name: Name of the menu
|
||||
|
||||
[getMenuHelp]
|
||||
type=method
|
||||
|
|
@ -591,7 +591,8 @@ doc_param_1=name: Name of the menu
|
|||
doc_param_2=menu_type: Type of the menu as in [getMenus] return value
|
||||
doc_return=Help string
|
||||
|
||||
[callMenu]
|
||||
[asyncCallMenu]
|
||||
async=
|
||||
type=method
|
||||
category=core
|
||||
sig_in=ssss
|
||||
|
|
@ -601,4 +602,4 @@ 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 an actionId or the empty string if something went wrong
|
||||
doc_return=return a XMLUI or empty string if it is a one shot action
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ class SAT(service.Service):
|
|||
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 @@ class SAT(service.Service):
|
|||
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 @@ class SAT(service.Service):
|
|||
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 @@ class SAT(service.Service):
|
|||
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 @@ class SAT(service.Service):
|
|||
|
||||
#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})
|
||||
|
|
|
|||
Loading…
Reference in a new issue