Skip to content

Commit 2c764f3

Browse files
committed
fix: Layout des KI-Workflows-Tabs aufräumen
Der KI-Workflows-Tab (und konsistent alle Settings-Tabs) wirkte unfertig: gequetschte, kontrastarme Hilfetexte, ein dominierendes Prompt-Feld und nicht bündig ausgerichtete Felder. - Hilfetexte über die volle Breite spannen statt in die schmale Feld-Spalte zu quetschen (addRow("", ...) -> addRow(...)) - create_help_label: Theme-Farbe APP_TEXT_DIM statt gray, 11px, padding-bottom für klare Gruppentrennung - FieldGrowthPolicy.AllNonFixedFieldsGrow für bündige Eingabefelder - Dampf-Prompt-Feld auf 72-120px und Begriffsliste auf max 120px begrenzt, damit sie die Seite nicht dominieren - Tabs in scrollbare QScrollArea gewrappt, damit der inhaltsreiche LLM-Tab nicht überläuft; Initialgröße 550x480 -> 580x560
1 parent c989d10 commit 2c764f3

1 file changed

Lines changed: 43 additions & 23 deletions

File tree

app/blitztext_linux.py

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
QApplication, QDialog, QVBoxLayout, QHBoxLayout, QTabWidget, QWidget,
2323
QFormLayout, QComboBox, QLineEdit, QCheckBox, QPlainTextEdit,
2424
QPushButton, QDialogButtonBox, QLabel, QMessageBox, QMenu, QSystemTrayIcon, QStyle,
25-
QListWidget,
25+
QListWidget, QScrollArea, QFrame,
2626
)
2727

2828
# Make project importable when running directly
@@ -119,8 +119,12 @@ def _require_display_environment() -> None:
119119

120120
def create_help_label(text: str) -> QLabel:
121121
"""Create a styled small help label for config fields."""
122+
from app import theme
123+
122124
label = QLabel(text)
123-
label.setStyleSheet("color: gray; font-size: 10px;")
125+
label.setStyleSheet(
126+
f"color: {theme.APP_TEXT_DIM}; font-size: 11px; padding: 1px 0 8px 2px;"
127+
)
124128
label.setWordWrap(True)
125129
return label
126130

@@ -132,9 +136,19 @@ def __init__(self, config: Config, parent: Optional[QWidget] = None) -> None:
132136
super().__init__(parent)
133137
self.config = config
134138
self.setWindowTitle("Blitztext Einstellungen")
135-
self.resize(550, 480)
139+
self.resize(580, 560)
136140
self.init_ui()
137141

142+
@staticmethod
143+
def _scrollable(content: QWidget) -> QScrollArea:
144+
"""Wrap a tab page so long forms scroll instead of overflowing the dialog."""
145+
scroll = QScrollArea()
146+
scroll.setWidgetResizable(True)
147+
scroll.setFrameShape(QFrame.Shape.NoFrame)
148+
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
149+
scroll.setWidget(content)
150+
return scroll
151+
138152
def init_ui(self) -> None:
139153
layout = QVBoxLayout(self)
140154
layout.setContentsMargins(15, 15, 15, 15)
@@ -147,6 +161,7 @@ def init_ui(self) -> None:
147161
tab_whisper = QWidget()
148162
form_whisper = QFormLayout(tab_whisper)
149163
form_whisper.setSpacing(10)
164+
form_whisper.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
150165

151166
self.combo_model = QComboBox()
152167
self.combo_model.addItems(["tiny", "base", "small", "medium", "large", "large-v2", "large-v3", "large-v3-turbo"])
@@ -173,29 +188,30 @@ def init_ui(self) -> None:
173188
self.combo_transcription_key.setCurrentText(self.config.transcription_hotkey)
174189

175190
form_whisper.addRow("Whisper-Modell:", self.combo_model)
176-
form_whisper.addRow("", create_help_label("Wählen Sie die Modellgröße. Größere Modelle sind genauer, benötigen aber mehr Ressourcen."))
191+
form_whisper.addRow(create_help_label("Wählen Sie die Modellgröße. Größere Modelle sind genauer, benötigen aber mehr Ressourcen."))
177192

178193
form_whisper.addRow("Transkription-Backend:", self.combo_backend)
179-
form_whisper.addRow("", create_help_label("faster-whisper ist deutlich schneller und ressourcenschonender."))
194+
form_whisper.addRow(create_help_label("faster-whisper ist deutlich schneller und ressourcenschonender."))
180195

181196
form_whisper.addRow("Sprache:", self.edit_language)
182-
form_whisper.addRow("", create_help_label("Zweistelliger Ländercode (z. B. 'de', 'en') oder 'auto' für automatische Erkennung."))
197+
form_whisper.addRow(create_help_label("Zweistelliger Ländercode (z. B. 'de', 'en') oder 'auto' für automatische Erkennung."))
183198

