1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 """high quality calendar rendering"""
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 import calendar
48 import sys
49 import time
50 import optparse
51 import lib.xcairo as xcairo
52 import lib.holiday as holiday
53 import lib
54
55 from lib.plugin import *
56
57 -def import_plugin(plugin_paths, cat, longcat, longcat2, listopt, preset):
58 """import a plugin making it visible
59
60 I{Example:}
61
62 >>> Language = import_plugin(get_plugin_paths(), "lang", "language", "languages", "--list-languages", "EN")
63
64 @param plugin_paths: list of plugin search paths
65 @param cat: short category name (for folder name)
66 @param longcat: long category name
67 @param longcat2: long category name in plural form
68 @param listopt: option name
69 @param preset: default value
70 @rtype: module
71
72 @note: Aimed for internal use with I{lang}, I{style}, I{geom}, I{layouts}.
73 """
74 try:
75 found = []
76 for path in plugin_paths:
77 found += available_files(path, cat, preset)
78 if len(found) == 0: raise IOError
79 if found[0][1] == "resource:":
80 m = __import__("%s.%s" % (cat,preset), globals(), locals(), [ "*" ])
81 else:
82 sys.path.insert(0, found[0][1])
83 m = __import__("%s.%s" % (cat,preset), globals(), locals(), [ "*" ])
84 sys.path.pop(0)
85 return m
86 except IOError:
87 sys.exit("callirhoe: %s definition '%s' not found, use %s to see available definitions" % (longcat,
88 preset,listopt))
89 except ImportError:
90 sys.exit("callirhoe: error loading %s definition '%s'" % (longcat, preset))
91
93 """print usage examples"""
94 print """Examples:
95
96 Create a calendar of the current year (by default in a 4x3 grid):
97 $ callirhoe my_calendar.pdf
98
99 Same as above, but in landscape mode (3x4) (for printing):
100 $ callirhoe --landscape my_calendar.pdf
101
102 Landscape via rotation (for screen):
103 $ callirhoe --paper=a4w --rows=3 my_calendar.pdf
104
105 Let's try with bars instead of boxes:
106 $ callirhoe -t bars my_calendar.pdf
107
108 In landscape mode, one row only looks quite good:
109 $ callirhoe -t bars --landscape --rows=1 my_calendar.pdf
110
111 How about a more flat look?
112 $ callirhoe -t sparse -s bw_sparse --rows=1 --cols=3 my_calendar.pdf
113
114 Calendar of 24 consecutive months, starting from current month:
115 $ callirhoe 0:24 0 my_calendar.pdf
116
117 Create a 600-dpi PNG file so that we can edit it with some effects in order to print an A3 poster:
118 $ callirhoe my_poster.png --paper=a3 --dpi=600 --opaque
119
120 Create a calendar as a full-hd wallpaper (1920x1080):
121 $ callirhoe wallpaper.png --paper=-1920:-1080 --opaque --rows=3 --no-shadow -s rainbow-gfs
122 and do some magic with ImageMagick! ;)
123 $ convert wallpaper.png -negate fancy.png
124
125 """
126
128 """add a --list-I{plugins} option to parser
129
130 @note: To be used with I{languages}, I{layouts}, I{styles} and I{geometries}.
131 """
132 parser.add_option("--list-%s" % opt, action="store_true", dest="list_%s" % opt, default=False,
133 help="list available %s" % opt)
134
136 """get the argument parser object
137
138 @rtype: optparse.OptionParser
139 """
140 parser = optparse.OptionParser(usage="usage: %prog [options] [[MONTH[-MONTH2|:SPAN]] YEAR] FILE",
141 description="High quality calendar rendering with vector graphics. "
142 "By default, a calendar of the current year in pdf format is written to FILE. "
143 "Alternatively, you can select a specific YEAR (0=current), "
144 "and a month range from MONTH (0-12, 0=current) to MONTH2 or for SPAN months.",
145 version="callirhoe " + lib._version + '\n' + lib._copyright)
146 parser.add_option("-l", "--lang", dest="lang", default="EN",
147 help="choose language [%default]")
148 parser.add_option("-t", "--layout", dest="layout", default="classic",
149 help="choose layout [%default]")
150 parser.add_option("-?", "--layout-help", dest="layouthelp", action="store_true", default=False,
151 help="show layout-specific help")
152 parser.add_option("--examples", dest="examples", action="store_true",
153 help="display some usage examples")
154 parser.add_option("-s", "--style", dest="style", default="default",
155 help="choose style [%default]")
156 parser.add_option("-g", "--geometry", dest="geom", default="default",
157 help="choose geometry [%default]")
158 parser.add_option("--landscape", action="store_true", dest="landscape", default=False,
159 help="landscape mode")
160 parser.add_option("--dpi", type="float", default=72.0,
161 help="set DPI (for raster output) [%default]")
162 parser.add_option("--paper", default="a4",
163 help="set paper type; PAPER can be an ISO paper type (a0..a9 or a0w..a9w) or of the "
164 "form W:H; positive values correspond to W or H mm, negative values correspond to "
165 "-W or -H pixels; 'w' suffix swaps width & height [%default]")
166 parser.add_option("--border", type="float", default=3,
167 help="set border size (in mm) [%default]")
168 parser.add_option("-H", "--with-holidays", action="append", dest="holidays",
169 help="load holiday file (can be used multiple times)")
170 parser.add_option("--short-monthnames", action="store_true", default=False,
171 help="user the short version of month names (defined in language file) [%default]")
172 parser.add_option("--long-daynames", action="store_true", default=False,
173 help="user the long version of day names (defined in language file) [%default]")
174 parser.add_option("-T", "--terse-holidays", action="store_false", dest="multiday_holidays",
175 default=True, help="do not print holiday end markers and omit dots")
176
177 for x in ["languages", "layouts", "styles", "geometries"]:
178 add_list_option(parser, x)
179
180 parser.add_option("--lang-var", action="append", dest="lang_assign",
181 help="modify a language variable")
182 parser.add_option("--style-var", action="append", dest="style_assign",
183 help="modify a style variable, e.g. dom.frame_thickness=0")
184 parser.add_option("--geom-var", action="append", dest="geom_assign",
185 help="modify a geometry variable")
186 return parser
187
189 parser = get_parser()
190
191 sys.argv,argv2 = lib.extract_parser_args(sys.argv,parser)
192 (options,args) = parser.parse_args()
193
194 list_and_exit = False
195 if options.list_languages:
196 for x in plugin_list("lang"): print x[0],
197 print
198 list_and_exit = True
199 if options.list_styles:
200 for x in plugin_list("style"): print x[0],
201 print
202 list_and_exit = True
203 if options.list_geometries:
204 for x in plugin_list("geom"): print x[0],
205 print
206 list_and_exit = True
207 if options.list_layouts:
208 for x in plugin_list("layouts"): print x[0],
209 print
210 list_and_exit = True
211 if list_and_exit: return
212
213 plugin_paths = get_plugin_paths()
214 Language = import_plugin(plugin_paths, "lang", "language", "languages", "--list-languages", options.lang)
215 Style = import_plugin(plugin_paths, "style", "style", "styles", "--list-styles", options.style)
216 Geometry = import_plugin(plugin_paths, "geom", "geometry", "geometries", "--list-geometries", options.geom)
217 Layout = import_plugin(plugin_paths, "layouts", "layout", "layouts", "--list-layouts", options.layout)
218
219 for x in argv2:
220 if '=' in x: x = x[0:x.find('=')]
221 if not Layout.parser.has_option(x):
222 parser.error("invalid option %s; use --help (-h) or --layout-help (-?) to see available options" % x)
223
224 (loptions,largs) = Layout.parser.parse_args(argv2)
225
226 if options.layouthelp:
227
228 Layout.parser.print_help()
229 return
230
231 if options.examples:
232 print_examples()
233 return
234
235
236 if len(args) < 1 or len(args) > 3:
237 parser.print_help()
238 return
239
240
241
242
243
244
245 if options.lang_assign:
246 for x in options.lang_assign: exec "Language.%s" % x
247 if options.style_assign:
248 for x in options.style_assign: exec "Style.%s" % x
249 if options.geom_assign:
250 for x in options.geom_assign: exec "Geometry.%s" % x
251
252 calendar.long_month_name = Language.long_month_name
253 calendar.long_day_name = Language.long_day_name
254 calendar.short_month_name = Language.short_month_name
255 calendar.short_day_name = Language.short_day_name
256
257 if len(args) == 1:
258 Year = time.localtime()[0]
259 Month, MonthSpan = 1, 12
260 Outfile = args[0]
261 elif len(args) == 2:
262 Year = lib.parse_year(args[0])
263 Month, MonthSpan = 1, 12
264 Outfile = args[1]
265 elif len(args) == 3:
266 Month, MonthSpan = lib.parse_month_range(args[0])
267 Year = lib.parse_year(args[1])
268 Outfile = args[2]
269
270 if MonthSpan == 0:
271 raise lib.Abort("callirhoe: empty calendar requested, aborting")
272
273 Geometry.landscape = options.landscape
274 xcairo.XDPI = options.dpi
275 Geometry.pagespec = options.paper
276 Geometry.border = options.border
277
278 hprovider = holiday.HolidayProvider(Style.dom, Style.dom_weekend,
279 Style.dom_holiday, Style.dom_weekend_holiday,
280 Style.dom_multi, Style.dom_weekend_multi, options.multiday_holidays)
281
282 if options.holidays:
283 for f in options.holidays:
284 hprovider.load_holiday_file(f)
285
286 if options.long_daynames:
287 Language.day_name = Language.long_day_name
288 else:
289 Language.day_name = Language.short_day_name
290
291 if options.short_monthnames:
292 Language.month_name = Language.short_month_name
293 else:
294 Language.month_name = Language.long_month_name
295
296 renderer = Layout.CalendarRenderer(Outfile, Year, Month, MonthSpan,
297 (Style,Geometry,Language), hprovider, lib._version, loptions)
298 renderer.render()
299
300 if __name__ == "__main__":
301 try:
302 main_program()
303 except lib.Abort as e:
304 sys.exit(e.args[0])
305