mirror of
https://github.com/AxonByteDev/paperless-asn-label-generator.git
synced 2026-08-06 08:42:03 +00:00
add start-position printing, post-open options, subprocess opener, exact A4 sheet mode (v0.1.5)
This commit is contained in:
parent
ae067c5d92
commit
4c669debb5
4 changed files with 103 additions and 25 deletions
|
|
@ -1,5 +1,12 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.1.5 - 2026-02-08
|
||||||
|
### Changed
|
||||||
|
- Startposition auf angebrochenem Bogen ist jetzt einstellbar (`1..189`), inklusive korrekter Seitenberechnung und Druckplatzierung.
|
||||||
|
- Option nach PDF-Erzeugung eingeführt: `none`, `file` oder `folder` direkt öffnen.
|
||||||
|
- Ordner/Datei-Öffnen ist plattformstabil über `subprocess` umgesetzt (ohne `os.system`), auch bei Sonderzeichen im Pfad.
|
||||||
|
- Im Modus `A4 Blätter` wird jetzt exakt die gewählte Blattanzahl erzeugt (erstes Blatt ab Startposition auffüllen, kein zusätzlich angebrochenes Folgeblatt).
|
||||||
|
|
||||||
## 0.1.4 - 2026-02-08
|
## 0.1.4 - 2026-02-08
|
||||||
### Changed
|
### Changed
|
||||||
- Vorschau für `CODE128` rendert jetzt als echter Barcode statt Platzhalter.
|
- Vorschau für `CODE128` rendert jetzt als echter Barcode statt Platzhalter.
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "paperless-asn-label-generator"
|
name = "paperless-asn-label-generator"
|
||||||
version = "0.1.4"
|
version = "0.1.5"
|
||||||
description = "GUI tool to generate ASN barcode/QR labels for paperless-ngx (A4/Avery L4731) with calibration."
|
description = "GUI tool to generate ASN barcode/QR labels for paperless-ngx (A4/Avery L4731) with calibration."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
__all__ = ["__version__"]
|
__all__ = ["__version__"]
|
||||||
__version__ = "0.1.4"
|
__version__ = "0.1.5"
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import math
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
|
import subprocess
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
@ -209,6 +210,7 @@ def generate_pdf(
|
||||||
offset_y_mm: float = 0.0, # + moves up
|
offset_y_mm: float = 0.0, # + moves up
|
||||||
pitch_dx_mm: float = 0.0, # added to pitch_x (distance between columns)
|
pitch_dx_mm: float = 0.0, # added to pitch_x (distance between columns)
|
||||||
pitch_dy_mm: float = 0.0, # added to pitch_y (distance between rows)
|
pitch_dy_mm: float = 0.0, # added to pitch_y (distance between rows)
|
||||||
|
start_position: int = 1, # 1..labels_per_page (first label slot on first page)
|
||||||
) -> Tuple[int, int]:
|
) -> Tuple[int, int]:
|
||||||
"""
|
"""
|
||||||
Returns: (pages_generated, next_number)
|
Returns: (pages_generated, next_number)
|
||||||
|
|
@ -221,10 +223,14 @@ def generate_pdf(
|
||||||
raise ValueError("leading_zeros must be >= 0")
|
raise ValueError("leading_zeros must be >= 0")
|
||||||
if not prefix:
|
if not prefix:
|
||||||
raise ValueError("prefix must not be empty")
|
raise ValueError("prefix must not be empty")
|
||||||
|
labels_per_page = layout.labels_per_page
|
||||||
|
if not (1 <= start_position <= labels_per_page):
|
||||||
|
raise ValueError(f"start_position must be between 1 and {labels_per_page}")
|
||||||
|
|
||||||
_page_w, page_h = A4
|
_page_w, page_h = A4
|
||||||
labels_per_page = layout.labels_per_page
|
first_page_capacity = labels_per_page - (start_position - 1)
|
||||||
pages = math.ceil(count / labels_per_page)
|
remaining_after_first = max(0, count - first_page_capacity)
|
||||||
|
pages = 1 + math.ceil(remaining_after_first / labels_per_page)
|
||||||
|
|
||||||
# Effective pitch + offsets (points)
|
# Effective pitch + offsets (points)
|
||||||
pitch_x = layout.pitch_x + (pitch_dx_mm * mm)
|
pitch_x = layout.pitch_x + (pitch_dx_mm * mm)
|
||||||
|
|
@ -237,12 +243,16 @@ def generate_pdf(
|
||||||
current = start_number
|
current = start_number
|
||||||
remaining = count
|
remaining = count
|
||||||
|
|
||||||
for _ in range(pages):
|
for page_idx in range(pages):
|
||||||
n_this_page = min(remaining, labels_per_page)
|
first_slot = start_position if page_idx == 0 else 1
|
||||||
|
first_slot_zero_based = first_slot - 1
|
||||||
|
slots_available = labels_per_page - first_slot_zero_based
|
||||||
|
n_this_page = min(remaining, slots_available)
|
||||||
|
|
||||||
for i in range(n_this_page):
|
for i in range(n_this_page):
|
||||||
r = i // layout.cols
|
slot = first_slot_zero_based + i
|
||||||
col = i % layout.cols
|
r = slot // layout.cols
|
||||||
|
col = slot % layout.cols
|
||||||
|
|
||||||
x = layout.margin_left + col * pitch_x + off_x
|
x = layout.margin_left + col * pitch_x + off_x
|
||||||
y = page_h - layout.margin_top - layout.label_h - r * pitch_y + off_y
|
y = page_h - layout.margin_top - layout.label_h - r * pitch_y + off_y
|
||||||
|
|
@ -252,8 +262,9 @@ def generate_pdf(
|
||||||
|
|
||||||
current += 1
|
current += 1
|
||||||
|
|
||||||
c.showPage()
|
|
||||||
remaining -= n_this_page
|
remaining -= n_this_page
|
||||||
|
if page_idx < pages - 1:
|
||||||
|
c.showPage()
|
||||||
|
|
||||||
c.save()
|
c.save()
|
||||||
return pages, current
|
return pages, current
|
||||||
|
|
@ -263,9 +274,11 @@ DEFAULT_SETTINGS = {
|
||||||
"mode": "labels",
|
"mode": "labels",
|
||||||
"count": str(AVERY_L4731.labels_per_page),
|
"count": str(AVERY_L4731.labels_per_page),
|
||||||
"pages": "1",
|
"pages": "1",
|
||||||
|
"start_pos": "1",
|
||||||
"prefix": "ASN",
|
"prefix": "ASN",
|
||||||
"zeros": "7",
|
"zeros": "7",
|
||||||
"kind": "QR",
|
"kind": "QR",
|
||||||
|
"post_open": "none",
|
||||||
"border": False,
|
"border": False,
|
||||||
# neutrale Kalibrierung für frische Installationen
|
# neutrale Kalibrierung für frische Installationen
|
||||||
"off_x": "0.0",
|
"off_x": "0.0",
|
||||||
|
|
@ -291,9 +304,11 @@ class App(ttk.Frame):
|
||||||
self.var_mode = tk.StringVar(value=DEFAULT_SETTINGS["mode"])
|
self.var_mode = tk.StringVar(value=DEFAULT_SETTINGS["mode"])
|
||||||
self.var_count = tk.StringVar(value=DEFAULT_SETTINGS["count"])
|
self.var_count = tk.StringVar(value=DEFAULT_SETTINGS["count"])
|
||||||
self.var_pages = tk.StringVar(value=DEFAULT_SETTINGS["pages"])
|
self.var_pages = tk.StringVar(value=DEFAULT_SETTINGS["pages"])
|
||||||
|
self.var_start_pos = tk.StringVar(value=DEFAULT_SETTINGS["start_pos"])
|
||||||
self.var_prefix = tk.StringVar(value=DEFAULT_SETTINGS["prefix"])
|
self.var_prefix = tk.StringVar(value=DEFAULT_SETTINGS["prefix"])
|
||||||
self.var_zeros = tk.StringVar(value=DEFAULT_SETTINGS["zeros"])
|
self.var_zeros = tk.StringVar(value=DEFAULT_SETTINGS["zeros"])
|
||||||
self.var_kind = tk.StringVar(value=DEFAULT_SETTINGS["kind"])
|
self.var_kind = tk.StringVar(value=DEFAULT_SETTINGS["kind"])
|
||||||
|
self.var_post_open = tk.StringVar(value=DEFAULT_SETTINGS["post_open"])
|
||||||
self.var_border = tk.BooleanVar(value=DEFAULT_SETTINGS["border"])
|
self.var_border = tk.BooleanVar(value=DEFAULT_SETTINGS["border"])
|
||||||
self.var_off_x = tk.StringVar(value=DEFAULT_SETTINGS["off_x"])
|
self.var_off_x = tk.StringVar(value=DEFAULT_SETTINGS["off_x"])
|
||||||
self.var_off_y = tk.StringVar(value=DEFAULT_SETTINGS["off_y"])
|
self.var_off_y = tk.StringVar(value=DEFAULT_SETTINGS["off_y"])
|
||||||
|
|
@ -345,9 +360,11 @@ class App(ttk.Frame):
|
||||||
"mode": self.var_mode.get(),
|
"mode": self.var_mode.get(),
|
||||||
"count": self.var_count.get(),
|
"count": self.var_count.get(),
|
||||||
"pages": self.var_pages.get(),
|
"pages": self.var_pages.get(),
|
||||||
|
"start_pos": self.var_start_pos.get(),
|
||||||
"prefix": self.var_prefix.get(),
|
"prefix": self.var_prefix.get(),
|
||||||
"zeros": self.var_zeros.get(),
|
"zeros": self.var_zeros.get(),
|
||||||
"kind": self.var_kind.get(),
|
"kind": self.var_kind.get(),
|
||||||
|
"post_open": self.var_post_open.get(),
|
||||||
"border": bool(self.var_border.get()),
|
"border": bool(self.var_border.get()),
|
||||||
"off_x": self.var_off_x.get(),
|
"off_x": self.var_off_x.get(),
|
||||||
"off_y": self.var_off_y.get(),
|
"off_y": self.var_off_y.get(),
|
||||||
|
|
@ -382,9 +399,11 @@ class App(ttk.Frame):
|
||||||
if "mode" in d: self.var_mode.set(str(d["mode"]))
|
if "mode" in d: self.var_mode.set(str(d["mode"]))
|
||||||
if "count" in d: self.var_count.set(str(d["count"]))
|
if "count" in d: self.var_count.set(str(d["count"]))
|
||||||
if "pages" in d: self.var_pages.set(str(d["pages"]))
|
if "pages" in d: self.var_pages.set(str(d["pages"]))
|
||||||
|
if "start_pos" in d: self.var_start_pos.set(str(d["start_pos"]))
|
||||||
if "prefix" in d: self.var_prefix.set(str(d["prefix"]))
|
if "prefix" in d: self.var_prefix.set(str(d["prefix"]))
|
||||||
if "zeros" in d: self.var_zeros.set(str(d["zeros"]))
|
if "zeros" in d: self.var_zeros.set(str(d["zeros"]))
|
||||||
if "kind" in d: self.var_kind.set(str(d["kind"]))
|
if "kind" in d: self.var_kind.set(str(d["kind"]))
|
||||||
|
if "post_open" in d: self.var_post_open.set(str(d["post_open"]))
|
||||||
if "border" in d: self.var_border.set(bool(d["border"]))
|
if "border" in d: self.var_border.set(bool(d["border"]))
|
||||||
set_calibration_var("off_x", self.var_off_x)
|
set_calibration_var("off_x", self.var_off_x)
|
||||||
set_calibration_var("off_y", self.var_off_y)
|
set_calibration_var("off_y", self.var_off_y)
|
||||||
|
|
@ -437,9 +456,11 @@ class App(ttk.Frame):
|
||||||
self.var_mode,
|
self.var_mode,
|
||||||
self.var_count,
|
self.var_count,
|
||||||
self.var_pages,
|
self.var_pages,
|
||||||
|
self.var_start_pos,
|
||||||
self.var_prefix,
|
self.var_prefix,
|
||||||
self.var_zeros,
|
self.var_zeros,
|
||||||
self.var_kind,
|
self.var_kind,
|
||||||
|
self.var_post_open,
|
||||||
self.var_border,
|
self.var_border,
|
||||||
self.var_off_x,
|
self.var_off_x,
|
||||||
self.var_off_y,
|
self.var_off_y,
|
||||||
|
|
@ -488,20 +509,21 @@ class App(ttk.Frame):
|
||||||
|
|
||||||
add_row("Anzahl Labels", self.var_count, 2, f"{AVERY_L4731.labels_per_page} Labels pro A4-Seite", store="count")
|
add_row("Anzahl Labels", self.var_count, 2, f"{AVERY_L4731.labels_per_page} Labels pro A4-Seite", store="count")
|
||||||
add_row("Anzahl A4 Blätter", self.var_pages, 3, "z.B. 3 → erzeugt 3 Seiten", store="pages")
|
add_row("Anzahl A4 Blätter", self.var_pages, 3, "z.B. 3 → erzeugt 3 Seiten", store="pages")
|
||||||
|
add_row("Startposition auf Bogen", self.var_start_pos, 4, f"1..{AVERY_L4731.labels_per_page} (z.B. 37 bei angebrochenem Bogen)")
|
||||||
|
|
||||||
add_row("Prefix", self.var_prefix, 4, "Muss zu PAPERLESS_CONSUMER_ASN_BARCODE_PREFIX passen")
|
add_row("Prefix", self.var_prefix, 5, "Muss zu PAPERLESS_CONSUMER_ASN_BARCODE_PREFIX passen")
|
||||||
add_row("Führende Nullen", self.var_zeros, 5, "z.B. 5 → ASN00001")
|
add_row("Führende Nullen", self.var_zeros, 6, "z.B. 5 → ASN00001")
|
||||||
|
|
||||||
ttk.Label(frm, text="Code-Typ").grid(row=6, column=0, sticky="w", padx=(10, 6), pady=6)
|
ttk.Label(frm, text="Code-Typ").grid(row=7, column=0, sticky="w", padx=(10, 6), pady=6)
|
||||||
cmb = ttk.Combobox(frm, textvariable=self.var_kind, values=["QR", "CODE128"], state="readonly", width=12)
|
cmb = ttk.Combobox(frm, textvariable=self.var_kind, values=["QR", "CODE128"], state="readonly", width=12)
|
||||||
cmb.grid(row=6, column=1, sticky="w", padx=(0, 10), pady=6)
|
cmb.grid(row=7, column=1, sticky="w", padx=(0, 10), pady=6)
|
||||||
cmb.bind("<<ComboboxSelected>>", lambda _e: self._update_preview())
|
cmb.bind("<<ComboboxSelected>>", lambda _e: self._update_preview())
|
||||||
|
|
||||||
chk = ttk.Checkbutton(frm, text="Rahmen um Labels zeichnen (Kalibrierung)", variable=self.var_border, command=self._update_preview)
|
chk = ttk.Checkbutton(frm, text="Rahmen um Labels zeichnen (Kalibrierung)", variable=self.var_border, command=self._update_preview)
|
||||||
chk.grid(row=6, column=2, columnspan=2, sticky="w", padx=(0, 10), pady=6)
|
chk.grid(row=7, column=2, columnspan=2, sticky="w", padx=(0, 10), pady=6)
|
||||||
|
|
||||||
cal = ttk.LabelFrame(frm, text="Kalibrierung (mm)")
|
cal = ttk.LabelFrame(frm, text="Kalibrierung (mm)")
|
||||||
cal.grid(row=7, column=0, columnspan=4, sticky="we", padx=10, pady=(10, 6))
|
cal.grid(row=8, column=0, columnspan=4, sticky="we", padx=10, pady=(10, 6))
|
||||||
for i in range(6):
|
for i in range(6):
|
||||||
cal.columnconfigure(i, weight=1)
|
cal.columnconfigure(i, weight=1)
|
||||||
|
|
||||||
|
|
@ -553,6 +575,15 @@ class App(ttk.Frame):
|
||||||
ttk.Button(btns, text="Config löschen", command=self.on_reset_config).grid(
|
ttk.Button(btns, text="Config löschen", command=self.on_reset_config).grid(
|
||||||
row=1, column=0, columnspan=2, sticky="we", pady=(6, 0)
|
row=1, column=0, columnspan=2, sticky="we", pady=(6, 0)
|
||||||
)
|
)
|
||||||
|
ttk.Label(btns, text="Nach PDF öffnen").grid(row=2, column=0, sticky="w", pady=(8, 0))
|
||||||
|
cmb_open = ttk.Combobox(
|
||||||
|
btns,
|
||||||
|
textvariable=self.var_post_open,
|
||||||
|
values=["none", "file", "folder"],
|
||||||
|
state="readonly",
|
||||||
|
width=12,
|
||||||
|
)
|
||||||
|
cmb_open.grid(row=2, column=1, sticky="e", pady=(8, 0))
|
||||||
|
|
||||||
self.lbl_status = ttk.Label(self, text="", foreground=STATUS_COLORS["info"], wraplength=900, justify="left")
|
self.lbl_status = ttk.Label(self, text="", foreground=STATUS_COLORS["info"], wraplength=900, justify="left")
|
||||||
self.lbl_status.grid(row=1, column=0, columnspan=2, sticky="we", pady=(10, 0))
|
self.lbl_status.grid(row=1, column=0, columnspan=2, sticky="we", pady=(10, 0))
|
||||||
|
|
@ -612,19 +643,34 @@ class App(ttk.Frame):
|
||||||
except Exception:
|
except Exception:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def _start_position(self) -> int:
|
||||||
|
pos = self._parse_int(self.var_start_pos.get(), "Startposition auf Bogen")
|
||||||
|
if not (1 <= pos <= AVERY_L4731.labels_per_page):
|
||||||
|
raise ValueError(f"Startposition auf Bogen muss zwischen 1 und {AVERY_L4731.labels_per_page} liegen.")
|
||||||
|
return pos
|
||||||
|
|
||||||
|
def _pages_for_count(self, count: int, start_position: int) -> int:
|
||||||
|
first_page_capacity = AVERY_L4731.labels_per_page - (start_position - 1)
|
||||||
|
remaining_after_first = max(0, count - first_page_capacity)
|
||||||
|
return 1 + math.ceil(remaining_after_first / AVERY_L4731.labels_per_page)
|
||||||
|
|
||||||
def _effective_count_and_pages(self) -> tuple[int, int]:
|
def _effective_count_and_pages(self) -> tuple[int, int]:
|
||||||
|
start_position = self._start_position()
|
||||||
mode = self.var_mode.get()
|
mode = self.var_mode.get()
|
||||||
if mode == "pages":
|
if mode == "pages":
|
||||||
pages = self._parse_int(self.var_pages.get(), "Anzahl A4 Blätter")
|
pages = self._parse_int(self.var_pages.get(), "Anzahl A4 Blätter")
|
||||||
if pages <= 0:
|
if pages <= 0:
|
||||||
raise ValueError("Anzahl A4 Blätter muss > 0 sein.")
|
raise ValueError("Anzahl A4 Blätter muss > 0 sein.")
|
||||||
count = pages * AVERY_L4731.labels_per_page
|
first_page_capacity = AVERY_L4731.labels_per_page - (start_position - 1)
|
||||||
|
# Im Seitenmodus exakt N Blätter erzeugen:
|
||||||
|
# erstes Blatt ab Startposition auffüllen, danach volle Blätter.
|
||||||
|
count = first_page_capacity + (pages - 1) * AVERY_L4731.labels_per_page
|
||||||
return count, pages
|
return count, pages
|
||||||
else:
|
else:
|
||||||
count = self._parse_int(self.var_count.get(), "Anzahl Labels")
|
count = self._parse_int(self.var_count.get(), "Anzahl Labels")
|
||||||
if count <= 0:
|
if count <= 0:
|
||||||
raise ValueError("Anzahl Labels muss > 0 sein.")
|
raise ValueError("Anzahl Labels muss > 0 sein.")
|
||||||
pages = math.ceil(count / AVERY_L4731.labels_per_page)
|
pages = self._pages_for_count(count, start_position)
|
||||||
return count, pages
|
return count, pages
|
||||||
|
|
||||||
def _current_text(self) -> str:
|
def _current_text(self) -> str:
|
||||||
|
|
@ -664,11 +710,12 @@ class App(ttk.Frame):
|
||||||
self.preview.configure(image=self._preview_imgtk)
|
self.preview.configure(image=self._preview_imgtk)
|
||||||
|
|
||||||
count, pages = self._effective_count_and_pages()
|
count, pages = self._effective_count_and_pages()
|
||||||
|
start_pos = self._start_position()
|
||||||
off_x_delta, off_y_delta, pdx_delta, pdy_delta = self._calibration_delta()
|
off_x_delta, off_y_delta, pdx_delta, pdy_delta = self._calibration_delta()
|
||||||
off_x, off_y, pdx, pdy = self._calibration()
|
off_x, off_y, pdx, pdy = self._calibration()
|
||||||
self._set_status(
|
self._set_status(
|
||||||
(
|
(
|
||||||
f"Beispiel: {text} | {count} Labels ≈ {pages} Seiten"
|
f"Beispiel: {text} | {count} Labels | Startposition {start_pos} | Ausgabe {pages} Seiten"
|
||||||
f" | Eingabe Offset({off_x_delta},{off_y_delta})mm PitchΔ({pdx_delta},{pdy_delta})mm"
|
f" | Eingabe Offset({off_x_delta},{off_y_delta})mm PitchΔ({pdx_delta},{pdy_delta})mm"
|
||||||
f" | Effektiv Offset({off_x},{off_y})mm PitchΔ({pdx},{pdy})mm"
|
f" | Effektiv Offset({off_x},{off_y})mm PitchΔ({pdx},{pdy})mm"
|
||||||
),
|
),
|
||||||
|
|
@ -725,6 +772,7 @@ class App(ttk.Frame):
|
||||||
raise ValueError("Prefix darf nicht leer sein.")
|
raise ValueError("Prefix darf nicht leer sein.")
|
||||||
|
|
||||||
count, _pages = self._effective_count_and_pages()
|
count, _pages = self._effective_count_and_pages()
|
||||||
|
start_pos = self._start_position()
|
||||||
kind: BarcodeKind = "QR" if self.var_kind.get() == "QR" else "CODE128"
|
kind: BarcodeKind = "QR" if self.var_kind.get() == "QR" else "CODE128"
|
||||||
off_x, off_y, pdx, pdy = self._calibration()
|
off_x, off_y, pdx, pdy = self._calibration()
|
||||||
|
|
||||||
|
|
@ -751,27 +799,50 @@ class App(ttk.Frame):
|
||||||
offset_y_mm=off_y,
|
offset_y_mm=off_y,
|
||||||
pitch_dx_mm=pdx,
|
pitch_dx_mm=pdx,
|
||||||
pitch_dy_mm=pdy,
|
pitch_dy_mm=pdy,
|
||||||
|
start_position=start_pos,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.var_start.set(str(next_number))
|
self.var_start.set(str(next_number))
|
||||||
self._update_preview()
|
self._update_preview()
|
||||||
self._set_status(
|
self._set_status(
|
||||||
f"PDF: {out} | Seiten: {pages_generated} | Labels: {count} | Nächster Start: {next_number}",
|
f"PDF: {out} | Seiten: {pages_generated} | Labels: {count} | Startposition: {start_pos} | Nächster Start: {next_number}",
|
||||||
"success",
|
"success",
|
||||||
)
|
)
|
||||||
|
try:
|
||||||
|
self._open_after_generate(out)
|
||||||
|
except Exception as e:
|
||||||
|
self._set_status(f"PDF erzeugt, aber Öffnen fehlgeschlagen: {e}", "warn")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._set_status(str(e), "error")
|
self._set_status(str(e), "error")
|
||||||
messagebox.showerror("Fehler", str(e))
|
messagebox.showerror("Fehler", str(e))
|
||||||
|
|
||||||
|
def _open_path(self, path: str) -> None:
|
||||||
|
if os.name == "nt":
|
||||||
|
os.startfile(path) # type: ignore[attr-defined]
|
||||||
|
return
|
||||||
|
if sys.platform == "darwin":
|
||||||
|
subprocess.Popen(["open", path], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
|
return
|
||||||
|
subprocess.Popen(["xdg-open", path], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
|
|
||||||
|
def _open_after_generate(self, output_pdf: str) -> None:
|
||||||
|
mode = self.var_post_open.get().strip().lower()
|
||||||
|
if mode == "none":
|
||||||
|
return
|
||||||
|
if mode == "file":
|
||||||
|
self._open_path(output_pdf)
|
||||||
|
return
|
||||||
|
if mode == "folder":
|
||||||
|
self._open_path(str(Path(output_pdf).resolve().parent))
|
||||||
|
return
|
||||||
|
raise ValueError(f"Ungültige Nach-PDF-Option: {mode}")
|
||||||
|
|
||||||
def on_open_folder(self) -> None:
|
def on_open_folder(self) -> None:
|
||||||
folder = os.getcwd()
|
folder = os.getcwd()
|
||||||
try:
|
try:
|
||||||
if os.name == "nt":
|
self._open_path(folder)
|
||||||
os.startfile(folder) # type: ignore[attr-defined]
|
except Exception as e:
|
||||||
elif os.name == "posix":
|
self._set_status(f"Ordner konnte nicht geöffnet werden: {e}", "warn")
|
||||||
cmd = "open" if sys.platform == "darwin" else "xdg-open"
|
|
||||||
os.system(f'{cmd} "{folder}"')
|
|
||||||
except Exception:
|
|
||||||
messagebox.showinfo("Info", f"Ordner: {folder}")
|
messagebox.showinfo("Info", f"Ordner: {folder}")
|
||||||
|
|
||||||
def on_reset_config(self) -> None:
|
def on_reset_config(self) -> None:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue