# -*- 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 # Create PDF container EXPIRATION_TIME = 300 # seconds WIDTH = 85 * mm HEIGHT = 60 * mm ICONSIZE = 10 * mm def Ribbon35(DispUser, canvas): canvas.saveState() canvas.rotate(35) offset_u=0 if DispUser.Staff: # Staff canvas.setFillColorRGB(1,.2,.2) canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1) canvas.setFillColorRGB(1,1,1) canvas.setFont('Liberation', 20) canvas.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+5, "STAFF") elif DispUser.is_Intervenant: # Intervenant canvas.setFillColorRGB(.3,.3,1) canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1) canvas.setFillColorRGB(1,1,1) canvas.setFont('Liberation', 15) canvas.drawCentredString(WIDTH/2-15, HEIGHT/2-offset_u+10, "Intervenant") else: # Visiteur canvas.setFillColorRGB(.8,.8,.8) canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1) canvas.setFillColorRGB(0,0,0) canvas.setFont('Liberation', 12) canvas.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+7, "Visiteur") canvas.restoreState() return canvas def Ribbon45(DispUser, canvas): canvas.saveState() canvas.rotate(45) offset_u=0 if DispUser.Staff: # Staff canvas.setFillColorRGB(1,.2,.2) canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1) canvas.setFillColorRGB(1,1,1) canvas.setFont('Liberation', 20) canvas.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+5, "STAFF") elif DispUser.is_Intervenant: # Intervenant canvas.setFillColorRGB(.3,.3,1) canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1) canvas.setFillColorRGB(1,1,1) canvas.setFont('Liberation', 15) canvas.drawCentredString(WIDTH/2-15, HEIGHT/2-offset_u+10, "Intervenant") else: # Visiteur canvas.setFillColorRGB(.8,.8,.8) canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1) canvas.setFillColorRGB(0,0,0) canvas.setFont('Liberation', 12) canvas.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+7, "Visiteur") canvas.restoreState() return canvas def Ribbon90(DispUser, canvas): canvas.saveState() canvas.rotate(90) offset_u=0 if DispUser.Staff: # Staff canvas.setFillColorRGB(1,.2,.2) canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1) canvas.setFillColorRGB(1,1,1) canvas.setFont('Liberation', 20) canvas.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+5, "STAFF") elif DispUser.is_Intervenant: # Intervenant canvas.setFillColorRGB(.3,.3,1) canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1) canvas.setFillColorRGB(1,1,1) canvas.setFont('Liberation', 15) canvas.drawCentredString(WIDTH/2-15, HEIGHT/2-offset_u+10, "Intervenant") else: # Visiteur canvas.setFillColorRGB(.8,.8,.8) canvas.rect(0, HEIGHT/2-offset_u, WIDTH, 10*mm, fill=1) canvas.setFillColorRGB(0,0,0) canvas.setFont('Liberation', 12) canvas.drawCentredString(WIDTH/2-10, HEIGHT/2-offset_u+7, "Visiteur") canvas.restoreState() return canvas 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("2 0 1 5") 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' )