Index: quintagroup.portlet.collection/tags/1.1/MANIFEST.in
===================================================================
--- quintagroup.portlet.collection/tags/1.1/MANIFEST.in	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/MANIFEST.in	(revision 3553)
@@ -0,0 +1,4 @@
+recursive-include docs *
+recursive-include quintagroup *
+global-exclude *.pyc
+global-exclude *.mo
Index: quintagroup.portlet.collection/tags/1.1/README.txt
===================================================================
--- quintagroup.portlet.collection/tags/1.1/README.txt	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/README.txt	(revision 3553)
@@ -0,0 +1,26 @@
+Introduction
+============
+
+This package extends collection portlet with some useful features:
+ - configurable appearance of portlet item . You can specify what
+   attributes to display in portlet. By default 'Title' and
+   'Description' attributes are configurable.
+
+ - configurable portlet style. You can set particular style for particular
+   portlet. To define your own styles for portlets, you should edit special
+   property named 'portlet_dropdown'. This property is located in
+   'portal_properties-> qcollectionportlet_properties'. To create
+   new style - add new line containing two values divided by pipe. The first
+   value is a css style class that will be added to portlet, the second value
+   is a label that will be shown in portlet dropdown menu.
+   For example: portletStaticClassOne|Class One
+
+ - more... link for each portlet item . You can enable showing  more link
+   for every item  displayed in portlet.
+
+ - configurable linking for portlet items. There is boolean field
+   named 'Link title', if enabled - item's title will be linked to the
+   corresponding object.
+
+ - batching. Portlet items can be split into pages. You can specify number
+   of items to be displayed on page.
Index: quintagroup.portlet.collection/tags/1.1/docs/HISTORY.txt
===================================================================
--- quintagroup.portlet.collection/tags/1.1/docs/HISTORY.txt	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/docs/HISTORY.txt	(revision 3553)
@@ -0,0 +1,12 @@
+Changelog
+=========
+
+1.1 (2012-09-14)
+----------------
+
+* Added Plone 4.2 compatibility
+
+1.0 (2010-08-xx)
+----------------
+
+* Initial release
Index: quintagroup.portlet.collection/tags/1.1/docs/INSTALL.txt
===================================================================
--- quintagroup.portlet.collection/tags/1.1/docs/INSTALL.txt	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/docs/INSTALL.txt	(revision 3553)
@@ -0,0 +1,33 @@
+Installation
+------------
+
+To install  quintagroup.portlet.collection to your buildout installation, open buildout.cfg file and:
+
+* Add ``quintagroup.portlet.collection`` to the list of eggs to install, e.g.::
+
+    [buildout]
+    ...
+    eggs =
+        ...
+        quintagroup.portlet.collection
+
+* Tell the plone.recipe.zope2instance recipe to install a ZCML slug::
+
+    [instance]
+    recipe = plone.recipe.zope2instance
+    ...
+    zcml =
+        quintagroup.portlet.collection
+
+After that:
+
+* Re-run buildout, e.g. with::
+
+    $ ./bin/buildout
+
+* Restart Zope server process, for example, with the following command in the terminal::
+
+   $ ./bin/instance restart
+
+Then install Quintagroup collection portlet with Quickinstaller in Plone.
+
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/__init__.py
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/__init__.py	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/__init__.py	(revision 3553)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/__init__.py
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/__init__.py	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/__init__.py	(revision 3553)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/__init__.py
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/__init__.py	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/__init__.py	(revision 3553)
@@ -0,0 +1,9 @@
+from zope.i18nmessageid import MessageFactory
+MessageFactory = MessageFactory('quintagroup.portlet.collection')
+
+from Products.CMFCore.permissions import setDefaultRoles
+
+PROJECTNAME = "quintagroup.portlet.collection"
+DEFAULT_ADD_CONTENT_PERMISSION = "%s: Add collection portlet" % PROJECTNAME
+
+setDefaultRoles(DEFAULT_ADD_CONTENT_PERMISSION, ('Manager', 'Owner',))
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/configlet.py
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/configlet.py	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/configlet.py	(revision 3553)
@@ -0,0 +1,89 @@
+from zope.interface import Interface
+from zope.component import adapts
+from zope.interface import implements
+from zope import schema
+from zope.app.form import CustomWidgetFactory
+from zope.app.form.browser import ObjectWidget
+from zope.app.form.browser import ListSequenceWidget
+from zope.formlib import form
+
+from Products.CMFCore.utils import getToolByName
+from Products.CMFDefault.formlib.schema import SchemaAdapterBase
+
+from Products.CMFPlone.interfaces import IPloneSiteRoot
+
+from plone.app.controlpanel.form import ControlPanelForm
+
+from quintagroup.portlet.collection import MessageFactory as _
+from quintagroup.portlet.collection.utils import getStylesVocabulary
+
+
+class IValueTitlePair(Interface):
+    value = schema.TextLine(title=u"value", required=True)
+    title = schema.TextLine(title=u"title", required=False)
+
+class ValueTitlePair(object):
+    implements(IValueTitlePair)
+    def __init__(self, value='', title=''):
+        self.value = value
+        self.title = title
+
+class IQCollectionPortletPanelSchema(Interface):
+
+    portlet_dropdown = schema.List(
+        title=_(u'Dropdown select'),
+        description=_(u"These entries are used for generating dropdown select "
+                      "for quintagroup collection portlet. Note: pipe (|) "
+                      "symbol is not allowed in the value field."),
+        value_type=schema.Object(IValueTitlePair, title=u"entry"),
+        required=True
+    )
+
+class QCollectionPortletControlPanelAdapter(SchemaAdapterBase):
+    adapts(IPloneSiteRoot)
+    implements(IQCollectionPortletPanelSchema)
+
+    def __init__(self, context):
+        super(QCollectionPortletControlPanelAdapter, self).__init__(context)
+        self.context = context
+        self.pp = getToolByName(context, 'portal_properties', None)
+
+    def get_portlet_dropdown(self):
+        return  [ValueTitlePair(v,t) for (v,t) in getStylesVocabulary(self.context)]
+
+    def set_portlet_dropdown(self, value):
+        dropdown_list = []
+        for vt in value:
+            value = vt.value
+            title = vt.title or value
+            dropdown_list.append('%s|%s' % (value, title))
+        self.setValue(dropdown_list)
+
+    portlet_dropdown = property(get_portlet_dropdown, set_portlet_dropdown)
+
+    def setValue(self, value):
+        if self.pp is not None:
+            if getattr(self.pp, 'qcollectionportlet_properties', None) is None:
+                self.pp.addPropertySheet(
+                    'qcollectionportlet_properties',
+                    'QCollection portlet properties'
+                )
+            sheet = getattr(self.pp, 'qcollectionportlet_properties', None)
+            if not sheet.hasProperty('portlet_dropdown'):
+                sheet.manage_addProperty('portlet_dropdown', value, 'lines')
+            else:
+                sheet.manage_changeProperties(portlet_dropdown=value)
+
+valuetitle_widget = CustomWidgetFactory(ObjectWidget, ValueTitlePair)
+combination_widget = CustomWidgetFactory(ListSequenceWidget,
+                                         subwidget=valuetitle_widget)
+
+class QCollectionPortletControlPanel(ControlPanelForm):
+
+    form_fields = form.FormFields(IQCollectionPortletPanelSchema)
+    form_fields['portlet_dropdown'].custom_widget = combination_widget
+
+    label = _("QCollection portlet settings")
+    description = _("This form is for managing QCollection portlet "
+                     "classes available on portlet add/edit form.")
+    form_name = _("QCollection portlet settings")
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/configure.zcml
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/configure.zcml	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/configure.zcml	(revision 3553)
@@ -0,0 +1,30 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:i18n="http://namespaces.zope.org/i18n"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    i18n_domain="quintagroup.portlet.collection">
+
+  <adapter factory=".configlet.QCollectionPortletControlPanelAdapter" />
+
+  <browser:page
+      name="qcollectionportlet-controlpanel"
+      for="Products.CMFPlone.interfaces.IPloneSiteRoot"
+      class=".configlet.QCollectionPortletControlPanel"
+      permission="cmf.ManagePortal"
+      />
+
+  <browser:resource
+      name="batch.js"
+      file="resources/batch.js" />
+
+  <browser:resource
+      name="batch_size_enable.js"
+      file="resources/batch_size_enable.js" />
+
+  <!-- Register resources -->
+  <browser:resource
+      name="batch_qcollective.css"
+      file="resources/batch_qcollective.css"
+      />
+
+</configure>
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/resources/batch.js
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/resources/batch.js	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/resources/batch.js	(revision 3553)
@@ -0,0 +1,97 @@
+jq(document).ready(function(e) {
+    var prev_link = jq('.prevlink');
+    var next_link = jq('.nextlink');
+    var nav_links = jq('.navlink');
+    var batch_size = 4;
+    batch_size = nav_links.size() > batch_size ? batch_size : nav_links.size();
+
+    var hideNavigation = function (){
+      jq.each(nav_links, function(index, link){
+        jq(link).hide();
+      });
+    };
+
+    var showPageByIndex = function(index){
+      jq('dd[class*=page]').hide();
+      jq('dd.page-'+(index)).show();
+    };
+
+    var bind_prev_handler = function(link, index){
+      if (index == 0) jq(link).hide();
+      jq(link).unbind();
+      jq(link).click(function(e) {
+        if (!(index % batch_size)) {
+          hideNavigation();
+          for (i=1;i<=batch_size;i++){
+            jq(nav_links[index-i]).show();
+          }
+        }
+        nav_link_handler(index-1);
+     });
+    };
+    var bind_next_handler = function(link, index){
+      if (index == nav_links.size()-1) jq(link).hide();
+      jq(link).unbind();
+      jq(link).click(function(e) {
+        if (!((index+1) % batch_size)) {
+          hideNavigation();
+          for (i=1;i<=batch_size;i++){
+            if (i+index<nav_links.size()){
+              jq(nav_links[i+index]).show();
+            }
+            if (i==batch_size) {
+              jq(nav_links[i+index]).find('.navlinkSeparator').hide();
+            }
+          }
+        }
+        nav_link_handler(index+1);
+      });
+    };
+    var nav_link_handler = function(index){
+      if (index > 0) {
+        prev_link.show();
+        bind_prev_handler(prev_link, index);
+      }
+      else {
+        prev_link.hide();
+      }
+      if (index < nav_links.size()-1) {
+        next_link.show();
+        bind_next_handler(next_link, index);
+      }
+      else {
+        next_link.hide();
+      }
+      showPageByIndex(index);
+      for (i=0;i<nav_links.size();i++){
+        if (i == index) {
+          jq(nav_links[i]).addClass('selected');
+        }
+        else{
+          jq(nav_links[i]).removeClass('selected');
+      }
+      }
+    }
+    var initialize_navigation = function(){
+      prev_link.show();
+      next_link.show();
+      for (i=0; i<batch_size;i++){
+          jq(nav_links[i]).show();
+          if (i==batch_size-1) {
+            jq(nav_links[i]).find('.navlinkSeparator').hide();
+          }
+      }
+      showPageByIndex(0);
+      bind_prev_handler(prev_link, 0);
+      bind_next_handler(next_link, 0);
+      jq.each(nav_links, function(index, link) {
+        jq(link).unbind();
+        jq(link).click(function(e) {
+          nav_link_handler(index);
+        });
+    });
+    };
+
+   initialize_navigation();
+
+});
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/resources/batch_qcollective.css
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/resources/batch_qcollective.css	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/resources/batch_qcollective.css	(revision 3553)
@@ -0,0 +1,15 @@
+dl.portlet.portletQCollection dt a {
+  display:inline;
+  }
+.portletNavSection {
+  color:#205c90;
+  float:right;
+  }
+.portletNavSection a.navlink,
+.portletNavSection a.prevlink,
+.portletNavSection a.nextlink {
+  cursor:pointer;
+  }
+.portletNavSection a.navlink.selected {
+  color:#75AD0A; 
+  }
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/resources/batch_size_enable.js
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/resources/batch_size_enable.js	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/resources/batch_size_enable.js	(revision 3553)
@@ -0,0 +1,13 @@
+jq(document).ready(function(e){
+    var allow = jq('input[id$=allow_batching]')
+    var batch_size = jq('input[id$=batch_size]');
+
+    var batch_sizeToggle = function (allow, batch_size) {
+      if (allow.is(':checked')) batch_size.removeAttr('disabled');
+      else batch_size.attr("disabled", 'true');
+    };
+
+    batch_sizeToggle(allow, batch_size);
+    allow.change(function () {
+      batch_sizeToggle(allow, batch_size);
+    });});
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/templates/items_listing.pt
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/templates/items_listing.pt	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/templates/items_listing.pt	(revision 3553)
@@ -0,0 +1,39 @@
+<tal:items define="plone_view context/@@plone;
+                   toLocalizedTime nocall:plone_view/toLocalizedTime;
+                   getIcon nocall:plone_view/getIcon;
+                   page_number options/page_number|nothing"
+           repeat="item options/portlet_items">
+  <dd class="portletItem"
+      tal:define="oddrow repeat/item/odd;
+                  item_icon python:plone_view.getIcon(item);
+                  show_title python:view.showProperty('Title');
+                  show_description python:view.showProperty('Description');
+                  item_class python:oddrow and 'portletItem even' or 'portletItem odd'"
+      tal:attributes="class python:page_number and item_class+' page-'+page_number or item_class">
+      <a href="#"
+         class="tile"
+         tal:attributes="href item/getURL;
+                         title python: show_description and item.Description or ''">
+          <img tal:replace="structure item_icon/html_tag" />
+          <span class="tileTitle"
+                tal:condition="show_title"
+                tal:content="item/pretty_title_or_id">
+           Title
+          </span>
+          <span class="tileDescription"
+                tal:condition="show_description">
+            <tal:descr content="item/Description" />
+            <span class="tileReadMore"
+                  tal:condition="view/data/show_item_more"
+                  tal:attributes="href item/getURL" i18n:translate="more_url">
+                  &hellip;more
+            </span>            
+          </span>
+          <span class="portletItemDetails"
+                tal:condition="view/data/show_dates"
+                tal:content="python:toLocalizedTime(item.Date)">
+              Date
+          </span>
+      </a>
+  </dd>
+</tal:items>
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/templates/navigation.pt
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/templates/navigation.pt	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/browser/templates/navigation.pt	(revision 3553)
@@ -0,0 +1,9 @@
+<tal:navigation>
+  <a class='prevlink' style="display:none">&#60;</a>
+  <tal:block repeat="batch options/batches">
+    <a class="navlink" style='display: none'>
+      <span class="navlinkValue" tal:content="repeat/batch/number"/>
+    </a><span class="navlinkSeparator" tal:condition="not:repeat/batch/end">|</span>
+  </tal:block>
+  <a class='nextlink' style="display:none">&#62;</a>
+</tal:navigation>
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/collection.pt
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/collection.pt	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/collection.pt	(revision 3553)
@@ -0,0 +1,30 @@
+<dl class="portlet portletCollection portletQCollection"
+    i18n:domain="plone"
+    tal:define="collection_url view/collection_url;
+                styling view/data/styling"
+    tal:attributes="class python: styling and '%s %s'% (attrs['class'], styling) or attrs['class']">
+
+    <dt class="portletHeader">
+        <span class="portletTopLeft"></span>
+        <span class="portletNavSection"
+              tal:condition="view/data/allow_batching"
+              tal:content="structure view/batch_navigation">
+        </span>
+        <a tal:attributes="href collection_url"
+           tal:omit-tag="not:view/data/link_title">
+            <span tal:content="view/data/header" />
+        </a>
+        <span class="portletTopRight"></span>
+    </dt>
+    <tal:items replace="structure view/render_items"/>
+    <dd class="portletFooter" tal:condition="view/data/show_more">
+        <span class="portletBottomLeft"></span>
+        <span>
+        <a tal:attributes="href collection_url" i18n:translate="more_url">
+             More&hellip;
+             </a>
+        </span>
+        <span class="portletBottomRight"></span>
+    </dd>
+
+</dl>
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/collection.py
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/collection.py	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/collection.py	(revision 3553)
@@ -0,0 +1,176 @@
+import random
+
+from zope.interface import implements
+from zope.component import getMultiAdapter
+
+from plone.portlets.interfaces import IPortletDataProvider
+from plone.portlet.collection import collection as base
+
+from zope import schema
+from zope.formlib import form
+
+from plone.memoize.instance import memoize
+from plone.memoize import ram
+from plone.memoize.compress import xhtml_compress
+
+from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
+from plone.app.vocabularies.catalog import SearchableTextSourceBinder
+from zope.schema import ValidationError
+from plone.app.form.widgets.uberselectionwidget import UberSelectionWidget
+
+from Products.ATContentTypes.interface import IATTopic
+from Products.CMFPlone.PloneBatch import Batch
+from plone.portlet.collection.collection import ICollectionPortlet
+
+from quintagroup.portlet.collection import MessageFactory as _
+
+MIN_BATCH_SIZE , MAX_BATCHSIZE = 1, 30
+
+class NotValidBatchSizeValue(ValidationError):
+    """This is not valid batch size value.
+
+    """
+
+def validate_batch_size(value):
+    if MIN_BATCH_SIZE <= value <= MAX_BATCHSIZE:
+        return True
+    raise NotValidBatchSizeValue(value)
+
+class IQCollectionPortlet(ICollectionPortlet):
+    """A portlet which based on plone.portlet.collection and
+       adds more functionalities.
+    """
+
+    item_attributes = schema.List(title=_(u"Attributes to display"),
+                                  description=_(u"description_attributes", default=u"Select attributes to show for collection item."),
+                                  required=False,
+                                  default=[u"Title", u"Description"],
+                                  value_type=schema.Choice(vocabulary='quintagroup.portlet.collection.vocabularies.PortletAttributesVocabulary'))
+
+    styling = schema.Choice(title=_(u"Portlet style"),
+                            description=_(u"description_styling", default=u"Choose a css style for the porlet."),
+                            required=False,
+                            default=u"",
+                            vocabulary='quintagroup.portlet.collection.vocabularies.PortletCSSVocabulary')
+
+
+    show_item_more = schema.Bool(title=_(u"Show more... link for collection items"),
+                                 description=_(u"If enabled, a more... link will appear in the bottom of the each collection item, "
+                                                "linking to the corresponding item."),
+                                 required=True,
+                                 default=True)
+
+    link_title = schema.Bool(title=_(u"Link title"),
+                                 description=_(u"If enabled, title will be shown as link to corresponding object. "),
+                                 required=True,
+                                 default=True)
+
+    allow_batching = schema.Bool(title=_(u"Allow batching"),
+                                 description=_(u"If enabled, items will be split into pages."),
+                                 required=False,
+                                 default=False)
+
+    batch_size = schema.Int(title=_(u"Batch size"),
+                            description=_("Amount of items per page"
+                                          "(if not set 3 items will be displayed as default)."),
+                            required=False,
+                            default=3,
+                            constraint=validate_batch_size)
+
+class Assignment(base.Assignment):
+    """
+    Portlet assignment.
+    This is what is actually managed through the portlets UI and associated
+    with columns.
+    """
+
+    implements(IQCollectionPortlet)
+
+    item_attributes = [u"Title", u"Description"]
+    styling = u""
+    show_item_more = False
+    link_title = True
+
+    def __init__(self, header=u"", target_collection=None, limit=None,
+                 random=False, show_more=True, show_dates=False,
+                 item_attributes=[], styling=u"", show_item_more=False,
+                 link_title=True, allow_batching=False, batch_size=3):
+
+        super(Assignment, self).__init__(header=header,
+            target_collection=target_collection, limit=limit,
+            random=random, show_more=show_more, show_dates=show_dates)
+
+        if len(item_attributes) > 0:
+            self.item_attributes = item_attributes
+        self.styling = styling
+        self.show_item_more = show_item_more
+        self.link_title = link_title
+        self.allow_batching = allow_batching
+        self.batch_size = batch_size
+
+    @property
+    def title(self):
+        """This property is used to give the title of the portlet in the
+        "manage portlets" screen. Here, we use the title that the user gave.
+        """
+        return self.header
+
+class Renderer(base.Renderer):
+    """Portlet renderer.
+
+    This is registered in configure.zcml. The referenced page template is
+    rendered, and the implicit variable 'view' will refer to an instance
+    of this class. Other methods can be added and referenced in the template.
+    """
+
+    render = ViewPageTemplateFile('collection.pt')
+    navigation = ViewPageTemplateFile('browser/templates/navigation.pt')
+    items_listing = ViewPageTemplateFile('browser/templates/items_listing.pt')
+
+    def showProperty(self, name):
+        return name in self.data.item_attributes
+
+    def batches(self):
+        items = super(Renderer, self).results()
+        delta = self.data.batch_size
+        return [items[idx:idx + delta] for idx in range(0, len(items), delta)]
+
+    def batch_navigation(self):
+        return self.navigation(batches=self.batches())
+
+    def render_items(self):
+        if self.data.allow_batching:
+            return ''.join([self.items_listing(portlet_items=batch,
+                                               page_number=str(index))
+                            for index, batch in enumerate(self.batches())])
+        return self.items_listing(portlet_items=self.results())
+
+class AddForm(base.AddForm):
+    """Portlet add form.
+
+    This is registered in configure.zcml. The form_fields variable tells
+    zope.formlib which fields to display. The create() method actually
+    constructs the assignment that is being added.
+    """
+
+    form_fields = form.Fields(IQCollectionPortlet)
+    form_fields['target_collection'].custom_widget = UberSelectionWidget
+
+    label = _(u"Add Collection Portlet")
+    description = _(u"This portlet display a listing of items from a Collection.")
+
+    def create(self, data):
+        return Assignment(**data)
+
+class EditForm(base.EditForm):
+    """Portlet edit form.
+
+    This is registered with configure.zcml. The form_fields variable tells
+    zope.formlib which fields to display.
+    """
+
+    form_fields = form.Fields(IQCollectionPortlet)
+    form_fields['target_collection'].custom_widget = UberSelectionWidget
+
+    label = _(u"Edit Collection Portlet")
+    description = _(u"This portlet display a listing of items from a Collection.")
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/configure.zcml
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/configure.zcml	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/configure.zcml	(revision 3553)
@@ -0,0 +1,48 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:five="http://namespaces.zope.org/five"
+    xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
+    xmlns:plone="http://namespaces.plone.org/plone"
+    i18n_domain="plone">
+
+    <five:registerPackage package="." />
+
+    <include package=".browser" />
+
+    <genericsetup:registerProfile
+       name="default"
+       title="Quintagroup collection portlet"
+       directory="profiles/default"
+       description="A simple portlet that displays the results of a collection object"
+       provides="Products.GenericSetup.interfaces.EXTENSION"
+       />
+
+     <permission
+       id="quintagroup.portlet.collection.AddCollectionPortlet"
+       title="quintagroup.portlet.collection: Add collection portlet"
+       />
+ 
+     <!-- Register the portlet -->
+     <plone:portlet
+         name="quintagroup.portlet.collection.Collection"
+         interface=".collection.IQCollectionPortlet"
+         assignment=".collection.Assignment"
+         view_permission="zope2.View"
+         edit_permission="quintagroup.portlet.collection.AddCollectionPortlet"
+         renderer=".collection.Renderer"
+         addview=".collection.AddForm"
+         editview=".collection.EditForm"
+         />
+
+     <utility
+       component=".vocabularies.PortletCSSVocabulary"
+       name="quintagroup.portlet.collection.vocabularies.PortletCSSVocabulary"
+       />
+     
+     <utility
+       component=".vocabularies.PortletAttributesVocabulary"
+       name="quintagroup.portlet.collection.vocabularies.PortletAttributesVocabulary"
+       />
+
+
+</configure>
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/profiles/default/controlpanel.xml
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/profiles/default/controlpanel.xml	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/profiles/default/controlpanel.xml	(revision 3553)
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<object name="portal_controlpanel"
+        meta_type="Plone Control Panel Tool"
+        xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+        i18n:domain="quintagroup.portlet.collection">
+ <configlet title="QCollection Portlet" action_id="QCollectionPortlet"
+    appId="quintagroup.portlet.collection" category="Products" condition_expr=""
+    url_expr="string:${portal_url}/@@qcollectionportlet-controlpanel"
+    visible="True" i18n:attributes="title">
+  <permission>Manage portal</permission>
+ </configlet>
+</object>
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/profiles/default/cssregistry.xml
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/profiles/default/cssregistry.xml	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/profiles/default/cssregistry.xml	(revision 3553)
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<object name="portal_css" meta_type="Stylesheets Registry">
+ <stylesheet title="Batch QCollective" cacheable="True" compression="safe" cookable="True"
+     enabled="1" expression="" id="++resource++batch_qcollective.css" media="screen"
+     rel="stylesheet" rendering="import"/>
+</object>
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/profiles/default/jsregistry.xml
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/profiles/default/jsregistry.xml	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/profiles/default/jsregistry.xml	(revision 3553)
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<object name="portal_javascripts">
+
+ <javascript cacheable="True" compression="safe" cookable="True" enabled="True"
+    expression="" id="++resource++batch.js" inline="False"/>    
+
+ <javascript cacheable="True" compression="safe" cookable="True" enabled="True"
+    expression="" id="++resource++batch_size_enable.js" inline="False"/>    
+
+</object>
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/profiles/default/metadata.xml
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/profiles/default/metadata.xml	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/profiles/default/metadata.xml	(revision 3553)
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<metadata>
+  <version>0.1</version>
+</metadata>
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/profiles/default/portlets.xml
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/profiles/default/portlets.xml	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/profiles/default/portlets.xml	(revision 3553)
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<portlets
+    xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+    i18n:domain="plone">
+
+ <!-- Portlet type registrations -->
+ 
+ <portlet
+   addview="quintagroup.portlet.collection.Collection"
+   title="QCollection portlet"
+   description="A portlet which displays the results of a collection query"
+   i18n:attributes="title title_collection_portlet;
+                    description description_collection_portlet"
+   />
+ 
+</portlets>
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/profiles/default/propertiestool.xml
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/profiles/default/propertiestool.xml	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/profiles/default/propertiestool.xml	(revision 3553)
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<object name="portal_properties" meta_type="Plone Properties Tool">
+ <object name="qcollectionportlet_properties" meta_type="Plone Property Sheet">
+  <property name="title">QCollection portlet properties</property>
+  <property name="portlet_dropdown" type="lines" purge="False">
+   <element value="portletStaticClassOne|Class One"/>
+  </property>
+ </object>
+</object>
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/tests/base.py
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/tests/base.py	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/tests/base.py	(revision 3553)
@@ -0,0 +1,42 @@
+from Products.Five import zcml
+from Products.Five import fiveconfigure
+
+from Testing import ZopeTestCase as ztc
+
+from Products.PloneTestCase import PloneTestCase as ptc
+from Products.PloneTestCase.layer import onsetup
+
+@onsetup
+def setup_product():
+    """Set up additional products and ZCML required to test this product.
+
+    The @onsetup decorator causes the execution of this body to be deferred
+    until the setup of the Plone site testing layer.
+    """
+
+    # Load the ZCML configuration for this package and its dependencies
+
+    fiveconfigure.debug_mode = True
+    import quintagroup.portlet.collection
+    zcml.load_config('configure.zcml', quintagroup.portlet.collection)
+    fiveconfigure.debug_mode = False
+
+    # We need to tell the testing framework that these products
+    # should be available. This can't happen until after we have loaded
+    # the ZCML.
+
+    ztc.installPackage('quintagroup.portlet.collection')
+
+# The order here is important: We first call the deferred function and then
+# let PloneTestCase install it during Plone site setup
+
+setup_product()
+ptc.setupPloneSite(products=['quintagroup.portlet.collection'])
+
+class TestCase(ptc.PloneTestCase):
+    """Base class used for test cases
+    """
+
+class FunctionalTestCase(ptc.FunctionalTestCase):
+    """Test case class used for functional (doc-)tests
+    """
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/tests/test_portlet.py
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/tests/test_portlet.py	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/tests/test_portlet.py	(revision 3553)
@@ -0,0 +1,260 @@
+from zope.component import getUtility, getMultiAdapter
+
+from plone.portlets.interfaces import IPortletType
+from plone.portlets.interfaces import IPortletManager
+from plone.portlets.interfaces import IPortletAssignment
+from plone.portlets.interfaces import IPortletDataProvider
+from plone.portlets.interfaces import IPortletRenderer
+
+from plone.app.portlets.storage import PortletAssignmentMapping
+
+from quintagroup.portlet.collection import collection
+
+from quintagroup.portlet.collection.tests.base import TestCase
+
+
+from Products.CMFCore.utils import getToolByName
+
+class TestQPortletCollection(TestCase):
+    def afterSetUp(self):
+        self.setRoles(('Manager',))
+
+    def testPortletTypeRegistered(self):
+        portlet = getUtility(IPortletType, name='quintagroup.portlet.collection.Collection')
+        self.assertEquals(portlet.addview, 'quintagroup.portlet.collection.Collection')
+
+    def testInterfaces(self):
+        portlet = collection.Assignment(header=u"title")
+        self.failUnless(IPortletAssignment.providedBy(portlet))
+        self.failUnless(IPortletDataProvider.providedBy(portlet.data))
+
+    def testInvokeAddview(self):
+        portlet = getUtility(IPortletType, name='quintagroup.portlet.collection.Collection')
+        mapping = self.portal.restrictedTraverse('++contextportlets++plone.leftcolumn')
+        for m in mapping.keys():
+            del mapping[m]
+        addview = mapping.restrictedTraverse('+/' + portlet.addview)
+
+        addview.createAndAdd(data={'header' : u"test title"})
+
+        self.assertEquals(len(mapping), 1)
+        self.failUnless(isinstance(mapping.values()[0], collection.Assignment))
+
+    def testInvokeEditView(self):
+        mapping = PortletAssignmentMapping()
+        request = self.folder.REQUEST
+
+        mapping['foo'] = collection.Assignment(header=u"title")
+        editview = getMultiAdapter((mapping['foo'], request), name='edit')
+        self.failUnless(isinstance(editview, collection.EditForm))
+
+    def testRenderer(self):
+        context = self.folder
+        request = self.folder.REQUEST
+        view = self.folder.restrictedTraverse('@@plone')
+        manager = getUtility(IPortletManager, name='plone.rightcolumn', context=self.portal)
+        assignment = collection.Assignment(header=u"title")
+
+        renderer = getMultiAdapter((context, request, view, manager, assignment), IPortletRenderer)
+        self.failUnless(isinstance(renderer, collection.Renderer))
+
+class TestQPortletCollectionRenderer(TestCase):
+
+    def afterSetUp(self):
+        self.setRoles(('Manager',))
+        self.pages = self._createType(self.folder, 'Topic', 'pages')
+        crit = self.folder.pages.addCriterion('portal_type', 'ATSimpleStringCriterion')
+        crit.setValue('Document')
+
+    def renderer(self, context=None, request=None, view=None, manager=None, assignment=None):
+        context = context or self.folder
+        request = request or self.folder.REQUEST
+        view = view or self.folder.restrictedTraverse('@@plone')
+        manager = manager or getUtility(IPortletManager, name='plone.rightcolumn', context=self.portal)
+        assignment = assignment or collection.Assignment(header=u"title")
+
+        return getMultiAdapter((context, request, view, manager, assignment), IPortletRenderer)
+
+    def _createType(self, context, portal_type, id, **kwargs):
+        """Helper method to create a new type
+        """
+        ttool = getToolByName(context, 'portal_types')
+        cat = self.portal.portal_catalog
+
+        fti = ttool.getTypeInfo(portal_type)
+        fti.constructInstance(context, id, **kwargs)
+        obj = getattr(context.aq_inner.aq_explicit, id)
+        cat.indexObject(obj)
+        return obj
+
+    def test_render(self):
+        r = self.renderer(context=self.portal, assignment=collection.Assignment(header=u"title"))
+        r = r.__of__(self.folder)
+        r.update()
+        output = r.render()
+
+        # this test failed due to changed behavior. We'll not output anything if the portlet does not point to a collection
+
+        #self.failUnless('title' in output)
+        #self.failUnless('<b>text</b>' in output)
+
+
+    def test_collection_path_unicode(self):
+        """
+        Cover problem in #9184
+        """
+        r = self.renderer(context=self.portal,
+                          assignment=collection.Assignment(header=u"title",
+                                                           target_collection=u"/events"))
+        r  = r.__of__(self.folder)
+        self.assertEqual(r.collection().id, 'events')
+
+    def test_portletStyle(self):
+        renderer = self.renderer(context=self.portal,
+                                 assignment=collection.Assignment(header=u"title",
+                                                                  styling="TestClass"))
+        renderer = renderer.__of__(self.folder)
+        renderer.update()
+
+        self.failUnless('TestClass' in renderer.render())
+
+    def test_attributes(self):
+        page = self._createType(self.folder, 'Document', 'page')
+        page.update(title="Test Page", description="Test description")
+        renderer = self.renderer(context=self.portal,
+                                 assignment=collection.Assignment(header=u"title",
+                                                                  item_attributes=[u'Title'],
+                                                                  target_collection='/Members/test_user_1_/pages'))
+        renderer = renderer.__of__(self.folder)
+        renderer.update()
+        self.failUnless('Test Page' in renderer.render())
+        self.failUnless('Test description' not in renderer.render())
+
+class TestQPortletCollectionQuery(TestCase):
+
+    def afterSetUp(self):
+        self.setRoles(('Manager',))
+        #make a collection
+        self.collection = self._createType(self.folder, 'Topic', 'collection')
+
+    def _createType(self, context, portal_type, id, **kwargs):
+        """Helper method to create a new type
+        """
+        ttool = getToolByName(context, 'portal_types')
+        cat = self.portal.portal_catalog
+
+        fti = ttool.getTypeInfo(portal_type)
+        fti.constructInstance(context, id, **kwargs)
+        obj = getattr(context.aq_inner.aq_explicit, id)
+        cat.indexObject(obj)
+        return obj
+
+
+    def renderer(self, context=None, request=None, view=None, manager=None, assignment=None):
+        context = context or self.folder
+        request = request or self.folder.REQUEST
+        view = view or self.folder.restrictedTraverse('@@plone')
+        manager = manager or getUtility(IPortletManager, name='plone.leftcolumn', context=self.portal)
+        assignment = assignment
+        return getMultiAdapter((context, request, view, manager, assignment), IPortletRenderer)
+
+    def testSimpleQuery(self):
+        # set up our collection to search for Folders
+        crit = self.folder.collection.addCriterion('portal_type', 'ATSimpleStringCriterion')
+        crit.setValue('Folder')
+
+        # add a few folders
+        for i in range(6):
+            self.folder.invokeFactory('Folder', 'folder_%s'%i)
+            getattr(self.folder, 'folder_%s'%i).reindexObject()
+
+        # the folders are returned by the topic
+        collection_num_items = len(self.folder.collection.queryCatalog())
+        # We better have some folders
+        self.failUnless(collection_num_items >= 6)
+
+        mapping = PortletAssignmentMapping()
+        request = self.folder.REQUEST
+        mapping['foo'] = collection.Assignment(header=u"title", target_collection='/Members/test_user_1_/collection')
+        collectionrenderer = self.renderer(context=None, request=None, view=None, manager=None, assignment=mapping['foo'])
+
+        # we want the portlet to return us the same results as the collection
+        self.assertEquals(collection_num_items, len(collectionrenderer.results()))
+
+    def testRandomQuery(self):
+        # we're being perhaps a bit too clever in random mode with the internals of the
+        # LazyMap returned by the collection query, so let's try a bunch of scenarios
+        # to make sure they work
+
+        def reset_memoize(inst):
+            # Decorator memoize adds attribute ('_memojito_') to class instance.
+            # It has cached function and their values so it should be deleted 
+            # for testing.
+            # Extra info: http://codereview.corp.quintagroup.com/171241/show
+            if hasattr(inst, '_memojito_'):
+                delattr(inst, '_memojito_')
+   
+        # set up our portlet renderer
+        mapping = PortletAssignmentMapping()
+        request = self.folder.REQUEST
+        mapping['foo'] = collection.Assignment(header=u"title",
+                                               random=True,
+                                               target_collection='/Members/test_user_1_/collection')
+        collectionrenderer = self.renderer(context=None, request=None, view=None, manager=None, assignment=mapping['foo'])
+
+        # add some folders
+        for i in range(6):
+            self.folder.invokeFactory('Folder', 'folder_%s'%i)
+            getattr(self.folder, 'folder_%s'%i).reindexObject()
+
+        # collection with no criteria -- should return empty list, without error
+        self.assertEqual(len(collectionrenderer.results()), 0)
+        reset_memoize(collectionrenderer)
+
+        # let's make sure the results aren't being memoized
+        old_func = self.folder.collection.queryCatalog
+        global collection_was_called
+        collection_was_called = False
+        def mark_collection_called(**kw):
+            global collection_was_called
+            collection_was_called = True
+        self.folder.collection.queryCatalog = mark_collection_called
+        collectionrenderer.results()
+        reset_memoize(collectionrenderer)
+        self.folder.collection.queryCatalog = old_func
+        self.failUnless(collection_was_called)
+
+        # collection with simple criterion -- should return 1 (random) folder
+        crit = self.folder.collection.addCriterion('portal_type', 'ATSimpleStringCriterion')
+        crit.setValue('Folder')
+        self.assertEqual(len(collectionrenderer.results()), 1)
+        reset_memoize(collectionrenderer)
+
+        # collection with multiple criteria -- should behave similarly
+        crit = self.folder.collection.addCriterion('Creator', 'ATSimpleStringCriterion')
+        crit.setValue('test_user_1_')
+        collectionrenderer.results()
+
+        # collection with sorting -- should behave similarly (sort is ignored internally)
+        self.folder.collection.setSortCriterion('modified', False)
+        self.assertEqual(len(collectionrenderer.results()), 1)
+        reset_memoize(collectionrenderer)
+
+        # same criteria, now with limit set to 2 -- should return 2 (random) folders
+        collectionrenderer.data.limit = 2
+        self.assertEqual(len(collectionrenderer.results()), 2)
+        reset_memoize(collectionrenderer)
+
+        # make sure there's no error if the limit is greater than the # of results found
+        collectionrenderer.data.limit = 10
+        self.failUnless(len(collectionrenderer.results()) >= 6)
+        reset_memoize(collectionrenderer)
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestQPortletCollection))
+    suite.addTest(makeSuite(TestQPortletCollectionRenderer))
+    suite.addTest(makeSuite(TestQPortletCollectionQuery))
+    return suite
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/utils.py
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/utils.py	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/utils.py	(revision 3553)
@@ -0,0 +1,26 @@
+"""Somme utility functions for common use"""
+from Products.CMFCore.utils import getToolByName
+
+def getStylesVocabulary(context):
+    pp = getToolByName(context, 'portal_properties', None)
+    styles = None
+    if pp is not None:
+        sheet = getattr(pp, 'qcollectionportlet_properties', None)
+        if sheet is not None:
+            dropdown_list = sheet.getProperty('portlet_dropdown', None)
+            if dropdown_list is not None:
+                styles = []
+                value_list = []
+                for line in dropdown_list:
+                    values = filter(lambda x:x.strip(), line.split('|', 1))
+                    if len(values) == 0:
+                        continue
+                    elif len(values) == 1:
+                        value = title = values[0]
+                    else:
+                        value = values[0]
+                        title = values[1]
+                    if value not in value_list:
+                        value_list.append(value)
+                        styles.append((value, title))
+    return styles
Index: quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/vocabularies.py
===================================================================
--- quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/vocabularies.py	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/quintagroup/portlet/collection/vocabularies.py	(revision 3553)
@@ -0,0 +1,59 @@
+try:
+    from zope.schema.interfaces import IVocabularyFactory
+except ImportError:
+    from zope.app.schema.vocabulary import IVocabularyFactory
+from zope.interface import implements
+from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
+
+from Products.CMFCore.utils import getToolByName
+
+from quintagroup.portlet.collection import MessageFactory as _
+from quintagroup.portlet.collection.utils import getStylesVocabulary
+
+PORTLET_CSS_STYLES = (
+     (u"class1", _(u"Class1")),
+     (u"class2", _(u"Class2")),
+)
+
+PORTLET_ATTRIBUTES_TO_SHOW = (
+     (u"Title", _(u"Title")),
+     (u"Description", _(u"Description")),
+)
+
+class PortletCSSVocabulary(object):
+    implements(IVocabularyFactory)
+
+
+    def __call__(self, context):
+        styles = getStylesVocabulary(context)
+        if styles is None:
+            styles = PORTLET_CSS_STYLES
+        charset = self._charset(context)
+        items = []
+        for value, title in styles:
+            if not isinstance(title, unicode):
+                title = title.decode(charset)
+            if not isinstance(value, unicode):
+                value = value.decode(charset)
+            items.append(SimpleTerm(value, value, _(title)))
+        return SimpleVocabulary(items)
+
+    def _charset(self, context):
+        pp = getToolByName(context, 'portal_properties', None)
+        if pp is not None:
+            site_properties = getattr(pp, 'site_properties', None)
+            if site_properties is not None:
+                return site_properties.getProperty('default_charset', 'utf-8')
+            return 'utf-8'
+
+PortletCSSVocabulary = PortletCSSVocabulary()
+
+class PortletAttributesVocabulary(object):
+     implements(IVocabularyFactory)
+
+     def __call__(self, context):
+         items = [SimpleTerm(value, value, title) for value, title in PORTLET_ATTRIBUTES_TO_SHOW]
+         return SimpleVocabulary(items)
+
+PortletAttributesVocabulary = PortletAttributesVocabulary()
+
Index: quintagroup.portlet.collection/tags/1.1/setup.cfg
===================================================================
--- quintagroup.portlet.collection/tags/1.1/setup.cfg	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/setup.cfg	(revision 3553)
@@ -0,0 +1,3 @@
+[egg_info]
+tag_build = dev
+tag_svn_revision = true
Index: quintagroup.portlet.collection/tags/1.1/setup.py
===================================================================
--- quintagroup.portlet.collection/tags/1.1/setup.py	(revision 3553)
+++ quintagroup.portlet.collection/tags/1.1/setup.py	(revision 3553)
@@ -0,0 +1,32 @@
+from setuptools import setup, find_packages
+import os
+
+version = '1.1'
+
+setup(name='quintagroup.portlet.collection',
+      version=version,
+      description="Extended collection portlet",
+      long_description=open("README.txt").read() + "\n" +
+                       open(os.path.join("docs", "HISTORY.txt")).read(),
+      # Get more strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[
+        "Programming Language :: Python",
+        "Topic :: Software Development :: Libraries :: Python Modules",
+        ],
+      keywords='portlet collection quintagroup',
+      author='Melnychuk Taras',
+      author_email='fenix@quintagroup.com',
+      url='',
+      license='GPL',
+      packages=find_packages(exclude=['ez_setup']),
+      namespace_packages=['quintagroup', 'quintagroup.portlet'],
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+          'setuptools',
+          # -*- Extra requirements: -*-
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )
