Index: quintagroup.plonecomments/trunk/quintagroup/plonecomments/browser/comments.pt
===================================================================
--- quintagroup.plonecomments/trunk/quintagroup/plonecomments/browser/comments.pt	(revision 822)
+++ quintagroup.plonecomments/trunk/quintagroup/plonecomments/browser/comments.pt	(revision 822)
@@ -0,0 +1,114 @@
+<tal:block define="userHasReplyPermission view/can_reply;
+                   isDiscussionAllowed view/is_discussion_allowed;
+                   replies view/get_replies;
+                   isAnon view/is_anonymous;
+                   ifModerate view/is_moderation_enabled;
+                   isModerationAllowed view/can_moderate"
+                   i18n:domain="plone">
+    <div class="discussion"
+         tal:condition="python:replies or (userHasReplyPermission and isDiscussionAllowed) or (isAnon and not userHasReplyPermission and isDiscussionAllowed)">
+        <form name="reply"
+              action=""
+              method="post"
+              tal:condition="python:userHasReplyPermission and isDiscussionAllowed"
+              tal:attributes="action string:${context/absolute_url}/discussion_reply_form#discussion">
+
+              <input class="standalone"
+                     style="margin-bottom: 1.25em;"
+                     type="submit"
+                     value="Add Comment"
+                     i18n:attributes="value label_add_comment;"
+                     />
+        </form>
+        <form tal:condition="python:isAnon and not userHasReplyPermission and isDiscussionAllowed"
+              tal:attributes="action view/login_action">
+            <input class="standalone"
+                   style="margin-bottom: 1.25em;"
+                   type="submit"
+                   value="Log in to add comments"
+                   i18n:attributes="value label_login_to_add_comments;"
+                   />
+        </form>
+
+        <tal:getreplies repeat="reply_dict replies">
+            <div class="comment" style=""
+                tal:condition="python:isModerationAllowed or isPublished"
+                tal:define="indent python:reply_dict['depth']*2;
+                            reply python:reply_dict['object'];
+                            isPublished python:reply.review_state=='published';"
+                tal:attributes="style string:margin-left:${indent}em;">
+
+                <h3>
+                    <a name="comments" tal:attributes="name reply/id">
+                    <span tal:replace="reply/pretty_title_or_id">Comment title</span>
+                    </a>
+                </h3>
+                <div class="documentByLine"
+                     tal:define="creator reply/Creator;
+                                 anonymous_creator python:creator=='Anonymous User';
+                                 mi python:not anonymous_creator and view.member_info(creator);
+                                 fullname python: mi and mi['fullname'] or creator;
+                                 gavatar_src python:view.getGravatar(reply)" >
+                    <img alt="Avatar" class="avatar" height="40" width="40"
+                         src="http://default.gavatar.gif"
+                         tal:attributes="src gavatar_src">
+                    <span i18n:translate="label_comment_by">Posted by</span>
+                    <span tal:content="fullname"
+                          tal:condition="not:anonymous_creator">Poster Name</span>
+                    <span i18n:translate="label_anonymous_user"
+                          tal:condition="anonymous_creator">Anonymous User</span>
+                    <span i18n:translate="label_commented_at">at</span>
+                    <span tal:replace="python:view.format_time(reply.ModificationDate())">8/23/2001 12:40:44 PM</span>
+                    <span tal:condition="python:ifModerate and not isPublished">[pending]</span>
+                </div>
+                <div class="commentBody"
+                     tal:content="structure reply/CookedBody">
+                     This is the body text of the comment.
+                </div>
+                <form name="reply"
+                      action="discussion_reply_form"
+                      method="post"
+                      style="display: inline;"
+                      tal:attributes="action string:${reply/absolute_url}/discussion_reply_form"
+                      tal:condition="python:userHasReplyPermission and isPublished">
+                    <input class="standalone"
+                           type="submit"
+                           value="Reply"
+                           i18n:attributes="value label_reply;"
+                           />
+                </form>
+                <form name="delete"
+                      action=""
+                      method="post"
+                      style="display: inline;"
+                      tal:condition="isModerationAllowed"
+                      tal:attributes="action string:${reply/absolute_url}/deleteDiscussion">
+                    <input class="destructive"
+                           type="submit"
+                           value="Remove"
+                           i18n:attributes="value label_remove;"
+                           />
+                </form>
+                <form name="publish_discussion"
+                      action=""
+                      method="post"
+                      style="display: inline;"
+                      tal:condition="not:isPublished"
+                      tal:attributes="action string:${reply/absolute_url}/discussion_publish_comment">
+
+                    <input class="standalone"
+                           type="submit"
+                           value="Publish"
+                           i18n:attributes="value"
+                           />
+                </form>
+                <br/>
+                <div class="documentByLine"
+                     i18n:translate="text_no_add_reply"
+                     i18n:domain="quintagroup.plonecomments"
+                     tal:condition="not:isPublished">Comment must be approved before replies to comment accepted.</div>
+
+            </div>
+        </tal:getreplies>
+    </div>
+</tal:block>
Index: quintagroup.plonecomments/trunk/quintagroup/plonecomments/browser/comments.py
===================================================================
--- quintagroup.plonecomments/trunk/quintagroup/plonecomments/browser/comments.py	(revision 822)
+++ quintagroup.plonecomments/trunk/quintagroup/plonecomments/browser/comments.py	(revision 822)
@@ -0,0 +1,53 @@
+import urllib, md5
+
+from Acquisition import aq_inner
+from AccessControl import getSecurityManager
+from Products.CMFPlone.utils import getToolByName
+
+from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
+from plone.app.layout.viewlets import comments
+
+class CommentsViewlet(comments.CommentsViewlet):
+    """A custom version of the comments viewlet
+    """
+
+    render = ViewPageTemplateFile('comments.pt')
+
+    def is_moderation_enabled(self):
+        """ Returns a boolean indicating whether the user has enabled moderation
+            in the qPloneComments configlet
+        """
+        portal_properties = getToolByName(self.context, 'portal_properties')
+        try:
+            return portal_properties.qPloneComments.getProperty('enable_moderation', None)
+        except AttributeError:
+            return False
+
+    def can_moderate(self):
+        """ Returns a boolean indicating whether the user has the 'Moderate Discussion'
+            permission
+        """
+        return getSecurityManager().checkPermission('Moderate Discussion', aq_inner(self.context))
+
+    def getGravatar(self, reply):
+        purl = getToolByName(self.context, 'portal_url')
+        default = purl() + '/defaultUser.gif' 
+        email = ''
+
+        creator = reply.Creator()
+        if creator and not creator=='Anonymous User':
+            mtool = getToolByName(self.context, "portal_membership")
+            member = mtool.getMemberById(creator)
+            email = member and member.getProperty('email','') or ''
+        else:
+            email = reply.getProperty('email',d='')
+        if not email:
+            return default
+
+        size = 40
+        gravatar_url = "http://www.gravatar.com/avatar.php?"
+        # construct the url
+        gravatar_url += urllib.urlencode({'gravatar_id':md5.md5(email).hexdigest(), 
+            'default':default, 'size':str(size)})
+
+        return gravatar_url
