CLAUDE.md Dokumentation hinzugefügt und Konfigurationspfad-Handling verbessert
- CLAUDE.md mit umfassender Projektdokumentation für Claude Code hinzugefügt - Beschreibt Architektur, Datenmodelle, UI-Muster und Entwicklungsworkflows - Konfigurationspfad-Verarbeitung in src/conf.py robuster gemacht: - os.path durch pathlib.Path ersetzt - Validierung für Schreibrechte und Verzeichnisexistenz hinzugefügt - Besseres Error-Handling mit sys.exit(1) bei fehlenden Berechtigungen 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,163 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
## 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
|
||||||
+11
-6
@@ -1,4 +1,5 @@
|
|||||||
from os import path
|
import os
|
||||||
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from sys import platform
|
from sys import platform
|
||||||
from typing import Tuple, Type
|
from typing import Tuple, Type
|
||||||
@@ -18,15 +19,15 @@ app_name = "DocuMentor"
|
|||||||
|
|
||||||
|
|
||||||
if platform == "win32":
|
if platform == "win32":
|
||||||
config_path = f"%APPDATA%\\{app_name}\\config.json"
|
tmp_config_path = f"%APPDATA%\\{app_name}\\config.json"
|
||||||
elif platform in ("linux", "linux2"):
|
elif platform in ("linux", "linux2"):
|
||||||
config_path = f"~/.config/{app_name}/config.json"
|
tmp_config_path = f"~/.config/{app_name}/config.json"
|
||||||
elif platform == "darwin":
|
elif platform == "darwin":
|
||||||
config_path = f"~/Library/Application Support/{app_name}/͏͏͏͏config.json"
|
tmp_config_path = f"~/Library/Application Support/{app_name}/͏͏͏͏config.json"
|
||||||
else:
|
else:
|
||||||
config_path = f"~/.config/{app_name}/config.json"
|
tmp_config_path = f"~/.config/{app_name}/config.json"
|
||||||
|
|
||||||
config_path = Path(path.expandvars(config_path)).expanduser()
|
config_path = Path(os.path.expandvars(tmp_config_path)).expanduser()
|
||||||
|
|
||||||
|
|
||||||
class JavaVm(BaseModel):
|
class JavaVm(BaseModel):
|
||||||
@@ -159,6 +160,10 @@ class AppSettings(BaseSettings):
|
|||||||
if not config_path.parent.exists():
|
if not config_path.parent.exists():
|
||||||
config_path.parent.mkdir(parents=True, exist_ok=True)
|
config_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
if not config_path.parent.is_dir() or not os.access(config_path.parent, os.W_OK):
|
||||||
|
logger.exception(f"{config_path.parent} ist kein Verzeichnis oder es gibt keine Schreibrechte")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
# Konfiguration speichern
|
# Konfiguration speichern
|
||||||
with open(config_path, "wb") as c:
|
with open(config_path, "wb") as c:
|
||||||
c.write(app_settings.model_dump_json(indent=4).encode())
|
c.write(app_settings.model_dump_json(indent=4).encode())
|
||||||
|
|||||||
Reference in New Issue
Block a user