""" Standalone PDF/obrázek náhled — spouští se jako subprocess z extract_patient_info.py. Argumenty: preview_viewer.py [--delete-on-close] """ import sys from pathlib import Path import tkinter as tk def main(): if len(sys.argv) < 2: sys.exit(1) pdf_path = Path(sys.argv[1]) delete_on_close = "--delete-on-close" in sys.argv try: from PIL import Image, ImageTk import fitz except ImportError as e: print(f"[preview_viewer] Chybí knihovna: {e}", file=sys.stderr) sys.exit(2) suffix = pdf_path.suffix.lower() if suffix in (".jpg", ".jpeg", ".png"): pil_img = Image.open(pdf_path) doc = None else: doc = fitz.open(str(pdf_path)) pil_img = None root = tk.Tk() root.tk.call("encoding", "system", "utf-8") sh = root.winfo_screenheight() page_count = len(doc) if doc else 1 current = [0] photo_ref = [None] def render(n) -> Image.Image: if doc is not None: page = doc[n] zoom = min(700 / page.rect.width, (sh - 150) / page.rect.height) pix = page.get_pixmap(matrix=fitz.Matrix(zoom, zoom)) return Image.frombytes("RGB", (pix.width, pix.height), pix.samples) else: img = pil_img.copy() img.thumbnail((700, sh - 150), Image.LANCZOS) return img def on_close(): if doc: try: doc.close() except Exception: pass if delete_on_close: try: pdf_path.unlink(missing_ok=True) except Exception: pass root.destroy() root.title(pdf_path.stem) root.attributes("-topmost", True) root.resizable(False, False) root.protocol("WM_DELETE_WINDOW", on_close) lbl_img = tk.Label(root) lbl_img.pack() frame_nav = tk.Frame(root) frame_nav.pack(pady=4) lbl_page = tk.Label(frame_nav, font=("Segoe UI", 9)) lbl_page.pack(side="left", padx=10) def show(n): current[0] = n img = render(n) photo_ref[0] = ImageTk.PhotoImage(img) lbl_img.config(image=photo_ref[0]) lbl_page.config(text=f"Strana {n + 1} / {page_count}") btn_prev.config(state="normal" if n > 0 else "disabled") btn_next.config(state="normal" if n < page_count - 1 else "disabled") btn_prev = tk.Button(frame_nav, text="◄ Předchozí", command=lambda: show(current[0] - 1)) btn_prev.pack(side="left") btn_next = tk.Button(frame_nav, text="Další ►", command=lambda: show(current[0] + 1)) btn_next.pack(side="left") show(0) root.update_idletasks() sw = root.winfo_screenwidth() w = root.winfo_width() h = root.winfo_height() x = (sw - w) // 2 root.geometry(f"+{x}+0") # Zapiš geometrii do souboru pokud byl předán argument --write-geometry= import json as _json for arg in sys.argv: if arg.startswith("--write-geometry="): geom_path = Path(arg.split("=", 1)[1]) geom_path.write_text(_json.dumps({"x": x, "y": 0, "w": w, "h": h}), encoding="utf-8") break root.lift() root.focus_force() root.after(100, lambda: root.focus_force()) root.mainloop() if __name__ == "__main__": main()