Erprobungshinweis: erst wenn das Fenster steht, und nach vorn geholt

Sein Befund: "die software haengt nun am dialog popup" - und gleich darauf:
"haengen tut er nicht, nur deine pruefung; wenn ich auf aktiv druecke, geht es".

Zwei getrennte Fehler, beide meine:

1. Der Hinweis lief an after(0). Da ist das Hauptfenster noch nicht gezeichnet -
   ein modaler Dialog daran wirkt eingefroren. Eine feste Wartezeit (150 ms) war
   aber auch falsch: die erreicht ein Pruefstand nie, der keine Ereignisschleife
   dreht, und pruef_api lief danach in die Zeitgrenze. Jetzt after_idle: laeuft,
   sobald Tk nichts mehr zu zeichnen hat - fuer den Nutzer nach dem Zeichnen,
   fuer den Pruefstand beim ersten update().

2. Der Dialog kam nicht nach vorn. Ein Hinweis, den man erst suchen muss, taugt
   nichts. theme.py holt das Meldungsfenster jetzt nach vorn und nimmt den
   Tastaturfokus (lift, kurz topmost, focus_force).

In der Aufgabenliste vermerkt: Updater als Starter (Schritt 4, mit den zwei
fehlenden Voraussetzungen Versionsnummer und Sichtbarkeit der Repositories),
Pcore-Design im Steuerrechnungstool (Schritt 5), und der ALTFEHLER in
pruef_wache - schon vor den heutigen Arbeiten rot, die Statuszeile wird vom
Ergebnis des Einlesens ueberschrieben.

Alle 17 Pruefstaende des Rechnungstools gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
This commit is contained in:
TheMockTv 2026-09-06 16:24:43 +02:00
parent 4cdc286d5b
commit 05ec56e4b8
3 changed files with 74 additions and 4 deletions

View file

@ -65,6 +65,67 @@ Betriebsprüfung. Beide bleiben nebeneinander bestehen.
--- ---
## Schritt 4 — Updater als Starter ⬜ OFFEN
Sein Bild (06.09.2026): *„der updater schaut beim starten erst: ist auf dem git link eine neue
version mit exe? wenn ja, erst laden, ersetzen und dann starten."* Dazu: *„einmal prüfen auf
vollständigkeit."*
**Warum das der richtige Aufbau ist:** Der Updater ist das, was der Nutzer startet. Er läuft
**bevor** das Programm läuft — damit gibt es das übliche Problem gar nicht, dass eine laufende EXE
sich nicht selbst ersetzen kann.
**Ablauf:**
1. Beim Start die Release-Angaben vom Repository holen.
2. Ist die dortige Version neuer als die installierte → Datei in einen **Zwischenordner** laden.
3. **Vollständigkeit prüfen** — Größe und Prüfsumme gegen die Angabe des Releases. Erst wenn beides
stimmt, wird ersetzt. Ein halb geladener Download darf die Installation nie erreichen.
4. Alte Fassung als **Rückfallebene** behalten; scheitert der Start, zurücktauschen.
5. Programm starten.
**⚠️ Zwei Voraussetzungen fehlen noch:**
- **Es gibt keine Versionsnummer im Programm.** Ohne die kann kein Updater vergleichen. Muss zuerst
eingeführt werden — an einer Stelle, aus der auch die EXE-Metadaten und der Info-Dialog lesen.
- **Sind die Repositories öffentlich?** Wenn nicht, braucht der Updater einen Zugangstoken — und
ein Token, das in einer verteilten EXE steckt, ist kein Geheimnis mehr. Dann müssten die Releases
öffentlich sein oder über eine andere Stelle ausgeliefert werden.
**Und Andreas' Ansage zu den Releases:** *„die alten als experimental taggen, nicht als stabil —
weil die sind nicht stabil."*
---
## Schritt 5 — Pcore-Design im Steuerrechnungstool ⬜ OFFEN
Sein Wunsch: *„aber bitte mit unserm theme style."*
**Befund:** Das Steuerrechnungstool hat **kein `theme.py`**. Es benutzt nackte ttk-Widgets mit
Segoe UI. Das Rechnungstool hat das ganze Pcore/Ravokk-Design — Farben, Roboto, Glass-Buttons,
eigene Meldungsfenster (`MeldungMixin`), hell und dunkel.
**Zu tun:** `theme.py` herüberziehen und die Oberfläche darauf umstellen. Das ist ein eigener Bau,
kein Nebenbei — Menüs, Tabellen, Dialoge, Statusleiste. Vorher planen.
---
## ⚠️ Gefundener Altfehler — `pruef_wache` (Steuerrechnungstool) ⬜ OFFEN
**Nicht von den Arbeiten am 06.09.2026 verursacht** — bei der Ausgangsmessung vor dem Umbau bereits
rot, nur mit anderem Text.
`pruef_wache.py` erwartet nach einem Push des Rechnungstools in der Statuszeile den Hinweis
**„Rechnungstool meldet"**. Tatsächlich steht dort das Ergebnis des anschließenden Einlesens
(`0 neu, 0 aktualisiert, 1 unverändert`; bei der Ausgangsmessung: `Nummernbuch: 1 Nummern
eingetragen`). Das Einlesen **überschreibt die Meldung**, bevor der Nutzer sie lesen kann.
**Zu klären:** Ist das ein Fehler im Programm (die Meldung soll stehen bleiben, das Ergebnis
danebengehören) oder eine veraltete Erwartung im Prüfstand? Nicht nebenbei entscheiden — die
Statuszeile ist das Einzige, was dem Nutzer sagt, dass die andere Anwendung etwas gemeldet hat.
Folgefehler derselben Stelle: „dann kommt keine Meldung dazu".
---
## Reihenfolge ## Reihenfolge
Schritt 2 zuerst — er schließt eine Lücke in dem, was gerade gebaut wurde, und ist klein. Schritt 2 zuerst — er schließt eine Lücke in dem, was gerade gebaut wurde, und ist klein.

