Logo in der Statuszeile, Bau an einer Stelle, Startprobe fuer die EXE
Logo Das Programmlogo steht jetzt klein neben "powered by ravokk" - dort sitzt die Kennung des Werkzeugs, nicht die des Kunden. Eine eigene Kopfzeile hat dieses Programm nicht; oben sind die Reiter. bauen.py Der Weg von der Quelle zur Setup-Datei war eine Folge von Befehlen, die jemand von Hand eintippen musste. Wer einen Schritt vergisst, liefert eine Setup-Datei mit einer alten EXE aus - und sieht es ihr nicht an. Genau das ist heute passiert. Jetzt ist es ein Befehl, die Nummer kommt aus version.py, und am Ende stehen die SHA256-Summen fuer den Release-Text. pruef_start_exe.py Prueft, was kein anderer Pruefstand prueft: ob die GEBAUTE EXE ein sichtbares Fenster zeigt. Alle uebrigen fahren das Programm aus der Quelle, dort trat der Fehler nie auf. "Der Prozess laeuft" beweist dabei nichts - er lief ja, waehrend nichts zu sehen war. Aufgeraeumt "Rechnung Campinghof.exe" ist weg; gebaute Dateien gehoeren ins Release, nicht ins Repo. Die .spec-Dateien dagegen schon: ohne sie kann niemand die EXE nachbauen, die der Updater ausliefert. Fassung 1.7.0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
This commit is contained in:
parent
fec0e8449c
commit
73042b771c
20 changed files with 1445 additions and 14 deletions
64
app.py
64
app.py
|
|
@ -32,6 +32,7 @@ import config
|
|||
import berechnung
|
||||
import gemeinsam
|
||||
import hinweis
|
||||
import wasserzeichen
|
||||
import ordnerwahl
|
||||
import pdf_renderer
|
||||
from helfer import ANREDEN, kunde_maengel, parse_date, parse_num, saeubern, safe_filename, ziffern
|
||||
|
|
@ -63,6 +64,7 @@ class RechnungsApp(ThemeMixin, MeldungMixin, KorrekturMixin, EinstellungenMixin,
|
|||
super().__init__()
|
||||
self.cfg = config.load_config()
|
||||
self.title(config.PROGRAMM)
|
||||
self._fenstersymbol()
|
||||
# Fensterhoehe an den Bildschirm anpassen, damit nichts unter den Rand rutscht
|
||||
hoehe = max(560, min(840, self.winfo_screenheight() - 90))
|
||||
self.geometry(f"1060x{hoehe}")
|
||||
|
|
@ -118,11 +120,12 @@ class RechnungsApp(ThemeMixin, MeldungMixin, KorrekturMixin, EinstellungenMixin,
|
|||
# es morgen ohne berichtigte Rechnung im Ordner und keiner weiss warum.
|
||||
self.protocol("WM_DELETE_WINDOW", self._beenden)
|
||||
|
||||
# after_idle statt after(0): laeuft, sobald Tk nichts mehr zu zeichnen hat -
|
||||
# also nachdem das Hauptfenster steht. Bei after(0) haengt der modale Dialog
|
||||
# an einem noch ungezeichneten Fenster und wirkt wie eingefroren; eine feste
|
||||
# Wartezeit dagegen erreicht ein Pruefstand nie, der keine Schleife dreht.
|
||||
self.after_idle(self._hinweis_pruefen)
|
||||
# Der Hinweis darf erst aufgehen, wenn das Hauptfenster WIRKLICH
|
||||
# gezeichnet ist. after_idle reicht dafuer nicht: in der gepackten
|
||||
# EXE ist das Fenster dann noch nicht sichtbar, der modale Dialog
|
||||
# sperrt es - und beide bleiben unsichtbar. Das sah aus wie ein
|
||||
# haengendes Programm (06.09.2026, am Installer aufgefallen).
|
||||
self.after(50, self._hinweis_wenn_sichtbar)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------- Menue
|
||||
|
|
@ -243,6 +246,11 @@ class RechnungsApp(ThemeMixin, MeldungMixin, KorrekturMixin, EinstellungenMixin,
|
|||
|
||||
self.flaeche = flaeche.Arbeitsflaeche(self, farben=self)
|
||||
self.flaeche.pack(side="top", fill="both", expand=True, padx=10, pady=(4, 0))
|
||||
# Das Wasserzeichen liegt HINTER der Arbeitsflaeche, unten rechts. Es
|
||||
# wird mit place() gesetzt, damit es die Anordnung der Kaesten nicht
|
||||
# anfasst - die darf der Benutzer ja selbst verschieben. lower() legt
|
||||
# es unter alles andere.
|
||||
self._wasserzeichen_setzen()
|
||||
|
||||
def _anordnen_umschalten(self):
|
||||
self.flaeche.anordnen_starten()
|
||||
|
|
@ -611,6 +619,12 @@ class RechnungsApp(ThemeMixin, MeldungMixin, KorrekturMixin, EinstellungenMixin,
|
|||
def _build_summen(self):
|
||||
# Statuszeile ganz unten
|
||||
status = ttk.Frame(self, padding=(12, 2))
|
||||
# Das Programmlogo neben der Marke - klein, immer sichtbar. Es steht
|
||||
# rechts bei "powered by ravokk", weil dort die Kennung des Werkzeugs
|
||||
# sitzt und nicht die des Kunden.
|
||||
self._kopf_bild = wasserzeichen.kopf(18, master=self)
|
||||
if self._kopf_bild is not None:
|
||||
ttk.Label(status, image=self._kopf_bild).pack(side="right", padx=(0, 6))
|
||||
status.pack(side="bottom", fill="x")
|
||||
ttk.Label(status, text=config.MARKE, foreground=self.col_muted,
|
||||
font=(theme.SCHRIFT_NAME, 8)).pack(side="right")
|
||||
|
|
@ -644,6 +658,40 @@ class RechnungsApp(ThemeMixin, MeldungMixin, KorrekturMixin, EinstellungenMixin,
|
|||
|
||||
# --------------------------------------------------- Gemeinsames Buch
|
||||
# ------------------------------------------------- Erprobungshinweis
|
||||
|
||||
def _wasserzeichen_setzen(self, groesse=240):
|
||||
"""Das Programmlogo blass hinter die Arbeitsflaeche legen."""
|
||||
bild = wasserzeichen.hole(groesse, 0.06, master=self)
|
||||
if bild is None:
|
||||
return
|
||||
# Die Referenz MUSS bleiben - sonst raeumt Python das Bild weg und Tk
|
||||
# zeigt eine leere Flaeche (der klassische PhotoImage-Fehler).
|
||||
self._wz_bild = bild
|
||||
self._wz = tk.Label(self.flaeche, image=bild, borderwidth=0,
|
||||
background=self.col_bg)
|
||||
self._wz.place(relx=1.0, rely=1.0, anchor='se', x=-12, y=-12)
|
||||
self._wz.lower()
|
||||
|
||||
def _fenstersymbol(self):
|
||||
"""Das Programmsymbol auf das Fenster legen."""
|
||||
return wasserzeichen.symbol_setzen(self)
|
||||
print("[symbol] assets/programm.ico nicht gefunden")
|
||||
return False
|
||||
|
||||
def _hinweis_wenn_sichtbar(self, versuche=0):
|
||||
"""Wartet, bis das Fenster gezeichnet ist, und fragt dann.
|
||||
|
||||
winfo_viewable() sagt, ob das Fenster tatsaechlich auf dem Schirm
|
||||
ist. Solange nicht, wird in kurzen Abstaenden nachgesehen. Nach
|
||||
rund zwei Sekunden wird trotzdem gefragt - im Pruefstand ist das
|
||||
Fenster absichtlich nicht sichtbar, und dort soll es trotzdem
|
||||
laufen.
|
||||
"""
|
||||
if not self.winfo_viewable() and versuche < 40:
|
||||
self.after(50, lambda: self._hinweis_wenn_sichtbar(versuche + 1))
|
||||
return
|
||||
self._hinweis_pruefen()
|
||||
|
||||
def _hinweis_pruefen(self):
|
||||
"""Hinweis auf die Erprobungsfassung. Ablehnen beendet das Programm.
|
||||
|
||||
|
|
@ -1821,7 +1869,11 @@ if __name__ == "__main__":
|
|||
if not fenster_nach_vorn(laufende_pid_lesen()):
|
||||
_r = tk.Tk()
|
||||
_r.withdraw()
|
||||
self.melden_fehler(
|
||||
# Hier gibt es kein self - das Fenster wird ja gerade NICHT gebaut.
|
||||
# Deshalb die schlichte Windows-Meldung statt des eigenen Dialogs.
|
||||
# (Frueher stand hier self.melden_fehler und ist beim Start eines
|
||||
# zweiten Fensters mit NameError abgestuerzt.)
|
||||
messagebox.showerror(
|
||||
"Rechnungstool läuft bereits",
|
||||
"""Das Rechnungstool ist schon geöffnet, das Fenster ließ sich
|
||||
aber nicht nach vorn holen - bitte über die Taskleiste zurückwechseln.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue