Le repo des sources pour le site web des JM2L
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

349 lines
12 KiB

  1. # -*- coding: utf8 -*-
  2. from pyramid.httpexceptions import HTTPNotFound, HTTPForbidden
  3. from pyramid.response import Response
  4. import cStringIO as StringIO
  5. from pyramid.view import view_config
  6. from .models import DBSession, User
  7. from reportlab.pdfgen import canvas
  8. from reportlab.pdfbase import pdfmetrics
  9. from reportlab.pdfbase.ttfonts import TTFont
  10. from reportlab.lib.units import mm
  11. import qrcode
  12. import subprocess
  13. from .upload import MediaPath
  14. # Create PDF container
  15. EXPIRATION_TIME = 300 # seconds
  16. WIDTH = 85 * mm
  17. HEIGHT = 60 * mm
  18. ICONSIZE = 10 * mm
  19. def Ribbon35(DispUser, canvas):
  20. canvas.saveState()
  21. canvas.rotate(35)
  22. offset_u=0
  23. if DispUser.Staff:
  24. # Staff
  25. canvas.setFillColorRGB(1,.2,.2)
  26. canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
  27. canvas.setFillColorRGB(1,1,1)
  28. canvas.setFont('Liberation', 20)
  29. canvas.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+5, "STAFF")
  30. elif DispUser.is_Intervenant:
  31. # Intervenant
  32. canvas.setFillColorRGB(.3,.3,1)
  33. canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
  34. canvas.setFillColorRGB(1,1,1)
  35. canvas.setFont('Liberation', 15)
  36. canvas.drawCentredString(WIDTH/2-15, HEIGHT/2-offset_u+10, "Intervenant")
  37. else:
  38. # Visiteur
  39. canvas.setFillColorRGB(.8,.8,.8)
  40. canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
  41. canvas.setFillColorRGB(0,0,0)
  42. canvas.setFont('Liberation', 12)
  43. canvas.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+7, "Visiteur")
  44. canvas.restoreState()
  45. return canvas
  46. def Ribbon45(DispUser, canvas):
  47. canvas.saveState()
  48. canvas.rotate(45)
  49. offset_u=0
  50. if DispUser.Staff:
  51. # Staff
  52. canvas.setFillColorRGB(1,.2,.2)
  53. canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
  54. canvas.setFillColorRGB(1,1,1)
  55. canvas.setFont('Liberation', 20)
  56. canvas.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+5, "STAFF")
  57. elif DispUser.is_Intervenant:
  58. # Intervenant
  59. canvas.setFillColorRGB(.3,.3,1)
  60. canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
  61. canvas.setFillColorRGB(1,1,1)
  62. canvas.setFont('Liberation', 15)
  63. canvas.drawCentredString(WIDTH/2-15, HEIGHT/2-offset_u+10, "Intervenant")
  64. else:
  65. # Visiteur
  66. canvas.setFillColorRGB(.8,.8,.8)
  67. canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
  68. canvas.setFillColorRGB(0,0,0)
  69. canvas.setFont('Liberation', 12)
  70. canvas.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+7, "Visiteur")
  71. canvas.restoreState()
  72. return canvas
  73. def Ribbon90(DispUser, canvas):
  74. canvas.saveState()
  75. canvas.rotate(90)
  76. offset_u=0
  77. if DispUser.Staff:
  78. # Staff
  79. canvas.setFillColorRGB(1,.2,.2)
  80. canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
  81. canvas.setFillColorRGB(1,1,1)
  82. canvas.setFont('Liberation', 20)
  83. canvas.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+5, "STAFF")
  84. elif DispUser.is_Intervenant:
  85. # Intervenant
  86. canvas.setFillColorRGB(.3,.3,1)
  87. canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
  88. canvas.setFillColorRGB(1,1,1)
  89. canvas.setFont('Liberation', 15)
  90. canvas.drawCentredString(WIDTH/2-15, HEIGHT/2-offset_u+10, "Intervenant")
  91. else:
  92. # Visiteur
  93. canvas.setFillColorRGB(.8,.8,.8)
  94. canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1)
  95. canvas.setFillColorRGB(0,0,0)
  96. canvas.setFont('Liberation', 12)
  97. canvas.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+7, "Visiteur")
  98. canvas.restoreState()
  99. return canvas
  100. def JM2L_Logo(canvas, Offset=(0,0)):
  101. OffX, OffY = Offset
  102. logoobject = canvas.beginText()
  103. logoobject.setFont('Logo', 32)
  104. logoobject.setFillColorRGB(.83,0,.33)
  105. logoobject.setTextOrigin(OffX+5, OffY+17)
  106. logoobject.textLines("JM2L")
  107. canvas.drawText(logoobject)
  108. yearobject = canvas.beginText()
  109. yearobject.setFont("Helvetica-Bold", 10)
  110. yearobject.setFillColorRGB(1,1,1)
  111. yearobject.setTextRenderMode(0)
  112. yearobject.setTextOrigin(OffX+12 , OffY+35)
  113. yearobject.setWordSpace(13)
  114. yearobject.textLines("2 0 1 5")
  115. canvas.drawText(yearobject)
  116. def Tiers_Logo(canvas, DispUser, StartPos=None, Offset=(0,0)):
  117. Border = 0
  118. OffX, OffY = Offset
  119. if StartPos is None:
  120. StartPos = ( 30 * mm, 2 )
  121. StartX, StartY = StartPos
  122. MaxX, MaxY = 34*mm, 18*mm
  123. num = 0
  124. canvas.setStrokeColorRGB(0.5,0.5,0.5)
  125. Logos = filter(lambda x:x.ThumbLinks, DispUser.tiers)[:3]
  126. # Should We compute a better positionning for logos ?
  127. DicPos = {}
  128. DicPos[1] = { 0:(1./2, 1./2) }
  129. DicPos[2] = { 0:(1./3, 1./2), 1:(2./3, 1./2) }
  130. DicPos[3] = { 0:(1./2, 1./4), 1:(1./3, 3./4), 2:(2./3, 3./4) }
  131. DicPos[4] = { 0:(1./3, 1./4), 1:(2./3, 1./4), 2:(1./3, 3./4),
  132. 3:(2./3, 3./4) }
  133. DicPos[5] = { 0:(1./3, 1./4), 1:(2./3, 1./4), 2:(1./6, 3./4),
  134. 3:(3./6, 3./4), 4:(5./6, 3./4) }
  135. DicPos[6] = { 0:(1./6, 1./4), 1:(3./6, 1./4), 2:(5./6, 1./4),
  136. 3:(1./6, 3./4), 4:(3./6, 3./4), 5:(5./6, 3./4) }
  137. DicPos[7] = { 0:(1./6, 1./4), 1:(3./6, 1./4), 2:(5./6, 1./4),
  138. 3:(1./8, 3./4), 4:(3./8, 3./4), 5:(5./8, 3./4),
  139. 6:(7./8, 3./4) }
  140. DicPos[8] = { 0:(1./8, 1./4), 1:(3./8, 1./4), 2:(5./8, 1./4),
  141. 3:(7./8, 1./4), 4:(1./8, 3./4), 5:(3./8, 3./4),
  142. 6:(5./8, 3./4), 7:(7./8, 3./4) }
  143. # draw overall border
  144. # canvas.roundRect(StartX, StartY, MaxX, MaxY, radius=2, stroke=True)
  145. for tiers in Logos:
  146. FileName = tiers.ThumbLinks.pop().split("/")[-1]
  147. ImagePath = "jm2l/upload/images/tiers/%s/%s" % (tiers.slug, FileName)
  148. PosX = OffX+StartX + DicPos[len(Logos)][num][0] * MaxX - (ICONSIZE+Border)/2
  149. PosY = OffY+StartY + DicPos[len(Logos)][num][1] * MaxY - (ICONSIZE+Border)/2
  150. canvas.setLineWidth(.1)
  151. if len(Logos)>1:
  152. size = ICONSIZE
  153. else:
  154. size = ICONSIZE*1.5
  155. canvas.drawImage(ImagePath,
  156. PosX, PosY, size, size,\
  157. preserveAspectRatio=True,
  158. anchor='c',
  159. mask='auto'
  160. )
  161. # draw icon border
  162. # canvas.roundRect(PosX, PosY, ICONSIZE, ICONSIZE, radius=2, stroke=True)
  163. num+=1
  164. def QRCode(DispUser):
  165. qr = qrcode.QRCode(
  166. version=1,
  167. error_correction=qrcode.constants.ERROR_CORRECT_L,
  168. box_size=10,
  169. border=2,
  170. )
  171. # Data of QR code
  172. qr.add_data('http://jm2l.linux-azur.org/user/%s' % DispUser.slug)
  173. qr.make(fit=True)
  174. return qr.make_image()
  175. def one_badge(c, DispUser, Offset=(0,0)):
  176. # Logo on Top
  177. JM2L_Logo(c, Offset)
  178. OffX, OffY = Offset
  179. c.rect(OffX-3, OffY-3, WIDTH+6, HEIGHT+6, fill=0, stroke=1)
  180. if DispUser.Staff:
  181. # Staff
  182. c.setFillColorRGB(.83,0,.33)
  183. c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0)
  184. c.setFillColorRGB(1,1,1)
  185. c.setFont('Liberation', 30)
  186. c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT-24, "STAFF")
  187. elif DispUser.is_Intervenant:
  188. # Intervenant
  189. c.setFillColorRGB(.21,.67,.78)
  190. c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0)
  191. c.setFillColorRGB(1,1,1)
  192. c.setFont('Liberation', 30)
  193. c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT-24, "Intervenant")
  194. elif DispUser.is_crew:
  195. # Benevole
  196. c.setFillColorRGB(.18,.76,.23)
  197. c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0)
  198. c.setFillColorRGB(1,1,1)
  199. c.setFont('Liberation', 30)
  200. c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT-24, "Bénévole")
  201. else:
  202. # Visiteur
  203. c.setFillColorRGB(.8,.8,.8)
  204. c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0)
  205. c.setFillColorRGB(1,1,1)
  206. c.setFont('Liberation', 30)
  207. c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT-24, "Visiteur")
  208. c.restoreState()
  209. c.setFont('Liberation', 18)
  210. c.setStrokeColorRGB(0,0,0)
  211. c.setFillColorRGB(0,0,0)
  212. # Feed Name and SurName
  213. if DispUser.prenom and DispUser.nom and len(DispUser.prenom) + len(DispUser.nom)>18:
  214. if DispUser.pseudo:
  215. c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 + 0 * mm , "%s" % DispUser.prenom )
  216. #c.setFont('Courier', 17)
  217. c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 - 8 * mm , "%s" % DispUser.nom )
  218. else:
  219. c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 + 4 * mm , "%s" % DispUser.prenom )
  220. #c.setFont('Courier', 17)
  221. c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 - 8 * mm , "%s" % DispUser.nom )
  222. else:
  223. c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 + 0 * mm , "%s %s" % (DispUser.prenom, DispUser.nom) )
  224. if DispUser.pseudo:
  225. c.setFont("Helvetica-Oblique", 18)
  226. c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 + 10 * mm , "%s" % DispUser.pseudo )
  227. # Put QR code to user profile
  228. c.drawInlineImage(QRCode(DispUser), \
  229. OffX+WIDTH - 20 * mm -5, OffY+5, \
  230. 20 * mm, 20 * mm, \
  231. preserveAspectRatio=True, \
  232. anchor='s')
  233. Tiers_Logo(c, DispUser, None, Offset)
  234. @view_config(route_name='badge_user', http_cache = (EXPIRATION_TIME, {'public':True}))
  235. def badge_user(request):
  236. isoutpng = request.params.get('png')
  237. user_slug = request.matchdict.get('user_slug', None)
  238. if user_slug is None or len(user_slug)==0:
  239. raise HTTPNotFound(u"Cet utilisateur n'a pas été reconnu")
  240. # Query database
  241. DispUser = User.by_slug(user_slug)
  242. if DispUser is None:
  243. raise HTTPNotFound()
  244. # Ok let's generate a PDF Badge
  245. # Register LiberationMono font
  246. ttfFile = "jm2l/static/fonts/LiberationMono-Regular.ttf"
  247. pdfmetrics.registerFont(TTFont("Liberation", ttfFile))
  248. # Import font
  249. ttfFile_Logo = "jm2l/static/fonts/PWTinselLetters.ttf"
  250. pdfmetrics.registerFont(TTFont("Logo", ttfFile_Logo))
  251. pdf = StringIO.StringIO()
  252. out_img = StringIO.StringIO()
  253. c = canvas.Canvas( pdf, pagesize=(WIDTH, HEIGHT) )
  254. c.translate(mm, mm)
  255. # Feed some metadata
  256. c.setCreator("linux-azur.org")
  257. c.setTitle("Badge")
  258. c.saveState()
  259. one_badge(c, DispUser)
  260. c.showPage()
  261. c.save()
  262. pdf.seek(0)
  263. if isoutpng:
  264. OutPDF = MediaPath().get_mediapath("badge", DispUser.uid, 'badge.pdf')
  265. OutPNG = MediaPath().get_mediapath("badge", DispUser.uid, 'badge.png')
  266. # Let's generate a png file for website
  267. with open( OutPDF ,'wb') as pdff:
  268. pdff.write(pdf.read())
  269. Command = ["convert","-density","150x150", OutPDF, OutPNG]
  270. subprocess.call(Command)
  271. with open( OutPNG, 'rb') as pngfile:
  272. out_img.write(pngfile.read())
  273. out_img.seek(0)
  274. return Response(app_iter=out_img, content_type = 'image/png' )
  275. else:
  276. return Response(app_iter=pdf, content_type = 'application/pdf' )
  277. @view_config(route_name='all_badges')
  278. def planche_badge(request):
  279. if request.user is None:
  280. # Don't answer to users that aren't logged
  281. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  282. # Query database about selected Year.
  283. Users = DBSession.query(User)
  284. # .join(User_Event)\
  285. # .filter(User_Event.year_uid == year)
  286. # Register LiberationMono font
  287. ttfFile = "jm2l/static/fonts/LiberationMono-Regular.ttf"
  288. pdfmetrics.registerFont(TTFont("Liberation", ttfFile))
  289. # Import font
  290. ttfFile_Logo = "jm2l/static/fonts/PWTinselLetters.ttf"
  291. pdfmetrics.registerFont(TTFont("Logo", ttfFile_Logo))
  292. pdf = StringIO.StringIO()
  293. FULLWIDTH = 210 * mm
  294. FULLHEIGHT = 297 * mm
  295. c = canvas.Canvas( pdf, pagesize=(FULLWIDTH, FULLHEIGHT) )
  296. c.translate(mm, mm)
  297. # Feed some metadata
  298. c.setCreator("linux-azur.org")
  299. c.setTitle("Badge")
  300. t=0
  301. ListUser = filter(lambda x: x.is_Intervenant or x.Staff or x.is_crew, Users)
  302. for num, DispUser in enumerate(ListUser):
  303. c.saveState()
  304. Offsets = (((num-t)%2)*(WIDTH+40)+40, ((num-t)/2)*(HEIGHT+25)+40)
  305. one_badge(c, DispUser, Offsets)
  306. if num%8==7:
  307. t=num+1
  308. c.showPage()
  309. c.showPage()
  310. c.save()
  311. pdf.seek(0)
  312. return Response(app_iter=pdf, content_type = 'application/pdf' )