10
app.py
View file

@ -118,10 +118,11 @@ class RechnungsApp(ThemeMixin, MeldungMixin, KorrekturMixin, EinstellungenMixin,
# es morgen ohne berichtigte Rechnung im Ordner und keiner weiss warum. # es morgen ohne berichtigte Rechnung im Ordner und keiner weiss warum.
self.protocol("WM_DELETE_WINDOW", self._beenden) self.protocol("WM_DELETE_WINDOW", self._beenden)
# NICHTS laeuft an, bevor der Erprobungshinweis bestaetigt ist. Wer ihn # after_idle statt after(0): laeuft, sobald Tk nichts mehr zu zeichnen hat -
# ablehnt, soll gar nicht erst arbeiten koennen - und es soll auch kein # also nachdem das Hauptfenster steht. Bei after(0) haengt der modale Dialog
# halb gestartetes Programm hinter dem Fenster stehenbleiben. # an einem noch ungezeichneten Fenster und wirkt wie eingefroren; eine feste
self.after(0, self._hinweis_pruefen) # Wartezeit dagegen erreicht ein Pruefstand nie, der keine Schleife dreht.
self.after_idle(self._hinweis_pruefen)
# ---------------------------------------------------------------- Menue # ---------------------------------------------------------------- Menue
@ -650,6 +651,7 @@ class RechnungsApp(ThemeMixin, MeldungMixin, KorrekturMixin, EinstellungenMixin,
stuenden beim Ablehnen noch Timer in der Warteschlange, die auf ein stuenden beim Ablehnen noch Timer in der Warteschlange, die auf ein
Fenster zugreifen, das es nicht mehr gibt. Fenster zugreifen, das es nicht mehr gibt.
""" """
self.update_idletasks() # Fenster fertig zeichnen lassen
if not hinweis.angenommen(self.cfg): if not hinweis.angenommen(self.cfg):
print(f"[hinweis] Kenntnisnahme noch offen (Fassung {hinweis.FASSUNG})") print(f"[hinweis] Kenntnisnahme noch offen (Fassung {hinweis.FASSUNG})")
if not self.frage(hinweis.TITEL, hinweis.text("rechnungstool"), if not self.frage(hinweis.TITEL, hinweis.text("rechnungstool"),

View file

@ -473,6 +473,13 @@ class MeldungMixin:
x = self.winfo_rootx() + max(0, (self.winfo_width() - d.winfo_reqwidth()) // 2) x = self.winfo_rootx() + max(0, (self.winfo_width() - d.winfo_reqwidth()) // 2)
y = self.winfo_rooty() + 140 y = self.winfo_rooty() + 140
d.geometry(f"+{max(0, x)}+{max(0, y)}") d.geometry(f"+{max(0, x)}+{max(0, y)}")
# Nach vorn holen und den Tastaturfokus nehmen. Ohne das kann der Dialog
# beim Start hinter dem Hauptfenster liegen - der Nutzer sieht nur ein
# Fenster, das nicht reagiert, und haelt es fuer haengen geblieben.
d.lift()
d.attributes("-topmost", True)
d.after(100, lambda: d.attributes("-topmost", False))
d.focus_force()
d.grab_set() d.grab_set()
d.focus_set() d.focus_set()
self.wait_window(d) self.wait_window(d)