145 lines
4.3 KiB
Python
145 lines
4.3 KiB
Python
"""
|
|
Standalone PDF/obrázek náhled — spouští se jako subprocess z extract_patient_info.py.
|
|
Argumenty: preview_viewer.py <soubor> [--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=<cesta>
|
|
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()
|