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

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

Menus: - Added experimental context showing.

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