source: products/quintagroup.dropdownmenu/trunk/quintagroup/dropdownmenu/browser/viewlets.py @ 2817

Last change on this file since 2817 was 2817, checked in by chervol, 14 years ago

removed the timer

  • Property svn:eol-style set to native
File size: 9.4 KB
Line 
1# -*- coding: utf-8 -*-
2from Acquisition import aq_inner
3
4from zope.component import getMultiAdapter, getUtility
5
6from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
7from Products.CMFCore.utils import getToolByName
8from Products.CMFCore.interfaces import IAction, IActionCategory
9from Products.CMFCore.ActionInformation import ActionInfo
10from Products.CMFPlone.utils import versionTupleFromString
11
12from plone.memoize.instance import memoize
13from plone.app.layout.viewlets import common
14from plone.app.layout.navigation.navtree import buildFolderTree
15from plone.app.layout.navigation.interfaces import INavtreeStrategy
16from plone.app.layout.navigation.interfaces import INavigationQueryBuilder
17
18from quintagroup.dropdownmenu.interfaces import IDropDownMenuSettings
19from quintagroup.dropdownmenu.browser.menu import DropDownMenuQueryBuilder
20from quintagroup.dropdownmenu.util import getDropDownMenuSettings
21
22from time import time
23from plone.memoize import ram
24import copy
25
26def cache_key(a,b,c):   
27    return c + str(time() // (60 * 60))
28
29class GlobalSectionsViewlet(common.GlobalSectionsViewlet):
30    index = ViewPageTemplateFile('templates/sections.pt')
31    recurse = ViewPageTemplateFile('templates/sections_recurse.pt')
32
33
34    def update(self):
35        # we may need some previously defined variables
36        #super(GlobalSectionsViewlet, self).update()
37
38        # prepare to gather portal tabs
39        tabs = []
40        context = aq_inner(self.context)
41        self.conf = conf = self._settings()
42        self.tool = getToolByName(context, 'portal_actions')
43        self.site_url = getToolByName(context, 'portal_url')()
44        self.context_state = getMultiAdapter((self.context, self.request), 
45                                              name="plone_context_state")
46        self.context_url =  self.context_state.is_default_page() and \
47            '/'.join(self.context.absolute_url().split('/')[:-1]) or \
48            self.context.absolute_url()
49           
50        self.cat_sufix  = self.conf.nested_category_sufix or ''
51        self.cat_prefix = self.conf.nested_category_prefix or ''
52        # fetch actions-based tabs?
53        if conf.show_actions_tabs:
54            tabs.extend(self._actions_tabs())
55
56        # fetch content structure-based tabs?
57        if conf.show_content_tabs:
58            # put content-based actions before content structure-based ones?
59            if conf.content_before_actions_tabs:
60                tabs = self._content_tabs() + tabs
61            else:
62                tabs.extend(self._content_tabs())
63
64        # assign collected tabs eventually
65        self.portal_tabs = tabs
66
67    def _actions_tabs(self):
68        """Return tree of tabs based on portal_actions tool configuration"""
69        conf = self.conf
70        tool = self.tool
71        context = aq_inner(self.context)
72
73        # check if we have required root actions category inside tool
74        if conf.actions_category not in tool.objectIds():
75            return []
76        listtabs = []
77        res, listtabs = self.prepare_tabs(self.site_url)
78        res = copy.deepcopy(res)
79        self.tabs = listtabs
80       
81        # if there is no custom menu in portal tabs return
82        if not listtabs:
83            return []
84           
85        current_item = -1
86        delta = 1000
87        for info in listtabs:
88            if  self.context_url.startswith(info['url']) and \
89               len(self.context_url) - len(info['url']) < delta:
90               delta = len(self.context_url) - len(info['url'])
91               current_item = listtabs.index(info)
92        self.id_chain = [] 
93       
94        if current_item > -1 and current_item < len(listtabs):
95            self.mark_active(listtabs[current_item]['id'], listtabs[current_item]['url'])
96
97        self._activate(res)
98        return res
99       
100    @ram.cache(cache_key)
101    def prepare_tabs(self, site_url):
102        def normalize_actions(category, object, level, parent_url = None):
103            """walk through the tabs dictionary and build list of all tabs"""
104            tabs = []
105            for info in self._actionInfos(category, object):
106                icon = info['icon'] and '<img src="%s" />' % info['icon'] or ''
107                children = []
108                bottomLevel = self.conf.actions_tabs_level
109                if bottomLevel < 1 or level < bottomLevel:
110                    # try to find out appropriate subcategory
111                    subcat_id = self.cat_prefix + info['id'] + self.cat_sufix
112                    if subcat_id != info['id'] and \
113                       subcat_id in category.objectIds():
114                        subcat = category._getOb(subcat_id)
115                        if IActionCategory.providedBy(subcat):
116                            children = normalize_actions(subcat, object, level+1, info['url'])
117
118                parent_id = category['id'].replace(self.cat_prefix,'').replace(self.cat_sufix,'')
119                tab = {'id' : info['id'],
120                   'title': info['title'],
121                   'url': info['url'],
122                   'parent': (parent_id, parent_url)}
123                tabslist.append(tab)
124               
125                tab = {'id' : info['id'],
126                       'Title': info['title'],
127                       'Description': info['description'],
128                       'getURL': info['url'],
129                       'show_children': len(children) > 0,
130                       'children': children,
131                       'currentItem': False, 
132                       'currentParent': False,
133                       'item_icon': {'html_tag': icon},
134                       'normalized_review_state': 'visible'}
135                tabs.append(tab)
136            return tabs   
137        tabslist = []
138        tabs = normalize_actions(self.tool._getOb(self.conf.actions_category), aq_inner(self.context), 0)
139        return tabs, tabslist
140
141    def _activate(self, res):
142        """Mark selected chain in the tabs dictionary"""
143        for info in res:
144            if info['getURL'] in self.id_chain:
145                info['currentItem'] = True
146                info['currentParent'] = True
147                if info['children']:
148                    self._activate(info['children'])
149
150       
151    def mark_active(self, current_id, url):
152        for info in self.tabs:
153            if info['id'] == current_id and info['url'] == url:
154                self.mark_active(info['parent'][0], info['parent'][1])
155                self.id_chain.append(info['url'])
156                   
157
158
159    def _actionInfos(self, category, object, check_visibility=1,
160                     check_permissions=1, check_condition=1, max=-1):
161        """Return action infos for a given category"""
162        context = aq_inner(self.context)
163        ec = self.tool._getExprContext(object)
164        actions = [ActionInfo(action, ec) for action in category.objectValues()
165                    if IAction.providedBy(action)]
166
167        action_infos = []
168        for ai in actions:
169            if check_visibility and not ai['visible']:
170                continue
171            if check_permissions and not ai['allowed']:
172                continue
173            if check_condition and not ai['available']:
174                continue
175            action_infos.append(ai)
176            if max + 1 and len(action_infos) >= max:
177                break
178        return action_infos
179
180    def _content_tabs(self):
181        """Return tree of tabs based on content structure"""
182        context = aq_inner(self.context)
183
184        queryBuilder = DropDownMenuQueryBuilder(context)
185        strategy = getMultiAdapter((context, None), INavtreeStrategy)
186        # XXX This works around a bug in plone.app.portlets which was
187        # fixed in http://dev.plone.org/svn/plone/changeset/18836
188        # When a release with that fix is made this workaround can be
189        # removed and the plone.app.portlets requirement in setup.py
190        # be updated.
191        if strategy.rootPath is not None and strategy.rootPath.endswith("/"):
192            strategy.rootPath = strategy.rootPath[:-1]
193
194        return buildFolderTree(context, obj=context, query=queryBuilder(),
195                               strategy=strategy).get('children', [])
196
197    @memoize
198    def _settings(self):
199        """Fetch dropdown menu settings registry"""
200        return getDropDownMenuSettings(self.context)
201
202    def createMenu(self):
203        return self.recurse(children=self.portal_tabs, level=1)
204
205    def _old_update(self):
206        context_state = getMultiAdapter((self.context, self.request),
207                                        name=u'plone_context_state')
208        actions = context_state.actions()
209        portal_tabs_view = getMultiAdapter((self.context, self.request),
210                                           name='portal_tabs_view')
211        self.portal_tabs = portal_tabs_view.topLevelTabs(actions=actions)
212
213        selectedTabs = self.context.restrictedTraverse('selectedTabs')
214        self.selected_tabs = selectedTabs('index_html',
215                                          self.context,
216                                          self.portal_tabs)
217        self.selected_portal_tab = self.selected_tabs['portal']
218
219    @memoize
220    def is_plone_four(self):
221        """Indicates if we are in plone 4.
222       
223        """
224        pm = getToolByName(aq_inner(self.context), 'portal_migration') 
225        try:
226            version = versionTupleFromString(pm.getSoftwareVersion())
227        except AttributeError:
228            version = versionTupleFromString(pm.getFileSystemVersion())
229
230        if version:
231            return version[0] == 4
232
Note: See TracBrowser for help on using the repository browser.