shared-gui / GUI-ARCHITECTURE.md
smlflg's picture
Initial public upload from Projekte/shared-gui
74f57c5 verified
|
Raw
History Blame Contribute Delete
10.6 kB

GUI-Architektur β€” 3 Standalone GTK3 Apps

Stand: 2026-03-04

1. Shared Base Module (~/Projekte/shared-gui/gui_base.py)

Gemeinsame Grundlage fuer alle drei GUIs. Importiert theme.py aus ClaudeCodePanel.

BaseApp Klasse

class BaseApp(Gtk.Window):
    def __init__(self, title, width, height, icon_name=None)

Bereitgestellte Features:

  • Window Setup: Titel, Groesse, Icon, destroy-Signal
  • HeaderBar: Gtk.HeaderBar mit Titel + optionalem Subtitle
  • StatusBar: Unten, CSS-Klasse .status-bar, mit set_status(text, css_class) Methode
  • Theme: Automatisches Laden von Catppuccin CSS via theme.py, COSMIC dark/light Watcher
  • CSS Provider: Gemeinsam fuer alle Widgets, erweiterbar via add_css(css_string)
  • Refresh Timer: start_refresh(interval_seconds, callback) β€” GLib.timeout_add_seconds
  • Main Box: Vertikaler Gtk.Box (self.content_box) zwischen Header und StatusBar

Theme-Modul Wiederverwendung

gui_base.py importiert direkt aus ClaudeCodePanel:

sys.path.insert(0, str(Path.home() / "Projekte/ClaudeCodePanel"))
from theme import build_css, setup_theme_watcher, get_palette, is_dark_mode

Gemeinsame CSS-Klassen (aus theme.py)

Alle Apps erben automatisch:

  • .panel-header, .stat-value, .stat-label β€” Ueberschriften + Statistiken
  • .section-frame, .section-title β€” Karten/Sektionen
  • .status-bar, .status-saved, .status-error β€” Statusleiste
  • .shortcut-btn β€” Aktionsbuttons
  • .monitor-value, .cost-value β€” Monospace-Werte

Zusaetzlich definiert gui_base.py:

  • .base-card β€” Standardkarte (border-radius 8px, card-bg, border)
  • .base-toolbar β€” Toolbar-Leiste (mantle-bg, border-radius 8px)
  • .base-badge β€” Kleine Status-Badges (border-radius 12px)

2. Design-Specs pro GUI

2.1 Sidecar-GUI (~/Projekte/Sidecar/gui/)

Zweck: Visuelles Dashboard fuer den Sidecar Daemon β€” Rules, Sessions, Findings.

Layout:

+-----------------------------------------------+
| [HeaderBar] Sidecar Control Panel    [Reload]  |
+-----------------------------------------------+
| [Notebook]                                     |
| +-------------------------------------------+  |
| | Tab: Status  | Tab: Rules | Tab: Findings |  |
| +-------------------------------------------+  |
|                                                 |
| STATUS TAB:                                     |
|   Daemon: running  PID: 12345  Uptime: 2h 15m  |
|   Rules: 22   Findings: 5   Plugins: 3          |
|                                                 |
| RULES TAB:                                      |
|   [SearchEntry filter]                          |
|   +------------------------------------------+ |
|   | Name        | Group    | Enabled | Fires  | |
|   | cli_first   | enforce  |   [x]   |   12   | |
|   | gate_rm_rf  | gate     |   [x]   |    3   | |
|   +------------------------------------------+ |
|   [Enable] [Disable] [Snooze 30m]              |
|                                                 |
| FINDINGS TAB:                                   |
|   [ScrolledWindow mit Finding-Cards]            |
|   Time | Rule | Severity | Message              |
+-----------------------------------------------+
| [StatusBar] Connected via /tmp/claude-sidecar.sock |
+-----------------------------------------------+

