Kaesten verschiebbar wie bei OPNsense: Knopf, schieben, speichern
Seine Ansage: "rechnungsdaten oben links, darunter rechnung an kunde, den tabellen kasten rechts - oder noch besser dnd einbauen" und dann genauer: "wie bei opnsense hast so einen kleinen knopf, dann drueckst drauf, ab da kannst du schieben, dann hast du einen save button, und dann ist die fest". - Seine Anordnung ist die Vorgabe (flaeche.STANDARD). - Verschieben muss man EINSCHALTEN. Ohne den Knopf sitzt alles fest, damit beim taeglichen Arbeiten nichts verrutscht. Im Modus stehen "Speichern" und "Verwerfen" daneben; erst Speichern schreibt in die config. - Waehrend des Ziehens haengt ein Etikett am Zeiger und der gegriffene Kasten wird blass - vorher sah man nur das Ziel und es wirkte "statisch" (sein Fund). - Getauscht statt frei abgelegt: freies Verschieben auf Pixel braucht Regeln fuer Ueberlappung, Groesse und leere Zellen, und am Ende steht das Fenster schief. Ein Tausch ist in einem Griff erledigt. - Der freie Platz folgt dem Kasten mit der langen Liste. Feste Gewichte gingen nicht: die Liste wandert, und der Kundenkasten wurde unten abgeschnitten. - Eine unbrauchbare Anordnung in der config faellt auf die Vorgabe zurueck. Icons: die Material Symbols vom Hub (M:/projekte/material-symbols), einmal nach PNG gewandelt und zur Laufzeit eingefaerbt (icons.py) - eine Datei je Icon, nicht drei Fassungen fuer hell/dunkel/Akzent. ⚠️ Ein PhotoImage gehoert GENAU EINEM Tk-Fenster. Der Icon-Cache reichte Bilder an das naechste weiter, sobald ein Pruefstand Journal und Rechnungstool nacheinander faehrt: 'image "pyimage1" doesn't exist'. Das Fenster wird jetzt mitgegeben, tk._default_root reicht dafuer nicht. Neu: pruef_flaeche.py. Alle 15 Pruefstaende gruen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
This commit is contained in:
parent
5403e01dd5
commit
c1e328c087
10 changed files with 561 additions and 17 deletions
82
app.py
82
app.py
|
|
@ -39,6 +39,8 @@ from bestand import (hoechster_zaehler_im_ordner, naechste_freie_nummer,
|
|||
vorhandene_rechnungen)
|
||||
from einzelinstanz import (eigene_pid_merken, einzelinstanz_pruefen, fenster_nach_vorn,
|
||||
laufende_pid_lesen)
|
||||
import flaeche
|
||||
import icons
|
||||
import reiter
|
||||
import theme
|
||||
from theme import MeldungMixin, ThemeMixin
|
||||
|
|
@ -102,9 +104,11 @@ class RechnungsApp(ThemeMixin, MeldungMixin, KorrekturMixin, EinstellungenMixin,
|
|||
|
||||
self._apply_theme() # Farben nach Windows hell/dunkel
|
||||
self._build_menu()
|
||||
self._build_kopf()
|
||||
self._build_summen() # untere Leiste (Summen + Buttons) zuerst -> bleibt immer sichtbar
|
||||
self._build_positionen() # Positionsliste fuellt den Rest und scrollt
|
||||
self._build_flaeche() # Werkzeugleiste + verschiebbare Kaesten
|
||||
self._build_kopf() # Rechnungsdaten + Kunde als Kaesten
|
||||
self._build_positionen() # Leistungen als Kasten, fuellt den Rest
|
||||
self.flaeche.anordnen()
|
||||
|
||||
self._neue_nummer_vorschlagen()
|
||||
self.recalc()
|
||||
|
|
@ -211,15 +215,62 @@ class RechnungsApp(ThemeMixin, MeldungMixin, KorrekturMixin, EinstellungenMixin,
|
|||
pass
|
||||
self._open_pop = None
|
||||
|
||||
# ------------------------------------------------------- Arbeitsflaeche
|
||||
def _build_flaeche(self):
|
||||
"""Die Kaesten und der Knopf, mit dem man sie verschieben darf.
|
||||
|
||||
Wie bei OPNsense: erst "Anordnen" druecken, dann schieben, dann
|
||||
speichern. Ohne diesen Schritt sitzt alles fest - beim taeglichen
|
||||
Arbeiten soll nichts verrutschen.
|
||||
"""
|
||||
leiste = ttk.Frame(self, padding=(16, 8, 16, 0))
|
||||
leiste.pack(side="top", fill="x")
|
||||
self.werkzeuge = ttk.Frame(leiste)
|
||||
self.werkzeuge.pack(side="right")
|
||||
|
||||
self._ic_anordnen = icons.hole("dashboard_customize", 16, self.col_muted, master=self)
|
||||
self._ic_speichern = icons.hole("check", 16, self.col_accent_hell, master=self)
|
||||
self._ic_verwerfen = icons.hole("close", 16, self.col_muted, master=self)
|
||||
|
||||
self.knopf_anordnen = ttk.Button(self.werkzeuge, text=" Anordnen",
|
||||
image=self._ic_anordnen, compound="left",
|
||||
command=self._anordnen_umschalten)
|
||||
self.knopf_anordnen.pack(side="left")
|
||||
self.knopf_speichern = ttk.Button(self.werkzeuge, text=" Speichern",
|
||||
image=self._ic_speichern, compound="left",
|
||||
style="Haupt.TButton",
|
||||
command=self._anordnen_speichern)
|
||||
self.knopf_verwerfen = ttk.Button(self.werkzeuge, text=" Verwerfen",
|
||||
image=self._ic_verwerfen, compound="left",
|
||||
command=self._anordnen_verwerfen)
|
||||
|
||||
self.flaeche = flaeche.Arbeitsflaeche(self, farben=self)
|
||||
self.flaeche.pack(side="top", fill="both", expand=True, padx=10, pady=(4, 0))
|
||||
|
||||
def _anordnen_umschalten(self):
|
||||
self.flaeche.anordnen_starten()
|
||||
self.knopf_anordnen.pack_forget()
|
||||
self.knopf_verwerfen.pack(side="left", padx=(0, 6))
|
||||
self.knopf_speichern.pack(side="left")
|
||||
|
||||
def _anordnen_fertig(self):
|
||||
self.knopf_speichern.pack_forget()
|
||||
self.knopf_verwerfen.pack_forget()
|
||||
self.knopf_anordnen.pack(side="left")
|
||||
|
||||
def _anordnen_speichern(self):
|
||||
self.flaeche.anordnen_speichern()
|
||||
self._anordnen_fertig()
|
||||
|
||||
def _anordnen_verwerfen(self):
|
||||
self.flaeche.anordnen_verwerfen()
|
||||
self._anordnen_fertig()
|
||||
|
||||
# ---------------------------------------------------------------- Kopf
|
||||
def _build_kopf(self):
|
||||
top = ttk.Frame(self, padding=(16, 14, 16, 6))
|
||||
top.pack(fill="x")
|
||||
|
||||
# Kunde (links)
|
||||
kunde = ttk.LabelFrame(top, text="RECHNUNG AN (KUNDE)", padding=14,
|
||||
style="Karte.TLabelframe")
|
||||
kunde.grid(row=0, column=0, sticky="nsew", padx=(0, 14))
|
||||
# Beide Bloecke sind Kaesten der Arbeitsflaeche - sie lassen sich
|
||||
# verschieben, deshalb platziert sie niemand mehr von Hand.
|
||||
kunde = self.flaeche.kasten("kunde", "Rechnung an (Kunde)")
|
||||
self.k_anrede = tk.StringVar()
|
||||
self.k_vorname = tk.StringVar()
|
||||
self.k_name = tk.StringVar() # Nachname oder Firma – die Zuordnung im Steuerjournal
|
||||
|
|
@ -249,10 +300,7 @@ class RechnungsApp(ThemeMixin, MeldungMixin, KorrekturMixin, EinstellungenMixin,
|
|||
row=len(felder), column=0, columnspan=2, sticky="w", pady=(6, 0))
|
||||
kunde.columnconfigure(1, weight=1)
|
||||
|
||||
# Rechnungsinfos (rechts)
|
||||
info = ttk.LabelFrame(top, text="RECHNUNGSDATEN", padding=14,
|
||||
style="Karte.TLabelframe")
|
||||
info.grid(row=0, column=1, sticky="nsew")
|
||||
info = self.flaeche.kasten("daten", "Rechnungsdaten")
|
||||
self.r_nummer = tk.StringVar()
|
||||
self.r_datum = tk.StringVar(value=datetime.date.today().strftime("%d.%m.%Y"))
|
||||
self.r_anreise = tk.StringVar()
|
||||
|
|
@ -296,8 +344,7 @@ class RechnungsApp(ThemeMixin, MeldungMixin, KorrekturMixin, EinstellungenMixin,
|
|||
self.r_anreise.trace_add("write", lambda *a: self._update_naechte())
|
||||
self.r_abreise.trace_add("write", lambda *a: self._update_naechte())
|
||||
|
||||
top.columnconfigure(0, weight=1)
|
||||
top.columnconfigure(1, weight=0)
|
||||
|
||||
|
||||
def _auto_datum_evt(self, event):
|
||||
"""Punkte automatisch setzen, Cursor ans Ende. Nach Tag+Monat das aktuelle
|
||||
|
|
@ -378,8 +425,9 @@ class RechnungsApp(ThemeMixin, MeldungMixin, KorrekturMixin, EinstellungenMixin,
|
|||
# Eigene Reiterleiste statt ttk.Notebook: unter clam liess sich der
|
||||
# ruhende Reiter nicht dunkel bekommen, er sah aus wie der offene.
|
||||
# Nach aussen verhaelt sie sich wie ein Notebook (siehe reiter.py).
|
||||
self.blaetter = reiter.Reiterleiste(self, farben=self)
|
||||
self.blaetter.pack(side="top", fill="both", expand=True, padx=16, pady=(4, 6))
|
||||
leistungen = self.flaeche.kasten("leistungen", "Leistungen")
|
||||
self.blaetter = reiter.Reiterleiste(leistungen, farben=self)
|
||||
self.blaetter.pack(side="top", fill="both", expand=True)
|
||||
self.blaetter.bind("<<NotebookTabChanged>>", lambda _e: self._blatt_gewechselt())
|
||||
|
||||
camping = ttk.Frame(self.blaetter.bereich, padding=(2, 6))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue