diff --git a/trytond/ir/ui/menu.py b/trytond/ir/ui/menu.py index 4e722030e5..74a58fb76d 100644 --- a/trytond/ir/ui/menu.py +++ b/trytond/ir/ui/menu.py @@ -58,6 +58,7 @@ CLIENT_ICONS = [(x, x) for x in ( 'tryton-system', 'tryton-undo', 'tryton-web-browser')] +SEPARATOR = ' / ' class UIMenu(ModelSQL, ModelView): @@ -72,7 +73,7 @@ class UIMenu(ModelSQL, ModelView): groups = fields.Many2Many('ir.ui.menu-res.group', 'menu_id', 'gid', 'Groups') complete_name = fields.Function(fields.Char('Complete Name', - order_field='name'), 'get_full_name') + order_field='name'), 'get_rec_name', searcher='search_rec_name') icon = fields.Selection('list_icons', 'Icon') action = fields.Function(fields.Reference('Action', selection=[ @@ -86,6 +87,14 @@ class UIMenu(ModelSQL, ModelView): def __init__(self): super(UIMenu, self).__init__() self._order.insert(0, ('sequence', 'ASC')) + self._constraints += [ + ('check_recursion', 'recursive_menu'), + ('check_name', 'wrong_name'), + ] + self._error_messages.update({ + 'recursive_menu': 'You can not create recursive menu!', + 'wrong_name': 'You can not use "%s" in name field!' % SEPARATOR, + }) def default_icon(self): return 'tryton-open' @@ -101,20 +110,40 @@ class UIMenu(ModelSQL, ModelView): return sorted(CLIENT_ICONS + [(name, name) for _, name in icon_obj.list_icons()]) - def get_full_name(self, ids, name): - res = {} + def check_name(self, ids): for menu in self.browse(ids): - res[menu.id] = self._get_one_full_name(menu) + if SEPARATOR in menu.name: + return False + return True + + def get_rec_name(self, ids, name): + if not ids: + return {} + res = {} + def _name(menu): + if menu.id in res: + return res[menu.id] + elif menu.parent: + return _name(menu.parent) + SEPARATOR + menu.name + else: + return menu.name + for menu in self.browse(ids): + res[menu.id] = _name(menu) return res - def _get_one_full_name(self, menu, level=6): - if level <= 0: - return '...' - if menu.parent: - parent_path = self._get_one_full_name(menu.parent, level-1) + "/" - else: - parent_path = '' - return parent_path + menu.name + def search_rec_name(self, name, clause): + if isinstance(clause[2], basestring): + values = clause[2].split(SEPARATOR) + values.reverse() + domain = [] + field = 'name' + for name in values: + domain.append((field, clause[1], name)) + field = 'parent.' + field + ids = self.search(domain, order=[]) + return [('id', 'in', ids)] + #TODO Handle list + return [('name',) + tuple(clause[1:])] def search(self, domain, offset=0, limit=None, order=None, count=False, query_string=False): diff --git a/trytond/ir/ui/menu.xml b/trytond/ir/ui/menu.xml index 2fce697e32..c9db9ab078 100644 --- a/trytond/ir/ui/menu.xml +++ b/trytond/ir/ui/menu.xml @@ -24,7 +24,7 @@ this repository contains the full copyright notices and license terms. --> - + ]]> @@ -68,14 +68,25 @@ this repository contains the full copyright notices and license terms. --> + + + Menu + ir.ui.menu + - + id="act_menu_list_view1"> + + + + + + - + + action="act_menu_list" id="menu_menu_list"/> diff --git a/trytond/res/ir.xml b/trytond/res/ir.xml index dffc554f0f..02ad948c85 100644 --- a/trytond/res/ir.xml +++ b/trytond/res/ir.xml @@ -444,7 +444,7 @@ this repository contains the full copyright notices and license terms. --> - +