diff --git a/.hgtags b/.hgtags
index f3028cde1494abe23e81cff0a85fa1be76668595_LmhndGFncw==..dfc1f4c541ed31d91f84c81e1ee537b692073def_LmhndGFncw== 100644
--- a/.hgtags
+++ b/.hgtags
@@ -15,3 +15,5 @@
 0a7368f774db033fc4839ee01480d12bf51f1630 cubicweb-comment-debian-version-1.6.1-1
 15faf8f3b555feb5422fe2c1edc567225b574a09 cubicweb-comment-version-1.6.2
 a14db4d459494a413d481c6e658718e5845a52d1 cubicweb-comment-debian-version-1.6.2-1
+4a103934e8352f41a82f42e9b1184d30a64aab5b cubicweb-comment-version-1.6.3
+afad635158a298ccc66a8592aad3a81bdc032233 cubicweb-comment-debian-version-1.6.3-1
diff --git a/README b/README
new file mode 100644
index 0000000000000000000000000000000000000000..dfc1f4c541ed31d91f84c81e1ee537b692073def_UkVBRE1F
--- /dev/null
+++ b/README
@@ -0,0 +1,28 @@
+Summary
+-------
+
+The `comment` cube provides threadable comments feature.
+
+Usage
+-----
+
+This cube creates a new entity type called `Comment` which could basically be
+read by every body but only added by application's users.
+It also defines a relation `comments` which provides the ability to add a
+`Comment` which `comments` a `Comment`.
+
+To use this cube, you want to add the relation `comments` on the entity type
+you want to be able to comment. For instance, let's say your cube defines a
+schema for a blog. You want all the blog entries to be commentable.
+Here is how to define it in your schema:
+
+.. sourcecode:: python
+
+    from yams.buildobjs import RelationDefinition
+    class comments(RelationDefinition):
+        subject = 'Comment'
+        object = 'BlogEntry'
+        cardinality = '1*'
+
+Once this relation is defined, you can post comments and view threadable
+comments automatically on blog entry's primary view.
diff --git a/__pkginfo__.py b/__pkginfo__.py
index f3028cde1494abe23e81cff0a85fa1be76668595_X19wa2dpbmZvX18ucHk=..dfc1f4c541ed31d91f84c81e1ee537b692073def_X19wa2dpbmZvX18ucHk= 100644
--- a/__pkginfo__.py
+++ b/__pkginfo__.py
@@ -4,7 +4,7 @@
 modname = 'comment'
 distname = "cubicweb-%s" % modname
 
-numversion = (1, 6, 2)
+numversion = (1, 6, 3)
 version = '.'.join(str(num) for num in numversion)
 
 license = 'LGPL'
@@ -8,10 +8,8 @@
 version = '.'.join(str(num) for num in numversion)
 
 license = 'LGPL'
-copyright = '''Copyright (c) 2003-2010 LOGILAB S.A. (Paris, FRANCE).
-http://www.logilab.fr/ -- mailto:contact@logilab.fr'''
 
 author = "Logilab"
 author_email = "contact@logilab.fr"
 web = 'http://www.cubicweb.org/project/%s' % distname
 
@@ -13,33 +11,8 @@
 
 author = "Logilab"
 author_email = "contact@logilab.fr"
 web = 'http://www.cubicweb.org/project/%s' % distname
 
-short_desc = "commenting system for the CubicWeb framework"
-long_desc = """\
-Summary
--------
-
-The `comment` cube provides threadable comments feature.
-
-Usage
------
-
-This cube creates a new entity type called `Comment` which could basically be
-read by every body but only added by application's users.
-It also defines a relation `comments` which provides the ability to add a
-`Comment` which `comments` a `Comment`.
-
-To use this cube, you want to add the relation `comments` on the entity type
-you want to be able to comment. For instance, let's say your cube defines a
-schema for a blog. You want all the blog entries to be commentable.
-Here is how to define it in your schema:
-
-.. sourcecode:: python
-
-    from yams.buildobjs import RelationDefinition
-    class comments(RelationDefinition):
-        subject = 'Comment'
-        object = 'BlogEntry'
-        cardinality = '1*'
+description = "commenting system for the CubicWeb framework"
+short_desc = description # XXX cw < 3.8 bw compat
 
@@ -45,38 +18,7 @@
 
-Once this relation is defined, you can post comments and view threadable
-comments automatically on blog entry's primary view.
-"""
-
-from os import listdir
-from os.path import join
-
-CUBES_DIR = join('share', 'cubicweb', 'cubes')
-
-try:
-    data_files = [
-        [join(CUBES_DIR, 'comment'),
-         [fname for fname in listdir('.')
-          if fname.endswith('.py') and fname != 'setup.py']],
-        [join(CUBES_DIR, 'comment', 'data'),
-         [join('data', fname) for fname in listdir('data')]],
-        [join(CUBES_DIR, 'comment', 'i18n'),
-         [join('i18n', fname) for fname in listdir('i18n')]],
-        [join(CUBES_DIR, 'comment', 'migration'),
-         [join('migration', fname) for fname in listdir('migration')]],
-        ]
-except OSError:
-    # we are in an installed directory
-    pass
-
-
-cube_eid = 20316
-# used packages
-__depends_cubes__ = {}
-__depends__ = {'cubicweb': '>= 3.6.0'}
-__use__ = tuple(__depends_cubes__)
 classifiers = [
            'Environment :: Web Environment',
            'Framework :: CubicWeb',
            'Programming Language :: Python',
            'Programming Language :: JavaScript',
 ]
@@ -77,6 +19,31 @@
 classifiers = [
            'Environment :: Web Environment',
            'Framework :: CubicWeb',
            'Programming Language :: Python',
            'Programming Language :: JavaScript',
 ]
+
+__depends__ = {'cubicweb': '>= 3.6.0'}
+
+# package ###
+
+from os import listdir as _listdir
+from os.path import join, isdir, exists
+from glob import glob
+
+THIS_CUBE_DIR = join('share', 'cubicweb', 'cubes', modname)
+
+def listdir(dirpath):
+    return [join(dirpath, fname) for fname in _listdir(dirpath)
+            if fname[0] != '.' and not fname.endswith('.pyc')
+            and not fname.endswith('~')
+            and not isdir(join(dirpath, fname))]
+
+data_files = [
+    # common files
+    [THIS_CUBE_DIR, [fname for fname in glob('*.py') if fname != 'setup.py']],
+    ]
+# check for possible extended cube layout
+for dname in ('entities', 'views', 'sobjects', 'hooks', 'schema', 'data', 'i18n', 'migration'):
+    if isdir(dname):
+        data_files.append([join(THIS_CUBE_DIR, dname), listdir(dname)])
diff --git a/data/cubes.comment.js b/data/cubes.comment.js
index f3028cde1494abe23e81cff0a85fa1be76668595_ZGF0YS9jdWJlcy5jb21tZW50Lmpz..dfc1f4c541ed31d91f84c81e1ee537b692073def_ZGF0YS9jdWJlcy5jb21tZW50Lmpz 100644
--- a/data/cubes.comment.js
+++ b/data/cubes.comment.js
@@ -66,12 +66,9 @@
     }
 }
 
