Index: quintagroup.plonetabs/branches/plone4/quintagroup/plonetabs/browser/plonetabs.py
===================================================================
--- quintagroup.plonetabs/branches/plone4/quintagroup/plonetabs/browser/plonetabs.py	(revision 3080)
+++ quintagroup.plonetabs/branches/plone4/quintagroup/plonetabs/browser/plonetabs.py	(revision 3081)
@@ -40,7 +40,7 @@
 
 class PloneTabsControlPanel(PloneKSSView):
-    
+
     implements(IPloneTabsControlPanel)
-    
+
     template = ViewPageTemplateFile("templates/plonetabs.pt")
     actionslist_template = ViewPageTemplateFile("templates/actionslist.pt")
@@ -48,12 +48,12 @@
     autogenerated_list = ViewPageTemplateFile("templates/autogeneratedlist.pt")
     link_template = ViewPageTemplateFile("templates/changemodelink.pt")
-    
+
     # custom templates used to update page sections
     sections_template = ViewPageTemplateFile("templates/sections.pt")
-    
+
     # configuration variables
     prefix = "tabslist_"
     sufix = ""
-    
+
     def __call__(self):
         """Perform the update and redirect if necessary, or render the page"""
@@ -61,9 +61,9 @@
         errors = {}
         context = aq_inner(self.context)
-        
+
         form = self.request.form
         action = form.get("action", "")
         submitted = form.get('form.submitted', False)
-        
+
         # action handler def handler(self, form)
         if submitted:
@@ -82,5 +82,5 @@
             else:
                 postback = True
-        
+
         mode = self.request.get(cookie_name, False)
         if mode in ('plain', 'rich'):
@@ -89,15 +89,15 @@
             self.request.response.setCookie(cookie_name, mode, path='/',
                                             expires=expires)
-        
+
         if postback:
             return self.template(errors=errors)
-    
+
     ########################################
     # Methods for processing configlet posts
     ########################################
-    
+
     def manage_setAutogeneration(self, form, errors):
         """Process managing autogeneration settings"""
