Aufraeumrunde nach der Pruefkette. Fuer den Nutzer sichtbar ist ein Punkt:
der Wechsel von einem Menuetitel zum anderen braucht nur noch EINEN Klick.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
Sein Befund: "hast du bei dem windows icon das gleich farbige wie im
programm, wo als wasserzeichen gilt, gemacht - weil das schaut blau aus".
Er hatte recht: auf der Kachel stand das ROHE Logo mit seinem Petrol
#004860, waehrend im Programm (Kopfzeile, Wasserzeichen) laengst die
umgefaerbte Fassung laeuft. Zwei Farben fuer dasselbe Zeichen.
Jetzt geht das Logo auch fuers Symbol durch _umfaerben() - dieselbe
Funktion, dieselben Farben: Tuerkis fuer die Wolke, Dunkelgrau fuer das
Zeichen daneben. Die Kachel ist weiss, also gilt die HELLE Fassung.
Fassung 1.8.1.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
Seine Ansage
"waere nun noch gut das mann in den einstellungen einstellen kann hell
oder dunkel oder automatik das fehlt sollte eigendlich drin sein"
Er hatte recht: beide Farbpaletten lagen laengst in theme.py, das Programm
folgte aber starr dem Windows-Theme. Jetzt steht die Wahl unter
Einstellungen -> Darstellung und wirkt SOFORT, nicht erst beim Neustart.
Umschalten heisst neu bauen
Die Farben stehen an ueber sechzig Stellen fest in den Widgets. Sie einzeln
nachzuziehen hiesse, ein Verzeichnis aller eingefaerbten Widgets zu fuehren
- und wer beim naechsten neuen Widget vergisst, es einzutragen, hat einen
hellen Fleck im dunklen Fenster, den niemand mehr findet. Neu bauen kann
nichts vergessen.
⚠️ Dabei gingen im ersten Versuch Kundenname und Rechnungsnummer verloren:
die _build_-Methoden legen ihre StringVars SELBST an, nach dem Neubau
standen leere da. Gesichert werden jetzt ALLE Tk-Variablen des Fensters,
nicht eine gepflegte Auswahl - wer spaeter ein Feld hinzufuegt, muss nichts
eintragen.
Titelleiste, Symbol und Logo gehen mit
Die Titelleiste gehoert Windows; sie folgt ueber
DWMWA_USE_IMMERSIVE_DARK_MODE. _dark_titlebar konnte bisher nur DUNKEL und
zeigt jetzt in beide Richtungen - vorher behielt man beim Wechsel auf hell
eine schwarze Leiste ueber einem hellen Fenster.
Sein Befund: "die svg fuer das dunkle heller machen weil die geht nun
unter" und "icon musst wenn es dunkel ist mit aendern auf das hellere".
Gemessen sind es zwei Farben: Petrol #004860 und ein fast schwarzes
#181818 - letzteres liegt genau auf der Kachelfarbe #15171b. Umgestellt
wird nur die HELLIGKEIT (L -> 1-L, gedeckelt bei 0.78), Farbton und
Saettigung bleiben: sonst waere es nicht mehr sein Logo. Betrifft
Wasserzeichen, Kopflogo und das Fenstersymbol; die aufgehellte ICO entsteht
beim Bauen.
menueleiste.py
Die selbstgebaute Menueleiste ist jetzt eine eigene Datei und liegt in
beiden Programmen gleich - das Steuerrechnungstool hatte noch das native
tk.Menu, das sich unter Windows nicht einfaerben laesst.
pruef_darstellung.py
Prueft die drei Modi, dass beim Umschalten NICHTS verlorengeht, und dass
danach kein Widget mehr eine Farbe der anderen Palette traegt - genau der
helle Fleck, den man sonst nie wiederfindet.
Nebenbei: die beiden Dauertimer melden beim Beenden kein
"invalid command name ..._api_pumpe" mehr. Ein Log, in dem beim normalen
Beenden immer zwei Fehler stehen, liest irgendwann niemand mehr.
Fassung 1.8.0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
Sein Befund
"die namen und datums bloecke koennen schmaler werden sind zu breit und
verdrengen die posten block"
Gemessen stimmte das genau: die sieben Spalten der Leistungstabelle
brauchten 743 Pixel, sichtbar waren 618 - "E.-Preis" und "Gesamt" standen
ausserhalb des Bildes.
Wo die Breite wirklich herkam
An den Feldbreiten zu drehen half NICHTS. Die Arbeitsflaeche verteilte
ueber eine uniform-Gruppe streng im Verhaeltnis 4:3; die Formularspalte war
so breit, weil das Gewicht es vorschrieb, nicht weil der Inhalt es
brauchte - 433 Pixel, ob die Felder nun 38 oder 22 Zeichen breit waren.
Jetzt bekommt die Formularseite eine feste Mindestbreite und kein Gewicht,
die Liste allen uebrigen Platz. Wird das Fenster groesser, waechst allein
die Tabelle - genau dort nuetzt Breite, waehrend ein 600 Pixel breites Feld
fuer eine Postleitzahl nichts besser macht. 433 -> 329.
Dazu passend
- Startbreite 1060 -> 1180 und Mindestbreite 900 -> 1080. Unterhalb von
1080 passen die sieben Spalten selbst dann nicht nebeneinander, wenn die
Textspalte auf ihrer Mindestbreite steht.
- Die Eingabefelder links auf das Mass gekuerzt, das sie wirklich brauchen
(22 statt 38 Zeichen; Datum 12 statt 18). Das senkt die Mindestbreite der
Formularseite - erst dadurch ist sie so klein moeglich.
- "Anreise (TT.MM.JJJJ)" -> "Anreise". Die Form steht jetzt einmal als
graue Zeile unter dem Block. Als Platzhalter IM Feld waere sie
gefaehrlich: ein nicht geloeschter Platzhalter stuende als Anreisedatum
auf der Rechnung.
- Der Textumbruch der Leistungsspalte folgt jetzt ihrer echten Breite. Fest
eingetragen schnitt er den Text ab, sobald die Spalte schmaler wurde.
pruef_spaltenbreiten.py
Prueft ueber die ganze erlaubte Spanne, dass alle Spalten hineinpassen, die
Formularseite lesbar bleibt und NICHT mitwaechst, und der Umbruch zur
Spalte passt. Kein anderer Pruefstand haette das gefunden: es stuerzt
nichts ab und rechnet nichts falsch - man sieht die Preise nur nicht.
Er hat sofort einen zweiten Fehler gefunden: beim Aendern der
Fenstergroesse lief der Umbruch nicht hinterher, weil ich abgebrochen
hatte, sobald sich mein eigener Wert nicht mehr aenderte. Die Spalte kann
aber breiter werden, ohne dass ich etwas aendere. Abbruch jetzt, wenn zwei
Messungen dieselbe Spaltenbreite ergeben.
Fassung 1.7.1.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
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
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."
"einmal pruefen auf vollstaendigkeit."
"wir werden den namen mit nummer fuehren - wenn er merkt, eh warte mal, die
heisst anders, dann neu machen"
DER AUFBAU
Der Updater IST der Starter. Er laeuft, BEVOR das Programm laeuft - damit gibt
es das Windows-Problem "laufende EXE laesst sich nicht ersetzen" gar nicht.
Und weil die installierte Datei die Nummer im Namen traegt
(Rechnungstool-1.6.0.exe), wird ueberhaupt nichts ueberschrieben: eine neue
Fassung ist eine neue Datei. Die vorige bleibt liegen und ist damit die
Rueckfallebene, ohne dass jemand eine Sicherung anlegen muesste. Der Updater
sieht am NAMEN, was da ist - er muss keiner Angabe glauben.
version.py: die Nummer an EINER Stelle, im Code, in die EXE kompiliert. Sie
entspricht dem Release-Tag ohne "v". Zusaetzlich fuehrt der Updater ein eigenes
Buch (installiert.json); wer eine Datei umbenennt, verursacht hoechstens einen
ueberfluessigen Download.
BEIM BAUEN AUFGEFALLEN
/releases/latest liefert NICHTS, weil alle Fassungen als Vorabversion
gekennzeichnet sind - Forgejo laesst Vorabversionen dort aus. Der Updater nimmt
deshalb die Liste und sucht selbst die hoechste Nummer. Waere das erst beim
Nutzer aufgefallen, haette der Updater nie ein Update gefunden.
Beide Repositories sind oeffentlich - kein Token noetig. Ein Token in einer
verteilten EXE waere ohnehin keins.
VOLLSTAENDIGKEIT
Geladen wird in einen Zwischenordner. Erst wenn GROESSE und (falls das Release
eine .sha256 anhaengt) PRUEFSUMME stimmen, kommt die Datei in den
Installationsordner. Sonst wird verworfen und die vorhandene Fassung gestartet -
lieber kein Update als ein kaputtes.
PRUEFSTAND
pruef_updater.py prueft vor allem, wann NICHT aktualisiert werden darf: gleiche
Fassung, aeltere im Netz, kein passender Anhang, Entwurf, kein Netz, falsche
Groesse, falsche Pruefsumme. Und den wichtigsten Punkt: eine halbe Datei
erreicht den Installationsordner nie.
Alle 18 Pruefstaende gruen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax