- # -*- coding: utf8 -*-
- from pyramid.httpexceptions import HTTPNotFound, HTTPForbidden
- from pyramid.response import Response
- import cStringIO as StringIO
- from pyramid.view import view_config
- from .models import DBSession, User
- from reportlab.pdfgen import canvas
- from reportlab.pdfbase import pdfmetrics
- from reportlab.pdfbase.ttfonts import TTFont
- from reportlab.lib.units import mm
- import qrcode
- import subprocess
- from .upload import MediaPath
- from jm2l.const import CurrentYear
- # Create PDF container
- EXPIRATION_TIME = 300 # seconds
- WIDTH = 85 * mm
- HEIGHT = 60 * mm
- ICONSIZE = 10 * mm
-
- def JM2L_Logo(canvas, Offset=(0,0)):
- OffX, OffY = Offset
- logoobject = canvas.beginText()
- logoobject.setFont('Logo', 32)
- logoobject.setFillColorRGB(.83,0,.33)
- logoobject.setTextOrigin(OffX+5, OffY+17)
- logoobject.textLines("JM2L")
- canvas.drawText(logoobject)
-
- yearobject = canvas.beginText()
- yearobject.setFont("Helvetica-Bold", 10)
- yearobject.setFillColorRGB(1,1,1)
- yearobject.setTextRenderMode(0)
- yearobject.setTextOrigin(OffX+12 , OffY+35)
- yearobject.setWordSpace(13)
- yearobject.textLines(" ".join(str(CurrentYear)))
- canvas.drawText(yearobject)
-
- def Tiers_Logo(canvas, DispUser, StartPos=None, Offset=(0,0)):
- Border = 0
- OffX, OffY = Offset
- if StartPos is None:
- StartPos = ( 30 * mm, 2 )
- StartX, StartY = StartPos
- MaxX, MaxY = 34*mm, 18*mm
- num = 0
- canvas.setStrokeColorRGB(0.5,0.5,0.5)
- Logos = filter(lambda x:x.ThumbLinks, DispUser.tiers)[:3]
- # Should We compute a better positionning for logos ?
- DicPos = {}
- DicPos[1] = { 0:(1./2, 1./2) }
- DicPos[2] = { 0:(1./3, 1./2), 1:(2./3, 1./2) }
- DicPos[3] = { 0:(1./2, 1./4), 1:(1./3, 3./4), 2:(2./3, 3./4) }
- DicPos[4] = { 0:(1./3, 1./4), 1:(2./3, 1./4), 2:(1./3, 3./4),
- 3:(2./3, 3./4) }
- DicPos[5] = { 0:(1./3, 1./4), 1:(2./3, 1./4), 2:(1./6, 3./4),
- 3:(3./6, 3./4), 4:(5./6, 3./4) }
- DicPos[6] = { 0:(1./6, 1./4), 1:(3./6, 1./4), 2:(5./6, 1./4),
- 3:(1./6, 3./4), 4:(3./6, 3./4), 5:(5./6, 3./4) }
- DicPos[7] = { 0:(1./6, 1./4), 1:(3./6, 1./4), 2:(5./6, 1./4),
- 3:(1./8, 3./4), 4:(3./8, 3./4), 5:(5./8, 3./4),
- 6:(7./8, 3./4) }
- DicPos[8] = { 0:(1./8, 1./4), 1:(3./8, 1./4), 2:(5./8, 1./4),
- 3:(7./8, 1./4), 4:(1./8, 3./4), 5:(3./8, 3./4),
- 6:(5./8, 3./4), 7:(7./8, 3./4) }
- # draw overall border
- # canvas.roundRect(StartX, StartY, MaxX, MaxY, radius=2, stroke=True)
- for tiers in Logos:
- FileName = tiers.ThumbLinks.pop().split("/")[-1]
- ImagePath = "jm2l/upload/images/tiers/%s/%s" % (tiers.slug, FileName)
- PosX = OffX+StartX + DicPos[len(Logos)][num][0] * MaxX - (ICONSIZE+Border)/2
- PosY = OffY+StartY + DicPos[len(Logos)][num][1] * MaxY - (ICONSIZE+Border)/2
- canvas.setLineWidth(.1)
- if len(Logos)>1:
- size = ICONSIZE
- else:
- size = ICONSIZE*1.5
- canvas.drawImage(ImagePath,
- PosX, PosY, size, size,\
- preserveAspectRatio=True,
- anchor='c',
- mask='auto'
- )
- # draw icon border
- # canvas.roundRect(PosX, PosY, ICONSIZE, ICONSIZE, radius=2, stroke=True)
- num+=1
-
- def QRCode(DispUser):
- qr = qrcode.QRCode(
- version=1,
- error_correction=qrcode.constants.ERROR_CORRECT_L,
- box_size=10,
- border=2,
- )
- # Data of QR code
- qr.add_data('http://jm2l.linux-azur.org/user/%s' % DispUser.slug)
- qr.make(fit=True)
-
- return qr.make_image()
-
- def one_badge(c, DispUser, Offset=(0,0)):
- # Logo on Top
- JM2L_Logo(c, Offset)
- OffX, OffY = Offset
-
- c.rect(OffX-3, OffY-3, WIDTH+6, HEIGHT+6, fill=0, stroke=1)
- if DispUser.Staff:
- # Staff
- c.setFillColorRGB(.83,0,.33)
- c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0)
- c.setFillColorRGB(1,1,1)
- c.setFont('Liberation', 30)
- c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT-24, "STAFF")
- elif DispUser.is_Intervenant:
- # Intervenant
- c.setFillColorRGB(.21,.67,.78)
- c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0)
- c.setFillColorRGB(1,1,1)
- c.setFont('Liberation', 30)
- c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT-24, "Intervenant")
- elif DispUser.is_crew:
- # Benevole
- c.setFillColorRGB(.18,.76,.23)
- c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0)
- c.setFillColorRGB(1,1,1)
- c.setFont('Liberation', 30)
- c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT-24, "Bénévole")
- else:
- # Visiteur
- c.setFillColorRGB(.8,.8,.8)
- c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0)
- c.setFillColorRGB(1,1,1)
- c.setFont('Liberation', 30)
- c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT-24, "Visiteur")
-
- c.restoreState()
-
- c.setFont('Liberation', 18)
- c.setStrokeColorRGB(0,0,0)
- c.setFillColorRGB(0,0,0)
- # Feed Name and SurName
- if DispUser.prenom and DispUser.nom and len(DispUser.prenom) + len(DispUser.nom)>18:
- if DispUser.pseudo:
- c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 + 0 * mm , "%s" % DispUser.prenom )
- #c.setFont('Courier', 17)
- c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 - 8 * mm , "%s" % DispUser.nom )
- else:
- c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 + 4 * mm , "%s" % DispUser.prenom )
- #c.setFont('Courier', 17)
- c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 - 8 * mm , "%s" % DispUser.nom )
- else:
- c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 + 0 * mm , "%s %s" % (DispUser.prenom, DispUser.nom) )
-
- if DispUser.pseudo:
- c.setFont("Helvetica-Oblique", 18)
- c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 + 10 * mm , "%s" % DispUser.pseudo )
-
- # Put QR code to user profile
- c.drawInlineImage(QRCode(DispUser), \
- OffX+WIDTH - 20 * mm -5, OffY+5, \
- 20 * mm, 20 * mm, \
- preserveAspectRatio=True, \
- anchor='s')
-
- Tiers_Logo(c, DispUser, None, Offset)
-
-
- @view_config(route_name='badge_user', http_cache = (EXPIRATION_TIME, {'public':True}))
- def badge_user(request):
- isoutpng = request.params.get('png')
- user_slug = request.matchdict.get('user_slug', None)
- if user_slug is None or len(user_slug)==0:
- raise HTTPNotFound(u"Cet utilisateur n'a pas été reconnu")
- # Query database
- DispUser = User.by_slug(user_slug)
- if DispUser is None:
- raise HTTPNotFound()
-
- # Ok let's generate a PDF Badge
-
- # Register LiberationMono font
- ttfFile = "jm2l/static/fonts/LiberationMono-Regular.ttf"
- pdfmetrics.registerFont(TTFont("Liberation", ttfFile))
- # Import font
- ttfFile_Logo = "jm2l/static/fonts/PWTinselLetters.ttf"
- pdfmetrics.registerFont(TTFont("Logo", ttfFile_Logo))
-
- pdf = StringIO.StringIO()
- out_img = StringIO.StringIO()
-
- c = canvas.Canvas( pdf, pagesize=(WIDTH, HEIGHT) )
- c.translate(mm, mm)
-
- # Feed some metadata
- c.setCreator("linux-azur.org")
- c.setTitle("Badge")
-
- c.saveState()
-
- one_badge(c, DispUser)
-
- c.showPage()
- c.save()
- pdf.seek(0)
- if isoutpng:
- OutPDF = MediaPath().get_mediapath("badge", DispUser.uid, 'badge.pdf')
- OutPNG = MediaPath().get_mediapath("badge", DispUser.uid, 'badge.png')
- # Let's generate a png file for website
- with open( OutPDF ,'wb') as pdff:
- pdff.write(pdf.read())
-
- Command = ["convert","-density","150x150", OutPDF, OutPNG]
- subprocess.call(Command)
-
- with open( OutPNG, 'rb') as pngfile:
- out_img.write(pngfile.read())
-
- out_img.seek(0)
- return Response(app_iter=out_img, content_type = 'image/png' )
- else:
- return Response(app_iter=pdf, content_type = 'application/pdf' )
-
-
- @view_config(route_name='all_badges')
- def planche_badge(request):
- if request.user is None:
- # Don't answer to users that aren't logged
- raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
- # Query database about selected Year.
- Users = DBSession.query(User)
- # .join(User_Event)\
- # .filter(User_Event.year_uid == year)
-
- # Register LiberationMono font
- ttfFile = "jm2l/static/fonts/LiberationMono-Regular.ttf"
- pdfmetrics.registerFont(TTFont("Liberation", ttfFile))
- # Import font
- ttfFile_Logo = "jm2l/static/fonts/PWTinselLetters.ttf"
- pdfmetrics.registerFont(TTFont("Logo", ttfFile_Logo))
-
- pdf = StringIO.StringIO()
-
- FULLWIDTH = 210 * mm
- FULLHEIGHT = 297 * mm
-
- c = canvas.Canvas( pdf, pagesize=(FULLWIDTH, FULLHEIGHT) )
- c.translate(mm, mm)
-
- # Feed some metadata
- c.setCreator("linux-azur.org")
- c.setTitle("Badge")
- t=0
- ListUser = filter(lambda x: x.is_Intervenant or x.Staff or x.is_crew, Users)
- for num, DispUser in enumerate(ListUser):
- c.saveState()
- Offsets = (((num-t)%2)*(WIDTH+40)+40, ((num-t)/2)*(HEIGHT+25)+40)
- one_badge(c, DispUser, Offsets)
- if num%8==7:
- t=num+1
- c.showPage()
-
- c.showPage()
- c.save()
- pdf.seek(0)
- return Response(app_iter=pdf, content_type = 'application/pdf' )
|