Feat: Ref-PDF automatisch im internen Viewer anzeigen wenn keine Diff-PDF vorhanden

Beim Auswählen eines XML-Knotens im Baum wird jetzt die Ref-PDF direkt im
internen Viewer geladen, sofern keine Diff-PDF existiert. Der Kontextmenü-Eintrag
"Ref-PDF öffnen" und der zugehörige Handler wurden entfernt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-14 17:01:19 +01:00
parent 93f9bb90dd
commit 4f2d136d17
3 changed files with 121 additions and 92 deletions
+2 -62
View File
@@ -1,8 +1,8 @@
import logging import logging
import shutil import shutil
from PySide6.QtCore import Qt, QUrl, QEvent from PySide6.QtCore import Qt, QEvent
from PySide6.QtGui import QAction, QDesktopServices from PySide6.QtGui import QAction
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
QMainWindow, QMainWindow,
QApplication, QApplication,
@@ -870,66 +870,6 @@ class MainWindow(
logger.error(f"Fehler beim Akzeptieren der Änderungen: {e}") logger.error(f"Fehler beim Akzeptieren der Änderungen: {e}")
QMessageBox.critical(self, "Fehler", f"Fehler beim Akzeptieren der Änderungen:\n{str(e)}") QMessageBox.critical(self, "Fehler", f"Fehler beim Akzeptieren der Änderungen:\n{str(e)}")
def _open_ref_pdf_for_xml_file(self, item):
"""
Handler für Kontextmenü-Aktion "Ref-PDF öffnen" bei XML-Dateien.
Öffnet die Referenz-PDF für die ausgewählte XML-Datei im systemseitig installierten PDF-Viewer.
Args:
item: Das TreeWidgetItem der XML-Datei
"""
try:
if not self.project:
QMessageBox.warning(self, "Fehler", "Kein Projekt geöffnet")
return
# Hole XML-Datei-Objekt
xml_file_obj = item.data(0, Qt.ItemDataRole.UserRole)
if not xml_file_obj:
QMessageBox.warning(self, "Fehler", "XML-Datei-Objekt nicht gefunden")
return
# Hole Parent-Item (XslFile)
parent_item = item.parent()
if not parent_item:
QMessageBox.warning(self, "Fehler", "Parent-Item nicht gefunden")
return
# Hole XslFile-Objekt
xsl_file_obj = parent_item.data(0, Qt.ItemDataRole.UserRole)
if not xsl_file_obj:
QMessageBox.warning(self, "Fehler", "XSL-Datei-Objekt nicht gefunden")
return
# Erstelle XSL-ID-String
xsl_id_str = "_".join(map(str, xsl_file_obj.id))
# Ermittle PDF-Dateinamen
xml_file_path = xml_file_obj.xml
xml_stem = xml_file_path.stem
pdf_basename = f"{xml_stem}_xsl_{xsl_id_str}.pdf"
# Pfad zur Ref-PDF
ref_dir = self.project.project_dir / "ref"
ref_pdf_path = ref_dir / pdf_basename
# Prüfe ob Ref-PDF existiert
if not ref_pdf_path.exists():
QMessageBox.warning(self, "Fehler", f"Referenz-PDF nicht gefunden:\n{pdf_basename}")
logger.warning(f"Referenz-PDF nicht gefunden: {ref_pdf_path}")
return
# Öffne Ref-PDF im System-Viewer
logger.info(f"Öffne Referenz-PDF im System-Viewer: {ref_pdf_path}")
url = QUrl.fromLocalFile(str(ref_pdf_path))
if not QDesktopServices.openUrl(url):
QMessageBox.critical(self, "Fehler", f"Konnte Referenz-PDF nicht öffnen:\n{ref_pdf_path}")
logger.error(f"Fehler beim Öffnen der Referenz-PDF: {ref_pdf_path}")
except Exception as e:
logger.error(f"Fehler beim Öffnen der Referenz-PDF: {e}")
QMessageBox.critical(self, "Fehler", f"Fehler beim Öffnen der Referenz-PDF:\n{str(e)}")
def eventFilter(self, obj, event): def eventFilter(self, obj, event):
""" """
Event-Filter für Zoom per STRG+Mausrad im PDF-Viewer. Event-Filter für Zoom per STRG+Mausrad im PDF-Viewer.
+112
View File
@@ -550,6 +550,118 @@ class PdfViewerMixin:
QMessageBox.critical(self, "Fehler", f"Konnte Referenz-PDF nicht öffnen:\n{self.current_ref_pdf_path}") QMessageBox.critical(self, "Fehler", f"Konnte Referenz-PDF nicht öffnen:\n{self.current_ref_pdf_path}")
logger.error(f"Fehler beim Öffnen der Referenz-PDF: {self.current_ref_pdf_path}") logger.error(f"Fehler beim Öffnen der Referenz-PDF: {self.current_ref_pdf_path}")
def _load_ref_pdf_for_display(self, xml_file_path: Path, xsl_id_str: str):
"""
Lädt nur die Ref-PDF in den Viewer (wenn keine Diff-PDF vorhanden ist).
Args:
xml_file_path: Pfad zur XML-Datei (relativ)
xsl_id_str: XSL-ID als String
"""
try:
if not self.project:
return
xml_stem = xml_file_path.stem
pdf_basename = f"{xml_stem}_xsl_{xsl_id_str}.pdf"
ref_pdf_path = self.project.project_dir / "ref" / pdf_basename
if not ref_pdf_path.exists():
if self.pdf_documents:
self._clear_pdf_viewer()
return
logger.info(f"Lade Ref-PDF für Anzeige: {pdf_basename}")
self._clear_layout(self.ui.verticalLayout_2)
self._clear_layout(self.ui.verticalLayout_3)
self.ui.verticalLayout_2.setSpacing(5)
self.ui.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
self.thumbnail_to_page = {}
self.pdf_documents = {}
self.current_rendered_pixmaps = None
self.fullsize_label = None
ref_doc = QPdfDocument()
ref_doc.load(str(ref_pdf_path))
if ref_doc.status() != QPdfDocument.Status.Ready:
QMessageBox.critical(self, "Fehler", f"Fehler beim Laden der Ref-PDF:\n{pdf_basename}")
return
# Ref-Doc in allen drei Slots speichern, damit render_and_display_page funktioniert
self.pdf_documents[pdf_basename] = {"diff": ref_doc, "ref": ref_doc, "new": ref_doc}
self.current_ref_pdf_path = ref_pdf_path
self.current_new_pdf_path = None
self.ui.view_ref_pdf.setEnabled(True)
self.ui.view_new_pdf.setEnabled(False)
# Alpha deaktivieren (Blending nicht sinnvoll ohne Diff), Zoom aktivieren
self.ui.alpha.setValue(0)
self.ui.alpha.setEnabled(False)
self.ui.zoom.setEnabled(True)
self.ui.accept_changes.setEnabled(False)
max_pages = ref_doc.pageCount()
logger.info(f"Ref-PDF geladen: {pdf_basename}, {max_pages} Seiten")
thumbnail_labels = []
for page_num in range(max_pages):
thumbnail = QLabel()
thumbnail.setObjectName(f"thumbnail_{pdf_basename}_page_{page_num + 1}")
thumbnail.setText(f"Seite {page_num + 1}\n")
thumbnail.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
thumbnail.setMouseTracking(True)
thumbnail.setAlignment(Qt.AlignmentFlag.AlignCenter)
thumbnail.setMinimumHeight(150)
self.ui.verticalLayout_2.addWidget(thumbnail)
thumbnail_info = QLabel(f"Seite {page_num + 1}")
thumbnail_info.setAlignment(Qt.AlignmentFlag.AlignCenter)
thumbnail_info.setMaximumHeight(18)
thumbnail_info.setContentsMargins(0, 0, 0, 0)
self.ui.verticalLayout_2.addWidget(thumbnail_info)
self.thumbnail_to_page[thumbnail] = {"pdf_filename": pdf_basename, "page_num": page_num}
thumbnail.mousePressEvent = lambda event, t=thumbnail: self.on_thumbnail_clicked(event, t)
thumbnail_labels.append(thumbnail)
self._schedule_thumbnail_rendering(ref_doc, pdf_basename, thumbnail_labels, 0)
spacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
self.ui.verticalLayout_2.addItem(spacer)
if self.fullsize_label is None:
self.fullsize_label = QLabel()
self.fullsize_label.setObjectName("fullsize_current_page")
self.fullsize_label.setAlignment(Qt.AlignmentFlag.AlignHCenter)
self.fullsize_label.setCursor(QCursor(Qt.CursorShape.OpenHandCursor))
self.ui.verticalLayout_3.addWidget(self.fullsize_label)
self.fullsize_label.mousePressEvent = lambda event: self.on_fullsize_mouse_press(
event, self.fullsize_label
)
self.fullsize_label.mouseMoveEvent = lambda event: self.on_fullsize_mouse_move(
event, self.fullsize_label
)
self.fullsize_label.mouseReleaseEvent = lambda event: self.on_fullsize_mouse_release(
event, self.fullsize_label
)
self.current_pdf = pdf_basename
self.current_diff_xml_path = None
self.current_diff_xsl_id = None
self.render_and_display_page(pdf_basename, 0)
logger.info(f"Ref-PDF-Anzeige geladen: {pdf_basename}")
except Exception as e:
logger.error(f"Fehler beim Laden der Ref-PDF: {e}")
QMessageBox.critical(self, "Fehler", f"Konnte Ref-PDF nicht laden:\n{str(e)}")
def _on_view_new_pdf_clicked(self): def _on_view_new_pdf_clicked(self):
""" """
Handler für view_new_pdf Button. Handler für view_new_pdf Button.
+7 -30
View File
@@ -140,9 +140,13 @@ class TreeManagerMixin:
logger.info(f"XML-Knoten mit Diff-PDF ausgewählt: {pdf_basename}, lade automatisch") logger.info(f"XML-Knoten mit Diff-PDF ausgewählt: {pdf_basename}, lade automatisch")
self._load_pdf_for_comparison(xml_file_path, xsl_id_str) self._load_pdf_for_comparison(xml_file_path, xsl_id_str)
else: else:
# Kein Diff-PDF - Viewer leeren falls noch ein PDF geladen ist # Kein Diff-PDF - Ref-PDF laden falls vorhanden, sonst Viewer leeren
if self.pdf_documents: ref_pdf_path = self.project.project_dir / "ref" / pdf_basename
logger.debug("XML-Knoten ohne Diff-PDF ausgewählt, leere Viewer") if ref_pdf_path.exists():
logger.info(f"XML-Knoten ohne Diff-PDF, lade Ref-PDF: {pdf_basename}")
self._load_ref_pdf_for_display(xml_file_path, xsl_id_str)
elif self.pdf_documents:
logger.debug("XML-Knoten ohne Diff-PDF und ohne Ref-PDF, leere Viewer")
self._clear_pdf_viewer() self._clear_pdf_viewer()
else: else:
logger.debug("XML-File-Daten fehlen (xml_file_obj oder xsl_id_str ist None)") logger.debug("XML-File-Daten fehlen (xml_file_obj oder xsl_id_str ist None)")
@@ -410,33 +414,6 @@ class TreeManagerMixin:
menu.addSeparator() menu.addSeparator()
# Ref-PDF öffnen Aktion (nur enabled wenn Ref-PDF existiert und keine Diff-PDF)
xml_file_obj = item.data(0, Qt.ItemDataRole.UserRole)
parent_item = item.parent()
ref_pdf_can_open = False
if xml_file_obj and parent_item and self.project:
xsl_file_obj = parent_item.data(0, Qt.ItemDataRole.UserRole)
if xsl_file_obj:
# Erstelle Pfade zu Ref-PDF und Diff-PDF
xsl_id_str = "_".join(map(str, xsl_file_obj.id))
xml_stem = xml_file_obj.xml.stem
pdf_basename = f"{xml_stem}_xsl_{xsl_id_str}.pdf"
ref_pdf_path = self.project.project_dir / "ref" / pdf_basename
diff_pdf_path = self.project.project_dir / "diff" / pdf_basename
# Ref-PDF kann geöffnet werden, wenn sie existiert und keine Diff-PDF vorhanden ist
ref_pdf_can_open = ref_pdf_path.exists() and not diff_pdf_path.exists()
action_open_ref_pdf = QAction("Ref-PDF öffnen", self)
action_open_ref_pdf.setIcon(QIcon(QIcon.fromTheme("document-open")))
action_open_ref_pdf.triggered.connect(lambda: self._open_ref_pdf_for_xml_file(item))
action_open_ref_pdf.setEnabled(ref_pdf_can_open)
menu.addAction(action_open_ref_pdf)
menu.addSeparator()
action_edit = QAction("Bearbeiten", self) action_edit = QAction("Bearbeiten", self)
action_edit.setIcon(QIcon(QIcon.fromTheme(QIcon.ThemeIcon.DocumentProperties))) action_edit.setIcon(QIcon(QIcon.fromTheme(QIcon.ThemeIcon.DocumentProperties)))
action_edit.triggered.connect(lambda: self._edit_xml_file(item)) action_edit.triggered.connect(lambda: self._edit_xml_file(item))