-$(document).ready(function() {
-    function scroll_top(event){
-        toggleVisibility('popupLoginBox');
-        $('html, body').animate({scrollTop:0}, 'fast');
-        return false;
-    }
-    $('a.loadPopupLogin').click(scroll_top);
-});
+function showLoginBox() {
+    toggleVisibility('popupLoginBox');
+    $('html, body').animate({scrollTop:0}, 'fast');
+    return false;
+}
 
@@ -77,3 +74,3 @@
 
-CubicWeb.provide('ecomment.js');
+CubicWeb.provide('comment.js');
 
diff --git a/debian/changelog b/debian/changelog
index f3028cde1494abe23e81cff0a85fa1be76668595_ZGViaWFuL2NoYW5nZWxvZw==..dfc1f4c541ed31d91f84c81e1ee537b692073def_ZGViaWFuL2NoYW5nZWxvZw== 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+cubicweb-comment (1.6.3-1) unstable; urgency=low
+
+  * new upstream release
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr>  Mon, 26 Apr 2010 15:33:26 +0200
+
 cubicweb-comment (1.6.2-1) unstable; urgency=low
 
   * new upstream release
diff --git a/debian/rules b/debian/rules
index f3028cde1494abe23e81cff0a85fa1be76668595_ZGViaWFuL3J1bGVz..dfc1f4c541ed31d91f84c81e1ee537b692073def_ZGViaWFuL3J1bGVz 100755
--- a/debian/rules
+++ b/debian/rules
@@ -7,7 +7,7 @@
 build: build-stamp
 build-stamp:
 	dh_testdir
-	python setup.py -q build
+	NO_SETUPTOOLS=1 python setup.py -q build
 	touch build-stamp
 
 clean:
@@ -24,7 +24,7 @@
 	dh_testroot
 	dh_clean -k
 	dh_installdirs -i
-	python setup.py -q install --no-compile --prefix=debian/cubicweb-comment/usr/
+	NO_SETUPTOOLS=1 python setup.py -q install --no-compile --prefix=debian/cubicweb-comment/usr/
 	# remove generated .egg-info file
 	rm -rf debian/cubicweb-comment/usr/lib/python*
 
diff --git a/entities.py b/entities.py
index f3028cde1494abe23e81cff0a85fa1be76668595_ZW50aXRpZXMucHk=..dfc1f4c541ed31d91f84c81e1ee537b692073def_ZW50aXRpZXMucHk= 100644
--- a/entities.py
+++ b/entities.py
@@ -1,7 +1,7 @@
 """entity classes for Comment entities
 
 :organization: Logilab
-:copyright: 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
@@ -14,6 +14,11 @@
 from cubicweb.selectors import implements
 from cubicweb.entities import AnyEntity, fetch_config
 
+
+def subcomments_count(commentable):
+    return sum([len(commentable.reverse_comments)]
+               + [subcomments_count(c) for c in commentable.reverse_comments])
+
 class Comment(TreeMixIn, AnyEntity):
     """customized class for Comment entities"""
     __regid__ = 'Comment'
@@ -34,7 +39,9 @@
         """
         return self.root().rest_path(), {}
 
+    subcomments_count = subcomments_count
+
 
 # some views potentially needed on web *and* server side (for notification)
 # so put them here
 
@@ -37,8 +44,7 @@
 
 # some views potentially needed on web *and* server side (for notification)
 # so put them here
 
-
 class CommentFullTextView(EntityView):
     __regid__ = 'fulltext'
     __select__ = implements('Comment')
diff --git a/i18n/en.po b/i18n/en.po
index f3028cde1494abe23e81cff0a85fa1be76668595_aTE4bi9lbi5wbw==..dfc1f4c541ed31d91f84c81e1ee537b692073def_aTE4bi9lbi5wbw== 100644
--- a/i18n/en.po
+++ b/i18n/en.po
@@ -24,6 +24,9 @@
 msgid "Comment_plural"
 msgstr "Comments"
 
+msgid "Latest comments"
+msgstr ""
+
 msgid "New Comment"
 msgstr "New comment"
 
@@ -37,6 +40,9 @@
 msgid "Unknown author"
 msgstr ""
 
+msgid "You are not authenticated."
+msgstr ""
+
 msgid "a comment is a reply about another entity"
 msgstr ""
 
@@ -58,10 +64,9 @@
 msgid "actions_reply_comment"
 msgstr "reply comment"
 
-# add related box generated message
 msgid "actions_reply_comment_description"
 msgstr ""
 
 msgid "add comment"
 msgstr ""
 
@@ -62,9 +67,12 @@
 msgid "actions_reply_comment_description"
 msgstr ""
 
 msgid "add comment"
 msgstr ""
 
+msgid "comment content"
+msgstr "comment"
+
 # #-#-#-#-#  schema.pot  #-#-#-#-#
 # subject and object forms for each relation type
 # (no object form for final relation types)
@@ -104,6 +112,12 @@
 "section containing comments thread an allowing to post comment on "
 "commentable entities"
 
+msgid "contentnavigation_latestcomments"
+msgstr ""
+
+msgid "contentnavigation_latestcomments_description"
+msgstr ""
+
 msgid "delete comment"
 msgstr ""
 
@@ -113,12 +127,9 @@
 msgid "i18n_by_author_field"
 msgstr "by"
 
-msgid "latest comment(s):"
-msgstr ""
-
 msgid "login"
 msgstr ""
 
 msgid "new comment for"
 msgstr ""
 
@@ -119,9 +130,12 @@
 msgid "login"
 msgstr ""
 
 msgid "new comment for"
 msgstr ""
 
+msgid "on date"
+msgstr "date"
+
 msgid "register"
 msgstr ""
 
@@ -135,9 +149,6 @@
 msgid "thread view"
 msgstr ""
 
-msgid "to comment"
-msgstr ""
-
 msgid "unknown author"
 msgstr ""
 