184199
form_whisper.addRow("Audio-Eingabegerät:", self.edit_audio_device)
185-
form_whisper.addRow("", create_help_label("'@DEFAULT_SOURCE@' nutzt das Standardmikrofon von PulseAudio/PipeWire."))
200+
form_whisper.addRow(create_help_label("'@DEFAULT_SOURCE@' nutzt das Standardmikrofon von PulseAudio/PipeWire."))
186201

187202
form_whisper.addRow("Hotkey-Modus:", self.combo_hotkey_mode)
188-
form_whisper.addRow("", create_help_label("toggle: Einmal drücken zum Starten, erneut drücken zum Stoppen.\nhold: Gedrückt halten zum Aufnehmen, Loslassen zum Stoppen."))
203+
form_whisper.addRow(create_help_label("toggle: Einmal drücken zum Starten, erneut drücken zum Stoppen.\nhold: Gedrückt halten zum Aufnehmen, Loslassen zum Stoppen."))
189204

190205
form_whisper.addRow("Aufnahme-Taste:", self.combo_transcription_key)
191-
form_whisper.addRow("", create_help_label("Einzelne Taste ohne Modifier (z. B. KEY_LEFTALT). Änderung wird sofort übernommen."))
206+
form_whisper.addRow(create_help_label("Einzelne Taste ohne Modifier (z. B. KEY_LEFTALT). Änderung wird sofort übernommen."))
192207

193-
self.tabs.addTab(tab_whisper, "Spracherkennung")
208+
self.tabs.addTab(self._scrollable(tab_whisper), "Spracherkennung")
194209

195210
# Tab 2: LLM (KI)
196211
tab_llm = QWidget()
197212
form_llm = QFormLayout(tab_llm)
198213
form_llm.setSpacing(10)
214+
form_llm.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
199215

200216
self.edit_api_key_env = QLineEdit()
201217
self.edit_api_key_env.setText(self.config.openai_api_key_env)
@@ -253,13 +269,16 @@ def init_ui(self) -> None:
253269
self.edit_dampf_prompt = QPlainTextEdit()
254270
self.edit_dampf_prompt.setPlainText(self.config.dampf_system_prompt)
255271
self.edit_dampf_prompt.setPlaceholderText("Standard-Systemprompt verwenden...")
272+
self.edit_dampf_prompt.setMinimumHeight(72)
273+
self.edit_dampf_prompt.setMaximumHeight(120)
256274

257275
self.edit_custom_term = QLineEdit()
258276
self.edit_custom_term.setPlaceholderText("z. B. Blitztext")
259277
self.edit_custom_term.returnPressed.connect(self._add_custom_term)
260278
self.list_custom_terms = QListWidget()
261279
self.list_custom_terms.addItems(self.config.custom_terms)
262280
self.list_custom_terms.setSelectionMode(QListWidget.SelectionMode.ExtendedSelection)
281+
self.list_custom_terms.setMaximumHeight(120)
263282
self.btn_add_custom_term = QPushButton("Hinzufügen")
264283
self.btn_add_custom_term.clicked.connect(self._add_custom_term)
265284
self.btn_remove_custom_term = QPushButton("Ausgewählte entfernen")
@@ -278,53 +297,54 @@ def init_ui(self) -> None:
278297
custom_terms_widget.setLayout(custom_terms_layout)
279298

280299
form_llm.addRow("API-Key-Umgebung:", api_key_layout)
281-
form_llm.addRow("", create_help_label("Nur der Name der Umgebungsvariable wird gespeichert. Der Schlüssel selbst wird aus os.environ gelesen (secrets.env). Für OpenRouter z. B. OPENROUTER_API_KEY."))
300+
form_llm.addRow(create_help_label("Nur der Name der Umgebungsvariable wird gespeichert. Der Schlüssel selbst wird aus os.environ gelesen (secrets.env). Für OpenRouter z. B. OPENROUTER_API_KEY."))
282301

283302
form_llm.addRow("LLM-Anbieter:", self.combo_llm_provider)
284-
form_llm.addRow("", create_help_label("OpenAI = Standard. OpenRouter und 'Eigener Endpunkt' nutzen das OpenAI-kompatible API über eine eigene Basis-URL und ein eigenes Modell."))
303+
form_llm.addRow(create_help_label("OpenAI = Standard. OpenRouter und 'Eigener Endpunkt' nutzen das OpenAI-kompatible API über eine eigene Basis-URL und ein eigenes Modell."))
285304
form_llm.addRow("Basis-URL (base_url):", self.edit_base_url)
286-
form_llm.addRow("", create_help_label("Leer = OpenAI-Standard. Für OpenRouter: https://openrouter.ai/api/v1. Muss mit http:// oder https:// beginnen."))
305+
form_llm.addRow(create_help_label("Leer = OpenAI-Standard. Für OpenRouter: https://openrouter.ai/api/v1. Muss mit http:// oder https:// beginnen."))
287306
form_llm.addRow("LLM-Modell:", self.edit_llm_model)
288-
form_llm.addRow("", create_help_label("Modellname beim Anbieter, z. B. 'gpt-4o-mini' (OpenAI) oder 'openai/gpt-4o' (OpenRouter)."))
307+
form_llm.addRow(create_help_label("Modellname beim Anbieter, z. B. 'gpt-4o-mini' (OpenAI) oder 'openai/gpt-4o' (OpenRouter)."))
289308

