source: trunk/plugins/menusplugin/tracmenus/web_ui.py @ 687

Revision 687, 6.4 KB checked in by cbalan, 5 years ago (diff)

Menus: - Fixed context showing.

Line 
1# -*- coding: utf-8 -*-
2#
3# Copyright 2008 Optaros, Inc.
4#
5import re
6from urlparse import urlsplit
7
8from trac.core import *
9from trac.web.api import IRequestFilter
10from trac.web.chrome import add_script, add_stylesheet,ITemplateProvider
11from trac.config import ListOption, BoolOption
12from trac.util.html import html
13
14class MenuManagerModule(Component):
15    implements(IRequestFilter, ITemplateProvider)
16
17    managed_menus = ListOption('menu-custom', 'managed_menus', 'mainnav,metanav', 
18                        doc="""List of menus to be controlled by the Menu Manager""")
19    serve_ui_files = BoolOption('menu-custom', 'serve_ui_files', True)
20
21    # ITemplateProvider
22    def get_templates_dirs(self):
23        return []
24    def get_htdocs_dirs(self):
25        from pkg_resources import resource_filename
26        return [('tracmenus',resource_filename(__name__, 'htdocs'))]
27   
28    # IRequestFilter methods
29    def pre_process_request(self, req, handler):
30        return handler
31    def post_process_request(self, req, template, data, content_type):
32        if 'nav_orig' in req.chrome: 
33            return template, data, content_type
34        req.chrome['nav_orig'] = req.chrome['nav'].copy()
35        if 'ctxtnav' in self.managed_menus and 'ctxtnav' in req.chrome:
36            req.chrome['nav_orig']['ctxtnav']=[dict(name='ctxtnav_'+str(idx), label=ctx_label) 
37                                               for idx, ctx_label in enumerate(req.chrome['ctxtnav'])]
38        for menu_name in self.managed_menus:
39            req.chrome['nav'][menu_name] = list(self._get_menu(req, menu_name, 
40                                                               req.chrome['nav_orig']))   
41            if menu_name=='ctxtnav':
42                req.chrome['ctxtnav'] = [ ctxt_item.get('label') for ctxt_item in req.chrome['nav'][menu_name] ]
43       
44        if self.serve_ui_files:
45            add_script(req, 'tracmenus/js/superfish.js')
46            add_script(req, 'tracmenus/js/tracmenus.js')
47            add_script(req, 'tracmenus/js/jquery.hoverIntent.minified.js')
48            add_stylesheet(req, 'tracmenus/css/superfish.css')
49        return template, data, content_type
50       
51    def _get_menu(self, req, menu_name, nav_orig):
52        config_menu, config_options = self._get_config_menus(req, menu_name)
53        menu_orig = nav_orig.get(menu_name, [])
54       
55        if 'inherit' in config_options:
56            menu_orig += nav_orig.get(config_options['inherit'], [])
57           
58        tree_menu={} 
59        for option in sorted(menu_orig+[{'name':key} for key in config_menu.keys() if config_menu[key].get('hide_if_disabled',False)==False], 
60                             key=lambda x:int(config_menu.get(x['name'],{}).get('order',999))):           
61            name = option['name']
62            if 'visited' in tree_menu.get(name, []) \
63                    or config_menu.get(name, {}).get('enabled', True)==False \
64                    or config_menu.get(name, {}).get('if_path_info', True)==False \
65                    or False in [req.perm.has_permission(perm) for perm in config_menu.get(name, {}).get('perm', [])]:
66                continue
67           
68            tree_node = tree_menu.setdefault(name, {})
69            tree_node.update(option.copy())
70           
71            if 'label' in option and 'label' in config_menu.get(name, []):
72                del config_menu[name]['label']
73            tree_node.update(config_menu.get(name, {'parent_name':'unassigned'}))
74           
75            tree_node['label'] = html(tree_node.setdefault('label', html.a(name)))
76            tree_node['visited'] = True 
77            if tree_node.get('href'):
78                tree_node.setdefault('active', urlsplit(tree_node['href']).path==req.path_info)   
79
80            if '_tmp_children' in tree_node:
81                tree_node['children'] = html.ul()
82                tree_node['label'].append(tree_node['children'])
83                tree_node['children'].children.extend(tree_node['_tmp_children'])
84                del tree_node['_tmp_children']
85                       
86            if (tree_node['parent_name']=='unassigned' and not 'unassigned' in config_menu) \
87                    or tree_node['parent_name']=='top': 
88                yield tree_node
89                continue
90
91            tree_node['parent'] = tree_menu.setdefault(tree_node['parent_name'], {})
92
93            child_node = html.li(class_=tree_node.get('active')==True and 'active' or None)
94            child_node.children=[tree_node['label']]
95            if 'label' in tree_node['parent']:
96                if not 'children' in tree_node['parent']:
97                    tree_node['parent']['children'] = html.ul()
98                    tree_node['parent']['label'].append(tree_node['parent']['children'])
99                tree_node['parent']['children'].append(child_node)
100            else:
101                tree_node['parent'].setdefault('_tmp_children',[]).append(child_node)
102
103    def _get_config_menus(self, req, menu_name):
104        new_menu_option=lambda name: dict(name=name, parent_name='top')
105        menu, options = {}, {}
106        for option, value in self.config[menu_name].options():
107            item_parts = option.split('.',1)
108            name, prop_name = item_parts[0], len(item_parts)>1 and item_parts[1] or 'enabled'
109            if name in ['inherit']:
110                options[name] = value
111                continue
112            menu.setdefault(name, new_menu_option(name)) 
113            if prop_name=='parent':
114                menu[name]['parent_name']=value
115                continue
116            elif prop_name=='enabled':
117                value=self.config[menu_name].getbool(option, True)
118            elif prop_name=='href':
119                value = value.replace('$PATH_INFO', req.path_info)
120                menu[name]['label']=menu[name].setdefault('label', html.a())(href=value.startswith('/') and req.href()+value or value)
121            elif prop_name=='label':
122                menu[name].setdefault('label', html.a())(value)
123                continue
124            elif prop_name=='path_info':
125                menu[name]['if_path_info'] = re.match(value, req.path_info) and True or False
126            elif prop_name=='hide_if_disabled':
127                menu[name][prop_name] = self.config[menu_name].getbool(option, False)
128                continue
129            elif prop_name=='perm':
130                menu[name][prop_name] = self.config[menu_name].getlist(option, default=[], sep=',')
131                continue
132            menu[name][prop_name]=value
133        return menu, options
Note: See TracBrowser for help on using the repository browser.