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()