Source code for fpiweb.qr_code_utilities


from io import BytesIO
from logging import getLogger

from pyqrcode import create as create_qrcode

import qrcode.image.svg

from reportlab.pdfgen.canvas import Canvas
from reportlab.lib.pagesizes import letter

from fpiweb.models import Box


logger = getLogger('fpiweb')

# Combined path factory, fixes white space that may occur when zooming
factory = qrcode.image.svg.SvgPathImage


[docs]def get_qr_code_svg(data_string, include_xml_declaration=False): img = qrcode.make(data_string, image_factory=factory) with BytesIO() as bytes_out: img.save(bytes_out, kind='SVG') some_bytes = bytes_out.getvalue() svg = some_bytes.decode('utf-8') if not include_xml_declaration: svg = svg.split('?>\n')[-1] return svg
[docs]class QRCodePrinter(object): def __init__(self, url_prefix): self.url_prefix = url_prefix self.pdf: Canvas width, height = letter self.width: int = width self.height: int = height self.next_pos = 0
[docs] def initialize_pdf_file(self, buffer): """ Prepare to scribble on a new pdf file. :param buffer: May be a string with a filename or a BytesIO or other File-like object """ self.pdf: Canvas(buffer, pagesize=letter)
[docs] @staticmethod def get_box_numbers(start, count) -> (str, int): next_box_number = start available_count = 0 while available_count < count: box_label = f'BOX{next_box_number:05}' logger.debug(f'Attempting to get {box_label}') if Box.objects.filter(box_number=box_label).exists(): next_box_number += 1 continue available_count += 1 logger.debug(f'{box_label} not found - using for label') yield box_label, next_box_number next_box_number += 1
[docs] def get_next_box_url(self, starting_number, count) -> (str, str): """ Build the URL for the next box. :return: """ for label, box_number in self.get_box_numbers( starting_number, count ): logger.debug(f'Got {label}, {box_number}') url = f"{self.url_prefix}{box_number:05}" yield url, label
[docs] def get_next_qr_img(self, starting_number, count) -> (str, str): """ Build the QR image for the next box label. :return: a QR code image ready to print """ for url, label in self.get_next_box_url(starting_number, count): label_file_name = f'{label}.png' qr = create_qrcode(url) qr.png(label_file_name, scale=5) yield label_file_name, label
[docs] def fill_pdf_pages(self, starting_number, count): # # draw lines around the boxes that will be filled with labels # self.draw_boxes_on_page() # # self.pdf.setFillColorRGB(1, 0, 1) # # self.pdf.rect(2*inch, 2*inch, 2*inch, 2*inch, fill=1) for label_file, label_name in self.get_next_qr_img( starting_number, count ): logger.debug(f'Got {label_file}') if self.next_pos >= len(self.label_locations) - 1: self.finish_page() self.next_pos = 0 else: self.next_pos += 1 self.draw_bounding_box(self.next_pos) self.place_label(label_file, label_name, self.next_pos) self.finish_page()
[docs] @staticmethod def finalize_pdf_file(): pass
[docs] def print(self, starting_number, count, buffer): self.initialize_pdf_file(buffer) self.fill_pdf_pages(starting_number, count) self.finalize_pdf_file()