diff --git a/i18n/fr.po b/i18n/fr.po
index f3028cde1494abe23e81cff0a85fa1be76668595_aTE4bi9mci5wbw==..dfc1f4c541ed31d91f84c81e1ee537b692073def_aTE4bi9mci5wbw== 100644
--- a/i18n/fr.po
+++ b/i18n/fr.po
@@ -24,6 +24,9 @@
 msgid "Comment_plural"
 msgstr "Commentaires"
 
+msgid "Latest comments"
+msgstr "Derniers commentaires"
+
 msgid "New Comment"
 msgstr "Nouveau commentaire"
 
@@ -37,6 +40,9 @@
 msgid "Unknown author"
 msgstr "Auteur inconnu"
 
+msgid "You are not authenticated."
+msgstr "Vous n'êtes pas authentifié."
+
 msgid "a comment is a reply about another entity"
 msgstr "un commentaire autour d'une autre entité"
 
@@ -65,6 +71,9 @@
 msgid "add comment"
 msgstr "ajouter un commentaire"
 
+msgid "comment content"
+msgstr "commentaire"
+
 # #-#-#-#-#  schema.pot  #-#-#-#-#
 # subject and object forms for each relation type
 # (no object form for final relation types)
@@ -101,7 +110,14 @@
 
 msgid "contentnavigation_commentsection_description"
 msgstr ""
-"partie affichant la liste des commentaires à propos de l'entité visualisée"
+"section affichant la liste des commentaires à propos de l'entité visualisée"
+
+msgid "contentnavigation_latestcomments"
+msgstr "derniers commentaires de l'utilisateur"
+
+msgid "contentnavigation_latestcomments_description"
+msgstr ""
+"section affichant la liste des dernierscommentaires postés par un utilisateur"
 
 msgid "delete comment"
 msgstr "supprimer ce commentaire"
@@ -112,12 +128,9 @@
 msgid "i18n_by_author_field"
 msgstr "par"
 
-msgid "latest comment(s):"
-msgstr "derniers commentaire(s) :"
-
 msgid "login"
 msgstr "s'authentifier"
 
 msgid "new comment for"
 msgstr "nouveau commentaire pour"
 
@@ -118,9 +131,12 @@
 msgid "login"
 msgstr "s'authentifier"
 
 msgid "new comment for"
 msgstr "nouveau commentaire pour"
 
+msgid "on date"
+msgstr "date"
+
 msgid "register"
 msgstr "s'enregistrer"
 
@@ -134,9 +150,6 @@
 msgid "thread view"
 msgstr "vue fil de discussions"
 
-msgid "to comment"
-msgstr "pour commenter"
-
 msgid "unknown author"
 msgstr "auteur inconnu"
 
diff --git a/schema.py b/schema.py
index f3028cde1494abe23e81cff0a85fa1be76668595_c2NoZW1hLnB5..dfc1f4c541ed31d91f84c81e1ee537b692073def_c2NoZW1hLnB5 100644
--- a/schema.py
+++ b/schema.py
@@ -3,11 +3,7 @@
 :copyright: 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
-from yams.buildobjs import EntityType, RelationType, SubjectRelation
-try:
-    from yams.buildobjs import RichString
-except:
-    from cubicweb.schema import RichString
+from yams.buildobjs import EntityType, RelationType, SubjectRelation, RichString
 from cubicweb.schema import RRQLExpression
 
 class Comment(EntityType):
diff --git a/setup.py b/setup.py
index f3028cde1494abe23e81cff0a85fa1be76668595_c2V0dXAucHk=..dfc1f4c541ed31d91f84c81e1ee537b692073def_c2V0dXAucHk= 100644
--- a/setup.py
+++ b/setup.py
@@ -1,22 +1,13 @@
 #!/usr/bin/env python
 # pylint: disable-msg=W0404,W0622,W0704,W0613,W0152
-# Copyright (c) 2003-2004 LOGILAB S.A. (Paris, FRANCE).
-# http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This program is free software; you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation; either version 2 of the License, or (at your option) any later
-# version.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-""" Generic Setup script, takes package info from __pkginfo__.py file """
+"""Generic Setup script, takes package info from __pkginfo__.py file.
+
+:copyright: 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
+"""
+__docformat__ = "restructuredtext en"
 
 import os
 import sys
 import shutil
@@ -19,9 +10,6 @@
 
 import os
 import sys
 import shutil
-from distutils.core import setup
-from distutils import command
-from distutils.command import install_lib
 from os.path import isdir, exists, join, walk
 
@@ -26,3 +14,16 @@
 from os.path import isdir, exists, join, walk
 
+try:
+    if os.environ.get('NO_SETUPTOOLS'):
+        raise ImportError()
+    from setuptools import setup
+    from setuptools.command import install_lib
+    USE_SETUPTOOLS = 1
+except ImportError:
+    from distutils.core import setup
+    from distutils.command import install_lib
+    USE_SETUPTOOLS = 0
+
+
+sys.modules.pop('__pkginfo__', None)
 # import required features
@@ -28,4 +29,4 @@
 # import required features
-from __pkginfo__ import distname, version, license, short_desc, long_desc, \
+from __pkginfo__ import modname, version, license, description, \
      web, author, author_email
 # import optional features
@@ -30,19 +31,14 @@
      web, author, author_email
 # import optional features
-try:
-    from __pkginfo__ import distname
-except ImportError:
-    distname = distname
-try:
-    from __pkginfo__ import scripts
-except ImportError:
-    scripts = []
-try:
-    from __pkginfo__ import data_files
-except ImportError:
-    data_files = None
-try:
-    from __pkginfo__ import include_dirs
-except ImportError:
-    include_dirs = []
+import __pkginfo__
+distname = getattr(__pkginfo__, 'distname', modname)
+scripts = getattr(__pkginfo__, 'scripts', [])
+data_files = getattr(__pkginfo__, 'data_files', None)
+include_dirs = getattr(__pkginfo__, 'include_dirs', [])
+ext_modules = getattr(__pkginfo__, 'ext_modules', None)
+dependency_links = getattr(__pkginfo__, 'dependency_links', [])
+
+STD_BLACKLIST = ('CVS', '.svn', '.hg', 'debian', 'dist', 'build')
+
+IGNORED_EXTENSIONS = ('.pyc', '.pyo', '.elc', '~')
 
@@ -48,6 +44,16 @@
 
-BASE_BLACKLIST = ('CVS', 'debian', 'dist', 'build', '__buildlog')
-IGNORED_EXTENSIONS = ('.pyc', '.pyo', '.elc')
-    
+if exists('README'):
+    long_description = file('README').read()
+else:
+    long_description = ''
+if USE_SETUPTOOLS:
+   requires = {}
+   for entry in ("__depends__", "__recommends__"):
+      requires.update(getattr(__pkginfo__, entry, {}))
+   install_requires = [("%s %s" % (d, v and v or "")).strip()
+                       for d, v in requires.iteritems()]
+else:
+   install_requires = []
+
 
 def ensure_scripts(linux_scripts):
