Progress Bar und Diff-PDF-Icon im TreeWidget implementiert

Neue Features:
- Progress Bar in Spalte 2 während XML-Transformationen
- Diff-PDF-Icon erscheint nach Transformation bei vorhandener Diff-PDF
- Doppelklick auf Icon öffnet Diff-PDF mit System-Viewer
- Initial-Laden von Icons für existierende Diff-PDFs beim Projektstart

Technische Implementierung:
- XML-Item-Mapping mit eindeutigem Key-Format: "xml_path|xsl_id"
- Unterstützt mehrfache Verwendung derselben XML bei verschiedenen XSL-Dateien
- TransformationThread-Signale erweitert um XSL-ID-Parameter
- Widget-Factory-Methoden für zentrierte Progress Bar und klickbare Icons
- Result-Dictionary in transform.py enthält jetzt xsl_id

UI-Anpassungen:
- TreeWidget Spaltenanzahl von 2 auf 3 erhöht
- setItemWidget() für dynamische Widget-Verwaltung in Spalte 2

Dateien:
- src/ui/MainWindow.py: Hauptimplementierung mit Signal-Handlern
- src/transform.py: xsl_id im Result-Dictionary
- src/ui/MainWinddow.ui: Spalte 3 hinzugefügt
- src/ui/MainWinddow_ui.py: Auto-generiert aus UI-Datei

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-13 21:06:40 +01:00
parent b961fe1e1a
commit 629485f5e4
4 changed files with 1084 additions and 838 deletions
+19 -9
View File
@@ -34,7 +34,7 @@ class TransformationJob:
apache_fop_dir: Path,
diff_pdf_path: Path,
diff_pdf_params: list[str],
xsl_id: tuple | None = None
xsl_id: tuple | None = None,
):
"""
Initialisiert einen Transformations-Job.
@@ -92,6 +92,7 @@ class TransformationJob:
# Apache FOP Binaries (plattformabhängig)
import sys
if sys.platform == "win32":
self.fop_cmd = self.apache_fop_dir / "fop.cmd"
else:
@@ -158,11 +159,13 @@ class TransformationJob:
# Sammle alle JAR-Dateien im Saxon-Verzeichnis für den Classpath
import glob
saxon_dir = self.saxon_jar_path.parent
all_jars = glob.glob(str(saxon_dir / "*.jar"))
# Verwende alle JARs im Classpath (getrennt durch : auf Linux/Mac, ; auf Windows)
import sys
classpath_separator = ";" if sys.platform == "win32" else ":"
classpath = classpath_separator.join(all_jars)
@@ -187,14 +190,16 @@ class TransformationJob:
cmd_line,
capture_output=True,
text=True,
timeout=120 # 2 Minuten Timeout
timeout=120, # 2 Minuten Timeout
)
if result.returncode == 0:
logger.info(f"Saxon-Transformation erfolgreich: {self.xml_file.name}")
return True, "Erfolgreich"
else:
error_msg = f"Saxon-Fehler (Exit {result.returncode}):\nStdOut: {result.stdout}\nStdErr: {result.stderr}"
error_msg = (
f"Saxon-Fehler (Exit {result.returncode}):\nStdOut: {result.stdout}\nStdErr: {result.stderr}"
)
logger.error(error_msg)
return False, error_msg
@@ -230,10 +235,13 @@ class TransformationJob:
# Apache FOP Kommandozeile
cmd_line = [
str(self.fop_cmd),
"-c", str(self.fop_conf) if self.fop_conf.exists() else "",
"-c",
str(self.fop_conf) if self.fop_conf.exists() else "",
"-r",
"-fo", str(self.temp_fo),
"-pdf", str(self.new_pdf),
"-fo",
str(self.temp_fo),
"-pdf",
str(self.new_pdf),
]
# Entferne leere Config-Parameter wenn fop.xconf nicht existiert
@@ -248,7 +256,7 @@ class TransformationJob:
cmd_line,
capture_output=True,
text=True,
timeout=180 # 3 Minuten Timeout
timeout=180, # 3 Minuten Timeout
)
# Temporäre FO-Datei löschen
@@ -264,6 +272,7 @@ class TransformationJob:
if not self.ref_pdf.exists():
try:
import shutil
shutil.copy2(self.new_pdf, self.ref_pdf)
logger.info(f"Ref-PDF erstellt: {self.ref_pdf}")
except Exception as e:
@@ -320,7 +329,7 @@ class TransformationJob:
cmd_compare,
capture_output=True,
text=True,
timeout=60 # 1 Minute Timeout
timeout=60, # 1 Minute Timeout
)
if result.returncode == 0:
@@ -355,7 +364,7 @@ class TransformationJob:
cmd_diff,
capture_output=True,
text=True,
timeout=90 # 1.5 Minuten Timeout
timeout=90, # 1.5 Minuten Timeout
)
if result_diff.returncode == 0 or self.diff_pdf.exists():
@@ -392,6 +401,7 @@ class TransformationJob:
result = {
"success": False,
"xml_file": str(self.xml_file),
"xsl_id": self.xsl_id,
"steps": {},
"duration": None,
"new_pdf": str(self.new_pdf) if self.new_pdf.exists() else None,