Docs: AGENTS.md mit CLAUDE.md konsolidiert und Einzeldatei entfernt
Code-Style-Richtlinien (Imports, Type Annotations, Naming, Logging, Docstrings), UI-Import-Pattern, Thread-Pattern, RAM-Optimierung und Test-Infos aus AGENTS.md übernommen. Veraltete Einträge korrigiert (qdarktheme entfernt, _execute_sql_query → DatabaseQueryThread, XslDependencyDialog dokumentiert). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,184 +1,350 @@
|
||||
# CLAUDE.md
|
||||
|
||||
Spreche mit mir auf Deutsch! (Communicate with me in German!)
|
||||
|
||||
## Projektübersicht
|
||||
|
||||
DocuMentor (ehemals xsl-validator) ist eine PySide6-basierte Desktop-Anwendung zur Verwaltung und Validierung von XSL-Transformationen mit XML-Dateien. Sie bietet eine GUI zur Konfiguration von Transformations-Toolchains (Saxon, Apache FOP, diff-pdf) und zur Verwaltung von PDF-Generierungsprojekten mit PostgreSQL-Datenbankintegration.
|
||||
|
||||
## Anvisiertes Nutzungsszenario
|
||||
Der primäre Einsatz ist die kontinuierliche Weiterentwicklung von PDF-Dokumenten in Flexnow (Software zur Prüfungsverwaltung). Dabei handelt es sich beispielsweise um amtliche Urkunden, Zeugnisse und Bescheide.
|
||||
|
||||
Die Basis bilden etwa 100 XSL-Dateien. Die meisten sind mittels `<xsl:import/>` bzw. `<xsl:include/>` miteinander verknüpft (ähnlich der Klassen-Vererbung). Daher können sich Änderungen in einer XSL-Datei auf (unerwartet) viele andere auswirken. Um diese Auswirkungen im Auge zu behalten, wird DocuMentor entwickelt.
|
||||
|
||||
**Typischer Workflow:**
|
||||
1. Entwickler führt benötigte Änderungen an den XSL-Dateien durch
|
||||
2. Entwickler startet die Transformation im DocuMentor und begutachtet die generierte PDF-Diff
|
||||
3. Prüfung: Wurden die richtigen PDF-Dateien geändert?
|
||||
4. Prüfung: Hat die Änderung der XSL-Dateien die erhoffte Änderung in den PDF-Dateien ergeben?
|
||||
|
||||
Diese Schritte können sich mehrfach wiederholen.
|
||||
|
||||
Da der DocuMentor permanent im Hintergrund läuft, ist ein sparsamer Umgang mit RAM wichtig.
|
||||
|
||||
## PySide6-GUI
|
||||
- Beim Erstellen neuer Dialoge und Fenster sollte immer eine entsprechende UI-Datei erstellt werden
|
||||
- Der Entwickler sollte später in der Lage sein, den neuen Dialog bzw. Fenster über diese UI-Datei zu gestalten
|
||||
- Aus der UI-Datei wird in Visual Studio Code über eine Erweiterung automatisch eine .py-Datei erzeugt
|
||||
- Die automatisch generierte .py-Datei muss in den Code eingebunden und verwendet werden
|
||||
|
||||
## Entwicklungskommandos
|
||||
|
||||
### Paketverwaltung
|
||||
Dieses Projekt verwendet den `uv` Paketmanager (nicht pip oder poetry):
|
||||
```bash
|
||||
uv sync # Abhängigkeiten installieren
|
||||
uv run python src/main.py # Anwendung starten
|
||||
uv run python test_hash_implementation.py # Hash-Tests ausführen
|
||||
```
|
||||
|
||||
### Linting
|
||||
```bash
|
||||
uv run ruff check # Code-Style prüfen (Zeilenlänge: 120)
|
||||
uv run ruff format # Code formatieren
|
||||
```
|
||||
|
||||
## Architektur
|
||||
|
||||
### Konfigurationssystem (src/conf.py)
|
||||
|
||||
Die Anwendung verwendet ein zentralisiertes Konfigurationsmodell mit Pydantic:
|
||||
|
||||
- **AppSettings**: Globales Singleton (`app_settings`), das die gesamte Anwendungskonfiguration speichert
|
||||
- Wird an plattformspezifischen Orten gespeichert:
|
||||
- Linux: `~/.config/DocuMentor/config.json`
|
||||
- Windows: `%APPDATA%\DocuMentor\config.json`
|
||||
- macOS: `~/Library/Application Support/DocuMentor/config.json`
|
||||
- Enthält Listen von Tools: `java_vms`, `saxon_jars`, `apache_fops`, `diff_pdfs`, `xsl_dirs`, `postgresql_dbs`
|
||||
|
||||
- **ProjectData**: Projektspezifische Einstellungen, die in `project.yaml` im jeweiligen Projektverzeichnis gespeichert werden
|
||||
- Enthält hierarchische Baumstruktur von Transformationsknoten
|
||||
- Verwendet `TreeNode` und `XslFile` zur Organisation
|
||||
- Jede `XmlFile` hat eine optionale `hashsum` (blake2b) zur Änderungsverfolgung
|
||||
|
||||
### Wichtige Datenmodelle
|
||||
|
||||
1. **Tool-Konfigurationsmodelle** (JavaVm, SaxonJar, ApacheFop, DiffPdf, XslDir, PostgreSqlDb):
|
||||
- Jedes hat eine `id` und `version`
|
||||
- Speichert Pfade zu Binärdateien/Verzeichnissen
|
||||
|
||||
2. **Project-Modell**:
|
||||
- Referenziert Tool-Konfigurationen über ID
|
||||
- Verlinkt zu einem Projektverzeichnis mit `project.yaml`
|
||||
- Hat Hilfsmethoden wie `getXsl()`, `getJavaVm()` um IDs in Namen/Versionen aufzulösen
|
||||
|
||||
3. **Baumstruktur** (TreeNode → XslFile → XmlFile):
|
||||
- Hierarchische Organisation von Transformations-Workflows
|
||||
- `TreeNode`: Organisationseinheit mit `xslt_params` und Kindknoten/-dateien
|
||||
- `XslFile`: XSL-Stylesheet mit zugehörigen XML-Dateien und XSLT-Parametern
|
||||
- `XmlFile`: XML-Eingabedatei mit optionalem blake2b-Hash
|
||||
|
||||
### UI-Architektur (src/ui/)
|
||||
|
||||
Die Anwendung folgt einem spezifischen PySide6-Muster:
|
||||
|
||||
1. **UI-Definitionsdateien** (`*_ui.py`): Automatisch generiert aus UI-Designer-Dateien
|
||||
- Diese Dateien definieren die UI-Struktur als Klassen (z.B. `Ui_MainWindow`)
|
||||
- Sollten NICHT manuell bearbeitet werden
|
||||
|
||||
2. **Implementierungsdateien** (ohne `_ui` Suffix): Tatsächliche Dialog-/Fenster-Implementierungen
|
||||
- Importieren und verwenden die entsprechende `*_ui.py` Datei
|
||||
- Enthalten Business-Logik und Signal/Slot-Verbindungen
|
||||
- Beispiel: `MainWindow.py` verwendet `Ui_MainWindow` aus `MainWinddow_ui.py`
|
||||
|
||||
Beim Erstellen neuer Dialoge:
|
||||
- Immer zuerst eine entsprechende UI-Datei erstellen
|
||||
- Die UI-Datei wird automatisch als `.py`-Datei von einer VS Code Extension generiert
|
||||
- Die generierte UI-Klasse in der Implementierungsdatei importieren und verwenden
|
||||
|
||||
### Hauptfenster (src/ui/MainWindow.py)
|
||||
|
||||
Zentrale Schaltstelle der Anwendung mit mehreren wichtigen Verantwortlichkeiten:
|
||||
|
||||
1. **Projektverwaltung**:
|
||||
- Öffnet und verwaltet PDF-Transformationsprojekte
|
||||
- Lädt/speichert `ProjectData` aus `project.yaml` Dateien
|
||||
|
||||
2. **Tree Widget**: Zeigt hierarchische Struktur von Transformationsknoten an
|
||||
- Kontextmenüs zum Hinzufügen/Bearbeiten/Löschen von Knoten, XSL-Dateien und XML-Dateien
|
||||
- Drag-and-Drop-Unterstützung für XML-Dateien
|
||||
|
||||
3. **PDF-Vergleichsansicht**:
|
||||
- Drei-Panel-Ansicht (Referenz, Diff, Neu)
|
||||
- Alpha-Blending für visuellen Vergleich
|
||||
- Zoom- und Pan-Funktionalität
|
||||
|
||||
4. **Asynchrone Operationen**:
|
||||
- `XmlHashCalculatorThread`: Hintergrund-blake2b-Hash-Berechnung für XML-Dateien
|
||||
- `DatabaseTestThread` (in PostgreSqlConfigDialog): Asynchrones Testen von Datenbankverbindungen
|
||||
|
||||
### Hash-Berechnungssystem
|
||||
|
||||
Die Anwendung verwendet blake2b-Hashing zur Verfolgung von XML-Dateiänderungen:
|
||||
|
||||
- **Automatisch**: Hashes werden berechnet, wenn Projekte geladen werden (nur für Dateien ohne existierenden Hash)
|
||||
- **Asynchron**: Hintergrund-Thread (`XmlHashCalculatorThread`) um die UI reaktionsfähig zu halten
|
||||
- **Format**: `blake2b:<64-Zeichen-Hexdigest>`
|
||||
- **Speicherung**: Persistiert in `project.yaml` innerhalb jedes `XmlFile`-Objekts
|
||||
- **Details**: Siehe `docs/blake2b_hash_implementation.md`
|
||||
|
||||
### Theme-System
|
||||
|
||||
Die Anwendung unterstützt mehrere Qt-Themes:
|
||||
- Theme-Auswahlmenü wird dynamisch aus `QStyleFactory.keys()` befüllt
|
||||
- Theme-Präferenz wird in `AppSettings.theme` gespeichert
|
||||
- Dark-Theme-Unterstützung via `qdarktheme` Paket (aktuell in main.py auskommentiert)
|
||||
|
||||
### Datenbankintegration
|
||||
|
||||
PostgreSQL-Integration mit Polars und ConnectorX:
|
||||
- Konfiguration wird im `PostgreSqlDb`-Modell mit SSL-Modus-Unterstützung gespeichert
|
||||
- SQL-Abfragen werden via `_execute_sql_query()` im MainWindow ausgeführt
|
||||
- Ergebnisse werden in Polars DataFrames geladen
|
||||
|
||||
## Wichtige Konventionen
|
||||
|
||||
### Deutsche Sprache
|
||||
Die Codebasis verwendet Deutsch für:
|
||||
- UI-Texte und Labels
|
||||
- Kommentare und Dokumentation
|
||||
- Variablennamen wo kontextuell passend
|
||||
- Log-Meldungen
|
||||
|
||||
### Pfadbehandlung
|
||||
- Immer `pathlib.Path`-Objekte verwenden, keine Strings
|
||||
- `expanduser()` und `expandvars()` für Benutzer-/Umgebungspfade verwenden
|
||||
- Projektrelative Pfade werden als relativ gespeichert, zur Laufzeit gegen `project_dir` aufgelöst
|
||||
|
||||
### ID-basierte Lookups
|
||||
Konfigurationsentitäten (Tools, Datenbanken) werden in Projekten über ID referenziert. Die Hilfsmethoden des `Project`-Modells (`getXsl()`, `getJavaVm()`, etc.) verwenden, um IDs in Anzeigewerte aufzulösen.
|
||||
|
||||
### Einstellungspersistenz
|
||||
- Globale Einstellungen: `app_settings.save()` nach Änderungen aufrufen
|
||||
- Projekteinstellungen: `project_data.writeSettings(project_dir)` nach Änderungen aufrufen
|
||||
|
||||
## Arbeiten mit der Codebasis
|
||||
|
||||
### Neue Tool-Konfigurationen hinzufügen
|
||||
1. Modell zu `conf.py` hinzufügen (ähnlich wie `JavaVm`, `SaxonJar`)
|
||||
2. Listenfeld zu `AppSettings` hinzufügen
|
||||
3. Konfigurationsdialog in `src/ui/` erstellen (UI-Datei + Implementierung)
|
||||
4. Zu `AppSettings.py` Tabs hinzufügen
|
||||
5. `Project`-Modell aktualisieren, falls das Tool projektspezifisch sein soll
|
||||
|
||||
### Neue Baumoperationen hinzufügen
|
||||
1. Aktion zum Kontextmenü in `_create_context_menu_for_type()` hinzufügen
|
||||
2. Handler-Methode implementieren nach Namensschema `_action_tree_node()`, `_action_xsl_file()`, etc.
|
||||
3. Baum nach Änderungen mit `_load_nodes_to_tree()` aktualisieren
|
||||
4. `self.project_data.writeSettings(self.project.project_dir)` aufrufen um Änderungen zu persistieren
|
||||
|
||||
### Projektstruktur modifizieren
|
||||
Das `ProjectData`-Modell ist die Quelle der Wahrheit. Alle Änderungen an der Baumstruktur müssen:
|
||||
1. Die `project_data.nodes` Liste modifizieren
|
||||
2. `project_data.writeSettings()` aufrufen um zu persistieren
|
||||
3. Baum mit `_load_nodes_to_tree()` neu laden um Änderungen in der UI zu reflektieren
|
||||
# CLAUDE.md
|
||||
|
||||
Spreche mit mir auf Deutsch! (Communicate with me in German!)
|
||||
|
||||
## Projektübersicht
|
||||
|
||||
DocuMentor (ehemals xsl-validator) ist eine PySide6-basierte Desktop-Anwendung zur Verwaltung und Validierung von XSL-Transformationen mit XML-Dateien. Sie bietet eine GUI zur Konfiguration von Transformations-Toolchains (Saxon, Apache FOP, diff-pdf) und zur Verwaltung von PDF-Generierungsprojekten mit PostgreSQL-Datenbankintegration.
|
||||
|
||||
## Anvisiertes Nutzungsszenario
|
||||
Der primäre Einsatz ist die kontinuierliche Weiterentwicklung von PDF-Dokumenten in Flexnow (Software zur Prüfungsverwaltung). Dabei handelt es sich beispielsweise um amtliche Urkunden, Zeugnisse und Bescheide.
|
||||
|
||||
Die Basis bilden etwa 100 XSL-Dateien. Die meisten sind mittels `<xsl:import/>` bzw. `<xsl:include/>` miteinander verknüpft (ähnlich der Klassen-Vererbung). Daher können sich Änderungen in einer XSL-Datei auf (unerwartet) viele andere auswirken. Um diese Auswirkungen im Auge zu behalten, wird DocuMentor entwickelt.
|
||||
|
||||
**Typischer Workflow:**
|
||||
1. Entwickler führt benötigte Änderungen an den XSL-Dateien durch
|
||||
2. Entwickler startet die Transformation im DocuMentor und begutachtet die generierte PDF-Diff
|
||||
3. Prüfung: Wurden die richtigen PDF-Dateien geändert?
|
||||
4. Prüfung: Hat die Änderung der XSL-Dateien die erhoffte Änderung in den PDF-Dateien ergeben?
|
||||
|
||||
Diese Schritte können sich mehrfach wiederholen.
|
||||
|
||||
Da der DocuMentor permanent im Hintergrund läuft, ist ein sparsamer Umgang mit RAM wichtig:
|
||||
- Worker-Pools nach Verwendung herunterfahren
|
||||
- Große Datenstrukturen frühzeitig freigeben
|
||||
- Polars DataFrames statt Pandas (geringerer RAM-Verbrauch)
|
||||
- Lazy Loading wo möglich
|
||||
|
||||
## Entwicklungskommandos
|
||||
|
||||
### Paketverwaltung
|
||||
Dieses Projekt verwendet den `uv` Paketmanager (nicht pip oder poetry):
|
||||
```bash
|
||||
uv sync # Abhängigkeiten installieren
|
||||
uv run python src/main.py # Anwendung starten
|
||||
```
|
||||
|
||||
### Linting
|
||||
```bash
|
||||
uv run ruff check # Code-Style prüfen (Zeilenlänge: 120)
|
||||
uv run ruff format # Code formatieren
|
||||
```
|
||||
|
||||
### Tests
|
||||
Dieses Projekt verwendet KEINE pytest/unittest-Frameworks. Tests sind standalone Python-Skripte:
|
||||
```bash
|
||||
uv run python test_hash_implementation.py # Hash-Tests
|
||||
uv run python test_xml_hash_duplicate_detection.py # Duplikatserkennung
|
||||
```
|
||||
|
||||
## Code-Style-Richtlinien
|
||||
|
||||
### Import-Organisation
|
||||
|
||||
Reihenfolge (keine Leerzeilen zwischen Gruppen):
|
||||
```python
|
||||
# 1. Standard Library
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
# 2. Drittanbieter
|
||||
from PySide6.QtCore import Qt, QThread, Signal
|
||||
from PySide6.QtWidgets import QDialog, QMainWindow
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
# 3. Lokale Imports (IMMER absolute Imports, KEINE relativen .imports)
|
||||
from conf import app_settings, TreeNode, XslFile
|
||||
from ui.MainWindow import MainWindow
|
||||
```
|
||||
|
||||
- `TYPE_CHECKING` für zirkuläre Import-Vermeidung nutzen
|
||||
- Keine relativen Imports (`.` oder `..`)
|
||||
|
||||
### Type Annotations
|
||||
|
||||
Moderne Union-Syntax verwenden:
|
||||
```python
|
||||
# RICHTIG
|
||||
def transform(xml_path: Path, params: dict[str, str]) -> tuple[bool, str]:
|
||||
result: str | None = None
|
||||
files: list[Path] = []
|
||||
|
||||
# FALSCH
|
||||
def transform(xml_path, params): # Keine Annotations
|
||||
result: Optional[str] = None # Alte Union-Syntax
|
||||
files: List[Path] = [] # Großgeschriebene Types
|
||||
```
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
```python
|
||||
# Klassen: PascalCase
|
||||
class SaxonWorkerPool:
|
||||
|
||||
# Funktionen/Methoden: snake_case
|
||||
def transform_saxon(xml_file: Path) -> bool:
|
||||
|
||||
# Private Methoden: _snake_case mit Unterstrich
|
||||
def _create_tree_item(self, node: TreeNode):
|
||||
|
||||
# Konstanten: UPPER_CASE
|
||||
SAXON_WORKER_JAVA = """..."""
|
||||
```
|
||||
|
||||
### Formatierung
|
||||
- **Zeilenlänge:** 120 Zeichen (via Ruff konfiguriert)
|
||||
- **Strings:** Bevorzugt Double-Quotes `"..."`, aber konsistent im File
|
||||
- **Trailing Commas:** Bei mehrzeiligen Strukturen verwenden
|
||||
|
||||
### Error Handling
|
||||
|
||||
IMMER Logging statt `print()` verwenden:
|
||||
```python
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def transform(xml_path: Path) -> tuple[bool, str]:
|
||||
try:
|
||||
logger.info(f"Transformation gestartet: {xml_path}")
|
||||
result = do_transform(xml_path)
|
||||
return True, "Erfolg"
|
||||
except FileNotFoundError as e:
|
||||
error_msg = f"XML-Datei nicht gefunden: {xml_path}"
|
||||
logger.error(error_msg)
|
||||
return False, error_msg
|
||||
except Exception as e:
|
||||
error_msg = f"Fehler bei Transformation: {str(e)}"
|
||||
logger.exception(error_msg) # Mit Stack Trace
|
||||
return False, error_msg
|
||||
```
|
||||
|
||||
- `logger.debug()` für Debugging-Infos
|
||||
- `logger.info()` für normale Operationen
|
||||
- `logger.warning()` für Warnungen
|
||||
- `logger.error()` für Fehler ohne Stack Trace
|
||||
- `logger.exception()` für Fehler MIT Stack Trace
|
||||
- Fehlermeldungen auf Deutsch
|
||||
|
||||
### Docstrings
|
||||
|
||||
Google-Style auf Deutsch:
|
||||
```python
|
||||
def transform_xml_to_pdf(xml_path: Path, xsl_path: Path, output_dir: Path) -> tuple[bool, str]:
|
||||
"""
|
||||
Transformiert eine XML-Datei mit XSL zu PDF.
|
||||
|
||||
Args:
|
||||
xml_path: Pfad zur XML-Eingabedatei
|
||||
xsl_path: Pfad zum XSL-Stylesheet
|
||||
output_dir: Zielverzeichnis für PDF-Ausgabe
|
||||
|
||||
Returns:
|
||||
tuple[bool, str]: (Erfolg, Fehlermeldung oder Info-Text)
|
||||
|
||||
Raises:
|
||||
FileNotFoundError: Wenn XML- oder XSL-Datei nicht existiert
|
||||
"""
|
||||
```
|
||||
|
||||
### Pfadbehandlung
|
||||
- Immer `pathlib.Path`-Objekte verwenden, keine Strings
|
||||
- `expanduser()` und `expandvars()` für Benutzer-/Umgebungspfade verwenden
|
||||
- Projektrelative Pfade werden als relativ gespeichert, zur Laufzeit gegen `project_dir` aufgelöst
|
||||
|
||||
## Architektur
|
||||
|
||||
### Konfigurationssystem (src/conf.py)
|
||||
|
||||
Die Anwendung verwendet ein zentralisiertes Konfigurationsmodell mit Pydantic:
|
||||
|
||||
- **AppSettings**: Globales Singleton (`app_settings`), das die gesamte Anwendungskonfiguration speichert
|
||||
- Wird an plattformspezifischen Orten gespeichert:
|
||||
- Linux: `~/.config/DocuMentor/config.json`
|
||||
- Windows: `%APPDATA%\DocuMentor\config.json`
|
||||
- macOS: `~/Library/Application Support/DocuMentor/config.json`
|
||||
- Enthält Listen von Tools: `java_vms`, `saxon_jars`, `apache_fops`, `diff_pdfs`, `xsl_dirs`, `postgresql_dbs`
|
||||
|
||||
- **ProjectData**: Projektspezifische Einstellungen, die in `project.yaml` im jeweiligen Projektverzeichnis gespeichert werden
|
||||
- Enthält hierarchische Baumstruktur von Transformationsknoten
|
||||
- Verwendet `TreeNode` und `XslFile` zur Organisation
|
||||
- Jede `XmlFile` hat eine optionale `hashsum` (blake2b) zur Änderungsverfolgung
|
||||
|
||||
### Wichtige Datenmodelle
|
||||
|
||||
1. **Tool-Konfigurationsmodelle** (JavaVm, SaxonJar, ApacheFop, DiffPdf, XslDir, PostgreSqlDb):
|
||||
- Jedes hat eine `id` und `version`
|
||||
- Speichert Pfade zu Binärdateien/Verzeichnissen
|
||||
|
||||
2. **Project-Modell**:
|
||||
- Referenziert Tool-Konfigurationen über ID
|
||||
- Verlinkt zu einem Projektverzeichnis mit `project.yaml`
|
||||
- Hat Hilfsmethoden wie `getXsl()`, `getJavaVm()` um IDs in Namen/Versionen aufzulösen
|
||||
|
||||
3. **Baumstruktur** (TreeNode → XslFile → XmlFile):
|
||||
- Hierarchische Organisation von Transformations-Workflows
|
||||
- `TreeNode`: Organisationseinheit mit `xslt_params` und Kindknoten/-dateien
|
||||
- `XslFile`: XSL-Stylesheet mit zugehörigen XML-Dateien und XSLT-Parametern
|
||||
- `XmlFile`: XML-Eingabedatei mit optionalem blake2b-Hash
|
||||
|
||||
### UI-Architektur (src/ui/)
|
||||
|
||||
Die Anwendung folgt einem spezifischen PySide6-Muster:
|
||||
|
||||
1. **UI-Definitionsdateien** (`*_ui.py`): Automatisch generiert aus UI-Designer-Dateien
|
||||
- Diese Dateien definieren die UI-Struktur als Klassen (z.B. `Ui_MainWindow`)
|
||||
- Sollten NICHT manuell bearbeitet werden
|
||||
|
||||
2. **Implementierungsdateien** (ohne `_ui` Suffix): Tatsächliche Dialog-/Fenster-Implementierungen
|
||||
- Importieren und verwenden die entsprechende `*_ui.py` Datei
|
||||
- Enthalten Business-Logik und Signal/Slot-Verbindungen
|
||||
- Beispiel: `MainWindow.py` verwendet `Ui_MainWindow` aus `MainWinddow_ui.py`
|
||||
|
||||
Beim Erstellen neuer Dialoge:
|
||||
- Immer zuerst eine entsprechende UI-Datei erstellen
|
||||
- Die UI-Datei wird automatisch als `.py`-Datei von einer VS Code Extension generiert
|
||||
- Die generierte UI-Klasse in der Implementierungsdatei importieren und verwenden
|
||||
|
||||
**UI-Import-Pattern:**
|
||||
```python
|
||||
from PySide6.QtWidgets import QDialog
|
||||
from ui.JavaVmConfigDialog_ui import Ui_JavaVmConfigDialog
|
||||
|
||||
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)
|
||||
```
|
||||
|
||||
- UI-Klassen NIEMALS direkt erben, nur als `self.ui` Member
|
||||
- Alle Widgets über `self.ui.widgetName` zugreifen
|
||||
- Signal-Verbindungen immer NACH `setupUi()` aufrufen
|
||||
|
||||
### Hauptfenster (src/ui/MainWindow.py)
|
||||
|
||||
Zentrale Schaltstelle der Anwendung mit mehreren wichtigen Verantwortlichkeiten:
|
||||
|
||||
1. **Projektverwaltung**:
|
||||
- Öffnet und verwaltet PDF-Transformationsprojekte
|
||||
- Lädt/speichert `ProjectData` aus `project.yaml` Dateien
|
||||
|
||||
2. **Tree Widget**: Zeigt hierarchische Struktur von Transformationsknoten an
|
||||
- Kontextmenüs zum Hinzufügen/Bearbeiten/Löschen von Knoten, XSL-Dateien und XML-Dateien
|
||||
- Drag-and-Drop-Unterstützung für XML-Dateien
|
||||
|
||||
3. **PDF-Vergleichsansicht**:
|
||||
- Drei-Panel-Ansicht (Referenz, Diff, Neu)
|
||||
- Alpha-Blending für visuellen Vergleich
|
||||
- Zoom- und Pan-Funktionalität
|
||||
|
||||
4. **Asynchrone Operationen**:
|
||||
- `XmlHashCalculatorThread`: Hintergrund-blake2b-Hash-Berechnung für XML-Dateien
|
||||
- `DatabaseTestThread` (in PostgreSqlConfigDialog): Asynchrones Testen von Datenbankverbindungen
|
||||
|
||||
### XSL-Abhängigkeitsgraph (src/ui/XslDependencyDialog.py)
|
||||
|
||||
Interaktiver Dialog zur Visualisierung von `<xsl:import/>`- und `<xsl:include/>`-Abhängigkeiten zwischen XSL-Dateien:
|
||||
- Sidebar mit Suchfilter zur Navigation
|
||||
- Abhängigkeitsgraph-Darstellung via vis.js
|
||||
- Parsing der XSL-Dateien mit lxml
|
||||
|
||||
### Hash-Berechnungssystem
|
||||
|
||||
Die Anwendung verwendet blake2b-Hashing zur Verfolgung von XML-Dateiänderungen:
|
||||
|
||||
- **Automatisch**: Hashes werden berechnet, wenn Projekte geladen werden (nur für Dateien ohne existierenden Hash)
|
||||
- **Asynchron**: Hintergrund-Thread (`XmlHashCalculatorThread`) um die UI reaktionsfähig zu halten
|
||||
- **Format**: `blake2b:<64-Zeichen-Hexdigest>`
|
||||
- **Speicherung**: Persistiert in `project.yaml` innerhalb jedes `XmlFile`-Objekts
|
||||
- **Details**: Siehe `docs/blake2b_hash_implementation.md`
|
||||
|
||||
### Theme-System
|
||||
|
||||
Die Anwendung unterstützt mehrere Qt-Themes:
|
||||
- Theme-Auswahlmenü wird dynamisch aus `QStyleFactory.keys()` befüllt
|
||||
- Theme-Präferenz wird in `AppSettings.theme` gespeichert
|
||||
|
||||
### Datenbankintegration
|
||||
|
||||
PostgreSQL-Integration mit Polars und ConnectorX:
|
||||
- Konfiguration wird im `PostgreSqlDb`-Modell mit SSL-Modus-Unterstützung gespeichert
|
||||
- SQL-Abfragen werden asynchron via `DatabaseQueryThread` im `DatabaseMixin` ausgeführt
|
||||
- Ergebnisse werden in Polars DataFrames geladen
|
||||
|
||||
### Thread-basierte Operationen
|
||||
|
||||
```python
|
||||
from PySide6.QtCore import QThread, Signal
|
||||
|
||||
class HashCalculatorThread(QThread):
|
||||
progress = Signal(int)
|
||||
finished = Signal(dict)
|
||||
|
||||
def __init__(self, files: list[Path]):
|
||||
super().__init__()
|
||||
self.files = files
|
||||
|
||||
def run(self):
|
||||
for i, file_path in enumerate(self.files):
|
||||
hash_value = calculate_hash(file_path)
|
||||
self.progress.emit(i + 1)
|
||||
self.finished.emit(results)
|
||||
|
||||
# Verwendung
|
||||
thread = HashCalculatorThread(xml_files)
|
||||
thread.progress.connect(self._on_progress)
|
||||
thread.finished.connect(self._on_finished)
|
||||
thread.start() # NICHT run() direkt aufrufen!
|
||||
```
|
||||
|
||||
## Wichtige Konventionen
|
||||
|
||||
### Deutsche Sprache
|
||||
Die Codebasis verwendet Deutsch für:
|
||||
- UI-Texte und Labels
|
||||
- Kommentare und Dokumentation
|
||||
- Variablennamen wo kontextuell passend
|
||||
- Log-Meldungen
|
||||
|
||||
### ID-basierte Lookups
|
||||
Konfigurationsentitäten (Tools, Datenbanken) werden in Projekten über ID referenziert. Die Hilfsmethoden des `Project`-Modells (`getXsl()`, `getJavaVm()`, etc.) verwenden, um IDs in Anzeigewerte aufzulösen.
|
||||
|
||||
### Einstellungspersistenz
|
||||
- Globale Einstellungen: `app_settings.save()` nach Änderungen aufrufen
|
||||
- Projekteinstellungen: `project_data.writeSettings(project_dir)` nach Änderungen aufrufen
|
||||
|
||||
## Arbeiten mit der Codebasis
|
||||
|
||||
### Neue Tool-Konfigurationen hinzufügen
|
||||
1. Modell zu `conf.py` hinzufügen (ähnlich wie `JavaVm`, `SaxonJar`)
|
||||
2. Listenfeld zu `AppSettings` hinzufügen
|
||||
3. Konfigurationsdialog in `src/ui/` erstellen (UI-Datei + Implementierung)
|
||||
4. Zu `AppSettings.py` Tabs hinzufügen
|
||||
5. `Project`-Modell aktualisieren, falls das Tool projektspezifisch sein soll
|
||||
|
||||
### Neue Baumoperationen hinzufügen
|
||||
1. Aktion zum Kontextmenü in `_create_context_menu_for_type()` hinzufügen
|
||||
2. Handler-Methode implementieren nach Namensschema `_action_tree_node()`, `_action_xsl_file()`, etc.
|
||||
3. Baum nach Änderungen mit `_load_nodes_to_tree()` aktualisieren
|
||||
4. `self.project_data.writeSettings(self.project.project_dir)` aufrufen um Änderungen zu persistieren
|
||||
|
||||
### Projektstruktur modifizieren
|
||||
Das `ProjectData`-Modell ist die Quelle der Wahrheit. Alle Änderungen an der Baumstruktur müssen:
|
||||
1. Die `project_data.nodes` Liste modifizieren
|
||||
2. `project_data.writeSettings()` aufrufen um zu persistieren
|
||||
3. Baum mit `_load_nodes_to_tree()` neu laden um Änderungen in der UI zu reflektieren
|
||||
|
||||
Reference in New Issue
Block a user