Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/DropDownMenuTool.py
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/DropDownMenuTool.py	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/DropDownMenuTool.py	(revision 2565)
@@ -0,0 +1,24 @@
+from Globals import InitializeClass
+from OFS.SimpleItem import SimpleItem
+from AccessControl import ClassSecurityInfo
+
+from Products.CMFCore.utils import UniqueObject, getToolByName
+
+from utils import updateMenu
+from config import MANAGE_PERMISSION, PROJECT_NAME, UNIQUE_ID
+
+
+class DropDownMenuTool(UniqueObject, SimpleItem):
+
+    meta_type = 'DropDownMenu Tool'
+    id = UNIQUE_ID
+    title="DropDown Menu Tool"
+
+    security = ClassSecurityInfo()
+
+    security.declareProtected(MANAGE_PERMISSION, 'regenerateMenu')
+    def regenerateMenu(self):
+        portal = getToolByName(self, 'portal_url').getPortalObject()
+        updateMenu(portal)
+
+InitializeClass(DropDownMenuTool)
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/HISTORY.txt
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/HISTORY.txt	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/HISTORY.txt	(revision 2565)
@@ -0,0 +1,78 @@
+0.2.1
+
+  * fix string encoding issues during product installation and menu regeneration
+    for details: http://talk.quintagroup.com/forums/plone-drop-down-menu/237707814
+
+0.2
+
+  * fixed documentation
+
+  * some minor fixes to portal status messages and validation stuff
+
+  * compatible with plone 3
+
+0.1.12
+
+  * added caching for static objects via .metadata
+
+0.1.11
+
+  * divided :hover javascript functionality into two parts: evaluating css by script, saving styles from configlet 
+
+0.1.10
+
+  * fixed kupu related bug (during editing with kupu in zoomed mode)
+
+0.1.9
+
+  * edited for correct work with IE before 6.0
+
+0.1.8 
+
+  * optimized page load time for IE
+
+0.1.7
+
+  * corrected and optimized csshover.htc script
+   
+0.1.6
+
+  * added to readme.txt explanation to use of dropdownmenutool
+
+0.1.5
+
+  * changed drop_down.css
+
+  * compatible with Plone 2.1
+
+0.1.4
+
+  * optimized csshover.htc script
+
+0.1.3+
+
+  * added portal_dropdownmenu tool for security of regenerate procedure
+
+  * added the possibility to regenerate menu
+
+0.1.3
+
+  * install procedure generate html code for portal menu and save it in portal properties
+
+0.1.2
+
+  * install procedure update default portal menu from config.py
+
+0.1.1
+
+  * added the possibility to change portal menu within Plone 
+
+  * Internet Explorer 5.0 and 6.0 compatibility
+
+  * added Plone colors and styles
+
+  * changed the look of second-level menu
+
+0.1.0
+
+  * initial realise
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/README.txt
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/README.txt	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/README.txt	(revision 2565)
@@ -0,0 +1,79 @@
+Quintagroup Plone Drop Down Menu
+
+  The product allows Plone websites to update multilevel portal
+  dropdown menu and edit it within Plone.
+
+  "Product Homepage":http://quintagroup.com/services/plone-development/products/ |
+  "Download":http://sourceforge.net/projects/quintagroup
+
+  (c) "Quintagroup":http://quintagroup.com/ , 2008. 
+
+  support@quintagroup.com * quintessence of modern business
+
+Requires
+
+  Plone 3.0+
+
+Install
+
+  1. Install with Quick Installer. 
+
+  2. For Plone below 2.1 to use drop_down.css add '<dtml-var drop_down.css>'
+     line to your portal ploneCustom.css.
+
+Usage
+
+  You have a list of items of your top level menu, which you can edit in
+  'drop down menu' configlet form. Now, to add submenu to the certain 
+  menu item, you need to add unordered list inside of top level menu 
+  item ('<li>...</li>') after its title ('<a></a>')::
+
+   <ul><li>...</li>...<li>...</li></ul>
+
+  To make your changes live click 'save' button.
+
+  Sample menu with 2 submenus::
+ 
+   <li id="portaltab-index_html" class="plain"><a href="http://example.com/" accesskey="t">Home</a></li>
+   <li id="portaltab-Members" class="plain"><a href="http://example.com/Members" accesskey="t">Members</a>
+       <ul>
+           <li><a href="http://example.com/Members/jdoe">John Doe</a><li>
+           <li><a href="http://example.com/Members/mmajor">Mary Major</a></li>
+       </ul>
+   </li>
+   <li id="portaltab-news" class="plain"><a href="http://example.com/news" accesskey="t">News</a></li>
+   <li id="portaltab-events" class="plain"><a href="http://example.com/events" accesskey="t">Events</a>
+       <ul>
+           <li><a href="http://example.com/events/previous">Past Events</a><li>
+           <li><a href="http://example.com/calendar">Calendar</a><li>
+       </ul>
+   </li>
+
+  In this example we added submenus to our 'Members', and 'Events' tabs.
+
+
+  Customize the following elements in your's css files to
+  changed the appearance of drop down menu:
+
+    * #portal-globalnav - global navigation bar
+    * #portal-globalnav .csshover li.plain a, #portal-globalnav li a - global navigation link
+    * #portal-globalnav .csshover li.plain a:hover, #portal-globalnav li a:hover - global navigation link hover
+    * #portal-globalnav .csshover li.plain ul, #portal-globalnav li ul - global navigation drop-down box
+    * #portal-globalnav .csshover li.plain ul li a, #portal-globalnav li ul li a - global navigation drop-down link
+    * #portal-globalnav .csshover li.plain ul li a:hover, #portal-globalnav li ul li a:hover - global navigation
+      drop-down link hover
+
+
+You can click  button on 'drop down menu' configlet form to reset menu.
+This can be usefull in case  broken html of menu code. Generated code is based
+on status of 'Automatically generate tabs' in your 'Navigation settings' 
+(in Plone 2.1+). However you will lose your previous code of menu with all submenus 
+after click on 'regenerate menu'. 
+
+If you want to 'regenerate menu' you should pay attention to status of 
+'Automatically generate tabs' in your 'Navigation settings' (in Plone 2.1+).
+
+
+Authors
+
+  * Vitaliy Podoba
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/__init__.py
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/__init__.py	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/__init__.py	(revision 2565)
@@ -0,0 +1,14 @@
+from AccessControl import allow_module
+from Products.CMFCore.utils import ToolInit
+
+from Products.qPloneDropDownMenu.DropDownMenuTool import DropDownMenuTool
+from Products.qPloneDropDownMenu.config import PROJECT_NAME
+
+allow_module('Products.qPloneDropDownMenu.utils')
+
+tools = (DropDownMenuTool,)
+ 
+def initialize(context):
+    ToolInit(PROJECT_NAME,
+             tools=tools,
+             icon='tool.gif').initialize(context)
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/browser/__init__.py
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/browser/__init__.py	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/browser/__init__.py	(revision 2565)
@@ -0,0 +1,1 @@
+#
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/browser/configure.zcml
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/browser/configure.zcml	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/browser/configure.zcml	(revision 2565)
@@ -0,0 +1,16 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    i18n_domain="qPloneDropDownMenu">
+
+    <include package="plone.browserlayer" />
+
+    <browser:viewlet
+        name="plone.global_sections"
+        manager="plone.app.layout.viewlets.interfaces.IPortalHeader"
+        template="sections.pt"
+        layer=".interfaces.IQPloneDropDownMenuLayer"
+        permission="zope2.View"
+        />
+
+</configure>
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/browser/interfaces.py
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/browser/interfaces.py	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/browser/interfaces.py	(revision 2565)
@@ -0,0 +1,5 @@
+from zope.interface import Interface
+
+class IQPloneDropDownMenuLayer(Interface):
+    """A layer specific to qPloneDropDownMenu product
+    """
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/browser/sections.pt
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/browser/sections.pt	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/browser/sections.pt	(revision 2565)
@@ -0,0 +1,11 @@
+<tal:tabs i18n:domain="plone">
+    <h5 class="hiddenStructure" i18n:translate="heading_sections">Sections</h5>
+    <div id="portal-globalnav">
+        <div class="csshover">
+            <ul>
+               <span tal:replace="structure context/portal_properties/dropdownmenu_properties/menu|string:qPloneDropDownMenu broken" />
+               <li class="invisibleHeightKeeper">&nbsp;</li>
+            </ul>
+        </div>
+    </div>
+</tal:tabs>
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/config.py
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/config.py	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/config.py	(revision 2565)
@@ -0,0 +1,12 @@
+try:
+    from Products.CMFCore import permissions
+except ImportError:
+    from Products.CMFCore import CMFCorePermissions as permissions
+ 
+MANAGE_PERMISSION = permissions.ManagePortal
+
+PROJECT_NAME = 'qPloneDropDownMenu'
+UNIQUE_ID = "portal_dropdownmenu"
+
+PROPERTY_SHEET = 'dropdownmenu_properties'
+PROPERTY_FIELD = 'menu'
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/configure.zcml
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/configure.zcml	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/configure.zcml	(revision 2565)
@@ -0,0 +1,20 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:cmf="http://namespaces.zope.org/cmf"
+    xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
+    i18n_domain="qPloneDropDownMenu">
+
+    <!-- Register the installation GenericSetup extension profile -->
+    <genericsetup:registerProfile
+      name="default"
+      title="qPloneDropDownMenu"
+      directory="profiles/default"
+      description="Allows Plone websites to update multilevel portal dropdown menu"
+      provides="Products.GenericSetup.interfaces.EXTENSION"
+      />
+
+    <cmf:registerDirectory name="qPloneDropDownMenu"/>
+
+    <include package=".browser" />
+
+</configure>
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/actionicons.xml
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/actionicons.xml	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/actionicons.xml	(revision 2565)
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<action-icons xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+    i18n:domain="qPloneDropDownMenu">
+ <action-icon category="controlpanel" action_id="qPloneDropDownMenu"
+              title="Drop Down Menu" priority="0"
+              icon_expr="qplonedropdownmenu.gif"
+              i18n:attributes="title"/>
+</action-icons>
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/browserlayer.xml
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/browserlayer.xml	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/browserlayer.xml	(revision 2565)
@@ -0,0 +1,4 @@
+<layers>
+  <layer name="qPloneDropDownMenu"
+         interface="Products.qPloneDropDownMenu.browser.interfaces.IQPloneDropDownMenuLayer" />
+</layers>
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/controlpanel.xml
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/controlpanel.xml	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/controlpanel.xml	(revision 2565)
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<object name="portal_controlpanel" meta_type="Plone Control Panel Tool"
+    xmlns:i18n="http://xml.zope.org/namespaces/i18n" i18n:domain="qPloneDropDownMenu">
+ <configlet title="Drop Down Menu" action_id="qPloneDropDownMenu"
+    appId="qPloneDropDownMenu" category="Products" condition_expr=""
+    url_expr="string:${portal_url}/prefs_dropdownmenu_edit_form"
+    visible="True" i18n:attributes="title">
+  <permission>Manage portal</permission>
+ </configlet>
+ <configlet title="CSS Hover" action_id="csshover"
+    appId="qPloneDropDownMenu" category="Products" condition_expr=""
+    url_expr="string:${portal_url}/prefs_csshover_edit_form"
+    visible="True" i18n:attributes="title">
+  <permission>Manage portal</permission>
+ </configlet>
+</object>
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/cssregistry.xml
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/cssregistry.xml	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/cssregistry.xml	(revision 2565)
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<object name="portal_css" meta_type="Stylesheets Registry">
+ <stylesheet title="DropDownMenu" cacheable="True" compression="safe" cookable="True"
+    enabled="1" expression="portal/portal_dropdownmenu|nothing"
+    id="drop_down.css" media="screen" rel="stylesheet" rendering="import"/>
+</object>
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/import_steps.xml
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/import_steps.xml	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/import_steps.xml	(revision 2565)
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<import-steps>
+ <import-step id="qPloneDropDownMenu_installMenu" version="20081107-01"
+              handler="Products.qPloneDropDownMenu.setuphandlers.installMenu"
+              title="Update Dropdown Menu">
+  <dependency step="toolset"/>
+    Update Dropdown Menu from portal actions or root items
+ </import-step>
+</import-steps>
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/metadata.xml
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/metadata.xml	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/metadata.xml	(revision 2565)
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<metadata>
+  <version>0.2</version>
+</metadata>
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/qplonedropdownmenu_various.txt
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/qplonedropdownmenu_various.txt	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/qplonedropdownmenu_various.txt	(revision 2565)
@@ -0,0 +1,1 @@
+The qplonedropdownmenu steps are run if this file is present in the profile
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/skins.xml
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/skins.xml	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/skins.xml	(revision 2565)
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<object name="portal_skins" meta_type="Plone Skins Tool" allow_any="False"
+   cookie_persistence="False" default_skin="Plone Default"
+   request_varname="plone_skin">
+ <object name="qPloneDropDownMenu" meta_type="Filesystem Directory View"
+    directory="Products.qPloneDropDownMenu:skins/qPloneDropDownMenu"/>
+ <skin-path name="*" purge="False">
+  <layer name="qPloneDropDownMenu" insert-after="custom"/>
+ </skin-path>
+</object>
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/toolset.xml
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/toolset.xml	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/profiles/default/toolset.xml	(revision 2565)
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<tool-setup>
+ <required tool_id="portal_dropdownmenu"
+           class="Products.qPloneDropDownMenu.DropDownMenuTool"/>
+</tool-setup>
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/setuphandlers.py
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/setuphandlers.py	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/setuphandlers.py	(revision 2565)
@@ -0,0 +1,21 @@
+from Products.CMFCore.utils import getToolByName
+
+from utils import updateMenu
+from config import PROPERTY_SHEET, PROPERTY_FIELD
+
+def installMenu(context):
+
+    if context.readDataFile('qplonedropdownmenu_various.txt') is None:
+        return
+
+    site = context.getSite()
+    portal_props = getToolByName(site, 'portal_properties')
+
+    # skip adding property if it already exists
+    prop_sheet = getattr(portal_props.aq_base, PROPERTY_SHEET, None)
+    if prop_sheet is not None:
+        prop_field = getattr(prop_sheet.aq_base, PROPERTY_FIELD, None)
+        if prop_field is not None:
+            return
+
+    updateMenu(site)
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/csshover.htc.dtml
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/csshover.htc.dtml	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/csshover.htc.dtml	(revision 2565)
@@ -0,0 +1,143 @@
+<dtml-call "REQUEST.RESPONSE.setHeader('Content-Type', 'text/x-component')">
+<attach event="ondocumentready" handler="parseStylesheets" />
+<script language="JScript">
+/**
+ *    HOVER - V1.11.040203 - whatever:hover in IE
+ *    ---------------------------------------------
+ *    Peterned - http://www.xs4all.nl/~peterned/
+ *    (c) 2004 - Peter Nederlof
+ *
+ *    Credits  - Arnoud Berendsen 
+ *        for finding some really -sick- bugs
+ *
+ *    howto: body { behavior:url("csshover.htc"); }
+ *    ---------------------------------------------
+ */
+var currentSheet, doc = window.document;
+var csshover_nodes = getElementsByClassName("csshover", doc);
+var csshover_rules = [], hoverStyleSheets = "", addRules = true;
+var IE5 = (doc.getElementsByTagName('*').length == 0) ? true : false, configlet = doc.getElementById('csshovering');
+var DEBUG = false, styles = "", parseCSSRulecounter = 0, timer, timerTable = "", d=true;
+
+function parseStylesheets() {
+    var sheets = doc.styleSheets, l = sheets.length;
+    for(var i=0; i<l; i++){
+        parseStylesheet(sheets[i]);
+    };
+    if (configlet) {configlet.innerText = hoverStyleSheets;};
+    if(DEBUG) {
+      alert(styles);
+      alert(timerTable);
+    };
+};
+
+function parseStylesheet(sheet) {
+    if(DEBUG) window.status += '|';
+//    if(sheet.href && sheet.href.indexOf('/ploneCustom.css') == -1) return;
+    var l, rules, imports;
+    if(sheet.imports) {
+        imports = sheet.imports, l = imports.length;
+        for(var i=0; i<l; i++)
+            parseStylesheet(sheet.imports[i]);
+    };
+    rules = (currentSheet = sheet).rules, l = rules.length;
+    for(var j=0; j<l; j++){parseCSSRule(rules[j]);};
+};
+
+function parseCSSRule(rule) {
+    if(DEBUG) {
+        if((parseCSSRulecounter++)%15 == 0) window.status += '.';
+        startTimer();
+    };
+    var select = rule.selectorText, style = rule.style.cssText;
+    if (addRules && (/\.cssHoverCSSExists/i).test(select)) {addRules = false;};
+    if(!(/\.csshover/i).test(select)) return;
+    if(style.replace(/ /, "") == "") return;
+    if(!(/(^|\s)(([^a]([^ ]+)?)|(a([^#.][^ ]+)+)):hover/i).test(select)) return;
+
+    var newSelect = select.replace(/(\.([a-z0-9_-]+):hover)|(:hover)/g, '.$2onHover');
+    if (addRules) {currentSheet.addRule(newSelect, style);};
+    if (configlet) {hoverStyleSheets += newSelect + ' \{\n  ' + style.replace('; ', '\;\n  ') + ';\n\}\n';};
+
+    var hasClass = (/(\.([a-z0-9_-]+):hover)/g).exec(select);
+    var className = (hasClass? hasClass[2]:'') + 'onHover';
+    var affected = select.replace(/:hover.*$/g, '');
+    affected = affected.replace(/^.*([ ]|^)(([^ ]*)\.csshover)/i, '$2');
+    if (DEBUG) {timerTable += stopTimer() + '\n';};
+    if(!csshover_rules[className + ',' + affected]) {
+        if (DEBUG) {startTimer();};
+        var elements = getElementsBySelect(affected);
+        if(DEBUG) {
+            window.status += " "+elements.length;
+            styles += "" + elements.length + ": " + affected + '\n';
+        };
+        for(var i=0; i<elements.length; i++)
+            new HoverElement(elements[i], className);
+        csshover_rules[className + ',' + affected] = true;
+    };
+};
+
+function HoverElement(node, className) {
+    if(!node.hovers) node.hovers = {};
+    if(node.hovers[className]) return;
+    node.hovers[className] = true;
+    node.attachEvent('onmouseover',
+        function() { node.className += ' ' + className; });
+    node.attachEvent('onmouseout',
+        function() { node.className =
+            node.className.replace((new RegExp('\\s+'+className)),''); });
+};
+
+function getElementsBySelect(rule) {
+    var parts, nodes = csshover_nodes;
+    parts = rule.split(' ');
+    for(var i=0; i<parts.length; i++) {
+        nodes = getSelectedNodes(parts[i], nodes, i==0);
+    };
+    return nodes;
+};
+
+function getSelectedNodes(select, elements, includeRoot) {
+    var element, result, node, nodes = [];
+    var classname = (/\.([a-z0-9_-]+)/i).exec(select);
+    if(classname) {classname_re = new RegExp('\\b' + classname[1] + '\\b');};
+    var identify = (/\#([a-z0-9_-]+)/i).exec(select);
+    var tagName = (/^[a-z0-9]+/i).exec(select.toUpperCase()) || '*',
+        ell = elements.length;
+    for(var i=0; i<ell; i++) {
+        element = elements[i]
+        if(includeRoot)
+          if((tagName == '*') || (element.nodeName == tagName)) result = [element]
+          else result = []
+        else
+            if (tagName == '*' && IE5) result = elements[i].all
+            else result = elements[i].getElementsByTagName(tagName)
+        rel = result.length;
+        for(var j=0; j<rel; j++) {
+            node = result[j];
+            if((identify && node.id != identify[1]) || (classname && !(classname_re.exec(node.className))) || arrayHasElement(nodes, node)) continue;
+            nodes[nodes.length] = node;
+        };
+    };
+    return nodes;
+};
+
+function arrayHasElement(a, el) {
+    var l = a.length;
+    for(var i=0; i<l; i++) if(a[i] == el) return true;
+    return false;
+};
+
+function getElementsByClassName(className, parentElement) {
+    var result = new Array(),
+        list = (parentElement || doc.body).getElementsByTagName('*');
+    if(list.length == 0) list = (parentElement || doc.body).all;
+    var class_re = new RegExp('(^|\\s)' + className + '(\\s|$)');
+    for(var i = 0; i < list.length; i++) if(list[i].className.match(class_re)) result[result.length] = list[i];
+    return result;
+};
+
+function startTimer() {timer = new Date().getTime();};
+function stopTimer(message) {return (new Date().getTime()) - timer;};
+
+</script>
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/csshover.htc.dtml.metadata
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/csshover.htc.dtml.metadata	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/csshover.htc.dtml.metadata	(revision 2565)
@@ -0,0 +1,3 @@
+[default]
+title=CSS Hover scripts for IE6
+cache=HTTPCache
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/csshover_save.cpy
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/csshover_save.cpy	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/csshover_save.cpy	(revision 2565)
@@ -0,0 +1,42 @@
+## Controller Python Script "csshover_save"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind state=state
+##bind subpath=traverse_subpath
+##parameters=enabled=False, csshovering=[], sheetId='csshover.css', title='CSS Hover'
+##title=
+##
+
+from Products.CMFCore.utils import getToolByName
+from Products.qPloneDropDownMenu.utils import addCSS
+folder = getToolByName(context, 'portal_skins').restrictedTraverse('custom')
+
+if csshovering.find('.cssHoverCSSExists {}') == -1: csshovering = '.cssHoverCSSExists {}\n\n' + csshovering
+if not sheetId in folder.objectIds():
+    if csshovering.find('Use this configlet in IE') != -1: csshovering = " "
+    addCSS(folder, sheetId, title, csshovering)
+    message = 'Added %s to plone_skins  custom folder. ' % sheetId
+else:
+    if csshovering.find('Use this configlet in IE') == -1:
+        getattr(folder, sheetId).manage_edit(csshovering,title)
+        message = 'Updated %s. ' % sheetId
+    else: message = 'Visit this page in IE to see and activate generated CSS. '
+cssreg = getToolByName(context, 'portal_css', None)
+if cssreg is not None:
+    stylesheet_ids = cssreg.getResourceIds()
+    if sheetId not in stylesheet_ids:
+        cssreg.registerStylesheet(id=sheetId, enabled=enabled)
+        try: cssreg.moveResource(sheetId, cssreg.getResourcePosition('textLarge.css')+1)
+        except: pass
+        cssreg.cookResources()
+    else:
+        cssreg.updateStylesheet(sheetId, **{'enabled' : enabled})
+        cssreg.cookResources()
+else:
+    message += "For activating csshover.css customize ploneCustom.css and add <dtml-var csshover.css> line before <dtml-var drop_down.css>"
+
+context.plone_utils.addPortalMessage(message)
+
+return state.set(status='success')
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/csshover_save.cpy.metadata
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/csshover_save.cpy.metadata	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/csshover_save.cpy.metadata	(revision 2565)
@@ -0,0 +1,3 @@
+[actions]
+action.failure=traverse_to:string:prefs_csshover_edit_form
+action.success=redirect_to:string:prefs_csshover_edit_form
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/drop_down.css.dtml
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/drop_down.css.dtml	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/drop_down.css.dtml	(revision 2565)
@@ -0,0 +1,163 @@
+/* <dtml-with base_properties> (do not remove this :) */
+/* <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either :) */
+
+body {
+  behavior:url("&dtml-portal_url;/csshover.htc");
+}
+
+
+/*             ------  Basic style  ------             */
+#portal-globalnav ul {
+        margin: 0;
+        padding: 0;
+        border: 0;
+        list-style-type: none;
+}
+
+#portal-globalnav li {
+        margin: 0;  
+        padding: 0;
+        border: 0; 
+        display: inline;
+        float: left;
+        z-index: 10000;
+        position: relative;
+}
+
+#portal-globalnav a {
+        float: left;/* \*/float: none;/*  */
+        display: block;
+}
+
+#portal-globalnav li ul {
+        visibility: hidden;
+        position: absolute;
+        width: 20em;
+}
+
+#portal-globalnav li ul li {
+        width: 100%;
+        display: block;
+        float: left;
+        position: static;
+}
+
+#portal-globalnav li ul li a {
+        width: 100%;
+}
+
+html>body #portal-globalnav li ul li {
+        float: none;
+        position: relative;
+}
+
+#portal-globalnav .csshover li ul li:hover {
+        position: relative;
+}
+
+
+/* fix the position */
+#portal-globalnav li ul li ul {
+        top: 0;
+        left: 100%;
+}
+
+
+
+/* simulate child selector for IE */
+div#portal-globalnav .csshover li:hover ul, #portal-globalnav .csshover li:hover li:hover ul, #portal-globalnav .csshover li:hover li:hover li:hover ul, #portal-globalnav .csshover li:hover li:hover li:hover li:hover ul {
+        visibility: visible;
+}
+#portal-globalnav .csshover li:hover li ul, #portal-globalnav .csshover li:hover li:hover li ul, #portal-globalnav .csshover li:hover li:hover li:hover li ul, #portal-globalnav .csshover li:hover li:hover li:hover li:hover li ul { 
+        visibility: hidden;
+}
+
+/* do the normal show, with increased specificity */
+#portal-globalnav ul#portal-globalnavList .csshover li:hover > ul {
+       visibility: visible;
+}
+
+/*     ------   Make-up --------            */
+
+#portal-globalnav li.invisibleHeightKeeper {
+        visibility: hidden;
+        float: none;
+}
+
+#portal-globalnav .csshover ul li ul li a:hover,
+#portal-globalnav .csshover ul li ul li:hover a {
+        color: &dtml-globalFontColor;;
+}
+
+#portal-globalnav ul li ul li a {
+        border-style: none;
+        margin-right: 0em;
+}
+
+#portal-globalnav ul li ul {
+        border: &dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;;
+        padding-bottom: 1px;
+        overflow: hidden;
+}
+
+#portal-globalnav .csshover ul li:hover ul li:hover ul  a {
+        color: &dtml-globalFontColor;;
+}
+
+/* latest changes */
+
+#portal-globalnav ul {
+        font-size:8pt;
+        list-style-type:none;
+        list-style-image:none;
+}
+
+#portal-globalnav ul li {
+        padding:0;
+        margin:0;
+        line-height:normal;
+}
+
+#portal-globalnav ul li.selected a,
+#portal-globalnav .csshover ul li a:hover {
+        background-color:&dtml-globalBackgroundColor;;
+        color:&dtml-globalFontColor;;
+}
+
+#portal-globalnav .csshover ul li:hover ul {
+        margin:0;
+        border: &dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;;
+        background-color: &dtml-backgroundColor;;
+        overflow:visible;
+}
+
+#portal-globalnav .csshover ul li:hover ul li {
+        padding:0;
+        margin:0;
+}
+
+#portal-globalnav .csshover ul li:hover ul li a {
+        color: &dtml-globalFontColor; !important;
+        margin:0;
+        line-height:normal;
+        width:auto;
+}
+
+#portal-globalnav .csshover ul li ul li a:hover {
+        background-image:none;
+}
+
+.kupu-fulleditor-zoomed #portal-globalnav {
+        display: none;
+}
+
+/*Configlet styles************************************************************/
+
+.ieVisible {display:none;}
+
+* html .ieHidden {display: none;}
+
+* html .ieVisible {display: block;}
+
+
+/* </dtml-with> (do not remove this either :) */
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/dropdownmenu_edit.cpy
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/dropdownmenu_edit.cpy	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/dropdownmenu_edit.cpy	(revision 2565)
@@ -0,0 +1,31 @@
+## Controller Python Script "dropdownmenu_edit"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind state=state
+##bind subpath=traverse_subpath
+##parameters=menu
+##title=
+##
+
+from Products.CMFCore.utils import getToolByName
+
+# some checks whether dropdown properties exist
+pp = getToolByName(context, 'portal_properties')
+if 'dropdownmenu_properties' not in pp.objectIds():
+    context.plone_utils.addPortalMessage('Dropdown menu property sheet does not exist. Please, firstly regenerate menu before editing it.',
+                                         type='error')
+    return state.set(status='failure')
+
+
+properties = pp.dropdownmenu_properties
+if not properties.hasProperty('menu'):
+    context.plone_utils.addPortalMessage('menu field does not exist in dropdown menu property sheet. Please, firstly regenerate menu before editing it.',
+                                         type='error')
+    return state.set(status='failure')
+
+# do actual work
+properties.manage_changeProperties(menu=menu)
+context.plone_utils.addPortalMessage('DropDown Menu updated.')
+return state.set(status='success')
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/dropdownmenu_edit.cpy.metadata
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/dropdownmenu_edit.cpy.metadata	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/dropdownmenu_edit.cpy.metadata	(revision 2565)
@@ -0,0 +1,6 @@
+[validators]
+validators=validate_dropdownmenu_edit
+ 
+[actions]
+action.failure=traverse_to:string:prefs_dropdownmenu_edit_form
+action.success=redirect_to:string:prefs_dropdownmenu_edit_form
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/dropdownmenu_update.cpy
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/dropdownmenu_update.cpy	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/dropdownmenu_update.cpy	(revision 2565)
@@ -0,0 +1,16 @@
+## Script (Python) "dropdownmenu_update"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind state=state
+##bind subpath=traverse_subpath
+##parameters=
+##title=
+##
+
+from Products.CMFCore.utils import getToolByName
+
+getToolByName(context, 'portal_dropdownmenu').regenerateMenu()
+context.plone_utils.addPortalMessage('DropDown Menu regenerated.')
+return state.set(status='success')
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/dropdownmenu_update.cpy.metadata
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/dropdownmenu_update.cpy.metadata	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/dropdownmenu_update.cpy.metadata	(revision 2565)
@@ -0,0 +1,6 @@
+[validators]
+validators=validate_dropdownmenu_edit
+ 
+[actions]
+action.failure=traverse_to:string:prefs_dropdownmenu_edit_form
+action.success=redirect_to:string:prefs_dropdownmenu_edit_form
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/prefs_csshover_edit_form.cpt
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/prefs_csshover_edit_form.cpt	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/prefs_csshover_edit_form.cpt	(revision 2565)
@@ -0,0 +1,71 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US"
+      xmlns:metal="http://xml.zope.org/namespaces/metal"
+      xmlns:tal="http://xml.zope.org/namespaces/tal"
+      lang="en-US"
+      metal:use-macro="here/prefs_main_template/macros/master"
+      i18n:domain="qPloneDropDownMenu">
+
+  <metal:block fill-slot="top_slot"
+             tal:define="dummy python:request.set('disable_border',1)" />
+
+<body>
+  <div metal:fill-slot="prefs_configlet_main"
+       tal:define="errors python:request.get('errors', {})">
+
+    <h1 i18n:translate="heading_plonecsshovering">Plone CSS Hover Functionality</h1>
+    <a href=""
+       class="link-parent"
+       tal:attributes="href string: $portal_url/plone_control_panel"
+       i18n:translate="label_up_to_plone_setup">
+    Up to Plone Setup
+    </a>
+
+    <div class="ieHidden">Visit this page in IE to see and activate generated CSS</div>
+
+    <form name="csshovering_edit_form"
+          action="."
+          method="post"
+          tal:attributes="action string:${here/absolute_url}/${template/getId}" >
+
+     <div class="field">
+         <label for="csshovering" class="ieVisible" i18n:translate="label_csshovering">CSS Hover</label>
+         <div class="formHelp" i18n:translate="help_csshovering_edit">
+         Due to limitation of IE &lt; 7 to understand :hover CSS pseudo-selector only on A elements
+         and performance issues while applying dynamic stylesheets on each page load, it is possible to 
+         pre-generate CSS that will enable IE with JavaScript turned on to understand :hover elements.
+         </div>
+         <textarea cols="80"
+                   rows="20"
+                   tabindex=""
+                   name="csshovering"
+                   id="csshovering"
+                   class="ieVisible"
+                   tal:attributes="tabindex tabindex/next;">Use this configlet in IE</textarea>
+     </div>
+
+     <div class="field"
+          tal:define="portal_css nocall:here/portal_css|nothing"
+          tal:condition="portal_css">
+         <input type="checkbox" name="enabled" id="enabled"  value="1"
+                tal:define="csshover python:portal_css and portal_css.getResource('csshover.css') or None"
+                tal:attributes="checked csshover/getEnabled|nothing" />
+         <label for="enabled" i18n:translate="label_enabled">Enabled</label>
+     </div>
+
+     <div class="formControls"
+             tal:define="process_creation request/process_creation|nothing;">
+         <input class="context"
+                tabindex=""
+                type="submit"
+                value="Save"
+                name="form.button.Save"
+                i18n:attributes="value"
+                tal:attributes="tabindex tabindex/next" />
+     </div>
+
+     <input type="hidden" name="form.submitted" value="1" />
+    </form>
+
+  </div>
+</body>
+</html>
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/prefs_csshover_edit_form.cpt.metadata
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/prefs_csshover_edit_form.cpt.metadata	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/prefs_csshover_edit_form.cpt.metadata	(revision 2565)
@@ -0,0 +1,11 @@
+[security]
+View=0:Authenticated
+
+[default]
+title=Set csshover functionality
+
+[actions]
+action.success..Save=traverse_to:string:csshover_save
+action.success=traverse_to:string:csshover_save
+action.failure..Save=traverse_to:string:prefs_csshover_edit_form
+action.failure=traverse_to:string:prefs_csshover_edit_form
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/prefs_dropdownmenu_edit_form.cpt
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/prefs_dropdownmenu_edit_form.cpt	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/prefs_dropdownmenu_edit_form.cpt	(revision 2565)
@@ -0,0 +1,90 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US"
+      xmlns:metal="http://xml.zope.org/namespaces/metal"
+      xmlns:tal="http://xml.zope.org/namespaces/tal"
+      lang="en-US"
+      metal:use-macro="here/prefs_main_template/macros/master"
+      i18n:domain="qPloneDropDownMenu">
+
+  <metal:block fill-slot="top_slot"
+             tal:define="dummy python:request.set('disable_border',1)" />
+
+<body>
+  <div metal:fill-slot="prefs_configlet_main"
+       tal:define="errors python:request.get('errors', {})">
+
+    <h1 i18n:translate="heading_plonedropdownmenu">Plone Drop Down Menu</h1>
+    <a href=""
+       class="link-parent"
+       tal:attributes="href string: $portal_url/plone_control_panel"
+       i18n:translate="label_up_to_plone_setup">
+      Up to Plone Setup
+    </a>
+
+    <div class="documentDescription"
+         i18n:translate="description_plonedropdownmenu">
+      Plone Drop Down Menu ...
+    </div>
+
+    <h2>Post-install instructions</h2>
+
+    <p>Congratulations, you've installed Plone Drop Down Menu product from Quintagroup.</p>
+
+    <p>In case you have some problems following editing DropDown Menu you
+    can only click <a href="dropdownmenu_update">regenerate menu</a>, and
+    you'll get the initial portal menu.</p>
+
+    <form name="menu_edit_form"
+          action="." 
+          method="post" 
+          tal:attributes="action string:${here/absolute_url}/${template/getId}" >
+
+      <div class="formControls" align="right"
+           tal:define="process_creation request/process_creation|nothing;">
+          <input class="context"
+                 tabindex=""
+                 type="submit"
+                 value="Regenerate Menu"
+                 name="form.button.Regenerate"
+                 i18n:attributes="value"
+                 tal:attributes="tabindex tabindex/next" />
+      </div>
+
+      <dl class="portalMessage warning"
+          tal:condition="not: portal/portal_properties/dropdownmenu_properties/menu|nothing">
+        <dt>Warning</dt>
+        <dd>
+          Dropdown menu property sheet or it's 'menu' field were deleted from portal_properties tool.
+          Before saving any portal tabs you have to 'Regenerate Menu'. This action will add
+          'menu' field back to your properties.
+        </dd>
+      </dl>
+
+      <div class="field">
+          <label for="menu" i18n:translate="label_portaltabs">Portal tabs</label>
+          <div class="formHelp" i18n:translate="help_portaltabs_edit">Here you can change your portal tabs.</div>
+          <textarea cols="80" 
+                    rows="20"
+                    tabindex=""
+                    name="menu"
+                    id="menu"
+                    tal:content="portal/portal_properties/dropdownmenu_properties/menu|string:"
+                    tal:attributes="tabindex tabindex/next;">Portal Tabs</textarea>
+      </div>
+
+      <div class="formControls"
+           tal:define="process_creation request/process_creation|nothing;">
+        <input class="context"
+               tabindex=""
+               type="submit"
+               value="Save"
+               name="form.button.Save"
+               i18n:attributes="value"
+               tal:attributes="tabindex tabindex/next" />
+      </div>
+
+      <input type="hidden" name="form.submitted" value="1" />
+    </form>
+
+  </div>
+</body>
+</html>
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/prefs_dropdownmenu_edit_form.cpt.metadata
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/prefs_dropdownmenu_edit_form.cpt.metadata	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/prefs_dropdownmenu_edit_form.cpt.metadata	(revision 2565)
@@ -0,0 +1,18 @@
+[security]
+View=0:Authenticated
+
+[default]
+title=Edit Drop Down Menu
+
+[validators]
+validators..Save=validate_dropdownmenu_edit
+validators..Regenerate=validate_dropdownmenu_edit
+validators=validate_dropdownmenu_edit
+
+[actions]
+action.success..Save=traverse_to:string:dropdownmenu_edit
+action.success..Regenerate=redirect_to:string:dropdownmenu_update
+action.success=traverse_to:string:dropdownmenu_edit
+action.failure..Save=traverse_to:string:prefs_dropdownmenu_edit_form
+action.failure..Regenerate=traverse_to:string:prefs_dropdownmenu_edit_form
+action.failure=traverse_to:string:prefs_dropdownmenu_edit_form
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/qplonedropdownmenu.gif.metadata
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/qplonedropdownmenu.gif.metadata	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/qplonedropdownmenu.gif.metadata	(revision 2565)
@@ -0,0 +1,3 @@
+[default]
+title=Drop Down Menu Control Panel Icon
+cache=HTTPCache
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/validate_dropdownmenu_edit.vpy
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/validate_dropdownmenu_edit.vpy	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/skins/qPloneDropDownMenu/validate_dropdownmenu_edit.vpy	(revision 2565)
@@ -0,0 +1,15 @@
+## Controlled Python Script "validate_dropdownmenu"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind state=state
+##bind subpath=traverse_subpath
+##parameters=
+##title=Validates a drop down menu edit_form contents
+##
+
+if state.getErrors():
+    context.plone_utils.addPortalMessage('Please correct the indicated errors.')
+    return state.set(status='failure')
+return state
Index: /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/utils.py
===================================================================
--- /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/utils.py	(revision 2565)
+++ /Products.qPloneDropDownMenu/trunk/Products/qPloneDropDownMenu/utils.py	(revision 2565)
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+""" Utility functions """
+
+from zope.component import getMultiAdapter
+
+from OFS.DTMLMethod import addDTMLMethod
+
+from Products.CMFCore.utils import getToolByName
+from Products.CMFPlone.migrations.migration_util import safeEditProperty
+from Products.CMFCore.Expression import Expression, createExprContext
+
+from config import PROPERTY_FIELD, PROPERTY_SHEET
+
+
+TAB_HTML_SNIPPET = """<li id="portaltab-%(id)s" class="plain">
+  <a href="%(url)s" accesskey="t" title="%(desc)s">%(name)s</a>
+</li>
+"""
+
+
+def addCSS(container, sheetId, title, csshovering):
+    """ Add DTML Method object to portal root """
+    addDTMLMethod(container, sheetId, title, csshovering)
+
+def updateMenu(site):
+    pu = getToolByName(site, 'plone_utils')
+    pa = getToolByName(site, 'portal_actions')
+    portal_props = getToolByName(site, 'portal_properties')
+
+    # collect all portal tabs
+    context_state = getMultiAdapter((site, site.REQUEST),
+                                    name=u'plone_context_state')
+    actions = context_state.actions()
+    portal_tabs_view = getMultiAdapter((site, site.REQUEST),
+                                       name='portal_tabs_view')
+    portal_tabs = portal_tabs_view.topLevelTabs(actions=actions)
+
+    # dump to html
+    value = u""
+    enc = portal_props.site_properties.getProperty('default_charset', 'utf-8')
+    for tab in portal_tabs:
+        value += TAB_HTML_SNIPPET % {'id': toUnicode(tab['id'], enc),
+                                     'url': toUnicode(tab['url'], enc),
+                                     'desc': toUnicode(tab['description'], enc),
+                                     'name': toUnicode(tab['name'], enc)}
+
+    if not hasattr(portal_props.aq_base, PROPERTY_SHEET):
+        portal_props.addPropertySheet(PROPERTY_SHEET,
+                                      'DropDown Menu Properties')
+    ap = getattr(portal_props.aq_base, PROPERTY_SHEET)
+    safeEditProperty(ap, PROPERTY_FIELD, value, 'text')
+
+def toUnicode(value, enc='utf-8'):
+    if isinstance(value, str):
+        return value.decode(enc)
+    else:
+        return value
