import io import zipfile import qrcode import pandas as pd from flask import Blueprint, render_template, request, send_file, flash, redirect, url_for from PIL import Image, ImageDraw, ImageFont from blueprints.auth import login_required from rechten import recht_vereist # Zorg dat dit pad klopt naar je auth_utils.py # definieren blueprint qr_code_bp = Blueprint('qr_generator', __name__, template_folder='templates') def generate_qr_images(excel_file, show_top, show_bottom): # Overslaan van de header rij df = pd.read_excel(excel_file, header=0) zip_buffer = io.BytesIO() try: # Try loading your local or system Arial font font = ImageFont.truetype("arial.ttf", 20) except IOError: try: font = ImageFont.load_default_font(size=20) except AttributeError: # Absolute fallback if Pillow is outdated, but textbbox WILL fail if this hits font = ImageFont.load_default() with zipfile.ZipFile(zip_buffer, "a", zipfile.ZIP_DEFLATED) as zip_file: for index, row in df.iterrows(): # Gebruik .iloc voor veiligheid tegen kolomnamen qr_text = str(row.iloc[0]) if not pd.isna(row.iloc[0]) else "" top_text = str(row.iloc[1]) if not pd.isna(row.iloc[1]) else "" bottom_text = str(row.iloc[2]) if not pd.isna(row.iloc[2]) else "" if qr_text.strip() == "": continue qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_H) qr.add_data(qr_text) qr.make(fit=True) qr_img = qr.make_image(fill_color="black", back_color="white").convert("RGB") qr_width, qr_height = qr_img.size padding = 40 total_height = qr_height + (2 * padding) canvas = Image.new("RGB", (qr_width + 40, total_height + 40), "white") draw = ImageDraw.Draw(canvas) qr_x = (canvas.width - qr_width) // 2 qr_y = padding canvas.paste(qr_img, (qr_x, qr_y)) if show_top and top_text: bbox = draw.textbbox((0, 0), top_text, font=font) text_w = bbox[2] - bbox[0] draw.text(((canvas.width - text_w) / 2, 5), top_text, fill="black", font=font) if show_bottom and bottom_text: bbox = draw.textbbox((0, 0), bottom_text, font=font) text_w = bbox[2] - bbox[0] draw.text(((canvas.width - text_w) / 2, qr_y + qr_height + 5), bottom_text, fill="black", font=font) img_io = io.BytesIO() canvas.save(img_io, 'PNG') img_io.seek(0) zip_file.writestr(f"qr_{index+1}.png", img_io.getvalue()) zip_buffer.seek(0) return zip_buffer @qr_code_bp.route('/') @login_required @recht_vereist('qr_codes') def qr_generator(): return render_template('qr_code.html') @qr_code_bp.route('/download-template') @login_required @recht_vereist('qr_codes') def download_template(): df = pd.DataFrame(columns=["QR-Code (Link/ID)", "Koptekst", "Voettekst"]) buffer = io.BytesIO() with pd.ExcelWriter(buffer, engine='openpyxl') as writer: df.to_excel(writer, index=False) buffer.seek(0) return send_file( buffer, as_attachment=True, download_name='sjabloon_qr.xlsx', mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ) @qr_code_bp.route('/upload', methods=['POST']) @login_required @recht_vereist('qr_codes') def upload_file(): if 'file' not in request.files: flash("Geen bestand geselecteerd", "warning") return redirect(url_for('qr_generator.qr_generator')) file = request.files['file'] show_top = request.form.get('show_top') == 'on' show_bottom = request.form.get('show_bottom') == 'on' if file and file.filename != '': try: zip_data = generate_qr_images(file, show_top, show_bottom) return send_file( zip_data, mimetype='application/zip', as_attachment=True, download_name='qr_codes.zip' ) except Exception as e: flash(f"Fout bij verwerken: {str(e)}", "danger") return redirect(url_for('qr_generator.qr_generator')) return redirect(url_for('qr_generator.qr_generator'))