home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 November / CHIP_2011_11.iso / Programy / Narzedzia / Inkscape / Inkscape-0.48.2-1-win32.exe / share / extensions / svgcalendar.py < prev    next >
Text File  |  2011-07-08  |  15KB  |  339 lines

  1. #!/usr/bin/env python
  2.  
  3. '''
  4. calendar.py
  5. A calendar generator plugin for Inkscape, but also can be used as a standalone
  6. command line application.
  7.  
  8. Copyright (C) 2008 Aurelio A. Heckert <aurium(a)gmail.com>
  9.  
  10. This program is free software; you can redistribute it and/or modify
  11. it under the terms of the GNU General Public License as published by
  12. the Free Software Foundation; either version 2 of the License, or
  13. (at your option) any later version.
  14.  
  15. This program is distributed in the hope that it will be useful,
  16. but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. GNU General Public License for more details.
  19.  
  20. You should have received a copy of the GNU General Public License
  21. along with this program; if not, write to the Free Software
  22. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  23. '''
  24.  
  25. __version__ = "0.2"
  26.  
  27. import inkex, simplestyle, re, calendar
  28. from datetime import *
  29.  
  30. class SVGCalendar (inkex.Effect):
  31.  
  32.     def __init__(self):
  33.         inkex.Effect.__init__(self)
  34.         self.OptionParser.add_option("--tab",
  35.           action="store", type="string",
  36.           dest="tab")
  37.         self.OptionParser.add_option("--month",
  38.           action="store", type="int",
  39.           dest="month", default=0,
  40.           help="Month to be generated. If 0, then the entry year will be generated.")
  41.         self.OptionParser.add_option("--year",
  42.           action="store", type="int",
  43.           dest="year", default=0,
  44.           help="Year to be generated. If 0, then the current year will be generated.")
  45.         self.OptionParser.add_option("--fill-empty-day-boxes",
  46.           action="store", type="inkbool",
  47.           dest="fill_edb", default=True,
  48.           help="Fill empty day boxes with next month days.")
  49.         self.OptionParser.add_option("--start-day",
  50.           action="store", type="string",
  51.           dest="start_day", default="sun",
  52.           help='Week start day. ("sun" or "mon")')
  53.         self.OptionParser.add_option("--weekend",
  54.           action="store", type="string",
  55.           dest="weekend", default="sat+sun",
  56.           help='Define the weekend days. ("sat+sun" or "sat" or "sun")')
  57.         self.OptionParser.add_option("--auto-organize",
  58.           action="store", type="inkbool",
  59.           dest="auto_organize", default=True,
  60.           help='Automatically set the size and positions.')
  61.         self.OptionParser.add_option("--months-per-line",
  62.           action="store", type="int",
  63.           dest="months_per_line", default=3,
  64.           help='Number of months side by side.')
  65.         self.OptionParser.add_option("--month-width",
  66.           action="store", type="string",
  67.           dest="month_width", default="6cm",
  68.           help='The width of the month days box.')
  69.         self.OptionParser.add_option("--month-margin",
  70.           action="store", type="string",
  71.           dest="month_margin", default="1cm",
  72.           help='The space between the month boxes.')
  73.         self.OptionParser.add_option("--color-year",
  74.           action="store", type="string",
  75.           dest="color_year", default="#888",
  76.           help='Color for the year header.')
  77.         self.OptionParser.add_option("--color-month",
  78.           action="store", type="string",
  79.           dest="color_month", default="#666",
  80.           help='Color for the month name header.')
  81.         self.OptionParser.add_option("--color-day-name",
  82.           action="store", type="string",
  83.           dest="color_day_name", default="#999",
  84.           help='Color for the week day names header.')
  85.         self.OptionParser.add_option("--color-day",
  86.           action="store", type="string",
  87.           dest="color_day", default="#000",
  88.           help='Color for the common day box.')
  89.         self.OptionParser.add_option("--color-weekend",
  90.           action="store", type="string",
  91.           dest="color_weekend", default="#777",
  92.           help='Color for the weekend days.')
  93.         self.OptionParser.add_option("--color-nmd",
  94.           action="store", type="string",
  95.           dest="color_nmd", default="#BBB",
  96.           help='Color for the next month day, in enpty day boxes.')
  97.         self.OptionParser.add_option("--month-names",
  98.           action="store", type="string",
  99.           dest="month_names", default='January February March April May June '+\
  100.                               'July August September October November December',
  101.           help='The month names for localization.')
  102.         self.OptionParser.add_option("--day-names",
  103.           action="store", type="string",
  104.           dest="day_names", default='Sun Mon Tue Wed Thu Fri Sat',
  105.           help='The week day names for localization.')
  106.         self.OptionParser.add_option("--encoding",
  107.           action="store", type="string",
  108.           dest="input_encode", default='utf-8',
  109.           help='The input encoding of the names.')
  110.  
  111.     def validate_options(self):
  112.         #inkex.errormsg( self.options.input_encode )
  113.         # Convert string names lists in real lists:
  114.         m = re.match( '\s*(.*[^\s])\s*', self.options.month_names )
  115.         self.options.month_names = re.split( '\s+', m.group(1) )
  116.         m = re.match( '\s*(.*[^\s])\s*', self.options.day_names )
  117.         self.options.day_names = re.split( '\s+', m.group(1) )
  118.         # Validate names lists:
  119.         if len(self.options.month_names) != 12:
  120.           inkex.errormsg('The month name list "'+
  121.                          str(self.options.month_names)+
  122.                          '" is invalid. Using default.')
  123.           self.options.month_names = ['January','February','March',
  124.                                       'April',  'May',     'June',
  125.                                       'July',   'August',  'September',
  126.                                       'October','November','December']
  127.         if len(self.options.day_names) != 7:
  128.           inkex.errormsg('The day name list "'+
  129.                          str(self.options.day_names)+
  130.                          '" is invalid. Using default.')
  131.           self.options.day_names = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
  132.         # Convert year 0 to current year:
  133.         if self.options.year == 0: self.options.year = datetime.today().year
  134.         # Set the calendar start day:
  135.         if self.options.start_day=='sun':
  136.           calendar.setfirstweekday(6)
  137.         else:
  138.           calendar.setfirstweekday(0)
  139.         # Convert string numbers with unit to user space float numbers:
  140.         self.options.month_width  = inkex.unittouu( self.options.month_width )
  141.         self.options.month_margin = inkex.unittouu( self.options.month_margin )
  142.  
  143.     # initial values:
  144.     month_x_pos = 0
  145.     month_y_pos = 0
  146.  
  147.     def calculate_size_and_positions(self):
  148.         #month_margin month_width months_per_line auto_organize
  149.         self.doc_w = inkex.unittouu(self.document.getroot().get('width'))
  150.         self.doc_h = inkex.unittouu(self.document.getroot().get('height'))
  151.         if self.options.auto_organize:
  152.           if self.doc_h > self.doc_w:
  153.             self.months_per_line = 3
  154.           else:
  155.             self.months_per_line = 4
  156.         else:
  157.           self.months_per_line = self.options.months_per_line
  158.         #self.month_w = self.doc_w / self.months_per_line
  159.         if self.options.auto_organize:
  160.           self.month_w = (self.doc_w * 0.8) / self.months_per_line
  161.           self.month_margin = self.month_w / 10
  162.         else:
  163.           self.month_w = self.options.month_width
  164.           self.month_margin = self.options.month_margin
  165.         self.day_w = self.month_w / 7
  166.         self.day_h = self.month_w / 9
  167.         self.month_h = self.day_w * 7
  168.         if self.options.month == 0:
  169.           self.year_margin = (( self.doc_w + self.day_w -
  170.                                (self.month_w*self.months_per_line) -
  171.                                (self.month_margin*(self.months_per_line-1))
  172.                              ) / 2 ) #- self.month_margin
  173.         else:
  174.           self.year_margin = ( self.doc_w - self.month_w ) / 2
  175.         self.style_day = {
  176.           'font-size': str( self.day_w / 2 ),
  177.           'font-family': 'arial',
  178.           'text-anchor': 'middle',
  179.           'text-align': 'center',
  180.           'fill': self.options.color_day
  181.           }
  182.         self.style_weekend = self.style_day.copy()
  183.         self.style_weekend['fill'] = self.options.color_weekend
  184.         self.style_nmd = self.style_day.copy()
  185.         self.style_nmd['fill'] = self.options.color_nmd
  186.         self.style_month = self.style_day.copy()
  187.         self.style_month['fill'] = self.options.color_month
  188.         self.style_month['font-size'] = str( self.day_w / 1.5 )
  189.         self.style_month['font-weight'] = 'bold'
  190.         self.style_day_name = self.style_day.copy()
  191.         self.style_day_name['fill'] = self.options.color_day_name
  192.         self.style_day_name['font-size'] = str( self.day_w / 3 )
  193.         self.style_year = self.style_day.copy()
  194.         self.style_year['fill'] = self.options.color_year
  195.         self.style_year['font-size'] = str( self.day_w * 2 )
  196.         self.style_year['font-weight'] = 'bold'
  197.  
  198.     def is_weekend(self, pos):
  199.         # weekend values: "sat+sun" or "sat" or "sun"
  200.         if self.options.start_day=='sun':
  201.           if self.options.weekend=='sat+sun' and pos==0: return True
  202.           if self.options.weekend=='sat+sun' and pos==6: return True
  203.           if self.options.weekend=='sat' and pos==6: return True
  204.           if self.options.weekend=='sun' and pos==0: return True
  205.         else:
  206.           if self.options.weekend=='sat+sun' and pos==5: return True
  207.           if self.options.weekend=='sat+sun' and pos==6: return True
  208.           if self.options.weekend=='sat' and pos==5: return True
  209.           if self.options.weekend=='sun' and pos==6: return True
  210.         return False
  211.  
  212.     def in_line_month(self, cal):
  213.         cal2 = []
  214.         for week in cal:
  215.           for day in week:
  216.             if day != 0:
  217.               cal2.append(day)
  218.         return cal2
  219.  
  220.     def write_month_header(self, g, m):
  221.         txt_atts = {'style': simplestyle.formatStyle(self.style_month),
  222.                     'x': str( (self.month_w - self.day_w) / 2 ),
  223.                     'y': str( self.day_h / 5 ) }
  224.         try:
  225.           inkex.etree.SubElement(g, 'text', txt_atts).text = unicode(self.options.month_names[m-1], self.options.input_encode)
  226.         except:
  227.           inkex.errormsg('You must select your correct system encode.')
  228.           exit(1)
  229.         gw = inkex.etree.SubElement(g, 'g')
  230.         week_x = 0
  231.         if self.options.start_day=='sun':
  232.           for wday in self.options.day_names:
  233.             txt_atts = {'style': simplestyle.formatStyle(self.style_day_name),
  234.                         'x': str( self.day_w * week_x ),
  235.                         'y': str( self.day_h ) }
  236.             try:
  237.               inkex.etree.SubElement(gw, 'text', txt_atts).text = unicode(wday, self.options.input_encode)
  238.             except:
  239.               inkex.errormsg('You must select your correct system encode.')
  240.               exit(1)
  241.             week_x += 1
  242.         else:
  243.           w2 = self.options.day_names[1:]
  244.           w2.append(self.options.day_names[0])
  245.           for wday in w2:
  246.             txt_atts = {'style': simplestyle.formatStyle(self.style_day_name),
  247.                         'x': str( self.day_w * week_x ),
  248.                         'y': str( self.day_h ) }
  249.             try:
  250.               inkex.etree.SubElement(gw, 'text', txt_atts).text = unicode(wday, self.options.input_encode)
  251.             except:
  252.               inkex.errormsg('You must select your correct system encode.')
  253.               exit(1)
  254.             week_x += 1
  255.  
  256.     def create_month(self, m):
  257.         txt_atts = {
  258.           'transform': 'translate('+str(self.year_margin +
  259.                                        (self.month_w + self.month_margin) *
  260.                                         self.month_x_pos) +
  261.                                 ','+str((self.day_h * 4) +
  262.                                        (self.month_h * self.month_y_pos))+')',
  263.           'id': 'month_'+str(m)+'_'+str(self.options.year) }
  264.         g = inkex.etree.SubElement(self.year_g, 'g', txt_atts)
  265.         self.write_month_header(g, m)
  266.         gdays = inkex.etree.SubElement(g, 'g')
  267.         cal = calendar.monthcalendar(self.options.year,m)
  268.         if m == 1:
  269.           before_month = \
  270.             self.in_line_month( calendar.monthcalendar(self.options.year-1, 12) )
  271.         else:
  272.           before_month = \
  273.             self.in_line_month( calendar.monthcalendar(self.options.year, m-1) )
  274.         if m == 12:
  275.           next_month = \
  276.             self.in_line_month( calendar.monthcalendar(self.options.year+1, 1) )
  277.         else:
  278.           next_month = \
  279.             self.in_line_month( calendar.monthcalendar(self.options.year, m+1) )
  280.         if len(cal) < 6: # add a line after the last week
  281.           cal.append([0,0,0,0,0,0,0])
  282.         if len(cal) < 6: # add a line before the first week (Feb 2009)
  283.           cal.reverse()
  284.           cal.append([0,0,0,0,0,0,0])
  285.           cal.reverse()
  286.         # How mutch before month days will be showed:
  287.         bmd = cal[0].count(0) + cal[1].count(0)
  288.         before = True
  289.         week_y = 0
  290.         for week in cal:
  291.           week_x = 0
  292.           for day in week:
  293.             style = self.style_day
  294.             if self.is_weekend(week_x): style = self.style_weekend
  295.             if day == 0: style = self.style_nmd
  296.             txt_atts = {'style': simplestyle.formatStyle(style),
  297.                         'x': str( self.day_w * week_x ),
  298.                         'y': str( self.day_h * (week_y+2) ) }
  299.             if day==0 and not self.options.fill_edb:
  300.           pass # draw nothing
  301.         elif day==0:
  302.               if before:
  303.                 inkex.etree.SubElement(gdays, 'text', txt_atts).text = str( before_month[-bmd] )
  304.                 bmd -= 1
  305.               else:
  306.                 inkex.etree.SubElement(gdays, 'text', txt_atts).text = str( next_month[bmd] )
  307.                 bmd += 1
  308.             else:
  309.               inkex.etree.SubElement(gdays, 'text', txt_atts).text = str(day)
  310.               before = False
  311.             week_x += 1
  312.           week_y += 1
  313.         self.month_x_pos += 1
  314.         if self.month_x_pos >= self.months_per_line:
  315.           self.month_x_pos = 0
  316.           self.month_y_pos += 1
  317.  
  318.     def effect(self):
  319.         self.validate_options()
  320.         self.calculate_size_and_positions()
  321.         parent = self.document.getroot()
  322.         txt_atts = {
  323.           'id': 'year_'+str(self.options.year) }
  324.         self.year_g = inkex.etree.SubElement(parent, 'g', txt_atts)
  325.         txt_atts = {'style': simplestyle.formatStyle(self.style_year),
  326.                     'x': str( self.doc_w / 2 ),
  327.                     'y': str( self.day_w * 1.5 ) }
  328.         inkex.etree.SubElement(self.year_g, 'text', txt_atts).text = str(self.options.year)
  329.         if self.options.month == 0:
  330.           for m in range(1,13):
  331.             self.create_month(m)
  332.         else:
  333.           self.create_month(self.options.month)
  334.  
  335.  
  336. if __name__ == '__main__':   #pragma: no cover
  337.     e = SVGCalendar()
  338.     e.affect()
  339.