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, mitset_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.Notebookmit 3 Tabs- Status-Tab: Grid mit Labels (key-value), aktualisiert via Refresh
- Rules-Tab:
Gtk.ListBoxmit Rows, SearchEntry fuer Filter, Toggle-Buttons - Findings-Tab:
Gtk.ListBoxmit 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_watchauf 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.ListBoxmit Session-Rows, SearchEntry, ComboBox fuer Sortierung - Costs-Tab: Stat-Labels oben,
Gtk.DrawingAreafuer 7-Tage-Balkendiagramm (Cairo), Tool-Rankings - Tools-Tab:
Gtk.ListBoxmit Tool-Usage, Skill-Usage
Datenquellen:
monitor.pyFunktionen: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.ComboBoxTextfuer Voice-Auswahl (aus/v1/audio/voicesEndpoint)Gtk.Scalefuer Speed (0.25 β 4.0, Step 0.25) und Pitch (-20Hz β +20Hz)Gtk.RadioButtonGruppe fuer FormatGtk.TextViewfuer Text-Eingabe (mehrzeilig)Gtk.ButtonSpeak + StopGtk.ProgressBarfuer Audio-Playback- Health-Indikator (Label mit Farbcode)
Datenquellen:
- HTTP API:
http://localhost:5050GET /v1/audio/voicesβ Voice-ListePOST /v1/audio/speechβ Audio-Bytes (body:{input, voice, speed, response_format})GET /healthβ Server-Status
- HTTP via
Gio.InputStream/ subprocesscurl+ GLib.spawn_async (kein threading!)
Audio-Playback:
- Tempfile schreiben β
subprocess.Popen(["mpv", "--no-video", tmpfile])viaGLib.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) |