""" Settings dialog. Built dynamically from app.config.SETTINGS_SCHEMA, grouped by section (Database, JIRA, ...). When a new service adds settings to that schema, they show up here automatically - no UI changes needed. """ from __future__ import annotations from collections import defaultdict from PyQt6.QtWidgets import ( QDialog, QVBoxLayout, QFormLayout, QLineEdit, QPushButton, QHBoxLayout, QGroupBox, QLabel, QMessageBox, ) from app import config class SettingsDialog(QDialog): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle("Settings") self.setMinimumWidth(480) self._fields: dict[str, QLineEdit] = {} current_values = config.load_settings() # Group schema entries by their group label, preserving order groups: dict[str, list[tuple[str, str, bool]]] = defaultdict(list) for key, (label, group, is_secret) in config.SETTINGS_SCHEMA.items(): groups[group].append((key, label, is_secret)) layout = QVBoxLayout(self) layout.addWidget( QLabel("Changes are saved to your .env file and applied immediately.") ) for group_name, entries in groups.items(): box = QGroupBox(group_name) form = QFormLayout(box) for key, label, is_secret in entries: field = QLineEdit(current_values.get(key, "")) if is_secret: field.setEchoMode(QLineEdit.EchoMode.Password) form.addRow(label, field) self._fields[key] = field layout.addWidget(box) button_row = QHBoxLayout() save_button = QPushButton("Save") cancel_button = QPushButton("Cancel") save_button.clicked.connect(self._on_save) cancel_button.clicked.connect(self.reject) button_row.addStretch() button_row.addWidget(cancel_button) button_row.addWidget(save_button) layout.addLayout(button_row) def _on_save(self) -> None: values = {key: field.text().strip() for key, field in self._fields.items()} try: config.save_settings(values) except OSError as exc: QMessageBox.critical(self, "Couldn't save settings", str(exc)) return self.accept()