source: products/qPloneTabs/branches/quintagroup.plonetabs/trunk/quintagroup/plonetabs/browser/plonetabs.py @ 48

Last change on this file since 48 was 48, checked in by crchemist, 18 years ago

rename file

  • Property svn:eol-style set to native
File size: 15.4 KB
Line 
1import copy
2
3from Acquisition import aq_inner
4
5from zope.interface import implements
6from zope.component import getUtility, getMultiAdapter
7from zope.i18n import translate
8from zope.schema.interfaces import IVocabularyFactory
9
10from Acquisition import aq_inner
11
12from Products.CMFCore.utils import getToolByName
13from Products.CMFCore.interfaces import IAction
14from Products.CMFEditions.setuphandlers import DEFAULT_POLICIES
15from Products.CMFPlone import PloneMessageFactory as _
16from Products.CMFPlone import PloneMessageFactory as pmf
17from Products.CMFPlone import utils
18from Products.CMFPlone.browser.navigation import get_view_url
19from Products.Five.browser import BrowserView
20from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
21
22from plone.app.layout.navigation.root import getNavigationRoot
23from plone.app.kss.plonekssview import PloneKSSView
24from plone.app.workflow.remap import remap_workflow
25from plone.memoize.instance import memoize
26from kss.core import kssaction, KSSExplicitError
27
28from quintagroup.plonetabs.config import *
29from interfaces import IPloneTabsControlPanel
30
31def format_description(text, request=None):
32    # We expect the workflow to be a text of "- " divided bullet points.
33    text = translate(text.strip(), domain="plone", context=request)
34    return [s.strip() for s in text.split("- ") if s]
35
36ACTION_ATTRS = ["id", "visible", "description", "url_expr", "title", "available_expr"]
37
38class PloneTabsControlPanel(PloneKSSView):
39   
40    implements(IPloneTabsControlPanel)
41   
42    actionslist_template = ViewPageTemplateFile("templates/actionslist.pt")
43    autogenerated_template = ViewPageTemplateFile("templates/autogenerated.pt")
44    sections_template = ViewPageTemplateFile("templates/sections.pt")
45   
46    def getPageTitle(self, category="portal_tabs"):
47        """ See interface """
48        portal_props = getToolByName(self.context, "portal_properties")
49        default_title = "Plone '%s' Configuration" % category
50       
51        if not hasattr(portal_props, PROPERTY_SHEET):
52            return default_title
53       
54        sheet = getattr(portal_props, PROPERTY_SHEET)
55        if not hasattr(sheet, FIELD_NAME):
56            return default_title
57       
58        field = sheet.getProperty(FIELD_NAME)
59        dict = {}
60        for line in field:
61            cat, title = line.split("|", 2)
62            dict[cat] = title
63       
64        return dict.get(category, None) or default_title
65   
66    def hasActions(self, category="portal_tabs"):
67        """ See interface """
68        return len(getToolByName(self.context, "portal_actions").listActions(categories=[category,])) > 0
69   
70    def getPortalActions(self, category="portal_tabs"):
71        """ See interface """
72        portal_actions = getToolByName(self.context, "portal_actions")
73       
74        if category not in portal_actions.objectIds():
75            return []
76       
77        actions = []
78        for item in portal_actions[category].objectValues():
79            if IAction.providedBy(item):
80                actions.append(item)
81       
82        return actions
83   
84    def isGeneratedTabs(self):
85        """ See interface """
86        site_properties = getToolByName(self.context, "portal_properties").site_properties
87        return not site_properties.getProperty("disable_folder_sections", False)
88   
89    def isNotFoldersGenerated(self):
90        """ See interface """
91        site_properties = getToolByName(self.context, "portal_properties").site_properties
92        return not site_properties.getProperty("disable_nonfolderish_sections", False)
93   
94    def getActionsList(self, category="portal_tabs"):
95        """ See interface """
96        return self.actionslist_template(category=category)
97   
98    def getGeneratedTabs(self):
99        """ See interface """
100        return self.autogenerated_template()
101   
102    def getRootTabs(self):
103        """ See interface """
104        context = aq_inner(self.context)
105       
106        portal_catalog = getToolByName(context, 'portal_catalog')
107        portal_properties = getToolByName(context, 'portal_properties')
108        navtree_properties = getattr(portal_properties, 'navtree_properties')
109       
110        # Build result dict
111        result = []
112       
113        # check whether we only want actions
114        if not self.isGeneratedTabs():
115            return result
116       
117        query = {}
118       
119        rootPath = getNavigationRoot(context)
120        query['path'] = {'query' : rootPath, 'depth' : 1}
121        query['portal_type'] = utils.typesToList(context)
122       
123        sortAttribute = navtree_properties.getProperty('sortAttribute', None)
124        if sortAttribute is not None:
125            query['sort_on'] = sortAttribute
126           
127            sortOrder = navtree_properties.getProperty('sortOrder', None)
128            if sortOrder is not None:
129                query['sort_order'] = sortOrder
130       
131        if navtree_properties.getProperty('enable_wf_state_filtering', False):
132            query['review_state'] = navtree_properties.getProperty('wf_states_to_show', [])
133       
134        query['is_default_page'] = False
135
136        if not self.isNotFoldersGenerated():
137            query['is_folderish'] = True
138
139        # Get ids not to list and make a dict to make the search fast
140        idsNotToList = navtree_properties.getProperty('idsNotToList', ())
141        excludedIds = {}
142        for id in idsNotToList:
143            excludedIds[id]=1
144
145        rawresult = portal_catalog.searchResults(**query)
146
147        # now add the content to results
148        for item in rawresult:
149            if not excludedIds.has_key(item.getId):
150                id, item_url = get_view_url(item)
151                data = {'name'       : utils.pretty_title_or_id(context, item),
152                        'id'         : id,
153                        'url'        : item_url,
154                        'description': item.Description,
155                        'exclude_from_nav' : item.exclude_from_nav}
156                result.append(data)
157       
158        return result
159   
160    def getCategories(self):
161        """ See interface """
162        portal_actions = getToolByName(self.context, "portal_actions")
163        return portal_actions.objectIds()
164   
165    def test(self, condition, ifTrue, ifFalse):
166        """ See interface """
167        if condition:
168            return ifTrue
169        else:
170            return ifFalse
171   
172    # methods for rendering global-sections viewlet via kss,
173    # due to bug in macroContent when global-section list is empty,
174    # ul have condition
175    def portal_tabs(self):
176        """ See global-sections viewlet """
177        actions = context_state = getMultiAdapter((self.context, self.request), name=u"plone_context_state").actions()
178        portal_tabs_view = getMultiAdapter((self.context, self.request), name="portal_tabs_view")
179       
180        return portal_tabs_view.topLevelTabs(actions=actions)
181   
182    def selected_portal_tab(self):
183        """ See global-sections viewlet """
184        selectedTabs = self.context.restrictedTraverse('selectedTabs')
185        selected_tabs = selectedTabs('index_html', self.context, self.portal_tabs())
186       
187        return selected_tabs['portal']
188   
189    ##########################
190    # kss server actions
191    ##########################
192   
193    def updateGlobalSections(self, ksscore):
194        """ Method for updating global-sections on client """
195        ksscore.replaceHTML(
196            ksscore.getHtmlIdSelector("portal-globalnav"),
197            self.sections_template(),
198            withKssSetup="False")
199   
200   
201    # XXX TODO
202    #def updateSection(self, ksscore, section):
203        #""" Method for updating global-sections on client """
204       
205        #replace_id = section
206        #macro = SECTION_MAPPING.get(section, None)
207       
208        #if macro is not None:
209            #ksscore.replaceHTML(
210                #ksscore.getHtmlIdSelector(replace_id),
211                #self.macroContent(macro),
212                ##self.sections_template(),
213                #withKssSetup="False")
214   
215    def validateAction(self, id, category, prefix="tabslist_"):
216        """ If action with given id and category doesn't exist - raise kss exception """
217        portal_actions = getToolByName(self.context, "portal_actions")
218       
219        # remove prefix, added for making ids on configlet unique ("tabslist_")
220        act_id = id[len("tabslist_"):]
221       
222        if category not in portal_actions.objectIds():
223            raise KSSExplicitError, "Unexistent root portal actions category %s" % category
224       
225        cat_container = portal_actions[category]
226        if act_id not in map(lambda x: x.id, filter(lambda x: IAction.providedBy(x), cat_container.objectValues())):
227            raise KSSExplicitError, "%s action does not exist in %s category" % (act_id, category)
228       
229        return (cat_container, act_id)
230   
231    @kssaction
232    def toggleGeneratedTabs(self, field, checked='0'):
233        """ Toggle autogenaration setting on configlet """
234       
235        changeProperties = getToolByName(self.context, "portal_properties").site_properties.manage_changeProperties
236        if checked == '1':
237            changeProperties(**{field : False})
238        else:
239            changeProperties(**{field : True})
240       
241        ksscore = self.getCommandSet("core")
242        replace_id = "roottabs"
243        content = self.getGeneratedTabs()
244       
245        ksscore.replaceInnerHTML(ksscore.getHtmlIdSelector(replace_id), content, withKssSetup="True")
246       
247        # update global-sections viewlet
248        self.updateGlobalSections(ksscore)
249   
250    @kssaction
251    def toggleActionsVisibility(self, id, checked='0', category=None):
252        """ Toggle visibility for portal actions """
253        portal_actions = getToolByName(self.context, "portal_actions")
254        cat_container, act_id = self.validateAction(id, category)
255       
256        if checked == '1':
257            checked = True
258        else:
259            checked = False
260       
261        cat_container[act_id].visible = checked
262       
263        ksscore = self.getCommandSet("core")
264        if checked:
265            ksscore.removeClass(ksscore.getHtmlIdSelector(id), value="invisible")
266        else:
267            ksscore.addClass(ksscore.getHtmlIdSelector(id), value="invisible")
268       
269        # update global-sections viewlet
270        if category == "portal_tabs":
271            self.updateGlobalSections(ksscore)
272   
273    @kssaction
274    def toggleRootsVisibility(self, id, checked='0'):
275        """ Toggle visibility for portal root objects (exclude_from_nav) """
276        portal = getMultiAdapter((aq_inner(self.context), self.request), name='plone_portal_state').portal()
277       
278        # remove prefix, added for making ids on configlet unique ("roottabs_")
279        obj_id = id[len("roottabs_"):]
280       
281        if obj_id not in portal.objectIds():
282            raise KSSExplicitError, "Object with %s id doesn't exist in portal root" % obj_id
283       
284        if checked == '1':
285            checked = True
286        else:
287            checked = False
288       
289        portal[obj_id].update(excludeFromNav=not checked)
290       
291        ksscore = self.getCommandSet("core")
292        if checked:
293            ksscore.removeClass(ksscore.getHtmlIdSelector(id), value="invisible")
294        else:
295            ksscore.addClass(ksscore.getHtmlIdSelector(id), value="invisible")
296       
297        # update global-sections viewlet
298        self.updateGlobalSections(ksscore)
299   
300    @kssaction
301    def deleteAction(self, id, category):
302        """ Delete portal action with given id & category """
303        portal_actions = getToolByName(self.context, "portal_actions")
304        cat_container, act_id = self.validateAction(id, category)
305       
306        cat_container.manage_delObjects(ids=[act_id,])
307       
308        # update action list on client
309        ksscore = self.getCommandSet("core")
310       
311        ksscore.deleteNode(ksscore.getHtmlIdSelector(id))
312       
313        # add "noitems" class to Reorder controls to hide it
314        if not filter(lambda x: IAction.providedBy(x), cat_container.objectValues()):
315            ksscore.addClass(ksscore.getHtmlIdSelector("reorder"), value="noitems")
316       
317        # XXX TODO: fade effect during removing, for this kukit js action/command plugin needed
318       
319        # update global-sections viewlet
320        if category == "portal_tabs":
321            self.updateGlobalSections(ksscore)
322   
323    @kssaction
324    def editAction(self, id, category):
325        """ Show edit form for given action """
326        cat_container, act_id = self.validateAction(id, category)
327       
328        # collect data
329        action_info = self.copyAction(cat_container[act_id])
330        action_info["editing"] = True
331       
332        ksscore = self.getCommandSet("core")
333        content = self.actionslist_template(tabs=[action_info,])
334        replace_id = id
335       
336        ksscore.replaceHTML(ksscore.getHtmlIdSelector(replace_id), content)
337       
338        # focus name field
339        ksscore.focus(ksscore.getCssSelector("#%s input[name=name_%s]" % (id, act_id)))
340   
341    @kssaction
342    def editCancel(self, id, category):
343        """ Hide edit form for given action """
344        cat_container, act_id = self.validateAction(id, category)
345       
346        ksscore = self.getCommandSet("core")
347        content = self.actionslist_template(tabs=[cat_container[act_id],])
348        replace_id = id
349       
350        ksscore.replaceHTML(ksscore.getHtmlIdSelector(replace_id), content)
351   
352   
353    # Methods for processing configlet actions without javascript/ajax
354   
355    def manage_setAutogeneration(self, generated_tabs="0", nonfolderish_tabs="0"):
356        """ Process managing autogeneration settings """
357       
358        # set excludeFromNav property for root objects
359        portal = getMultiAdapter((aq_inner(self.context), self.request), name='plone_portal_state').portal()
360        form = self.request.form
361       
362        for item in self.getRootTabs():
363            obj = getattr(portal, item['id'], None)
364            if obj is not None:
365                checked = form.get(item['id'], None)
366                if checked == '1':
367                    obj.update(excludeFromNav=False)
368                else:
369                    obj.update(excludeFromNav=True)
370
371        # set disable_folder_sections property
372        changeProperties = getToolByName(self.context, "portal_properties").site_properties.manage_changeProperties
373       
374        if int(generated_tabs) == 1:
375            changeProperties(disable_folder_sections=False)
376        else:
377            changeProperties(disable_folder_sections=True)
378       
379        # set disable_nonfolderish_sections property
380        if int(nonfolderish_tabs) == 1:
381            changeProperties(disable_nonfolderish_sections=False)
382        else:
383            changeProperties(disable_nonfolderish_sections=True)
384       
385        self.redirect()
386
387   
388    def redirect(self, url="", search="", hash=""):
389        """ Redirect to @@plonetabs-controlpanel configlet """
390       
391        if url == "":
392            portal_url =  getMultiAdapter((self.context, self.request), name=u"plone_portal_state").portal_url()
393            url = "%s/%s" % (portal_url, "@@plonetabs-controlpanel")
394       
395        if search != "":
396            search = "?%s" % search
397       
398        if hash != "":
399            hash = "#%s" % hash
400       
401        self.request.response.redirect("%s%s%s" % (url, search, hash))
402   
403   
404    # Utility Methods
405   
406    def copyAction(self, action):
407        """ Copyt action to dictionary """
408        action_info = {}
409        for attr in ACTION_ATTRS:
410            action_info[attr] = getattr(action, attr)
411        return action_info
412   
413
414
415
416
417
418
419
420
421
422
Note: See TracBrowser for help on using the repository browser.