import time import os import datetime import math import re import logging from django import template from django.utils.encoding import smart_unicode from django.utils.safestring import mark_safe from forum.const import * from forum.models import Question, Answer, QuestionRevision, AnswerRevision from django.utils.translation import ugettext as _ from django.utils.translation import ungettext from django.conf import settings register = template.Library() GRAVATAR_TEMPLATE = ('') @register.simple_tag def gravatar(user, size): """ Creates an ```` for a user's Gravatar with a given size. This tag can accept a User object, or a dict containing the appropriate values. """ try: gravatar = user['gravatar'] username = user['username'] except (TypeError, AttributeError, KeyError): gravatar = user.gravatar username = user.username return mark_safe(GRAVATAR_TEMPLATE % { 'size': size, 'gravatar_hash': gravatar, 'username': template.defaultfilters.urlencode(username), }) MAX_FONTSIZE = 18 MIN_FONTSIZE = 12 @register.simple_tag def tag_font_size(max_size, min_size, current_size): """ do a logarithmic mapping calcuation for a proper size for tagging cloud Algorithm from http://blogs.dekoh.com/dev/2007/10/29/choosing-a-good-font-size-variation-algorithm-for-your-tag-cloud/ """ #avoid invalid calculation if current_size == 0: current_size = 1 try: weight = (math.log10(current_size) - math.log10(min_size)) / (math.log10(max_size) - math.log10(min_size)) except: weight = 0 return MIN_FONTSIZE + round((MAX_FONTSIZE - MIN_FONTSIZE) * weight) LEADING_PAGE_RANGE_DISPLAYED = TRAILING_PAGE_RANGE_DISPLAYED = 5 LEADING_PAGE_RANGE = TRAILING_PAGE_RANGE = 4 NUM_PAGES_OUTSIDE_RANGE = 1 ADJACENT_PAGES = 2 @register.inclusion_tag("paginator.html") def cnprog_paginator(context): """ custom paginator tag Inspired from http://blog.localkinegrinds.com/2007/09/06/digg-style-pagination-in-django/ """ if (context["is_paginated"]): " Initialize variables " in_leading_range = in_trailing_range = False pages_outside_leading_range = pages_outside_trailing_range = range(0) if (context["pages"] <= LEADING_PAGE_RANGE_DISPLAYED): in_leading_range = in_trailing_range = True page_numbers = [n for n in range(1, context["pages"] + 1) if n > 0 and n <= context["pages"]] elif (context["page"] <= LEADING_PAGE_RANGE): in_leading_range = True page_numbers = [n for n in range(1, LEADING_PAGE_RANGE_DISPLAYED + 1) if n > 0 and n <= context["pages"]] pages_outside_leading_range = [n + context["pages"] for n in range(0, -NUM_PAGES_OUTSIDE_RANGE, -1)] elif (context["page"] > context["pages"] - TRAILING_PAGE_RANGE): in_trailing_range = True page_numbers = [n for n in range(context["pages"] - TRAILING_PAGE_RANGE_DISPLAYED + 1, context["pages"] + 1) if n > 0 and n <= context["pages"]] pages_outside_trailing_range = [n + 1 for n in range(0, NUM_PAGES_OUTSIDE_RANGE)] else: page_numbers = [n for n in range(context["page"] - ADJACENT_PAGES, context["page"] + ADJACENT_PAGES + 1) if n > 0 and n <= context["pages"]] pages_outside_leading_range = [n + context["pages"] for n in range(0, -NUM_PAGES_OUTSIDE_RANGE, -1)] pages_outside_trailing_range = [n + 1 for n in range(0, NUM_PAGES_OUTSIDE_RANGE)] extend_url = context.get('extend_url', '') return { "base_url": context["base_url"], "is_paginated": context["is_paginated"], "previous": context["previous"], "has_previous": context["has_previous"], "next": context["next"], "has_next": context["has_next"], "page": context["page"], "pages": context["pages"], "page_numbers": page_numbers, "in_leading_range" : in_leading_range, "in_trailing_range" : in_trailing_range, "pages_outside_leading_range": pages_outside_leading_range, "pages_outside_trailing_range": pages_outside_trailing_range, "extend_url" : extend_url } @register.inclusion_tag("pagesize.html") def cnprog_pagesize(context): """ display the pagesize selection boxes for paginator """ if (context["is_paginated"]): return { "base_url": context["base_url"], "pagesize" : context["pagesize"], "is_paginated": context["is_paginated"] } @register.inclusion_tag("post_contributor_info.html") def post_contributor_info(post,contributor_type='original_author'): """contributor_type: original_author|last_updater """ if isinstance(post,Question): post_type = 'question' elif isinstance(post,Answer): post_type = 'answer' elif isinstance(post,AnswerRevision) or isinstance(post,QuestionRevision): post_type = 'revision' return { 'post':post, 'post_type':post_type, 'wiki_on':settings.WIKI_ON, 'contributor_type':contributor_type } @register.simple_tag def get_score_badge(user): BADGE_TEMPLATE = '%(reputation)s' if user.gold > 0 : BADGE_TEMPLATE = '%s%s' % (BADGE_TEMPLATE, '' '' '%(gold)s' '') if user.silver > 0: BADGE_TEMPLATE = '%s%s' % (BADGE_TEMPLATE, '' '' '%(silver)s' '') if user.bronze > 0: BADGE_TEMPLATE = '%s%s' % (BADGE_TEMPLATE, '' '' '%(bronze)s' '') BADGE_TEMPLATE = smart_unicode(BADGE_TEMPLATE, encoding='utf-8', strings_only=False, errors='strict') return mark_safe(BADGE_TEMPLATE % { 'reputation' : user.reputation, 'gold' : user.gold, 'silver' : user.silver, 'bronze' : user.bronze, 'badgesword' : _('badges'), 'reputationword' : _('reputation points'), }) @register.simple_tag def get_score_badge_by_details(rep, gold, silver, bronze): BADGE_TEMPLATE = '%(reputation)s' if gold > 0 : BADGE_TEMPLATE = '%s%s' % (BADGE_TEMPLATE, '' '' '%(gold)s' '') if silver > 0: BADGE_TEMPLATE = '%s%s' % (BADGE_TEMPLATE, '' '' '%(silver)s' '') if bronze > 0: BADGE_TEMPLATE = '%s%s' % (BADGE_TEMPLATE, '' '' '%(bronze)s' '') BADGE_TEMPLATE = smart_unicode(BADGE_TEMPLATE, encoding='utf-8', strings_only=False, errors='strict') return mark_safe(BADGE_TEMPLATE % { 'reputation' : rep, 'gold' : gold, 'silver' : silver, 'bronze' : bronze, 'repword' : _('reputation points'), 'badgeword' : _('badges'), }) @register.simple_tag def get_user_vote_image(dic, key, arrow): if dic.has_key(key): if int(dic[key]) == int(arrow): return '-on' return '' @register.simple_tag def get_age(birthday): current_time = datetime.datetime(*time.localtime()[0:6]) year = birthday.year month = birthday.month day = birthday.day diff = current_time - datetime.datetime(year,month,day,0,0,0) return diff.days / 365 @register.simple_tag def get_total_count(up_count, down_count): return up_count + down_count @register.simple_tag def format_number(value): strValue = str(value) if len(strValue) <= 3: return strValue result = '' first = '' pattern = re.compile('(-?\d+)(\d{3})') m = re.match(pattern, strValue) while m != None: first = m.group(1) second = m.group(2) result = ',' + second + result strValue = first + ',' + second m = re.match(pattern, strValue) return first + result @register.simple_tag def convert2tagname_list(question): question['tagnames'] = [name for name in question['tagnames'].split(u' ')] return '' @register.simple_tag def diff_date(date, limen=2): now = datetime.datetime.now()#datetime(*time.localtime()[0:6])#??? diff = now - date days = diff.days hours = int(diff.seconds/3600) minutes = int(diff.seconds/60) if days > 2: if date.year == now.year: return date.strftime(_("%b %d at %H:%M")) else: return date.strftime(_("%b %d '%y at %H:%M")) elif days == 2: return _('2 days ago') elif days == 1: return _('yesterday') elif minutes >= 60: return ungettext('%(hr)d hour ago','%(hr)d hours ago',hours) % {'hr':hours} else: return ungettext('%(min)d min ago','%(min)d mins ago',minutes) % {'min':minutes} @register.simple_tag def get_latest_changed_timestamp(): try: from time import localtime, strftime from os import path root = settings.SITE_SRC_ROOT dir = ( root, '%s/forum' % root, '%s/templates' % root, ) stamp = (path.getmtime(d) for d in dir) latest = max(stamp) timestr = strftime("%H:%M %b-%d-%Y %Z", localtime(latest)) except: timestr = '' return timestr @register.simple_tag def href(url): url = '///' + settings.FORUM_SCRIPT_ALIAS + '/' + url return os.path.normpath(url) + '?v=%d' % settings.RESOURCE_REVISION class ItemSeparatorNode(template.Node): def __init__(self,separator): sep = separator.strip() if sep[0] == sep[-1] and sep[0] in ('\'','"'): sep = sep[1:-1] else: raise template.TemplateSyntaxError('separator in joinitems tag must be quoted') self.content = sep def render(self,context): return self.content class JoinItemListNode(template.Node): def __init__(self,separator=ItemSeparatorNode("''"), items=()): self.separator = separator self.items = items def render(self,context): out = [] empty_re = re.compile(r'^\s*$') for item in self.items: bit = item.render(context) if not empty_re.search(bit): out.append(bit) return self.separator.render(context).join(out) @register.tag(name="joinitems") def joinitems(parser,token): try: tagname,junk,sep_token = token.split_contents() except ValueError: raise template.TemplateSyntaxError("joinitems tag requires 'using \"separator html\"' parameters") if junk == 'using': sep_node = ItemSeparatorNode(sep_token) else: raise template.TemplateSyntaxError("joinitems tag requires 'using \"separator html\"' parameters") nodelist = [] while True: nodelist.append(parser.parse(('separator','endjoinitems'))) next = parser.next_token() if next.contents == 'endjoinitems': break return JoinItemListNode(separator=sep_node,items=nodelist) class BlockResourceNode(template.Node): def __init__(self,nodelist): self.items = nodelist def render(self,context): out = '///' + settings.FORUM_SCRIPT_ALIAS if self.items: out += '/' for item in self.items: bit = item.render(context) out += bit out = os.path.normpath(out) + '?v=%d' % settings.RESOURCE_REVISION return out.replace(' ','') @register.tag(name='blockresource') def blockresource(parser,token): try: tagname = token.split_contents() except ValueError: raise template.TemplateSyntaxError("blockresource tag does not use arguments") nodelist = [] while True: nodelist.append(parser.parse(('endblockresource'))) next = parser.next_token() if next.contents == 'endblockresource': break return BlockResourceNode(nodelist)