# HG changeset patch # User Goffi # Date 1391528960 -3600 # Node ID 629c99bbd031dea752d0cc17ba5200110a6e4681 # Parent e8c26e24a6c793348adad0be0761fc3217300991 browser + server side: refactored menus: - getMenus is added to Register class, so it can be used before being logged - dynamic menus are added to main menu bar - security limit is used - menus use i18n diff -r e8c26e24a6c7 -r 629c99bbd031 browser_side/menu.py --- a/browser_side/menu.py Tue Feb 04 16:49:20 2014 +0100 +++ b/browser_side/menu.py Tue Feb 04 16:49:20 2014 +0100 @@ -43,12 +43,13 @@ import dialog from contact_group import ContactGroupEditor import re +from sat.core.i18n import _ class MenuCmd: - def __init__(self, object, handler): - self._object = object + def __init__(self, object_, handler): + self._object = object_ self._handler = handler def execute(self): @@ -56,6 +57,16 @@ handler() +class PluginMenuCmd: + + def __init__(self, host, action_id): + self.host = host + self.action_id = action_id + + def execute(self): + self.host.launchAction(self.action_id, None) + + class LiberviaMenuBar(MenuBar): def __init__(self): @@ -138,51 +149,65 @@ self.host = host SimplePanel.__init__(self) self.setStyleName('menuContainer') + + def createMenus(self, add_menus): _item_tpl = "%s" - - menu_general = MenuBar(vertical=True) - menu_general.addItem("Web widget", MenuCmd(self, "onWebWidget")) - menu_general.addItem("Disconnect", MenuCmd(self, "onDisconnect")) + menus_dict = {} + menus_order = [] - menu_contacts = MenuBar(vertical=True) - menu_contacts.addItem("Add contact", MenuCmd(self, "onAddContact")) - menu_contacts.addItem("Update contact", MenuCmd(self, "onUpdateContact")) - menu_contacts.addItem("Remove contact", MenuCmd(self, "onRemoveContact")) - menu_contacts.addItem("Manage groups", MenuCmd(self, "onManageContactGroups")) + def addMenu(menu_name, menu_name_i18n, item_name_i18n, icon, menu_cmd): + """ add a menu to menu_dict """ + print "addMenu:",menu_name, menu_name_i18n, item_name_i18n, icon, menu_cmd + try: + menu_bar = menus_dict[menu_name] + except KeyError: + menu_bar = menus_dict[menu_name] = MenuBar(vertical=True) + menus_order.append((menu_name, menu_name_i18n, icon)) + menu_bar.addItem(item_name_i18n, menu_cmd) - menu_group = MenuBar(vertical=True) - menu_group.addItem("Discussion", MenuCmd(self, "onJoinRoom")) - menu_group.addItem("Collective radio", MenuCmd(self, "onCollectiveRadio")) - - menu_games = MenuBar(vertical=True) - menu_games.addItem("Tarot", MenuCmd(self, "onTarotGame")) - menu_games.addItem("Xiangqi", MenuCmd(self, "onXiangqiGame")) + addMenu("General", _("General"), _("Web widget"), 'home', MenuCmd(self, "onWebWidget")) + addMenu("General", _("General"), _("Disconnect"), 'home', MenuCmd(self, "onDisconnect")) + addMenu("Contacts", _("Contacts"), _("Add contact"), 'social', MenuCmd(self, "onAddContact")) + addMenu("Contacts", _("Contacts"), _("Update contact"), 'social', MenuCmd(self, "onUpdateContact")) + addMenu("Contacts", _("Contacts"), _("Remove contact"), 'social', MenuCmd(self, "onRemoveContact")) + addMenu("Contacts", _("Contacts"), _("Manage groups"), 'social', MenuCmd(self, "onManageContactGroups")) + addMenu("Groups", _("Groups"), _("Discussion"), 'social', MenuCmd(self, "onJoinRoom")) + addMenu("Groups", _("Groups"), _("Collective radio"), 'social', MenuCmd(self, "onCollectiveRadio")) + addMenu("Games", _("Games"), _("Tarot"), 'games', MenuCmd(self, "onTarotGame")) + addMenu("Games", _("Games"), _("Xiangqi"), 'games', MenuCmd(self, "onXiangqiGame")) - menu_help = MenuBar(vertical=True) - menu_help.addItem("Social contract", MenuCmd(self, "onSocialContract")) - menu_help.addItem("About", MenuCmd(self, "onAbout")) + # additional menus + for action_id, type_, path, path_i18n in add_menus: + if not path: + print "WARNING: skipping menu without path" + continue + menu_name = path[0] + menu_name_i18n = path_i18n[0] + item_name_i18n = ' | '.join(path_i18n[1:]) + if not item_name: + print "WARNING: skipping menu with a path of lenght 1 [%s]" % path[0] + continue + addMenu(menu_name, menu_name_i18n, item_name_i18n, 'plugins', PluginMenuCmd(self.host, action_id)) - self.menu_settings = MenuBar(vertical=True) - self.item_params = self.menu_settings.addItem("Parameters", - MenuCmd(self, "onParameters")) + menus_order.append(None) # we add separator + + addMenu("Help", _("Help"), _("Social contract"), 'help', MenuCmd(self, "onSocialContract")) + addMenu("Help", _("Help"), _("About"), 'help', MenuCmd(self, "onAbout")) + addMenu("Settings", _("Settings"), _("Parameters"), 'settings', MenuCmd(self, "onParameters")) + # XXX: temporary, will change when a full profile will be managed in SàT - self.menu_settings.addItem("Upload avatar", MenuCmd(self, "onAvatarUpload")) + addMenu("Settings", _("Settings"), _("Upload avatar"), 'settings', MenuCmd(self, "onAvatarUpload")) menubar = LiberviaMenuBar() - for _name, _icon, _menu in [('General', 'home', menu_general), - ('Contacts', 'social', menu_contacts), - ('Groups', 'social', menu_group), - ('Games', 'games', menu_games)]: - menubar.addItem(MenuItem(_item_tpl % (_icon, _name), True, _menu)) - - _separator = MenuItem('', None) - _separator.setStyleName('menuSeparator') - menubar.addItem(_separator, None) - - for _name, _icon, _menu in [('Help', 'help', menu_help), - ('Settings', 'settings', self.menu_settings)]: - menubar.addItem(MenuItem(_item_tpl % (_icon, _name), True, _menu)) + for menu_data in menus_order: + if menu_data is None: + _separator = MenuItem('', None) + _separator.setStyleName('menuSeparator') + menubar.addItem(_separator, None) + else: + menu_name, menu_name_i18n, icon = menu_data + menubar.addItem(MenuItem(_item_tpl % (icon, menu_name_i18n), True, menus_dict[menu_name])) self.add(menubar) @@ -335,7 +360,7 @@ return body = XMLUI(self.host, xmlui) _dialog = dialog.GenericDialog("Parameters", body, options=['NO_CLOSE']) - body.setCloseCb(_dialog.close) + body.setCloseCb(_dialog.close) _dialog.setSize('80%', '80%') _dialog.show() self.host.bridge.call('getParamsUI', gotParams) diff -r e8c26e24a6c7 -r 629c99bbd031 libervia.py --- a/libervia.py Tue Feb 04 16:49:20 2014 +0100 +++ b/libervia.py Tue Feb 04 16:49:20 2014 +0100 @@ -113,7 +113,7 @@ class RegisterCall(LiberviaJsonProxy): def __init__(self): LiberviaJsonProxy.__init__(self, "/register_api", - ["isRegistered", "isConnected", "connect", "registerParams"]) + ["isRegistered", "isConnected", "connect", "registerParams", "getMenus"]) class BridgeCall(LiberviaJsonProxy): @@ -127,7 +127,7 @@ "getWaitingSub", "subscription", "delContact", "updateContact", "getCard", "getEntityData", "getParamsUI", "asyncGetParamA", "setParam", "launchAction", "disconnect", "chatStateComposing", "getNewAccountDomain", "confirmationAnswer", - "syntaxConvert" + "syntaxConvert", ]) @@ -184,6 +184,7 @@ self.notification = Notification() DOM.addEventPreview(self) self._register = RegisterCall() + self._register.call('getMenus', self.panel.menu.createMenus) self._register.call('registerParams', None) self._register.call('isRegistered', self._isRegisteredCB) self.initialised = False diff -r e8c26e24a6c7 -r 629c99bbd031 libervia_server/__init__.py --- a/libervia_server/__init__.py Tue Feb 04 16:49:20 2014 +0100 +++ b/libervia_server/__init__.py Tue Feb 04 16:49:20 2014 +0100 @@ -480,6 +480,8 @@ % (name, category)) def jsonrpc_launchAction(self, callback_id, data): + #FIXME: any action can be launched, this can be a huge security issue if callback_id can be guessed + # a security system with authorised callback_id must be implemented, similar to the one for authorised params profile = ISATSession(self.session).profile d = self.asyncBridgeCall("launchAction", callback_id, data, profile) return d @@ -540,8 +542,8 @@ _session = request.getSession() parsed = jsonrpclib.loads(request.content.read()) method = parsed.get("method") - if method != "isRegistered" and method != "registerParams": - #if we don't call login or isRegistered, we need to be identified + if method not in ['isRegistered', 'registerParams', 'getMenus']: + #if we don't call these methods, we need to be identified profile = ISATSession(_session).profile if not profile: #user is not identified, we return a jsonrpc fault @@ -741,6 +743,11 @@ self.sat_host.bridge.paramsRegisterApp(params, Const.SECURITY_LIMIT, Const.APP_NAME) + def jsonrpc_getMenus(self): + """Return the parameters XML for profile""" + # XXX: we put this method in Register because we get menus before being logged + return self.sat_host.bridge.getMenus('', Const.SECURITY_LIMIT) + class SignalHandler(jsonrpc.JSONRPC):