290309
form_llm.addRow("Text-Verbesserer Tonfall:", self.combo_tone)
291310
form_llm.addRow("Schreibstil-Vorlage:", self.combo_writing_preset)
292-
form_llm.addRow("", create_help_label("Vorlage für den Text-Verbesserer (z. B. E-Mail formell, Stichpunkte). Bei 'Standard' greift der Tonfall oben; jede andere Vorlage bestimmt den Schreibstil selbst und ersetzt den Tonfall."))
311+
form_llm.addRow(create_help_label("Vorlage für den Text-Verbesserer (z. B. E-Mail formell, Stichpunkte). Bei 'Standard' greift der Tonfall oben; jede andere Vorlage bestimmt den Schreibstil selbst und ersetzt den Tonfall."))
293312
form_llm.addRow("Emoji-Dichte:", self.combo_emoji)
294313

295314
form_llm.addRow("Dampf-Umschreiber Prompt:", self.edit_dampf_prompt)
296-
form_llm.addRow("", create_help_label("Eigener System-Prompt, um wütende Aussagen in eine professionelle Form umzuschreiben."))
315+
form_llm.addRow(create_help_label("Eigener System-Prompt, um wütende Aussagen in eine professionelle Form umzuschreiben."))
297316
form_llm.addRow("Eigennamen / Begriffe:", custom_terms_widget)
298-
form_llm.addRow("", create_help_label("Wörter, Namen und Fachbegriffe, die bei Transkription und KI-Umschreibung exakt beibehalten werden sollen."))
317+
form_llm.addRow(create_help_label("Wörter, Namen und Fachbegriffe, die bei Transkription und KI-Umschreibung exakt beibehalten werden sollen."))
299318

300-
self.tabs.addTab(tab_llm, "KI-Workflows")
319+
self.tabs.addTab(self._scrollable(tab_llm), "KI-Workflows")
301320

302321
# Tab 3: Allgemein
303322
tab_general = QWidget()
304323
form_general = QFormLayout(tab_general)
305324
form_general.setSpacing(10)
325+
form_general.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
306326

307327
self.check_autopaste = QCheckBox("Text automatisch einfügen (Auto-Paste)")
308328
self.check_autopaste.setChecked(self.config.autopaste)
309329
form_general.addRow(self.check_autopaste)
310-
form_general.addRow("", create_help_label("Simuliert Strg+V nach Abschluss der Aufnahme. Benötigt das Tool 'ydotool'."))
330+
form_general.addRow(create_help_label("Simuliert Strg+V nach Abschluss der Aufnahme. Benötigt das Tool 'ydotool'."))
311331

312332
self.edit_notes_folder = QLineEdit()
313333
self.edit_notes_folder.setText(self.config.notes_folder)
314334
self.edit_notes_folder.setPlaceholderText(str(Path.home() / "Blitztext-Notizen"))
315335
form_general.addRow("Diktat-Notizordner:", self.edit_notes_folder)
316-
form_general.addRow("", create_help_label("Ordner für Diktat-Notizen (muss innerhalb von ~ liegen). Leer = Speichern deaktiviert."))
336+
form_general.addRow(create_help_label("Ordner für Diktat-Notizen (muss innerhalb von ~ liegen). Leer = Speichern deaktiviert."))
317337

318338
self.spin_history_size = QComboBox()
319339
self.spin_history_size.addItems(["10", "25", "50", "75", "100"])
320340
self.spin_history_size.setCurrentText(str(self.config.history_size))
321341
form_general.addRow("Verlauf-Größe:", self.spin_history_size)
322-
form_general.addRow("", create_help_label("Maximale Anzahl der im Verlauf gespeicherten Einträge."))
342+
form_general.addRow(create_help_label("Maximale Anzahl der im Verlauf gespeicherten Einträge."))
323343

324344
self.btn_open_config = QPushButton("📄 Konfigurationsdatei öffnen")
325345
self.btn_open_config.clicked.connect(self._open_config_file)
326346
form_general.addRow(self.btn_open_config)
327-
form_general.addRow("", create_help_label(
347+
form_general.addRow(create_help_label(
328348
"Öffnet config.json im Standard-Editor – für erweiterte Prompt- und "
329349
"Workflow-Anpassungen, die über die Felder oben hinausgehen."))
330350

@@ -334,7 +354,7 @@ def init_ui(self) -> None:
334354
version_label.setAlignment(Qt.AlignmentFlag.AlignRight)
335355
form_general.addRow(version_label)
336356

337-
self.tabs.addTab(tab_general, "Allgemein")
357+
self.tabs.addTab(self._scrollable(tab_general), "Allgemein")
338358

339359
layout.addWidget(self.tabs)
340360

0 commit comments

Comments
 (0)