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

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

result tab does not have to be globally available at this point

  • Property svn:eol-style set to native
File size: 9.0 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
22
23class GlobalSectionsViewlet(common.GlobalSectionsViewlet):
24    index = ViewPageTemplateFile('templates/sections.pt')
25    recurse = ViewPageTemplateFile('templates/sections_recurse.pt')
26
27
28    def update(self):
29        # we may need some previously defined variables
30        #super(GlobalSectionsViewlet, self).update()
31
32        # prepare to gather portal tabs
33        tabs = []
34        context = aq_inner(self.context)
35        self.conf = conf = self._settings()
36        self.tool = getToolByName(context, 'portal_actions')
37        self.site_url = getToolByName(context, 'portal_url')()
38        self.context_state = getMultiAdapter((self.context, self.request), 
39                                              name="plone_context_state")
40        self.context_url =  self.context_state.is_default_page() and \
41            '/'.join(self.context.absolute_url().split('/')[:-1]) or \
42            self.context.absolute_url()
43
44        # fetch actions-based tabs?
45        if conf.show_actions_tabs:
46            tabs.extend(self._actions_tabs())
47
48        # fetch content structure-based tabs?
49        if conf.show_content_tabs:
50            # put content-based actions before content structure-based ones?
51            if conf.content_before_actions_tabs:
52                tabs = self._content_tabs() + tabs
53            else:
54                tabs.extend(self._content_tabs())
55
56        # assign collected tabs eventually
57        self.portal_tabs = tabs
58
59    def _actions_tabs(self):
60        """Return tree of tabs based on portal_actions tool configuration"""
61        conf = self.conf
62        tool = self.tool
63        context = aq_inner(self.context)
64
65        # check if we have required root actions category inside tool
66        if conf.actions_category not in tool.objectIds():
67            return []
68
69        self.chain = []  #save not traversable chain here
70        self.tchain = []  #save the best traversable chain here
71        res, c = self._subactions(tool._getOb(conf.actions_category), context, 0, self.chain)
72        self.tchain.reverse()
73        self.chain.reverse()
74        self.chain = self.chain and self.chain or self.tchain
75        self._activate(res)
76        return res
77   
78    def _activate(self, res, level=0):
79        """Mark selected chain in the tabs dictionary"""
80        if self.chain and len(self.chain) > level:
81            res[self.chain[level]]['currentItem'] = True
82            res[self.chain[level]]['currentParent'] = True
83            if level + 1 < len(self.chain):
84                self._activate(res[self.chain[level]]['children'], level+1)
85
86
87    def _subactions(self, category, object, level=0, lchain=[]):
88        """Build tabs dictionary out of portal actions"""
89        tabs = []
90        currentParentId = -1
91        index = -1
92        local = False     
93        for info in self._actionInfos(category, object):
94            # prepare data for action
95            # TODO: implement current element functionality, maybe should be
96            #       done on a template level because of separate content and
97            #       actions tabs are rendered separately
98
99            index += 1
100            icon = info['icon'] and '<img src="%s" />' % info['icon'] or ''
101   
102            if  self.context_url.startswith(info['url']) and info['url'] != self.site_url:
103                if currentParentId > -1:
104                    if len(tabs[currentParentId]['getURL']) < len(info['url']): 
105                        currentParentId = index
106                else:
107                    currentParentId = index
108            if  self.context_url == info['url']:
109                lchain.append(index)
110                local = True
111               
112            # look up children for a given action
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 = info['id']
118                if self.conf.nested_category_sufix is not None:
119                    subcat_id += self.conf.nested_category_sufix
120                if self.conf.nested_category_prefix is not None:
121                    subcat_id = self.conf.nested_category_prefix + subcat_id
122                if subcat_id != info['id'] and \
123                   subcat_id in category.objectIds():
124                    subcat = category._getOb(subcat_id)
125                    if IActionCategory.providedBy(subcat):
126                        children, local = self._subactions(subcat, object, level+1, lchain)
127                        if local:
128                            lchain.append(index)
129           
130            # make up final tab dictionary
131            tab = {'Title': info['title'],
132                   'Description': info['description'],
133                   'getURL': info['url'],
134                   'show_children': len(children) > 0,
135                   'children': children,
136                   'currentItem': False, 
137                   'currentParent': False,
138                   'item_icon': {'html_tag': icon},
139                   'normalized_review_state': 'visible'}
140            tabs.append(tab)
141
142        if currentParentId > -1:
143            self.tchain.append(currentParentId)
144        return tabs, local
145
146    def _actionInfos(self, category, object, check_visibility=1,
147                     check_permissions=1, check_condition=1, max=-1):
148        """Return action infos for a given category"""
149        context = aq_inner(self.context)
150        ec = self.tool._getExprContext(object)
151        actions = [ActionInfo(action, ec) for action in category.objectValues()
152                    if IAction.providedBy(action)]
153
154        action_infos = []
155        for ai in actions:
156            if check_visibility and not ai['visible']:
157                continue
158            if check_permissions and not ai['allowed']:
159                continue
160            if check_condition and not ai['available']:
161                continue
162            action_infos.append(ai)
163            if max + 1 and len(action_infos) >= max:
164                break
165        return action_infos
166
167    def _content_tabs(self):
168        """Return tree of tabs based on content structure"""
169        context = aq_inner(self.context)
170
171        queryBuilder = DropDownMenuQueryBuilder(context)
172        strategy = getMultiAdapter((context, None), INavtreeStrategy)
173        # XXX This works around a bug in plone.app.portlets which was
174        # fixed in http://dev.plone.org/svn/plone/changeset/18836
175        # When a release with that fix is made this workaround can be
176        # removed and the plone.app.portlets requirement in setup.py
177        # be updated.
178        if strategy.rootPath is not None and strategy.rootPath.endswith("/"):
179            strategy.rootPath = strategy.rootPath[:-1]
180
181        return buildFolderTree(context, obj=context, query=queryBuilder(),
182                               strategy=strategy).get('children', [])
183
184    @memoize
185    def _settings(self):
186        """Fetch dropdown menu settings registry"""
187        return getDropDownMenuSettings(self.context)
188
189    def createMenu(self):
190        return self.recurse(children=self.portal_tabs, level=1)
191
192    def _old_update(self):
193        context_state = getMultiAdapter((self.context, self.request),
194                                        name=u'plone_context_state')
195        actions = context_state.actions()
196        portal_tabs_view = getMultiAdapter((self.context, self.request),
197                                           name='portal_tabs_view')
198        self.portal_tabs = portal_tabs_view.topLevelTabs(actions=actions)
199
200        selectedTabs = self.context.restrictedTraverse('selectedTabs')
201        self.selected_tabs = selectedTabs('index_html',
202                                          self.context,
203                                          self.portal_tabs)
204        self.selected_portal_tab = self.selected_tabs['portal']
205
206    @memoize
207    def is_plone_four(self):
208        """Indicates if we are in plone 4.
209       
210        """
211        pm = getToolByName(aq_inner(self.context), 'portal_migration') 
212        try:
213            version = versionTupleFromString(pm.getSoftwareVersion())
214        except AttributeError:
215            version = versionTupleFromString(pm.getFileSystemVersion())
216
217        if version:
218            return version[0] == 4
219
Note: See TracBrowser for help on using the repository browser.