# -*- coding: utf-8 -*- """Steuerung fuer Pruefstaende: keine Fenster, keine Popups, keine Maus. WARUM ----- Ein Pruefstand baut das Programm auf, um es zu BEDIENEN - nicht, um es zu zeigen. Solange er wie ein Benutzer arbeitet, reisst jeder Lauf dem Menschen am Rechner Fokus und Maus weg, und jeder Dialog bleibt stehen und wartet auf einen Klick, den niemand macht. Deshalb zwei Dinge, beide nur im Testlauf (`--test` / `CAMPINGHOF_TEST=1`): * Das Fenster wird gar nicht erst gezeigt (`withdraw()` in app.py). * Alle Dialoge laufen hierueber statt ueber echte Fenster. WAS EIN DIALOG HIER TUT ----------------------- `showinfo/showwarning/showerror` werden ins PROTOKOLL geschrieben und verschwinden. `askyesno` und Verwandte schlagen im Fahrplan nach: pruefsteuerung.antwortet("Hausnummer", True) Passt kein Eintrag, bricht der Lauf mit einer Meldung ab - ABSICHTLICH. Ein unbekannter Dialog heisst: das Programm fragt etwas Neues, und niemand hat entschieden, was der Pruefstand darauf antworten soll. Stillschweigend "ja" zu sagen waere die faule Loesung und wuerde genau die Faelle uebergehen, wegen denen es die Pruefung gibt. BENUTZUNG IM PRUEFSTAND ----------------------- import pruefsteuerung as PS PS.antwortet("Storno wirklich", True) ... PS.gemeldet("Kundenangaben fehlen") -> True, wenn das Programm es sagte """ from tkinter import messagebox # Was das Programm gemeldet haette: Liste aus (art, titel, text). PROTOKOLL = [] # Fahrplan fuer Ja/Nein-Fragen: Textstueck im Titel -> Antwort. ANTWORTEN = {} _aktiv = False def antwortet(titelstueck, wert): """Legt fest, wie eine Frage beantwortet wird, deren Titel das Stueck enthaelt.""" ANTWORTEN[titelstueck] = wert def zuruecksetzen(): PROTOKOLL.clear() ANTWORTEN.clear() def meldungen(stueck=""): """Alle Meldungen (oder die, in denen das Stueck vorkommt).""" return [m for m in PROTOKOLL if stueck in m[1] or stueck in m[2]] def gemeldet(stueck): """Hat das Programm etwas gemeldet, in dem das Stueck vorkommt?""" return bool(meldungen(stueck)) def _melden(art): def gemeldet_(titel="", text="", **_kw): PROTOKOLL.append((art, str(titel), str(text))) print(f"[dialog] {art}: {titel}") return "ok" return gemeldet_ def _fragen(vorgabe=None): def gefragt(titel="", text="", **_kw): PROTOKOLL.append(("frage", str(titel), str(text))) for stueck, wert in ANTWORTEN.items(): if stueck in str(titel) or stueck in str(text): print(f"[dialog] frage: {titel} -> {wert}") return wert if vorgabe is not None: return vorgabe raise AssertionError( f"unangemeldeter Dialog: {titel!r}\n" f" {text!r}\n" " -> im Pruefstand mit pruefsteuerung.antwortet(, True/False) " "beantworten") return gefragt def einschalten(): """Dialoge umleiten. Mehrfaches Aufrufen schadet nicht.""" global _aktiv if _aktiv: return messagebox.showinfo = _melden("info") messagebox.showwarning = _melden("warnung") messagebox.showerror = _melden("fehler") messagebox.askyesno = _fragen() messagebox.askokcancel = _fragen() messagebox.askretrycancel = _fragen(False) messagebox.askquestion = _fragen() _aktiv = True print("[pruefsteuerung] Dialoge laufen ohne Fenster")