# -*- 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' )