Fügt OpenWiki-Setup (Workflow, Seiten, CLAUDE.md-Verweis) und AGENTS.md hinzu, damit wiederkehrende Code-Dokumentation automatisch gepflegt wird. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
6.1 KiB
type, title, description, tags
| type | title | description | tags | |||||
|---|---|---|---|---|---|---|---|---|
| Architecture Overview | Architektur-Überblick | PySide6-Mixin-Architektur, UI-Pattern (generierte UI vs. Implementierung), Thread-Modell und Konfigurationssystem von DocuMentor. |
|
Architektur-Überblick
Technologie-Stack
| Schicht | Technologie | Zweck |
|---|---|---|
| GUI | PySide6 (Qt 6) | Native Desktop-Oberfläche |
| Konfiguration | Pydantic + pydantic-settings | Typsichere Datenmodelle, JSON/YAML-Persistenz |
| Datenverarbeitung | Polars + ConnectorX | PostgreSQL-Abfragen, DataFrames |
| XSL-Parsing | lxml | XSL-Abhängigkeitsgraph |
| Hashing | hashlib (blake2b) | Duplikatserkennung |
| Build | PyInstaller + WiX/Inno Setup | Windows-Distribution |
| Paketverwaltung | uv | Dependency-Management |
Einstiegspunkt
Die Anwendung startet in src/main.py:
- Logging konfigurieren (Datei + Konsole, 24h Auto-Cleanup)
QApplicationerstellen, App-Icon setzenMainWindowinstanziieren und anzeigen- Bei fehlender Tool-Konfiguration
AppSettingsDlgmodal öffnen - Qt-Event-Loop starten
MainWindow – Mixin-Architektur
MainWindow (src/ui/MainWindow.py) ist die zentrale Klasse und erbt von mehreren Mixins, um Funktionalität zu trennen:
MainWindow
├── IconRefreshMixin (src/icons.py) – Theme-Wechsel → Icons neu einfärben
├── QMainWindow (PySide6) – Qt-Basisfenster
├── TreeManagerMixin (mixins/tree_manager.py) – Baum-Widget, Kontextmenüs, Node-Operationen
├── PdfViewerMixin (mixins/pdf_viewer.py) – PDF-Rendering, Alpha-Blending, Zoom
├── WorkerPoolMixin (mixins/worker_pool.py) – Saxon/FOP Worker-Pool Lebenszyklus
├── DatabaseMixin (mixins/database.py) – PostgreSQL-Abfragen, Obsolete-Erkennung
├── DragDropMixin (mixins/drag_drop.py) – Drag-and-Drop für XML-Dateien
├── HashCalculationMixin (mixins/hash_calculation.py) – blake2b-Hash-Berechnung, Duplikatserkennung
└── TransformationMixin (mixins/transformation.py) – XSL-Transformations-Ausführung
Jedes Mixin erwartet bestimmte Attribute (self.ui, self.project, self.pdf_project) und Methoden von anderen Mixins. Die Mixins sind in src/ui/mixins/__init__.py gebündelt.
Mixin-Abhängigkeiten
TransformationMixin benötigt Methoden aus WorkerPoolMixin (_initialize_saxon_worker_pool, _shutdown_saxon_worker_pool) und TreeManagerMixin (_collect_parent_params, _create_centered_progress_bar). HashCalculationMixin und DragDropMixin benötigen _save_project_settings() und _load_nodes_to_tree() von MainWindow.
UI-Pattern: Generierte UI vs. Implementierung
DocuMentor folgt einem strikten PySide6-Pattern:
-
UI-Definitionsdateien (
*_ui.py, z.B.MainWinddow_ui.py): Aus.ui-Dateien von einer VS Code Extension generiert. Enthalten nur Widget-Layout-Definitionen als Klasse (Ui_MainWindow). Nicht manuell bearbeiten. -
Implementierungsdateien (ohne
_ui-Suffix, z.B.MainWindow.py): Importieren die UI-Klasse, instanziieren sie alsself.uiund fügen Business-Logik hinzu.
class JavaVmConfigDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_JavaVmConfigDialog()
self.ui.setupUi(self)
# Signale NACH setupUi() verbinden
self.ui.browseButton.clicked.connect(self._browse_file)
Regeln:
- UI-Klassen niemals direkt erben, nur als
self.ui-Member verwenden - Alle Widgets über
self.ui.widgetNamezugreifen - Signal-Verbindungen immer nach
setupUi()
Thread-Modell
Asynchrone Operationen verwenden QThread-Subklassen aus src/ui/threads.py:
| Thread-Klasse | Zweck | Signale |
|---|---|---|
XmlHashCalculatorThread |
blake2b-Hash-Berechnung für XML-Dateien | hash_calculated, calculation_finished, error_occurred |
XmlBatchProcessingThread |
Batch-Verarbeitung: Hash + Duplikatserkennung + Dateikopieren | progress_update, file_processed, processing_finished |
TransformationThread |
Ausführung der XSL-Transformations-Pipeline | Fortschritts- und Abschluss-Signale |
DatabaseQueryThread |
Asynchrone PostgreSQL-Abfragen (in mixins/database.py) |
query_completed (DataFrame), query_failed |
Wichtig: Threads immer mit .start() starten, nie .run() direkt aufrufen.
Konfigurationssystem
Die Konfiguration ist in Datenmodelle & Konfiguration detailliert beschrieben. Zusammenfassung:
AppSettings(src/conf.py): Globales Singleton (app_settings), gespeichert als JSON. Enthält Tool-Listen, UI-Zustand, Worker-Pool-Einstellungen.ProjectData(src/conf.py): Projektspezifisch, gespeichert alsproject.yamlim Projektverzeichnis. Enthält die Baumstruktur (TreeNode → XslFile → XmlFile).
Icon-System
Icons werden über src/icons.py verwaltet:
- Feather Icons aus dem Qt-Ressource-System (
:/icons/<name>.svg) - Einmaliges Rendern bei 64px, Qt skaliert für 16/24/32px
- Theme-reactiv: Färbung nach
QPalette.WindowText, Cache-Schlüssel enthält Theme-Farbe IconRefreshMixinerlaubt Theme-Wechsel zur Laufzeit ohne manuellen Cache-Reset
XSL-Abhängigkeitsgraph
src/xsl_dependencies.py (XslDependencyGraph) parst XSL-Dateien mit lxml und baut einen Abhängigkeitsgraph für <xsl:import/> und <xsl:include/>. Der Graph wird über Datei-mtime automatisch invalidiert. Visualisiert wird er im Dialog src/ui/XslDependencyDialog.py via vis.js.
Der Abhängigkeitsgraph ist auch für die Transformations-Pipeline relevant: wenn eine importierte XSL-Datei neuer ist als das Output-PDF, gilt die Transformation als veraltet.
Obsolete-Erkennung
src/obsolete_detector.py enthält reine Analyselogik (ohne Qt-Abhängigkeit) zum Finden veralteter XslFile-Einträge nach Datenbank-Import. Wird vom DatabaseMixin nach dem DB-Laden aufgerufen und im ObsoleteEntriesDialog (src/ui/ObsoleteEntriesDialog.py) angezeigt.