""" 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() # Zjisti cílovou šířku z layoutu (pokud existuje), jinak výchozí 700px try: import sys as _sys_tmp _sys_tmp.path.insert(0, str(Path(__file__).parent)) from window_layout import get_layout as _get_layout _lw = _get_layout().get("preview_viewer") RENDER_W = (_lw.get("w", 700) - 20) if _lw else 700 RENDER_H = (_lw.get("h", sh) - 80) if _lw else (sh - 150) except Exception: RENDER_W = 700 RENDER_H = sh - 150 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(RENDER_W / page.rect.width, RENDER_H / 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((RENDER_W, RENDER_H), 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.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() try: import sys as _sys _sys.path.insert(0, str(Path(__file__).parent)) from window_layout import get_layout, apply_geometry _layout = get_layout() def _fallback_prev(): sw = root.winfo_screenwidth() w = root.winfo_width() x = (sw - w) // 2 root.geometry(f"+{x}+0") apply_geometry(root, _layout, "preview_viewer", fallback_fn=_fallback_prev) except Exception: sw = root.winfo_screenwidth() w = root.winfo_width() 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]) root.update_idletasks() _x = root.winfo_x() _y = root.winfo_y() _w = root.winfo_width() _h = root.winfo_height() geom_path.write_text(_json.dumps({"x": _x, "y": _y, "w": _w, "h": _h}), encoding="utf-8") break root.lift() root.attributes("-topmost", True) root.after(1500, lambda: root.attributes("-topmost", False)) root.mainloop() if __name__ == "__main__": main()