# -*- coding: utf8 -*- from pyramid.httpexceptions import HTTPNotFound, HTTPForbidden from pyramid.response import Response try: from StringIO import StringIO except ImportError: from io import StringIO import io 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)): off_x, off_y = Offset logo_object = canvas.beginText() logo_object.setFont('Logo', 32) logo_object.setFillColorRGB(.83, 0, .33) logo_object.setTextOrigin(off_x + 5, off_y + 17) logo_object.textLines("JM2L") canvas.drawText(logo_object) year_object = canvas.beginText() year_object.setFont("Helvetica-Bold", 10) year_object.setFillColorRGB(1, 1, 1) year_object.setTextRenderMode(0) year_object.setTextOrigin(off_x + 12, off_y + 35) year_object.setWordSpace(13) year_object.textLines(" ".join(str(CurrentYear))) canvas.drawText(year_object) def Tiers_Logo(canvas, DispUser, start_pos=None, Offset=(0, 0)): border = 0 off_x, off_y = Offset if start_pos is None: start_pos = (30 * mm, 2) start_x, start_y = start_pos max_x, max_y = 34 * mm, 18 * mm num = 0 canvas.setStrokeColorRGB(0.5, 0.5, 0.5) list_logos = list() for thumb in DispUser.tiers: if thumb.ThumbLinks: list_logos.append(thumb.ThumbLinks[:3]) # list_logos = list(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(start_x, start_y, max_x, max_y, radius=2, stroke=True) for tiers in list_logos: file_name = tiers.ThumbLinks.pop().split("/")[-1] image_path = "jm2l/upload/images/tiers/%s/%s" % (tiers.slug, file_name) pos_x = off_x + start_x + DicPos[len(list_logos)][num][0] * max_x - (ICONSIZE + border) / 2 pos_y = off_y + start_y + DicPos[len(list_logos)][num][1] * max_y - (ICONSIZE + border) / 2 canvas.setLineWidth(.1) if len(list_logos) > 1: size = ICONSIZE else: size = ICONSIZE * 1.5 canvas.drawImage(image_path, pos_x, pos_y, size, size, preserveAspectRatio=True, anchor='c', mask='auto' ) # draw icon border # canvas.roundRect(pos_x, pos_y, 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) off_x, off_y = Offset c.rect(off_x - 3, off_y - 3, WIDTH + 6, HEIGHT + 6, fill=0, stroke=1) if DispUser.Staff: # Staff c.setFillColorRGB(.83, 0, .33) c.rect(off_x - 3, off_y + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0) c.setFillColorRGB(1, 1, 1) c.setFont('Liberation', 30) c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT - 24, "STAFF") elif DispUser.is_Intervenant: # Intervenant c.setFillColorRGB(.21, .67, .78) c.rect(off_x - 3, off_y + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0) c.setFillColorRGB(1, 1, 1) c.setFont('Liberation', 30) c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT - 24, "Intervenant") elif DispUser.is_crew: # Benevole c.setFillColorRGB(.18, .76, .23) c.rect(off_x - 3, off_y + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0) c.setFillColorRGB(1, 1, 1) c.setFont('Liberation', 30) c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT - 24, "Bénévole") else: # Visiteur c.setFillColorRGB(.8, .8, .8) c.rect(off_x - 3, off_y + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0) c.setFillColorRGB(1, 1, 1) c.setFont('Liberation', 30) c.drawCentredString(off_x + WIDTH / 2, off_y + 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(off_x + WIDTH / 2, off_y + HEIGHT / 2 + 0 * mm, "%s" % DispUser.prenom) # c.setFont('Courier', 17) c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT / 2 - 8 * mm, "%s" % DispUser.nom) else: c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT / 2 + 4 * mm, "%s" % DispUser.prenom) # c.setFont('Courier', 17) c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT / 2 - 8 * mm, "%s" % DispUser.nom) else: c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT / 2 + 0 * mm, "%s %s" % (DispUser.prenom, DispUser.nom)) if DispUser.pseudo: c.setFont("Helvetica-Oblique", 18) c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT / 2 + 10 * mm, "%s" % DispUser.pseudo) #  Put QR code to user profile c.drawInlineImage(QRCode(DispUser), off_x + WIDTH - 20 * mm - 5, off_y + 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 ttf_file = "jm2l/static/fonts/LiberationMono-Regular.ttf" pdfmetrics.registerFont(TTFont("Liberation", ttf_file)) #  Import font ttf_file_logo = "jm2l/static/fonts/PWTinselLetters.ttf" pdfmetrics.registerFont(TTFont("Logo", ttf_file_logo)) pdf = io.BytesIO() out_img = io.BytesIO() 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) out_pdf = MediaPath().get_mediapath("badge", DispUser.uid, 'badge.pdf') c.showPage() c.save() pdf.seek(0) if isoutpng: out_png = MediaPath().get_mediapath("badge", DispUser.uid, 'badge.png') #  Let's generate a png file for website with open("./%s" % out_pdf, 'wb') as pdff: pdff.write(pdf.read()) Command = ["convert", "-density", "150x150", out_pdf, out_png] subprocess.call(Command) with open("./%s" % out_png, 'rb') as pngfile: out_img.write(pngfile.read()) # pngfile.read(), "utf8")) 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 ttf_file = "jm2l/static/fonts/LiberationMono-Regular.ttf" pdfmetrics.registerFont(TTFont("Liberation", ttf_file)) #  Import font ttf_file_logo = "jm2l/static/fonts/PWTinselLetters.ttf" pdfmetrics.registerFont(TTFont("Logo", ttf_file_logo)) pdf = io.BytesIO() 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 list_user = filter(lambda x: x.is_Intervenant or x.Staff or x.is_crew, Users) for num, disp_user in enumerate(list_user): c.saveState() offsets = (((num - t) % 2) * (WIDTH + 40) + 40, int(((num - t) / 2)) * (HEIGHT + 25) + 40) one_badge(c, disp_user, 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')