Widgets:

  • Gtk.Notebook mit 3 Tabs
  • Status-Tab: Grid mit Labels (key-value), aktualisiert via Refresh
  • Rules-Tab: Gtk.ListBox mit Rows, SearchEntry fuer Filter, Toggle-Buttons
  • Findings-Tab: Gtk.ListBox mit farbcodierten Karten (Severity β†’ Farbe)

Datenquellen:

  • Primaer: Unix Socket /tmp/claude-sidecar.sock (JSON-Protokoll, wie sidecar-ctl)
  • Kommandos: status, rules, findings, enable, disable, snooze, reload
  • Socket-Kommunikation non-blocking via GLib.io_add_watch auf Socket-FD

Refresh: 5 Sekunden (Status + Rules), Findings on-demand

Interaktion:

  • Rules: Klick auf Row β†’ Enable/Disable Toggle, Rechtsklick β†’ Snooze
  • Findings: Nur Anzeige, scrollbar
  • Reload-Button in HeaderBar

2.2 Tools-GUI (~/Projekte/ClaudeCodePanel/tools-gui/)

Zweck: Session-History + Kosten-Tracking fuer Claude Code.

Layout:

+-----------------------------------------------+
| [HeaderBar] Claude Code Tools           [Ref]  |
+-----------------------------------------------+
| [Notebook]                                     |
| +-------------------------------------------+  |
| | Tab: Sessions | Tab: Costs | Tab: Tools   |  |
| +-------------------------------------------+  |
|                                                 |
| SESSIONS TAB:                                   |
|   [SearchEntry]  [ComboBox: Sortierung]         |
|   +------------------------------------------+ |
|   | Projekt      | Letztes Msg | Kosten | Res | |
|   | Sidecar      | vor 2h      | $0.12  | [>] | |
|   | ClaudePanel  | vor 1d      | $0.45  | [>] | |
|   +------------------------------------------+ |
|                                                 |
| COSTS TAB:                                      |
|   Heute: $1.23   Woche: $8.50   Monat: $32.10  |
|   [BarChart via DrawingArea β€” letzte 7 Tage]    |
|   Top Tools: Read(45) Edit(23) Bash(18)         |
|                                                 |
| TOOLS TAB:                                      |
|   Tool-Usage Breakdown (ListBox)                |
|   Skill-Usage + Missed Skills                   |
+-----------------------------------------------+
| [StatusBar] 12 Sessions | $1.23 heute           |
+-----------------------------------------------+

Widgets:

  • Sessions-Tab: Gtk.ListBox mit Session-Rows, SearchEntry, ComboBox fuer Sortierung
  • Costs-Tab: Stat-Labels oben, Gtk.DrawingArea fuer 7-Tage-Balkendiagramm (Cairo), Tool-Rankings
  • Tools-Tab: Gtk.ListBox mit Tool-Usage, Skill-Usage

Datenquellen:

  • monitor.py Funktionen: get_daily_cost(), get_top_tools(), get_recent_sessions(), get_usage_timeline(), get_provider_costs(), get_skill_usage(), get_missed_skills_summary()
  • Import: sys.path.insert(0, "~/Projekte/ClaudeCodePanel") + from monitor import ...

Refresh: 30 Sekunden (passend zum TTL-Cache in monitor.py)


2.3 Florian-GUI (~/Projekte/MyAIGame/florian-gui/)

Zweck: TTS Control Panel β€” Voice-Auswahl, Test, Speed/Pitch, Audio-Playback.

Layout:

+-----------------------------------------------+
| [HeaderBar] Florian TTS Control        [Play]  |
+-----------------------------------------------+
|                                                 |
| Voice: [ComboBox: florian|katja|conrad|...]     |
|                                                 |
| Speed:  [=====|========] 1.0x                   |
| Pitch:  [=====|========] +0Hz                   |
|                                                 |
| Format: ( ) mp3  ( ) wav  ( ) opus  ( ) flac    |
|                                                 |
| Text:                                           |
| +------------------------------------------+   |
| | Guten Tag, ich bin Florian und teste     |   |
| | die Sprachausgabe.                        |   |
| +------------------------------------------+   |
|                                                 |
| [  Speak  ]         [Stop]                      |
|                                                 |
| +------------------------------------------+   |
| | Audio-Wellenform / Fortschrittsbalken    |   |
| +------------------------------------------+   |
|                                                 |
| Server: localhost:5050 [Health: OK]             |
+-----------------------------------------------+
| [StatusBar] Ready β€” Florian (de-DE)             |
+-----------------------------------------------+