-        
+
         # set excludeFromNav property for root objects
         portal = getMultiAdapter((aq_inner(self.context), self.request),
@@ -105,5 +105,5 @@
         generated_tabs = form.get("generated_tabs", '0')
         nonfolderish_tabs = form.get("nonfolderish_tabs", '0')
-        
+
         for item in self.getRootTabs():
             obj = getattr(portal, item['id'], None)
@@ -120,5 +120,5 @@
         else:
             self.setSiteProperties(disable_folder_sections=True)
-        
+
         # set disable_nonfolderish_sections property
         if int(nonfolderish_tabs) == 1:
@@ -126,5 +126,5 @@
         else:
             self.setSiteProperties(disable_nonfolderish_sections=True)
-        
+
         # after successfull form processing make redirect with good message
         IStatusMessage(self.request).addStatusMessage(_(u"Changes saved!"),
@@ -132,5 +132,5 @@
         self.redirect()
         return False
-    
+
     def manage_addAction(self, form, errs):
         """Manage method to add a new action to given category,
@@ -139,8 +139,8 @@
         # extract posted data
         id, cat_name, data = self.parseAddForm(form)
-        
+
         # validate posted data
         errors = self.validateActionFields(cat_name, data)
-        
+
         # if not errors find (or create) category and set action to it
         if not errors:
@@ -156,18 +156,18 @@
                 _(u"Please correct the indicated errors."), type="error")
             return True
-    
+
     def manage_editAction(self, form, errs):
         """Manage Method to update action"""
         # extract posted data
         id, cat_name, data = self.parseEditForm(form)
-        
+
         # get category and action to edit
         category = self.getActionCategory(cat_name)
         action = category[id]
-        
+
         # validate posted data
         errors = self.validateActionFields(cat_name, data,
             allow_dup=(id == data['id']))
-        
+
         if not errors:
             action = self.updateAction(id, cat_name, data)
@@ -183,10 +183,10 @@
                 _(u"Please correct the indicated errors."), type="error")
             return True
-    
+
     def manage_deleteAction(self, form, errs):
         """Manage Method to delete action"""
         # extract posted data
         id, cat_name, data = self.parseEditForm(form)
-        
+
         # get category and action to delete
         category = self.getActionCategory(cat_name)
@@ -203,10 +203,10 @@
                 type="error")
             return True
-    
+
     def manage_moveUpAction(self, form, errs):
         """Manage Method for moving up given action by one position"""
         # extract posted data
         id, cat_name, data = self.parseEditForm(form)
-        
+
         # get category and action to move
         category = self.getActionCategory(cat_name)
@@ -222,10 +222,10 @@
                   mapping={'id': id, 'cat_name': cat_name}), type="error")
             return True
-    
+
     def manage_moveDownAction(self, form, errs):
         """Manage Method for moving down given action by one position"""
         # extract posted data
         id, cat_name, data = self.parseEditForm(form)
-        
+
         # get category and action to move
         category = self.getActionCategory(cat_name)
@@ -243,5 +243,5 @@
                 type="error")
             return True
-    
+
     def redirect(self, url="", search="", url_hash=""):
         """Redirect to @@plonetabs-controlpanel configlet"""
@@ -255,5 +255,5 @@
             url_hash = '#%s' % url_hash
         self.request.response.redirect("%s%s%s" % (url, search, url_hash))
-    
+
     ###################################
     #
@@ -261,5 +261,5 @@
     #
     ###################################
-    
+
     def _charset(self):
         pp = getToolByName(self.context, 'portal_properties', None)
@@ -269,5 +269,5 @@
                 return site_properties.getProperty('default_charset', 'utf-8')
         return 'utf-8'
-    
+
     def getPageTitle(self, category="portal_tabs"):
         """See interface"""
@@ -275,12 +275,12 @@
         default_title = _(u"Plone '${cat_name}' Configuration",
                           mapping={'cat_name': category})
-        
+
         if not hasattr(portal_props, PROPERTY_SHEET):
             return default_title
-        
+
         sheet = getattr(portal_props, PROPERTY_SHEET)
         if not hasattr(sheet, FIELD_NAME):
             return default_title
-        
+
         field = sheet.getProperty(FIELD_NAME)
         dict = {}
@@ -288,34 +288,34 @@
             cat, title = line.split("|", 2)
             dict[cat] = title
-        
+
         title = dict.get(category, None)
         if title is None:
             return default_title
-        
+
         charset = self._charset()
         if not isinstance(title, unicode):
             title = title.decode(charset)
-        
+
         return _(title)
-    
+
     def hasActions(self, category="portal_tabs"):
         """See interface"""
         tool = getToolByName(self.context, "portal_actions")
         return len(tool.listActions(categories=[category,])) > 0
-    
+
     def getPortalActions(self, category="portal_tabs"):
         """See interface"""
         portal_actions = getToolByName(self.context, "portal_actions")
-        
+
         if category not in portal_actions.objectIds():
             return []
-        
+
         actions = []
         for item in portal_actions[category].objectValues():
             if IAction.providedBy(item):
                 actions.append(item)
-        
+
         return actions
-    
+
     def isGeneratedTabs(self):
         """See interface"""
@@ -323,5 +323,5 @@
                                         "portal_properties").site_properties
         return not site_properties.getProperty("disable_folder_sections", False)
-    
+
     def isNotFoldersGenerated(self):
         """See interface"""
@@ -331,5 +331,5 @@
                                            False)
         return not prop
-    
+
     def getActionsList(self, category="portal_tabs", errors={}, tabs=[]):
         """See interface"""
@@ -338,45 +338,45 @@
             kw['tabs'] = tabs
         return self.actionslist_template(**kw)
-    
+
     def getAutoGenereatedSection(self, cat_name, errors={}):
         """See interface"""
         return self.autogenerated_template(category=cat_name, errors=errors)
-    
+
     def getGeneratedTabs(self):
         """See interface"""
         return self.autogenerated_list()
-    
+
     def getRootTabs(self):
         """See interface"""
         context = aq_inner(self.context)
-        
+
         portal_catalog = getToolByName(context, 'portal_catalog')
         portal_properties = getToolByName(context, 'portal_properties')
         navtree_properties = getattr(portal_properties, 'navtree_properties')
-        
+
         # Build result dict
         result = []
-        
+
         # check whether tabs autogeneration is turned on
         if not self.isGeneratedTabs():
             return result
-        
+
         query = {}
         rootPath = getNavigationRoot(context)
         query['path'] = {'query' : rootPath, 'depth' : 1}
         query['portal_type'] = utils.typesToList(context)
-        
+
         sortAttribute = navtree_properties.getProperty('sortAttribute', None)
         if sortAttribute is not None:
             query['sort_on'] = sortAttribute
-            
+
             sortOrder = navtree_properties.getProperty('sortOrder', None)
             if sortOrder is not None:
                 query['sort_order'] = sortOrder
-        
+
         if navtree_properties.getProperty('enable_wf_state_filtering', False):
             query['review_state'] = navtree_properties.getProperty(
                 'wf_states_to_show', [])
-        
+
         query['is_default_page'] = False
 
@@ -402,16 +402,16 @@
                         'exclude_from_nav' : item.exclude_from_nav}
                 result.append(data)
-        
+
         return result
-    
+
     def getCategories(self):
         """See interface"""
         portal_actions = getToolByName(self.context, "portal_actions")
         return portal_actions.objectIds()
-    
+
     #
     # Methods to make this class looks like global sections viewlet
     #
-    
+
     def test(self, condition, ifTrue, ifFalse):
         """See interface"""
@@ -420,5 +420,5 @@
         else:
             return ifFalse
-    
+
     # methods for rendering global-sections viewlet via kss,
     # due to bug in macroContent when global-section list is empty,
@@ -430,7 +430,6 @@
         portal_tabs_view = getMultiAdapter((self.context, self.request),
             name="portal_tabs_view")
-        
-        return portal_tabs_view.topLevelTabs(actions=actions)
-    
+        return portal_tabs_view.topLevelTabs(actions=actions['portal_tabs'])
+
     def selected_portal_tab(self):
         """See global-sections viewlet"""
@@ -438,7 +437,7 @@
         selected_tabs = selectedTabs('index_html', self.context,
             self.portal_tabs())
-        
+
         return selected_tabs['portal']
-    
+
     ##########################
     #
@@ -446,24 +445,24 @@
     #
     ##########################
-    
+
     @kssaction
     def kss_insertModeLink(self):
         """Insert link which allows change categories between plain and rich"""
         ksscore = self.getCommandSet('core')
-        
+
         html = self.link_template()
         target = ksscore.getCssSelector('.link-parent')
         ksscore.insertHTMLAfter(target, html, withKssSetup='False')
-    
+
     @kssaction
     def kss_changeCategory(self, cat_name):
         """Change action category to manage"""
         ksscore = self.getCommandSet('core')
-        
+
         # update actions list
         actionslist = self.getActionsList(category=cat_name)
         ksscore.replaceInnerHTML(ksscore.getHtmlIdSelector('tabslist'),
             actionslist)
-        
+
         # update autogenerated sections
         section = self.getAutoGenereatedSection(cat_name)
@@ -475,5 +474,5 @@
         ksscore.replaceInnerHTML(
             ksscore.getHtmlIdSelector('plonetabs-form-title'), title)
-        
+
         # update category hidden field on adding form
         ksscore.setAttribute(ksscore.getCssSelector(
@@ -481,14 +480,14 @@
             'value',
             cat_name)
-        
+
         # update state variable 'plonetabs-category' on client
         ksscore.setStateVar('plonetabs-category', cat_name)
-        
+
         # hide adding form
         self.kss_hideAddForm()
-        
+
         # issue portal status message
         self.kss_issueMessage(_(u"Category changed successfully."))
-    
+
     @kssaction
     def kss_toggleGeneratedTabs(self, field, checked='0'):
@@ -506,16 +505,16 @@
             else:
                 message = _(u"Generated tabs switched off.")
-        
+
         # update client
         ksscore = self.getCommandSet("core")
         content = self.getGeneratedTabs()
         ksscore.replaceInnerHTML(ksscore.getHtmlIdSelector('roottabs'), content)
-        
+
         # update global-sections viewlet
         self.updatePortalTabsPageSection()
-        
+
         # issue portal status message
         self.kss_issueMessage(message)
-    
+
     @kssaction
     def kss_toggleRootsVisibility(self, id, checked='0'):
@@ -523,20 +522,20 @@
         portal = getMultiAdapter((aq_inner(self.context), self.request),
             name='plone_portal_state').portal()
-        
+
         # remove prefix, added for making ids on configlet unique ("roottabs_")
         obj_id = id[len("roottabs_"):]
-        
+
         if obj_id not in portal.objectIds():
             raise KSSExplicitError, \
                   _(u"Object with '${id}' id doesn't exist in portal root.",
                     mapping={'id': obj_id})
-        
+
         if checked == '1':
             checked = True
         else:
             checked = False
-        
+
         portal[obj_id].update(excludeFromNav=not checked)
-        
+
         # update client
         ksscore = self.getCommandSet("core")
@@ -550,11 +549,11 @@
             message = _(u"'${id}' object was excluded from navigation.",
                         mapping={'id':obj_id})
-        
+
         # update global-sections viewlet
         self.updatePortalTabsPageSection()
-        
+
         # issue portal status message
         self.kss_issueMessage(message)
-    
+
     @kssaction
     def kss_toggleActionsVisibility(self, id, checked='0', cat_name=None):
@@ -564,5 +563,5 @@
         self.updateAction(act_id, cat_name,
             {'id': act_id, 'visible': (checked == '1') or False})
-        
+
         # update client
         ksscore = self.getCommandSet("core")
@@ -577,8 +576,8 @@
                         mapping={'id':act_id})
         self.updatePage(cat_name)
-    
+
         # issue portal status message
         self.kss_issueMessage(message)
-    
+
     @kssaction
     def kss_deleteAction(self, id, cat_name):
@@ -587,5 +586,5 @@
         act_id, category, action = self.kss_validateAction(id, cat_name)
         self.deleteAction(act_id, cat_name)
-        
+
         # update client
         ksscore = self.getCommandSet("core")
@@ -593,12 +592,12 @@
         # we need kukit js action/command plugin
         ksscore.deleteNode(ksscore.getHtmlIdSelector(id))
-        
+
         # update different sections of page depending on actions category
         self.updatePage(cat_name)
-        
+
         # issue portal status message
         self.kss_issueMessage(_(u"'${id}' action successfully removed.",
                                 mapping={'id':act_id}))
-    
+
     @kssaction
     def kss_addAction(self, cat_name):
@@ -606,8 +605,8 @@
         # extract posted data
         id, ie7bad_category, data = self.parseAddForm(self.request.form)
-        
+
         # validate posted data
         errors = self.validateActionFields(cat_name, data)
-        
+
         # if not errors find (or create) category and set action to it
         ksscore = self.getCommandSet('core')
@@ -615,5 +614,5 @@
         if not errors:
             action = self.addAction(cat_name, data)
-            
+
             # update client
             # add one more action to actions list
@@ -621,8 +620,8 @@
             ksscore.insertHTMLAsLastChild(ksscore.getHtmlIdSelector('tabslist'),
                  content)
-            
+
             # update reorder controls
             #self.kss_checkReorderControls(cat_name)
-            
+
             # hide adding form
             ksscore.removeClass(ksscore.getHtmlIdSelector('addaction'),
@@ -631,19 +630,19 @@
                 ksscore.getCssSelector('form[name=addaction_form] '
                                        '.headerAdvanced'), collapse='true')
-            
+
             # set client state var 'plonetabs-addingTitle' to empty
             # string for correct id autogeneration functionality
             ksscore.setStateVar('plonetabs-addingTitle', '')
-            
+
             # reset adding form
             self.kss_resetForm(ksscore.getHtmlIdSelector('addaction'))
-            
+
             # remove focus from name input
             self.kss_blur(ksscore.getHtmlIdSelector('actname'))
-            
+
             message = _(u"'${id}' action successfully added.",
                         mapping={'id':action.id})
             msgtype = "info"
-            
+
             # update page
             self.updatePage(cat_name)
@@ -654,14 +653,14 @@
                     ksscore.getCssSelector('form[name=addaction_form] '
                                            '.headerAdvanced'), collapse='false')
-            
+
             message = _(u"Please correct the indicated errors.")
             msgtype = "error"
-        
+
         # update errors on client form
         self.kss_issueErrors(errors)
-        
+
         # issue portal status message
         self.kss_issueMessage(message, msgtype)
-    
+
     @kssaction
     def kss_hideAddForm(self):
@@ -669,73 +668,73 @@
         # no server changes, only update client
         ksscore = self.getCommandSet("core")
-        
+
         # hide form itself
         ksscore.removeClass(ksscore.getHtmlIdSelector('addaction'), 'adding')
-        
+
         # collapse advanced section
         self.kss_toggleCollapsible(
             ksscore.getCssSelector('form[name=addaction_form] .headerAdvanced'),
             collapse='true')
-        
+
         # reset form inputs
         self.kss_resetForm(ksscore.getHtmlIdSelector('addaction'))
-        
+
         # set client state var 'plonetabs-addingTitle' to empty string for
         # correct id autogeneration functionality
         ksscore.setStateVar('plonetabs-addingTitle', '')
-        
+
         # remove form errors if such exist
         self.kss_issueErrors({})
-        
+
         # issue portal status message
         self.kss_issueMessage(_(u"Adding canceled."))
-    
+
     @kssaction
     def kss_showEditForm(self, id, cat_name):
         """Show edit form for given action"""
         act_id, category, action = self.kss_validateAction(id, cat_name)
-        
+
         # fetch data
         action_info = self.copyAction(action)
         action_info["editing"] = True
-        
+
         # update client
         ksscore = self.getCommandSet("core")
         content = self.getActionsList(category=cat_name, tabs=[action_info,])
         ksscore.replaceHTML(ksscore.getHtmlIdSelector(id), content)
-        
+
         # focus name field
         ksscore.focus(
             ksscore.getCssSelector("#%s input[name=title_%s]" % (id, act_id)))
-        
+
         # issue portal status message
         self.kss_issueMessage(_(u"Fill in required fields and click on Add."))
-    
+
     @kssaction
     def kss_hideEditForm(self, id, cat_name):
         """Hide edit form for given action"""
         act_id, category, action = self.kss_validateAction(id, cat_name)
-        
+
         # update client
         ksscore = self.getCommandSet("core")
         content = self.getActionsList(category=cat_name, tabs=[action,])
         ksscore.replaceHTML(ksscore.getHtmlIdSelector(id), content)
-        
+
         # issue portal status message
         self.kss_issueMessage(_(u"Changes discarded."))
-    
+
     @kssaction
     def kss_editAction(self):
         """Update action's properties"""
         id, cat_name, data = self.parseEditForm(self.request.form)
-        
+
         # get category and action to edit
         category = self.getActionCategory(cat_name)
         action = category[id]
-        
+
         # validate posted data
         errors = self.validateActionFields(cat_name, data,
             allow_dup=(id == data['id']))
-        
+
         html_id = '%s%s%s' % (self.prefix, id, self.sufix)
         ksscore = self.getCommandSet('core')
@@ -743,14 +742,14 @@
         if not errors:
             action = self.updateAction(id, cat_name, data)
-            
+
             # update client
             # replace action item with updated one
             content = self.getActionsList(category=cat_name, tabs=[action,])
             ksscore.replaceHTML(ksscore.getHtmlIdSelector(html_id), content)
-            
+
             message = _(u"'${id}' action successfully updated.",
                         mapping={'id':action.id})
             msgtype = "info"
-            
+
             # update page
             self.updatePage(cat_name)
@@ -758,5 +757,5 @@
             # issue error messages
             self.kss_issueErrors(errors, editform=id)
-            
+
             # expand advanced section if there are errors in id,
             # action url or condition
@@ -766,11 +765,11 @@
                     ksscore.getCssSelector('#%s .headerAdvanced' % html_id),
                     collapse='false')
-            
+
             message = _(u"Please correct the indicated errors.")
             msgtype = "error"
-        
+
         # issue portal status message
         self.kss_issueMessage(message, msgtype)
-    
+
     @kssaction
     def kss_orderActions(self):
@@ -779,5 +778,5 @@
         cat_name = form['cat_name']
         category = self.getActionCategory(cat_name)
-        
+
         # decode URI components and collect ids from request
         components = urllib.unquote(form['actions']).split('&')
@@ -787,18 +786,18 @@
             ids = [component[len(self.prefix):-len(self.sufix)]
                 for component in components]
-        
+
         # do actual sorting
         category.moveObjectsByDelta(ids, -len(category.objectIds()))
-        
+
         # update client
         self.updatePage(cat_name)
-        
+
         # issue portal status message
         self.kss_issueMessage(_(u"Actions successfully sorted."))
-    
+
     #
     # Utility Methods
     #
-    
+
     def fixExpression(self, expr):
         """Fix expression appropriately for tal format"""
@@ -814,5 +813,5 @@
         else:
             return 'string:${object_url}/%s' % expr
-    
+
     def copyAction(self, action):
         """Copy action to dictionary"""
@@ -821,9 +820,9 @@
             action_info[attr] = getattr(action, attr)
         return action_info
-    
+
     def validateActionFields(self, cat_name, data, allow_dup=False):
         """Check action fields on validity"""
         errors = {}
-        
+
         if allow_dup:
             # create dummy category to avoid id
@@ -833,5 +832,5 @@
             # get or create (if necessary) actions category
             category = self.getOrCreateCategory(cat_name)
-        
+
         # validate action id
         chooser = INameChooser(category)
@@ -840,9 +839,9 @@
         except Exception, e:
             errors['id'] = self._formatError(e, **{'id':data['id']})
-        
+
         # validate action name
         if not data['title'].strip():
             errors['title'] = _(u"Empty or invalid title specified")
-        
+
         # validate condition expression
         if data['available_expr']:
@@ -855,5 +854,5 @@
                     mapping['expr_type'] = data['available_expr'][:idx]
                 errors["available_expr"] = self._formatError(e, **mapping)
-        
+
         # validate action expression
         if data['url_expr']:
@@ -866,7 +865,7 @@
                     mapping['expr_type'] = data['url_expr'][:idx]
                 errors["url_expr"] = self._formatError(e, **mapping)
-        
+
         return errors
-    
+
     def _formatError(self, message, **kw):
         """Make error message a little bit prettier to ease translation"""
@@ -881,7 +880,7 @@
         message = message.strip()
         return _(unicode(message, charset), mapping=mapping)
-    
+
     def processErrors(self, errors, prefix='', sufix=''):
-        """Add prefixes, sufixes to error ids 
+        """Add prefixes, sufixes to error ids
         This is necessary during edit form validation,
         because every edit form on the page has it's own sufix (id)
@@ -889,11 +888,11 @@
         if not (prefix or sufix):
             return errors
-        
+
         result = {}
         for key, value in errors.items():
             result['%s%s%s' % (prefix, key, sufix)] = value
-        
+
         return result
-    
+
     def parseEditForm(self, form):
         """Extract all needed fields from edit form"""
@@ -902,5 +901,5 @@
         id = form['orig_id']
         category = form['category']
-        
+
         # preprocess 'visible' field (checkbox needs special checking)
         if form.has_key('visible_%s' % id):
@@ -908,11 +907,11 @@
         else:
             form['visible_%s' % id] = False
-        
+
         # collect all action fields
         for attr in ACTION_ATTRS:
             info[attr] = form['%s_%s' % (attr, id)]
-        
+
         return (id, category, info)
-    
+
     def parseAddForm(self, form):
         """Extract all needed fields from add form"""
@@ -920,5 +919,5 @@
         id = form['id']
         category = form['category']
-        
+
         # preprocess 'visible' field (checkbox needs special checking)
         if form.has_key('visible') and form['visible']:
@@ -926,18 +925,18 @@
         else:
             form['visible'] = False
-        
+
         # fix expression fields
         form['url_expr'] = self.fixExpression(form['url_expr'])
-        
+
         # collect all action fields
         for attr in ACTION_ATTRS:
             info[attr] = form[attr]
-        
+
         return (id, category, info)
-    
+
     def getActionCategory(self, name):
         portal_actions = getToolByName(self.context, 'portal_actions')
         return portal_actions[name]
-    
+
     def getOrCreateCategory(self, name):
         """Get or create (if necessary) category"""
@@ -948,5 +947,5 @@
             portal_actions._setObject(name, ActionCategory(name))
         return self.getActionCategory(name)
-    
+
     def setSiteProperties(self, **kw):
         """Change site_properties"""
@@ -955,9 +954,9 @@
         site_properties.manage_changeProperties(**kw)
         return True
-    
+
     #
     # Utility methods for the kss actions management
     #
-    
+
     def kss_validateAction(self, id, cat_name):
         """Check whether action with given id exists in cat_name category"""
@@ -968,5 +967,5 @@
                   _(u"'${cat_name}' action category does not exist.",
                     mapping={'cat_name': cat_name})
-        
+
         # extract action id from given list item id on client
         action_id = self.sufix and id[len(self.prefix):-len(self.sufix)] or \
@@ -978,7 +977,7 @@
                   _(u"No '${id}' action in '${cat_name}' category.",
                     mapping={'id': action_id, 'cat_name': cat_name})
-        
+
         return (action_id, category, action)
-    
+
     def kss_issueErrors(self, errors, editform=False, fields=ACTION_ATTRS):
         """Display error messages on the client"""
@@ -988,5 +987,5 @@
             self.kss_issueFieldError(ksscore, field,
                                      errors.get(field, False), editform, ts)
-    
+
     def kss_issueFieldError(self, ksscore, name, error, editform, ts):
         """Issue this error message for the field"""
@@ -1011,5 +1010,5 @@
             ksscore.clearChildNodes(field_error_selector)
             ksscore.removeClass(field_selector, 'error')
-    
+
     def kss_toggleCollapsible(self, selector, collapsed=None,
                               expanded=None, collapse=None):
@@ -1025,13 +1024,13 @@
         if collapse is not None:
             data = command.addParam('collapse', collapse)
-    
+
     def kss_resetForm(self, selector):
         """KSS Server command to reset form on client"""
         command = self.commands.addCommand('plonetabs-resetForm', selector)
-    
+
     def kss_blur(self, selector):
         """KSS Server command to remove focus from input"""
         command = self.commands.addCommand('plonetabs-blur', selector)
-    
+
     def kss_replaceOrInsert(self, selector, parentSelector, html,
                             withKssSetup='True', alternativeHTML='',
@@ -1055,5 +1054,5 @@
             data = command.addParam('positionSelectorType',
                                     positionSelectorType)
-    
+
     def kss_issueMessage(self, message, msgtype="info"):
         """"Issues portal status message and removes it afte 10 seconds"""
@@ -1065,9 +1064,9 @@
             cmd_name='setStyle', name='display', value='none'
         )
-    
+
     def kss_timeout(self, selector, **kw):
         """KSS Server command to execute plonetabs-timeout client action"""
         command = self.commands.addCommand('plonetabs-timeout', selector, **kw)
-    
+
     def renderViewlet(self, manager, name):
         if isinstance(manager, basestring):
@@ -1079,9 +1078,9 @@
         renderer.update()
         return renderer.render()
-    
+
     #
     # Basic API to work with portal actions tool in a more pleasent way
     #
-    
+
     def addAction(self, cat_name, data):
         """Create and add new action to category with given name"""
@@ -1091,24 +1090,24 @@
         category._setObject(id, action)
         return action
-    
+
     def updateAction(self, id, cat_name, data):
         """Update action with given id and category"""
         new_id = data.pop('id')
         category = self.getActionCategory(cat_name)
-        
+
         # rename action if necessary
         if id != new_id:
             category.manage_renameObject(id, new_id)
-        
+
         # get action
         action = category[new_id]
-        
+
         # update action properties
         for attr in data.keys():
             if data.has_key(attr):
                 action._setPropValue(attr, data[attr])
-        
+
         return action
-    
+
     def deleteAction(self, id, cat_name):
         """Delete action with given id from given category"""
@@ -1116,5 +1115,5 @@
         category.manage_delObjects(ids=[id,])
         return True
-    
+
     def moveAction(self, id, cat_name, steps=0):
         """Move action by a given steps"""
@@ -1127,10 +1126,10 @@
             return True
         return False
-    
+
     #
     # KSS Methods that are used to update different parts of the page
     # accordingly to category
     #
-    
+
     def updatePage(self, category):
         """Seek for according method in class and calls it if found
@@ -1142,5 +1141,5 @@
         if hasattr(self, method_name):
             getattr(self, method_name)()
-    
+
     def updatePortalTabsPageSection(self):
         """Method for updating global-sections on client"""
@@ -1151,5 +1150,5 @@
                                  withKssSetup='False',
                                  selectorType='htmlid')
-    
+
     def updateSiteActionsPageSection(self):
         """Method for updating site action on client"""
@@ -1164,5 +1163,5 @@
                                  positionSelector="portal-searchbox",
                                  positionSelectorType="htmlid")
-        
+
         #ksszope = self.getCommandSet("zope")
         #ksszope.refreshViewlet(
@@ -1170,5 +1169,5 @@
             #"plone.portalheader",
             #"plone.site_actions")
-    
+
     def updateUserPageSection(self):
         """Method for updating site action on client"""
@@ -1181,5 +1180,5 @@
 
 class PloneTabsMode(BrowserView):
-    
+
     def __call__(self):
         mode = self.request.get(cookie_name, False)
