3 # YouRule: Onscreen Ruler Generator
5 # Copyright (C) 2007 Benjamin Mako Hill <mako@atdot.cc>
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the Affero General Public License as published
9 # by the Free Software Foundation, either version 1 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 # General Public License for more details.
17 # You should have received a copy of the Affero General Public License
18 # along with this program. If not, see
19 # <http://http://www.affero.org/oagpl.html>.
22 from __future__ import division
25 from storm.locals import *
27 # recalculate the path based on the location of the file
28 sys.path.append(os.path.dirname(__file__))
29 from svgruler import SVGRuler
31 from jinja import Environment, FileSystemLoader
32 jinja_env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>',
33 loader=FileSystemLoader(os.path.dirname(__file__) + "/templates/"))
35 def render(filename, vars={}):
36 if re.match(r'.+\.\css$', filename):
37 web.header("Content-Type","text/css; charset=utf-8")
39 web.header("Content-Type","text/html; charset=utf-8")
41 tmpl = jinja_env.get_template(filename + '.tmpl')
42 vars['homepath'] = web.ctx.homepath
44 print tmpl.render(vars)
46 # the url map for the application
47 urls = ( '/?', 'index',
48 '/ruler_([0-9\.]+)px_([0-9\.]+)([A-Za-z]+).(svg|png|jpg)', 'ruler_img',
49 '/show/(.*(svg|png|jpg))', 'show_ruler',
50 '/gallery(.*)', 'gallery',
51 '/delete/(\d+)', 'delete',
52 '/undelete/(\d+)', 'undelete',
55 database = create_database("mysql:yourule")
57 store = Store(database)
60 __storm_table__ = "gallery"
61 id = Int(primary=True)
69 def __init__(self, **kw):
70 self.pixel_width = float(kw['pixel_width'])
71 self.unit_width = float(kw['unit_width'])
72 self.units = unicode(kw['units'])
73 if kw.has_key('model'):
74 self.model = unicode(kw['model'])
79 if self.units == 'centimeters':
80 return self.unit_width
81 elif self.units == 'inches':
82 return(round(self.unit_width / self.cm_in_ratio, 2))
85 if self.units == 'inches':
86 return self.unit_width
87 elif self.units == 'centimeters':
88 return(round(self.unit_width * self.cm_in_ratio, 2))
91 return('ruler_%spx_%s%s.png' % (self.pixel_width,
92 self.unit_width, self.units))
97 render('index', locals())
102 errormsg = validate_input(input)
105 pixel_width = input['pixel_width']
106 unit_width = input['unit_width']
107 units = input['units']
108 render('index', locals())
110 ruler = Ruler(pixel_width = input['pixel_width'],
111 unit_width = input['unit_width'],
112 units = input['units'])
114 web.redirect('/show/%s' % ruler.url())
117 def GET(self, ruler_url, ext):
118 if web.input().has_key('fromgallery'):
123 other_unit, other_unit_url = get_other_unit(ruler_url)
125 render('show_ruler', locals())
128 def GET(self, pixel_width=None, unit_width=None, units=None, ext=None):
130 # TODO check to see if it's a format that we support
132 # set ruler height to be 200 px always
133 pixel_width = float(pixel_width)
134 unit_width = float(unit_width)
138 scale = pixel_width / unit_width
139 ruler_length = int(unit_width)
141 ruler = SVGRuler(scale, units, ruler_height, ruler_length)
144 if ext == 'svg': ext = 'svg+xml'
145 web.header("Content-Type", "image/%s" % ext)
148 sys.stdout.write(ruler.getxml())
150 pin, pout = os.popen2('convert -size %sx%s - %s:-' % \
151 (pixel_width, ruler_height, ext))
153 pin.write(ruler.getxml())
155 sys.stdout.write(pout.read())
158 def GET(self, ruler_url):
161 pixel_width, unit_width, units = process_ruler_url(ruler_url)[0:3]
163 new_rulers = store.find(Ruler, Ruler.visible == 1)#.order_by(Ruler.model)
166 for ruler in new_rulers:
169 #rulers = map(lambda x: x, rulers)
171 render('gallery', locals())
173 def POST(self, ruler_url):
176 errormsg = validate_input(input)
178 errormsg = 'Please fill out all fields.'
181 pixel_width = input['pixel_width']
182 unit_width = input['unit_width']
183 units = input['units']
184 model = input['model']
186 new_ruler = Ruler(pixel_width = input['pixel_width'],
187 unit_width = input['unit_width'],
188 units = input['units'],
189 model = input['model'])
194 rulers = store.find(Ruler, Ruler.visible == 1)
195 #rulers.order_by(Ruler.model)
196 render('gallery', locals())
200 ruler = store.get(Ruler, int(id))
203 web.redirect('/gallery')
208 ruler = store.get(Ruler, int(id))
211 web.redirect('/gallery')
217 def get_other_unit(url):
218 pixel_width, unit_width, units = process_ruler_url(url)[0:3]
220 ruler = Ruler(pixel_width=pixel_width, unit_width=unit_width, units=units)
221 pixel_width, unit_width, units = process_ruler_url(url)[0:3]
223 if units == 'centimeters':
225 unit_width = ruler.in_width()
226 elif units == 'inches':
227 units = 'centimeters'
228 unit_width = ruler.cm_width()
230 new_ruler = Ruler(pixel_width=pixel_width, unit_width=unit_width,
233 return(units, new_ruler.url())
236 def process_ruler_url(url):
237 url = re.sub(r'^/?(ruler.*)$', r'\1', url)
238 return(re.match( r'ruler_([\d\.]+)px_([\d\.]+)(\w+).(png|svg|jpg)',
241 def validate_input(input):
244 if not input.pixel_width \
245 or not input.unit_width:
246 errormsg = 'Please fill out all fields.'
247 elif not re.match('^[\d\.]+$', input.pixel_width) \
248 or not re.match('^[\d\.]+$', input.unit_width):
249 errormsg = "Widths must be numbers."
250 elif input['pixel_width'] < 0 \
251 or input['unit_width'] < 0:
252 errormsg = 'Widths must be greater than postive.'
257 web.webapi.internalerror = web.debugerror
258 if __name__ == "__main__":
259 web.run(urls, globals(), web.reloader)
261 application = web.wsgifunc(web.webpyfunc(urls, globals()))