Widgets:

  • Gtk.ComboBoxText fuer Voice-Auswahl (aus /v1/audio/voices Endpoint)
  • Gtk.Scale fuer Speed (0.25 β€” 4.0, Step 0.25) und Pitch (-20Hz β€” +20Hz)
  • Gtk.RadioButton Gruppe fuer Format
  • Gtk.TextView fuer Text-Eingabe (mehrzeilig)
  • Gtk.Button Speak + Stop
  • Gtk.ProgressBar fuer Audio-Playback
  • Health-Indikator (Label mit Farbcode)

Datenquellen:

  • HTTP API: http://localhost:5050
    • GET /v1/audio/voices β†’ Voice-Liste
    • POST /v1/audio/speech β†’ Audio-Bytes (body: {input, voice, speed, response_format})
    • GET /health β†’ Server-Status
  • HTTP via Gio.InputStream / subprocess curl + GLib.spawn_async (kein threading!)

Audio-Playback:

  • Tempfile schreiben β†’ subprocess.Popen(["mpv", "--no-video", tmpfile]) via GLib.spawn_async
  • Stop = Kill des mpv-Prozesses

Refresh: Health-Check alle 10 Sekunden


3. Dateistruktur pro Projekt

shared-gui/

~/Projekte/shared-gui/
  gui_base.py          # BaseApp + Theme-Integration + gemeinsame CSS

Sidecar-GUI

~/Projekte/Sidecar/gui/
  main.py              # Entry-Point, SidecarApp(BaseApp)
  socket_client.py     # Non-blocking Unix Socket Client (GLib.io_add_watch)
  tabs/
    status_tab.py      # Daemon-Status Anzeige
    rules_tab.py       # Rules ListBox + Filter + Enable/Disable
    findings_tab.py    # Findings ListBox

Tools-GUI

~/Projekte/ClaudeCodePanel/tools-gui/
  main.py              # Entry-Point, ToolsApp(BaseApp)
  tabs/
    sessions_tab.py    # Session-ListBox + Search + Sort
    costs_tab.py       # Kosten-Stats + Cairo BarChart
    tools_tab.py       # Tool-Usage + Skill-Usage

Florian-GUI

~/Projekte/MyAIGame/florian-gui/
  main.py              # Entry-Point, FlorianApp(BaseApp)
  tts_client.py        # HTTP Client (Gio/subprocess, non-blocking)
  audio_player.py      # mpv-basierter Player (GLib.spawn_async)

4. Constraints

Constraint Detail
Toolkit GTK 3.0 via PyGObject (gi.require_version("Gtk", "3.0"))
Theme Catppuccin Mocha (dark) / Latte (light) via theme.py
Desktop COSMIC β€” is_dark_mode() liest ~/.config/cosmic/CosmicTheme.Mode/v1/is_dark
Event Loop GLib Main Loop β€” KEIN threading, KEIN asyncio im GUI-Thread
Timer GLib.timeout_add_seconds() fuer Refresh, Return True fuer Repeat
Non-Blocking I/O Socket: GLib.io_add_watch, HTTP: GLib.spawn_async mit Callback
CSS Alle Styles via Gtk.CssProvider, keine inline-Styles
GLib.idle_add Nur als One-Shot (return False), NIE mit return True
Python 3.11+ (match/case erlaubt, aber nicht erforderlich)
Abhaengigkeiten PyGObject >= 3.42, gir1.2-gtk-3.0 (keine zusaetzlichen Pakete)