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

Last change on this file since 3151 was 3151, checked in by vmaksymiv, 13 years ago

pep8 fixes

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