@@ -52,6 +58,6 @@
 
 def ensure_scripts(linux_scripts):
-    """creates the proper script names required for each platform
+    """Creates the proper script names required for each platform
     (taken from 4Suite)
     """
     from distutils import util
@@ -61,4 +67,18 @@
         scripts_ = linux_scripts
     return scripts_
 
+def get_packages(directory, prefix):
+    """return a list of subpackages for the given directory"""
+    result = []
+    for package in os.listdir(directory):
+        absfile = join(directory, package)
+        if isdir(absfile):
+            if exists(join(absfile, '__init__.py')) or \
+                   package in ('test', 'tests'):
+                if prefix:
+                    result.append('%s.%s' % (prefix, package))
+                else:
+                    result.append(package)
+                result += get_packages(absfile, result[-1])
+    return result
 
@@ -64,4 +84,58 @@
 
+def export(from_dir, to_dir,
+           blacklist=STD_BLACKLIST,
+           ignore_ext=IGNORED_EXTENSIONS,
+           verbose=True):
+    """make a mirror of from_dir in to_dir, omitting directories and files
+    listed in the black list
+    """
+    def make_mirror(arg, directory, fnames):
+        """walk handler"""
+        for norecurs in blacklist:
+            try:
+                fnames.remove(norecurs)
+            except ValueError:
+                pass
+        for filename in fnames:
+            # don't include binary files
+            if filename[-4:] in ignore_ext:
+                continue
+            if filename[-1] == '~':
+                continue
+            src = join(directory, filename)
+            dest = to_dir + src[len(from_dir):]
+            if verbose:
+                print >> sys.stderr, src, '->', dest
+            if os.path.isdir(src):
+                if not exists(dest):
+                    os.mkdir(dest)
+            else:
+                if exists(dest):
+                    os.remove(dest)
+                shutil.copy2(src, dest)
+    try:
+        os.mkdir(to_dir)
+    except OSError, ex:
+        # file exists ?
+        import errno
+        if ex.errno != errno.EEXIST:
+            raise
+    walk(from_dir, make_mirror, None)
+
+
+class MyInstallLib(install_lib.install_lib):
+    """extend install_lib command to handle  package __init__.py and
+    include_dirs variable if necessary
+    """
+    def run(self):
+        """overridden from install_lib class"""
+        install_lib.install_lib.run(self)
+        # manually install included directories if any
+        if include_dirs:
+            base = modname
+            for directory in include_dirs:
+                dest = join(self.install_dir, base, directory)
+                export(directory, dest, verbose=False)
 
 def install(**kwargs):
     """setup entry point"""
@@ -65,18 +139,32 @@
 
 def install(**kwargs):
     """setup entry point"""
-    #kwargs['distname'] = modname
-    return setup(name=distname,
-                 version=version,
-                 license =license,
-                 description=short_desc,
-                 long_description=long_desc,
-                 author=author,
-                 author_email=author_email,
-                 url=web,
-                 scripts=ensure_scripts(scripts),
-                 data_files=data_files,
-                 **kwargs)
-            
+    if USE_SETUPTOOLS:
+        if '--force-manifest' in sys.argv:
+            sys.argv.remove('--force-manifest')
+    # install-layout option was introduced in 2.5.3-1~exp1
+    elif sys.version_info < (2, 5, 4) and '--install-layout=deb' in sys.argv:
+        sys.argv.remove('--install-layout=deb')
+    kwargs['package_dir'] = {modname : '.'}
+    packages = [modname] + get_packages(os.getcwd(), modname)
+    if USE_SETUPTOOLS and install_requires:
+        kwargs['install_requires'] = install_requires
+        kwargs['dependency_links'] = dependency_links
+    kwargs['packages'] = packages
+    return setup(name = distname,
+                 version = version,
+                 license = license,
+                 description = description,
+                 long_description = long_description,
+                 author = author,
+                 author_email = author_email,
+                 url = web,
+                 scripts = ensure_scripts(scripts),
+                 data_files = data_files,
+                 ext_modules = ext_modules,
+                 cmdclass = {'install_lib': MyInstallLib},
+                 **kwargs
+                 )
+
 if __name__ == '__main__' :
     install()
diff --git a/test/unittest_comment.py b/test/unittest_comment.py
index f3028cde1494abe23e81cff0a85fa1be76668595_dGVzdC91bml0dGVzdF9jb21tZW50LnB5..dfc1f4c541ed31d91f84c81e1ee537b692073def_dGVzdC91bml0dGVzdF9jb21tZW50LnB5 100644
--- a/test/unittest_comment.py
+++ b/test/unittest_comment.py
@@ -7,7 +7,12 @@
 
 class CommentTC(CubicWebTC):
     """Comment"""
+
+    def setup_database(self):
+        req = self.request()
+        self.b = req.create_entity('BlogEntry', title=u"yo", content=u"qu\'il est beau")
+
     def test_schema(self):
         self.assertEquals(self.schema['comments'].rdef('Comment', 'BlogEntry').composite,
                           'object')
 
@@ -10,13 +15,7 @@
     def test_schema(self):
         self.assertEquals(self.schema['comments'].rdef('Comment', 'BlogEntry').composite,
                           'object')
 
-    def setup_database(self):
-        super(CommentTC, self).setup_database()
-        self.b = self.execute('INSERT BlogEntry X: X title "yo", X content "qu\'il est beau"').get_entity(0, 0)
-        self.c = self.execute('INSERT Comment X: X content "bouh!", X comments B WHERE B is BlogEntry')
-        self.create_user('user')
-
     def test_possible_views(self):
         # comment primary view priority
         req = self.request()
@@ -20,7 +19,7 @@
     def test_possible_views(self):
         # comment primary view priority
         req = self.request()
-        rset = req.execute('Comment X')
+        rset = req.create_entity('Comment', content=u"bouh!", comments=self.b).as_rset()
         self.assertIsInstance(self.vreg['views'].select('primary', req, rset=rset),
                              views.CommentPrimaryView)
         self.assertIsInstance(self.vreg['views'].select('tree', req, rset=rset),
@@ -28,6 +27,8 @@
 
     def test_possible_actions(self):
         req = self.request()
+        req.create_entity('Comment', content=u"bouh!", comments=self.b)
+        self.create_user('user') # will commit
         rset = req.execute('Any X WHERE X is BlogEntry')
         actions = self.pactions(req, rset)
         self.failUnless(('reply_comment', views.AddCommentAction) in actions)
@@ -56,14 +57,13 @@
 
     def test_nonregr_possible_actions(self):
         req = self.request()
-        rset = req.execute('Any B WHERE B is BlogEntry')
-        beid = rset[0][0]
-        self.execute('INSERT Comment X: X content "Yooo !", X comments B WHERE B eid %s' % beid)
-        # now two comments are commenting this blog
-        rset = req.execute('Any C WHERE C comments X, X eid %s' % beid)
+        req.create_entity('Comment', content=u"bouh!", comments=self.b)
+        req.create_entity('Comment', content=u"Yooo!", comments=self.b)
+        # now two comments are commenting the blog
+        rset = self.b.related('comments', 'object')
         self.assertEquals(len(rset), 2)
         self.failUnless(self.vreg['actions'].select('reply_comment', req, rset=rset, row=0))
         self.failUnless(self.vreg['actions'].select('reply_comment', req, rset=rset, row=1))
 
     def test_add_related_actions(self):
         req = self.request()
@@ -64,9 +64,11 @@
         self.assertEquals(len(rset), 2)
         self.failUnless(self.vreg['actions'].select('reply_comment', req, rset=rset, row=0))
         self.failUnless(self.vreg['actions'].select('reply_comment', req, rset=rset, row=1))
 
     def test_add_related_actions(self):
         req = self.request()
+        req.create_entity('Comment', content=u"bouh!", comments=self.b)
+        self.create_user('user') # will comit
         rset = req.execute('Any X WHERE X is Comment')
         self.failUnlessEqual(self.pactions_by_cats(req, rset), [])
         cnx = self.login('user')
@@ -79,14 +81,12 @@
         cnx.rollback()
 
     def test_path(self):
-        teid = self.execute('BlogEntry X')[0][0]
-        eid1 = self.execute('INSERT Comment X: X content "oijzr", X comments Y WHERE Y is BlogEntry')[0][0]
-        eid2 = self.execute('INSERT Comment X: X content "duh?", X comments Y WHERE Y eid %s'%eid1)[0][0]
-        comment1 = self.entity('Any X WHERE X eid %(x)s', {'x':eid1}, 'x')
-        self.assertEquals(comment1.path(), [teid, eid1])
-        self.assertEquals(comment1.root().eid, teid)
-        comment2 = self.entity('Any X WHERE X eid %(x)s', {'x':eid2}, 'x')
-        self.assertEquals(comment2.path(), [teid, eid1, eid2])
-        self.assertEquals(comment2.root().eid, teid)
+        req = self.request()
+        c1 = req.create_entity('Comment', content=u"oijzr", comments=self.b)
+        c11 = req.create_entity('Comment', content=u"duh?", comments=c1)
+        self.assertEquals(c1.path(), [self.b.eid, c1.eid])
+        self.assertEquals(c1.root().eid, self.b.eid)
+        self.assertEquals(c11.path(), [self.b.eid, c1.eid, c11.eid])
+        self.assertEquals(c11.root().eid, self.b.eid)
 
     def test_comments_ascending_order(self):
@@ -91,20 +91,21 @@
 
     def test_comments_ascending_order(self):
-        teid = self.execute('BlogEntry X')[0][0]
-        c1 = self.entity('INSERT Comment X: X content "one", X comments Y WHERE Y eid %s'%teid)
-        eid1 = c1.eid
-        c11 = self.execute('INSERT Comment X: X content "one-one", X comments Y WHERE Y eid %s'%eid1)
-        c12 = self.execute('INSERT Comment X: X content "one-two", X comments Y WHERE Y eid %s'%eid1)
-        c2 = self.entity('INSERT Comment X: X content "two", X comments Y WHERE Y eid %s'%teid)
-        eid2 = c2.eid
-        c21= self.execute('INSERT Comment X: X content "two-one", X comments Y WHERE Y eid %s'%eid2)
-        c22= self.execute('INSERT Comment X: X content "two-two", X comments Y WHERE Y eid %s'%eid2)
-        self.commit()
-        rql = u'Any C,CD,CC,CCF,U,UL,US,UF ORDERBY CD WHERE C is Comment, '\
-              'C comments X, C creation_date CD, C content CC, C content_format CCF, ' \
-              'C created_by U?, U login UL, U firstname UF, U surname US, X eid %(x)s'
-        all_comments = self.execute(rql, {'x': teid})
-        self.assertEquals([c.eid for c in all_comments.entities()], [self.c[0][0], eid1, eid2])
-        self.assertEquals([c.eid for c in c1.children()], [c11[0][0], c12[0][0]])
+        req = self.request()
+        c1 = req.create_entity('Comment', content=u"one", comments=self.b)
+        c11 = req.create_entity('Comment', content=u"one-one", comments=c1)
+        c12 = req.create_entity('Comment', content=u"one-two", comments=c1)
+        c2 = req.create_entity('Comment', content=u"two", comments=self.b)
+        self.assertEquals([c.eid for c in self.b.reverse_comments],
+                          [c1.eid, c2.eid])
+        self.assertEquals([c.eid for c in c1.children()],
+                          [c11.eid, c12.eid])
+
+    def test_subcomments_count(self):
+        req = self.request()
+        c1 = req.create_entity('Comment', content=u"one", comments=self.b)
+        c11 = req.create_entity('Comment', content=u"one-one", comments=c1)
+        c12 = req.create_entity('Comment', content=u"one-two", comments=c1)
+        c21 = req.create_entity('Comment', content=u"two-one", comments=c12)
+        self.assertEquals(c1.subcomments_count(), 3)
 
     def test_fullthreadtext_views(self):
@@ -109,7 +110,6 @@
 
     def test_fullthreadtext_views(self):
-        c = self.entity('Comment X')
-        c2eid = self.execute('INSERT Comment X: X content %(text)s, X content_format "text/html", '
-                              'X comments %(x)s',
-                            {'x': c.eid, 'text': u"""
+        req = self.request()
+        c = req.create_entity('Comment', content=u"bouh!", comments=self.b)
+        c2 = req.create_entity('Comment', content=u"""
 some long <b>HTML</b> text which <em>should not</em> fit on 80 characters, so i'll add some extra xxxxxxx.
@@ -115,10 +115,7 @@
 some long <b>HTML</b> text which <em>should not</em> fit on 80 characters, so i'll add some extra xxxxxxx.
-Yeah !"""})[0][0]
-        self.commit()
-        c2rset= self.execute('Any X WHERE X eid %(x)s', {'x': c2eid}, 'x')
-        v = self.vreg['views'].select('fullthreadtext', self.request(),
-                                      rset=c2rset, row=0)
-        content = v.render(row=0)
+Yeah !""", content_format=u"text/html", comments=c)
+        self.commit() # needed to set author
+        content = c2.view('fullthreadtext')
         # remove date
         content = re.sub('..../../.. ..:..', '', content)
         self.assertTextEquals(content,
diff --git a/views.py b/views.py
index f3028cde1494abe23e81cff0a85fa1be76668595_dmlld3MucHk=..dfc1f4c541ed31d91f84c81e1ee537b692073def_dmlld3MucHk= 100644
--- a/views.py
+++ b/views.py
@@ -14,10 +14,8 @@
 
 from simplejson import dumps
 
-from cubicweb.selectors import (one_line_rset, implements,
-                                has_permission, relation_possible, yes,
-                                match_kwargs, score_entity,
-                                authenticated_user)
+from cubicweb.selectors import (implements, has_permission, authenticated_user,
+                                score_entity, relation_possible, one_line_rset)
 from cubicweb.view import EntityView
 from cubicweb.uilib import rql_for_eid, cut, safe_cut
 from cubicweb.mixins import TreeViewMixIn
@@ -21,5 +19,5 @@
 from cubicweb.view import EntityView
 from cubicweb.uilib import rql_for_eid, cut, safe_cut
 from cubicweb.mixins import TreeViewMixIn
-from cubicweb.web import stdmsgs, uicfg
+from cubicweb.web import stdmsgs, uicfg, component, form, formwidgets as fw
 from cubicweb.web.action import LinkToEntityAction, Action
@@ -25,7 +23,3 @@
 from cubicweb.web.action import LinkToEntityAction, Action
-from cubicweb.web.form import FormViewMixIn
-from cubicweb.web.formwidgets import Button
-from cubicweb.web.views import primary, baseviews, xmlrss
-from cubicweb.web.component import EntityVComponent
-from cubicweb.web.views.basecontrollers import JSonController, jsonize
+from cubicweb.web.views import primary, baseviews, xmlrss, basecontrollers
 
@@ -31,2 +25,5 @@
 
+_afs = uicfg.autoform_section
+_afs.tag_subject_of(('*', 'comments', '*'), formtype='main', section='hidden')
+_afs.tag_object_of(('*', 'comments', '*'), formtype='main', section='hidden')
 
@@ -32,14 +29,5 @@
 
-uicfg.autoform_section.tag_subject_of(('*', 'comments', '*'), formtype='main', section='hidden')
-uicfg.autoform_section.tag_object_of(('*', 'comments', '*'), formtype='main', section='hidden')
-uicfg.actionbox_appearsin_addmenu.tag_subject_of(('*', 'comments', '*'),  False)
-uicfg.actionbox_appearsin_addmenu.tag_object_of(('*', 'comments', '*'), False)
-uicfg.primaryview_section.tag_subject_of(('*', 'comments', '*'),  'hidden')
-uicfg.primaryview_section.tag_object_of(('*', 'comments', '*'), 'hidden')
-# XXX this is probably *very* inefficient since we'll fetch all entities created by the user
-uicfg.primaryview_section.tag_object_of(('*', 'created_by', 'CWUser'), 'relations')
-uicfg.primaryview_display_ctrl.tag_object_of(
-    ('*', 'created_by', 'CWUser'),
-    {'vid': 'list', 'label': _('latest comment(s):'), 'limit': True,
-     'filter': lambda rset: rset.filtered_rset(lambda x: x.e_schema == 'Comment')})
+_abaa = uicfg.actionbox_appearsin_addmenu
+_abaa.tag_subject_of(('*', 'comments', '*'),  False)
+_abaa.tag_object_of(('*', 'comments', '*'), False)
 
@@ -45,12 +33,8 @@
 
-def _login_register_link(req):
-    if 'registration' in req.vreg.config.cubes():
-        link = u'<a href="%s">%s</a> or ' % (req.build_url('register'),
-                                             req._(u'register'))
-    else:
-        link = u''
-    link += u'<a class="loadPopupLogin">%s</a>' % req._(u'login')
-    return link
+_pvs = uicfg.primaryview_section
+_pvs.tag_subject_of(('*', 'comments', '*'),  'hidden')
+_pvs.tag_object_of(('*', 'comments', '*'), 'hidden')
+
 
 # comment views ###############################################################
 
@@ -88,9 +72,32 @@
         self.w(u'</div>\n')
 
 
+class CommentRootView(EntityView):
+    __regid__ = 'commentroot'
+    __select__ = implements('Comment')
+
+    def cell_call(self, row, col, **kwargs):
+        entity = self.cw_rset.get_entity(row, col)
+        root = entity.root()
+        self.w(u'<a href="%s">%s %s</a> ' % (
+            xml_escape(root.absolute_url()),
+            xml_escape(root.dc_type()),
+            xml_escape(cut(root.dc_title(), 40))))
+
+
+class CommentSummary(EntityView):
+    __regid__ = 'commentsummary'
+    __select__ = implements('Comment')
+
+    def cell_call(self, row, col, **kwargs):
+        entity = self.cw_rset.get_entity(row, col)
+        maxsize = self._cw.property_value('navigation.short-line-size')
+        content = entity.printable_value('content', format='text/plain')
+        self.w(xml_escape(cut(content, maxsize)))
+
 
 class CommentOneLineView(baseviews.OneLineView):
     __select__ = implements('Comment')
 
     def cell_call(self, row, col, **kwargs):
         entity = self.cw_rset.get_entity(row, col)
@@ -91,18 +98,13 @@
 
 class CommentOneLineView(baseviews.OneLineView):
     __select__ = implements('Comment')
 
     def cell_call(self, row, col, **kwargs):
         entity = self.cw_rset.get_entity(row, col)
-        root = entity.root()
-        self.w(u'[<a href="%s">#%s</a>] '
-               % (xml_escape(root.absolute_url()), root.eid))
-        maxsize = self._cw.property_value('navigation.short-line-size')
-        maxsize = maxsize - len(str(root.eid))
-        content = entity.printable_value('content', format='text/plain')
-        content = xml_escape(cut(content, maxsize))
-        self.w(u'<a href="%s">#%s <i>%s</i></a>\n' % (
-            xml_escape(entity.absolute_url()), entity.eid, content))
+        self.w(u'[%s] ' % entity.view('commentroot'))
+        self.w(u'<a href="%s"><i>%s</i></a>\n' % (
+            xml_escape(entity.absolute_url()),
+            entity.view('commentsummary')))
 
 
 class CommentTreeItemView(baseviews.ListItemView):
@@ -129,17 +131,12 @@
         if replyaction is not None:
             url = self._cw.build_ajax_replace_url(
                 'comment%sHolder' % entity.eid, rql_for_eid(entity.eid),
-                'inlinecomment')
-            if self._cw.cnx.anonymous_connection:
-                self.w(u' | <span class="replyto">%s <a href="%s">%s</a></span>'
-                       % (_login_register_link(self._cw),
-                          xml_escape(url), self._cw._(replyaction.title)))
-            else:
-                self.w(u' | <span class="replyto"><a href="%s">%s</a></span>'
-                       % (xml_escape(url), self._cw._(replyaction.title)))
+                'addcommentform')
+            self.w(u' | <span class="replyto"><a href="%s">%s</a></span>'
+                   % (xml_escape(url), self._cw._(replyaction.title)))
         editaction = actions.select_or_none('edit_comment', self._cw,
                                             rset=self.cw_rset, row=row)
         if editaction is not None:
             # split(':', 1)[1] to remove javascript:
             formjs = self._cw.build_ajax_replace_url(
                 cdivid, rql_for_eid(entity.eid),
@@ -140,10 +137,10 @@
         editaction = actions.select_or_none('edit_comment', self._cw,
                                             rset=self.cw_rset, row=row)
         if editaction is not None:
             # split(':', 1)[1] to remove javascript:
             formjs = self._cw.build_ajax_replace_url(
                 cdivid, rql_for_eid(entity.eid),
-                'editcomment', 'append').split(':', 1)[1]
+                'editcommentform', 'append').split(':', 1)[1]
             url = "javascript: jQuery('#%s div').hide(); %s" % (cdivid, formjs)
             self.w(u' | <span class="replyto"><a href="%s">%s</a></span>'
                    % (xml_escape(url), self._cw._(editaction.title)))
@@ -174,10 +171,7 @@
         self.w(u'<li id="comment%s" class="comment">\n' % entity.eid)
 
 
-# comment edition views #######################################################
-
-class InlineCommentView(EntityView):
-    __regid__ = 'inlinecomment'
-    __select__ = yes() # explicit call when it makes sense
+class RssItemCommentView(xmlrss.RSSItemView):
+    __select__ = implements('Comment')
 
     def cell_call(self, row, col):
@@ -182,5 +176,17 @@
 
     def cell_call(self, row, col):
-        entity = self.cw_rset.get_entity(row, col)
-        self.wview('inlinecommentform', None, commented=entity)
+        entity = self.cw_rset.complete_entity(row, col)
+        self.w(u'<item>\n')
+        self.w(u'<guid isPermaLink="true">%s</guid>\n'
+               % xml_escape(entity.absolute_url()))
+        self.render_title_link(entity)
+        description = entity.dc_description(format='text/html') + \
+                      self._cw._(u'about') + \
+                      u' <a href=%s>%s</a>' % (entity.root().absolute_url(),
+                                               entity.root().dc_title())
+        self._marker('description', description)
+        self._marker('dc:date', entity.dc_date(self.date_format))
+        self.render_entity_creator(entity)
+        self.w(u'</item>\n')
+        self.wview('rssitem', entity.related('comments', 'object'), 'null')
 
@@ -186,6 +192,9 @@
 
-class InlineEditCommentForm(FormViewMixIn, EntityView):
-    __regid__ = 'editcomment'
+
+# comment forms ################################################################
+
+class InlineEditCommentForm(form.FormViewMixIn, EntityView):
+    __regid__ = 'editcommentform'
     __select__ = implements('Comment')
 
     jsfunc = "processComment(%s, '%s', false)"
@@ -194,7 +203,15 @@
     def cell_call(self, row, col):
         self.comment_form(self.cw_rset.get_entity(row, col))
 
+    def propose_to_login(self):
+        self.w(u'<div class="warning">%s ' % self._cw._('You are not authenticated.'))
+        if 'registration' in self._cw.vreg.config.cubes():
+            self.w(u'<a href="%s">%s</a> or ' % (self._cw.build_url('register'),
+                                                 self._cw._(u'register')))
+        self.w(u'<a onclick="showLoginBox()">%s</a>' % self._cw._(u'login'))
+        self.w(u'</div>')
+
     def comment_form(self, commented, newcomment=None):
         self._cw.add_js('cubes.comment.js')
         if newcomment is None:
             newcomment = commented
@@ -197,8 +214,10 @@
     def comment_form(self, commented, newcomment=None):
         self._cw.add_js('cubes.comment.js')
         if newcomment is None:
             newcomment = commented
+        if self._cw.cnx.anonymous_connection:
+            self.propose_to_login()
         # hack to avoid tabindex conflicts caused by Ajax requests
         self._cw.next_tabindex = count(20).next
         jseid = dumps(commented.eid)
         cancel_action = self.jsfunc % (jseid, '')
@@ -201,10 +220,10 @@
         # hack to avoid tabindex conflicts caused by Ajax requests
         self._cw.next_tabindex = count(20).next
         jseid = dumps(commented.eid)
         cancel_action = self.jsfunc % (jseid, '')
-        buttons = [Button(onclick=self.jsfunc % (jseid, self.jsonmeth)),
-                   Button(stdmsgs.BUTTON_CANCEL,
-                          onclick=cancel_action)]
+        buttons = [fw.Button(onclick=self.jsfunc % (jseid, self.jsonmeth)),
+                   fw.Button(stdmsgs.BUTTON_CANCEL,
+                             onclick=cancel_action)]
         form = self._cw.vreg['forms'].select('edition', self._cw,
                                              entity=newcomment,
                                              form_buttons=buttons)
@@ -214,10 +233,10 @@
                                        display_relations_form=False)))
 
 
-class InlineCommentForm(InlineEditCommentForm):
-    __regid__ = 'inlinecommentform'
-    __select__ = match_kwargs('commented') # explicit call when it makes sense
+class InlineAddCommentForm(InlineEditCommentForm):
+    __regid__ = 'addcommentform'
+    __select__ = relation_possible('comments', 'object', 'Comment', 'add')
 
     jsfunc = "processComment(%s, '%s', true)"
     jsonmeth = 'add_comment'
 
@@ -220,10 +239,11 @@
 
     jsfunc = "processComment(%s, '%s', true)"
     jsonmeth = 'add_comment'
 
-    def call(self, commented):
+    def cell_call(self, row, col):
+        commented = self.cw_rset.get_entity(row, col)
         newcomment = self._cw.vreg['etypes'].etype_class('Comment')(self._cw)
         newcomment.eid = self._cw.varmaker.next()
         self.comment_form(commented, newcomment)
 
 
@@ -225,7 +245,7 @@
         newcomment = self._cw.vreg['etypes'].etype_class('Comment')(self._cw)
         newcomment.eid = self._cw.varmaker.next()
         self.comment_form(commented, newcomment)
 
 
-# comment component ###########################################################
+# contextual components ########################################################
 
@@ -231,6 +251,6 @@
 
-class CommentSectionVComponent(EntityVComponent):
+class CommentSectionVComponent(component.EntityVComponent):
     """a component to display a <div> html section including comments
     related to an object
     """
     __regid__ = 'commentsection'
@@ -233,8 +253,8 @@
     """a component to display a <div> html section including comments
     related to an object
     """
     __regid__ = 'commentsection'
-    __select__ = (EntityVComponent.__select__
+    __select__ = (component.EntityVComponent.__select__
                   & relation_possible('comments', 'object', 'Comment'))
 
     context = 'navcontentbottom'
@@ -263,8 +283,8 @@
         if addcomment is not None:
             self.w(u'<div id="comment%sHolder"></div>' % eid)
             url = req.build_ajax_replace_url(
-                'comment%sHolder' % eid, rql_for_eid(eid), 'inlinecomment')
-            self.w(u' (<a href="%s" onclick="javascript:toggleVisibility(\'addCommentLinks\');">%s</a>)' % (url, req._(addcomment.title)))
+                'comment%sHolder' % eid, rql_for_eid(eid), 'addcommentform')
+            self.w(u' (<a href="%s">%s</a>)' % (url, req._(addcomment.title)))
             # XXX still necessary?
             #if req.use_fckeditor() and req.property_value('ui.default-text-format') == 'text/html':
             #    req.fckeditor_config()
@@ -268,8 +288,5 @@
             # XXX still necessary?
             #if req.use_fckeditor() and req.property_value('ui.default-text-format') == 'text/html':
             #    req.fckeditor_config()
-        if req.cnx.anonymous_connection:
-            self.w(u'<div id="addCommentLinks" class="hidden">%s %s</div>' % \
-                   (_login_register_link(req), req._(u'to comment')))
 
 
@@ -274,6 +291,32 @@
 
 
-# comment actions #############################################################
+class UserLatestCommentsSection(component.EntityVComponent):
+    """a section to display latest comments by a user"""
+    __select__ = component.EntityVComponent.__select__ & implements('CWUser')
+    __regid__ = 'latestcomments'
+
+    def cell_call(self, row, col, view=None):
+        user = self.cw_rset.get_entity(row, col)
+        maxrelated = self._cw.property_value('navigation.related-limit') + 1
+        rset = self._cw.execute(
+            'Any C,CD,C,CCF ORDERBY CD DESC LIMIT %s WHERE C is Comment, '
+            'C creation_date CD, C content CC, C content_format CCF, '
+            'C created_by U, U eid %%(u)s' % maxrelated,
+            {'u': user.eid})
+        if rset:
+            self.w(u'<div class="section">')
+            self.w(u'<h4>%s</h4>\n' % self._cw._('Latest comments').capitalize())
+            self.wview('table', rset,
+                       displaycols=range(3), # XXX may be removed with cw >= 3.8
+                       headers=[_('about'), _('on date'),
+                                _('comment content')],
+                       cellvids={0: 'commentroot',
+                                 2: 'commentsummary',
+                                 })
+            self.w(u'</div>')
+
+
+# actions ######################################################################
 
 class ReplyCommentAction(LinkToEntityAction):
     __regid__ = 'reply_comment'
@@ -323,8 +366,7 @@
 
 class DeleteCommentAction(Action):
     __regid__ = 'delete_comment'
-    __select__ = implements('Comment') & \
-                 authenticated_user() & \
+    __select__ = implements('Comment') & authenticated_user() & \
                  score_entity(lambda x: not x.reverse_comments and x.has_perm('delete'))
 
     title = _('delete comment')
@@ -334,5 +376,6 @@
     def url(self):
         return self._cw.build_url(rql=self.cw_rset.printable_rql(), vid='deleteconf')
 
-# add some comments related methods to the Jsoncontroller #####################
+
+# JSONController extensions through monkey-patching ############################
 
@@ -338,8 +381,8 @@
 
-@monkeypatch(JSonController)
-@jsonize
+@monkeypatch(basecontrollers.JSonController)
+@basecontrollers.jsonize
 def js_add_comment(self, commented, text, format):
     return self._cw.execute('INSERT Comment C: C comments X, C content %(text)s, '
                             'C content_format %(format)s  WHERE X eid %(x)s',
                             {'format' : format, 'text' : text, 'x' : commented}, 'x')[0][0]
 
@@ -341,11 +384,11 @@
 def js_add_comment(self, commented, text, format):
     return self._cw.execute('INSERT Comment C: C comments X, C content %(text)s, '
                             'C content_format %(format)s  WHERE X eid %(x)s',
                             {'format' : format, 'text' : text, 'x' : commented}, 'x')[0][0]
 
-@monkeypatch(JSonController)
-@jsonize
+@monkeypatch(basecontrollers.JSonController)
+@basecontrollers.jsonize
 def js_edit_comment(self, comment, text, format):
     self._cw.execute('SET C content %(text)s, C content_format %(format)s '
                      'WHERE C eid %(x)s',
                      {'format' : format, 'text' : text, 'x' : comment}, 'x')
@@ -348,26 +391,4 @@
 def js_edit_comment(self, comment, text, format):
     self._cw.execute('SET C content %(text)s, C content_format %(format)s '
                      'WHERE C eid %(x)s',
                      {'format' : format, 'text' : text, 'x' : comment}, 'x')
-
-
-# RSS view ####################################################################
-
-class RssItemCommentView(xmlrss.RSSItemView):
-    __select__ = implements('Comment')
-
-    def cell_call(self, row, col):
-        entity = self.cw_rset.complete_entity(row, col)
-        self.w(u'<item>\n')
-        self.w(u'<guid isPermaLink="true">%s</guid>\n'
-               % xml_escape(entity.absolute_url()))
-        self.render_title_link(entity)
-        description = entity.dc_description(format='text/html') + \
-                      self._cw._(u'about') + \
-                      u' <a href=%s>%s</a>' % (entity.root().absolute_url(),
-                                               entity.root().dc_title())
-        self._marker('description', description)
-        self._marker('dc:date', entity.dc_date(self.date_format))
-        self.render_entity_creator(entity)
-        self.w(u'</item>\n')
-        self.wview('rssitem', entity.related('comments', 'object'), 'null')