Attachment 'MonthCalendar2.py'

Download

   1 """
   2     MoinMoin - MonthCalendar Macro
   3 
   4     You can use this macro to put a months calendar page on a Wiki page.
   5 
   6     The days are links to Wiki pages following this naming convention:
   7     BasePageName/year-month-day
   8 
   9     Copyright (c) 2002 by Thomas Waldmann <ThomasWaldmann@gmx.de>
  10     Licensed under GNU GPL - see COPYING for details.
  11 
  12     Please review this code, this is one of my first python / MoinMoin pieces of code.
  13 
  14 ----
  15     
  16     Revisions:
  17     * first revision without a number (=1.0):
  18         * was only online for a few hours and then replaced by 1.1
  19     * 1.1:
  20         * changed name to MonthCalendar to avoid conflict with "calendar" under case-insensitive OSes like Win32
  21         * days as subpages
  22         * basepage argument
  23         * change order of year/month argument
  24         * browsing links to prev/next month/year
  25 	    * current limitation: you can only browse one calendar on the same
  26               page/url, if you try 
  27 to browse another calendar on the same page, the first one jumps back to its original display
  28 	* show basepage in calendar header if basepage<>currentpage
  29     * 1.2:
  30         * minor fixes in argument parsing
  31 	* cosmetic fix for netscape, other cosmetic changes, changed css
  32         * i18n support (weekday short names)
  33     * 1.3:
  34         * fixes to run with MoinMoin 0.11, thanks to JuergenHermann
  35 	* fix: withspace before "," allowed in argument list
  36         * BasePage in calendar header (if present) is a link now
  37 	* more i18n
  38         * HTML cleanup, generating code avoids bracketing errors
  39         * colour cosmetics
  40     * 1.4:
  41         * new parameter for enabling fixed height of 6 "calendar weeks",
  42 	  if you want to show a whole year's calendar, this just looks
  43 	  better than having some months with 4, some with 5 and some with 6.
  44 	* group calendaring functions:
  45 	  * you can give mutliple BasePages UserName1*UserName2*UserName3
  46 	  * first BasePage is considered "your" Basepage,
  47             used days are bright red
  48 	  * 2nd and all other BasePages are considered "others" BasePages
  49 	    and lead to an increasing green component the more "used" days
  50 	    the others have. So white gets greener and red gets more yellowish.
  51           * in the head part of the calendar, you can click on each name
  52 	    to get to the Page of the same name
  53 	  * colouring of my and others BasePage is done in a way to show
  54 	    the colouring used in the calendar:
  55 	    * others use green colouring (increasingly green if multiply used)
  56 	    * I use red colouring, which gets more and more yellowish as
  57 	      the day is used by more and more others, too
  58     * 1.5:
  59         * fixed username colouring when using a BasePage
  60         * fixed navigation header of MonthCalendar not to get broken into
  61 	  multiple lines
  62 	* fixed SubPage handling (please do not use relative SubPages like
  63 	  /SubPage yet. Use MyName/SubPage.)
  64 			      
  65 TODO:
  66     * integrate patch for including day page contents directly into cal
  67      * still thinking over: does this make sense in a MonthCalendar?
  68      * it would be definitely nice in a week or day calendar (more space to
  69        burn)
  70     * integr. daycal -link-> monthcal
  71 
  72 ----
  73 
  74     Usage:
  75         [[MonthCalendar(BasePage,year,month,monthoffset,monthoffset2,height6)]]
  76         each parameter can be empty and then defaults to currentpage or currentdate or monthoffset=0
  77 
  78     Samples (paste that to one of your pages for a first try):
  79 
  80 Calendar of current month for current page:
  81 [[MonthCalendar]]
  82 
  83 Calendar of last month:
  84 [[MonthCalendar(,,,-1)]]
  85 
  86 Calendar of next month:
  87 [[MonthCalendar(,,,+1)]]
  88 
  89 Calendar of Page SampleUser, this years december:
  90 [[MonthCalendar(SampleUser,,12)]]
  91 
  92 Calendar of current Page, this years december:
  93 [[MonthCalendar(,,12)]]
  94 
  95 Calendar of December, 2001:
  96 [[MonthCalendar(,2001,12)]]
  97 
  98 Calendar of the month two months after December, 2001
  99 (maybe doesn't make much sense, but is possible)
 100 [[MonthCalendar(,2001,12,+2)]]
 101 
 102 Calendar of year 2002 (every month padded to height of 6):
 103 ||||||Year 2002||
 104 ||[[MonthCalendar(,2002,1,,,1)]]||[[MonthCalendar(,2002,2,,,1)]]||[[MonthCalendar(,2002,3,,,1)]]||
 105 ||[[MonthCalendar(,2002,4,,,1)]]||[[MonthCalendar(,2002,5,,,1)]]||[[MonthCalendar(,2002,6,,,1)]]||
 106 ||[[MonthCalendar(,2002,7,,,1)]]||[[MonthCalendar(,2002,8,,,1)]]||[[MonthCalendar(,2002,9,,,1)]]||
 107 ||[[MonthCalendar(,2002,10,,,1)]]||[[MonthCalendar(,2002,11,,,1)]]||[[MonthCalendar(,2002,12,,,1)]]||
 108 
 109 Current calendar of me, also showing entries of A and B:
 110 [[MonthCalendar(MyPage*TestUserA*TestUserB)]]
 111 
 112 SubPage calendars:
 113 [[MonthCalendar(MyName/CalPrivate)]]
 114 [[MonthCalendar(MyName/CalBusiness)]]
 115 [[MonthCalendar(MyName/CalBusiness*MyName/CalPrivate)]]
 116 
 117 ----
 118 
 119     You need to have some stylesheet entries like the following.
 120     Paste that to  default.css / moinmoin.css:
 121     
 122 /* begin css for MonthCalendar macro */
 123 /* days without and with pages linked to them */
 124 a.cal-emptyday {
 125     color: #777777;
 126     text-align: center;
 127 }
 128 a.cal-usedday {
 129     font-weight: bold;
 130     color: #000000;
 131     text-align: center;
 132 }
 133 /* general stuff: workdays, weekend, today */
 134 td.cal-workday {
 135     background-color: #DDDDFF;
 136     text-align: center;
 137 }
 138 td.cal-weekend {
 139     background-color: #FFDDDD;
 140     text-align: center;
 141 }
 142 td.cal-today {
 143     background-color: #CCFFCC;
 144     border-style: solid;
 145     border-width: 2pt;
 146     text-align: center;
 147 }
 148 /* invalid places on the monthly calendar sheet */
 149 td.cal-invalidday {
 150     background-color: #CCCCCC;
 151 }
 152 /* links to prev/next month/year */
 153 a.cal-link {
 154     color: #000000;
 155     text-decoration: none;
 156 }
 157 th.cal-header {
 158     background-color: #DDBBFF;
 159     text-align: center;
 160 }
 161 /* end css for MonthCalendar macro */
 162 
 163 ----
 164 
 165     If you want translated (german) messages, add something like this to
 166     i18n/de.py (if you have 0.11, the weekday translation might be already
 167     there):
 168     
 169 'Mon':'Mo','Tue':'Di','Wed':'Mi','Thu':'Do','Fri':'Fr','Sat':'Sa','Sun':'So',
 170     
 171 'Invalid MonthCalendar calparms "%s"!':
 172 'Ung\366ltige MonthCalendar calparms "%s"!',
 173 
 174 'Invalid MonthCalendar arguments "%s"!':
 175 'Ung\366ltige MonthCalendar Argumente "%s"!',
 176 
 177 """
 178 
 179 # Imports
 180 from MoinMoin import config, user, wikiutil, webapi
 181 from MoinMoin.Page import Page
 182 import calendar, cgi, time, re, string
 183 calendar.setfirstweekday(calendar.SUNDAY)
 184 
 185 # in MoinMoin version >= 0.11 we need "_" - that's what we try first
 186 # in MoinMoin version <= 0.10 we need "user.current.text" - try that if first fails
 187 try:
 188     from MoinMoin.i18n import _
 189 except ImportError:
 190     _ = user.current.text
 191 
 192 def cliprgb(r,g,b): # don't use 255!
 193     if r<0:   r=0
 194     if r>254: r=254
 195     if b<0:   b=0
 196     if b>254: b=254
 197     if g<0:   g=0
 198     if g>254: g=254
 199     return (r,g,b)
 200 
 201 def yearmonthplusoffset(year, month, offset):
 202     month = month+offset
 203     # handle offset and under/overflows - quick and dirty, yes!
 204     while month < 1:
 205         month = month+12
 206         year = year-1
 207     while month > 12:
 208         month = month-12
 209         year = year+1
 210     return (year, month)
 211 
 212 def parseargs(args, defpagename, defyear, defmonth, defoffset, defoffset2, defheight6):
 213 
 214     strpagename = args.group('basepage')
 215     if strpagename:
 216         parmpagename=strpagename
 217     else:
 218         parmpagename=defpagename
 219     # multiple pagenames separated by "*" - split into list of pagenames
 220     parmpagename = re.split(r'\*',parmpagename)
 221 
 222     stryear = args.group('year')
 223     if stryear:
 224         parmyear=int(stryear)
 225     else:
 226         parmyear=defyear
 227 
 228     strmonth = args.group('month')
 229     if strmonth:
 230         parmmonth=int(strmonth)
 231     else:
 232         parmmonth=defmonth
 233     
 234     stroffset = args.group('offset')
 235     if stroffset:
 236         parmoffset=int(stroffset)
 237     else:
 238         parmoffset=defoffset
 239 
 240     stroffset2 = args.group('offset2')
 241     if stroffset2:
 242         parmoffset2=int(stroffset2)
 243     else:
 244         parmoffset2=defoffset2
 245 
 246     strheight6 = args.group('height6')
 247     if strheight6:
 248         parmheight6=int(strheight6)
 249     else:
 250         parmheight6=defheight6
 251 
 252     return (parmpagename,parmyear,parmmonth,parmoffset,parmoffset2,parmheight6)
 253         
 254 # FIXME:                          vvvvvv is there a better way for matching a pagename ?
 255 _arg_basepage = r'\s*(?P<basepage>[^, ]+)?\s*'
 256 _arg_year = r',\s*(?P<year>\d+)?\s*'
 257 _arg_month = r',\s*(?P<month>\d+)?\s*'
 258 _arg_offset = r',\s*(?P<offset>[+-]?\d+)?\s*'
 259 _arg_offset2 = r',\s*(?P<offset2>[+-]?\d+)?\s*'
 260 _arg_height6 = r',\s*(?P<height6>[+-]?\d+)?\s*'
 261 _args_re_pattern = r'^(%s)?(%s)?(%s)?(%s)?(%s)?(%s)?$' % \
 262                    (_arg_basepage,_arg_year,_arg_month, \
 263 		    _arg_offset,_arg_offset2,_arg_height6)
 264 
 265 
 266 def getTcUseDays(macro, pagename):    ### yong27's modification ###
 267     heading = re.compile(r"^\s*(?P<hmarker>=+)\s(.*)\s(?P=hmarker)$")
 268     baseindent = 0
 269     indent = 0
 270     lineno = 0
 271     tcUseDays={}
 272     #page=Page(pagename)
 273 
 274     for line in macro.parser.lines:
 275         # Filter out the headings
 276         lineno = lineno + 1
 277         match = heading.match(line)
 278         if not match: continue
 279 
 280         # Get new ident level
 281         newindent = len(match.group(1))
 282         if not indent:
 283             baseindent = newindent - 1
 284             indent = baseindent
 285 
 286         tcUseDays[match.group(2)]=lineno
 287 
 288         # Set new indent level
 289         indent = newindent
 290     return tcUseDays
 291 
 292 
 293 def execute(macro, text, args_re=re.compile(_args_re_pattern)):
 294     result=''
 295     #print "pathinfo... ", webapi.getPathinfo()
 296     #print "subbed... ", re.sub('_2d(\d{2})_2d(\d{2})', r'_2d\1#\2', webapi.getPathinfo())
 297     (currentyear,currentmonth,currentday,h,m,s,wd,yd,ds) = time.localtime(time.time())
 298     thispage = macro.formatter.page.page_name
 299     # does the url have calendar params (= somebody has clicked on prev/next links in calendar) ?
 300     if macro.form.has_key('calparms'):
 301         text2 = macro.form['calparms'].value
 302         args2 = args_re.match(text2)
 303         if not args2:
 304             return ('<p><strong class="error">%s</strong></p>' % _('Invalid MonthCalendar calparms "%s"!')) % (text2,)
 305         else:
 306 	    has_calparms = 1 # yes!
 307 	    (cparmpagename,cparmyear,cparmmonth,cparmoffset,cparmoffset2,cparmheight6) = parseargs(args2,thispage,currentyear,currentmonth,0,0,0)
 308     else:
 309         has_calparms = 0
 310 	
 311     if text is None: # macro call without parameters
 312         (parmpagename,parmyear,parmmonth,parmoffset,parmoffset2,parmheight6) = \
 313 	([thispage],currentyear,currentmonth,0,0,0)
 314     else:
 315         # parse and check arguments
 316         args = args_re.match(text)
 317         if not args:
 318             return ('<p><strong class="error">%s</strong></p>' % _('Invalid MonthCalendar arguments "%s"!')) % (text,)
 319         else:
 320 	    (parmpagename,parmyear,parmmonth,parmoffset,parmoffset2,parmheight6) = \
 321 	    parseargs(args,thispage,currentyear,currentmonth,0,0,0)
 322 
 323     # does url have calendar params and is THIS the right calendar to modify (we can have multiple
 324     # calendars on the same page)?
 325     if has_calparms and (cparmpagename,cparmyear,cparmmonth,cparmoffset) == (parmpagename,parmyear,parmmonth,parmoffset):
 326         (year,month) = yearmonthplusoffset(parmyear,parmmonth,parmoffset+cparmoffset2)
 327 	parmoffset2 = cparmoffset2
 328     else:
 329         (year,month) = yearmonthplusoffset(parmyear,parmmonth,parmoffset)
 330 
 331     # get the calendar
 332     monthcal = calendar.monthcalendar(year,month)
 333     colorstep=85
 334     p = Page(thispage)
 335     querystr = "calparms=%s,%d,%d,%d,%%d" % (string.join(parmpagename,'*'),parmyear,parmmonth,parmoffset)
 336     prevlink  = p.url(querystr % (parmoffset2-1 ))
 337     nextlink  = p.url(querystr % (parmoffset2+1 ))
 338     prevylink = p.url(querystr % (parmoffset2-12))
 339     nextylink = p.url(querystr % (parmoffset2+12))
 340     prevmonth = macro.formatter.url(prevlink,'&lt;-','cal-link')
 341     nextmonth = macro.formatter.url(nextlink,'-&gt;','cal-link')
 342     prevyear  = macro.formatter.url(prevylink,'&lt;&lt;-','cal-link')
 343     nextyear  = macro.formatter.url(nextylink,'-&gt;&gt;','cal-link')
 344     
 345     restable = '<table border="2" cellspacing="2" cellpadding="2">\n%s%s%s</table>\n\n'
 346     if parmpagename <> [thispage]:
 347         pagelinks = ''
 348         (r,g,b)=(255,0,0)
 349 	l=len(parmpagename[0])
 350         steps=len(parmpagename)
 351 	maxsteps=(255/colorstep)
 352 	if steps>maxsteps:
 353 	    steps=maxsteps
 354 	chstep=int(l/steps)
 355 	st=0
 356 	while st < l:
 357 	    ch = parmpagename[0][st:st+chstep]
 358 	    (r,g,b) = cliprgb(r,g,b)
 359 	    pagelinks = pagelinks+'<a style="%s" href="%s">%s</a>' % ('background-color:#%02x%02x%02x;color:#000000;text-decoration:none' % (r,g,b),Page(parmpagename[0]).url(),ch)
 360 	    (r,g,b) = (r,g+colorstep,b)
 361 	    st = st+chstep
 362         (r,g,b)=(255-colorstep,255,255-colorstep)
 363         for page in parmpagename[1:]:
 364 	    pagelinks = pagelinks + '*<a style="%s" href="%s">%s</a>' % \
 365 	                ('background-color:#%02x%02x%02x;color:#000000;text-decoration:none' % (r,g,b),Page(page).url(),page)
 366         showpagename = '   %s<BR>\n' % pagelinks
 367     else:
 368         showpagename = ''
 369     resth1 = '  <th colspan="7" class="cal-header">\n' \
 370              '%s' \
 371 	     '   %s&nbsp;%s&nbsp;<b>&nbsp;%s&nbsp;/&nbsp;%s</b>&nbsp;%s\n&nbsp;%s\n' \
 372 	     '  </th>\n' % (showpagename,prevyear,prevmonth,str(year),str(month),nextmonth,nextyear)
 373     restr1 = ' <tr>\n%s </tr>\n' % resth1
 374 
 375     r7=range(7)
 376     restr2 = ' <tr>\n%s </tr>\n'
 377     restd2 = ''
 378 
 379     ######### set first weekday to Sun by yong27 ###########
 380     #for wkday in r7:
 381     for wkday in [6,0,1,2,3,4,5]:
 382     ########################################################
 383         wday=_(calendar.day_abbr[wkday])
 384         if wkday==5 or wkday==6:
 385             cssday="cal-weekend"
 386         else:
 387             cssday="cal-workday"
 388         restd2 = restd2 + '  <td class="%s" width="12%%"><font size="2">%s</font></td>\n' % (cssday,wday)
 389     restr2 = restr2 % restd2
 390 
 391     if parmheight6:
 392         while len(monthcal)<6:
 393             monthcal = monthcal + [[0,0,0,0,0,0,0]]
 394 
 395     testpagename = wikiutil.quoteWikiname("%s/%4d-%02d"%(parmpagename[0],year,month))
 396     tcUseDays = getTcUseDays(macro, testpagename)
 397 
 398 	
 399     restrn = ''
 400     for week in monthcal:
 401         restrn = restrn + ' <tr>\n%s </tr>\n'
 402 	restdn = ''
 403         for wkday in r7:
 404             day=week[wkday]
 405             if not day:
 406                 restdn = restdn + '  <td class="cal-invalidday">&nbsp;</td>\n'
 407             else:
 408 	        csslink="cal-emptyday"
 409 		(r,g,b,u) = (255,255,255,0)
 410 		page = parmpagename[0]
 411                 link = "%s/%4d-%02d-%02d" % (page,year,month,day)
 412                 dayStr=link.split('/')[1]
 413                 if dayStr in tcUseDays:
 414     	            csslink="cal-usedday"
 415 		    (r,g,b,u) = (255,150,0,1)
 416                     link = "%s/%4d-%02d#line%d" % (page,year,month,tcUseDays[dayStr])
 417                 else:
 418                     link = "%s/%4d-%02d" % (page,year,month)
 419                     
 420 		for otherpage in parmpagename[1:]:
 421                     otherlink = "%s/%4d-%02d-%02d" % (otherpage,year,month,day)
 422                     dayStr=otherlink.split('/')[1]
 423                     if dayStr in tcUseDays:
 424     	                csslink="cal-usedday"
 425 			if u==0:
 426 			    (r,g,b) = (r-colorstep,g,b-colorstep)
 427 			else:
 428 			    (r,g,b) = (r,g+colorstep,b)
 429 		(r,g,b) = cliprgb(r,g,b)
 430 		style = 'background-color:#%02x%02x%02x' % (r,g,b)
 431                 userquery = webapi.getPathinfo()
 432                 if '/' in webapi.getPathinfo()[1:]:
 433                     link=link.split('/')[1]
 434 	        fmtlink = macro.formatter.url(wikiutil.unquoteWikiname(link),str(day),csslink)
 435 	        if day==currentday and month==currentmonth and year==currentyear:
 436 	            cssday="cal-today"
 437 		else:
 438 		    cssday="cal-nottoday"
 439 	        restdn = restdn + '  <td style="%s" class="%s">%s</td>\n' % (style,cssday,fmtlink)
 440         restrn = restrn % restdn
 441 
 442     result = result + '\n' + restable % (restr1,restr2,restrn)
 443 
 444     ## ToDo
 445     testpagename = wikiutil.quoteWikiname("%s/%4d-%02d"%(parmpagename[0],year,month))
 446     tp = Page(testpagename, formatter=macro.formatter.__class__())
 447     return result

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2011-11-25 19:35:59, 15.5 KB) [[attachment:MonthCalendar2.py]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.

web biohackers.net