Vergleich der PDF

This commit is contained in:
2025-05-27 18:31:45 +02:00
parent 6cd1cb8a2a
commit c2826695c7
+202 -61
View File
@@ -3,7 +3,7 @@ import os
import pymupdf # PyMuPDF import pymupdf # PyMuPDF
from PySide6.QtCore import Qt from PySide6.QtCore import Qt
from PySide6.QtGui import QCursor, QPixmap, QImage from PySide6.QtGui import QCursor, QPixmap, QImage, QPainter
from PySide6.QtWidgets import QLabel, QMainWindow from PySide6.QtWidgets import QLabel, QMainWindow
from ui.MainWinddow_ui import Ui_MainWindow from ui.MainWinddow_ui import Ui_MainWindow
@@ -26,8 +26,10 @@ class MainWindow(QMainWindow):
# Dict zum Speichern der Beziehung zwischen Thumbnails und großen Bildern # Dict zum Speichern der Beziehung zwischen Thumbnails und großen Bildern
self.thumbnail_to_full_image = {} self.thumbnail_to_full_image = {}
# Dict zum Speichern der Original-Pixmaps für Zoom-Funktion # Dicts zum Speichern der Original-Pixmaps für alle drei Ebenen
self.original_pixmaps = {} self.ref_pixmaps = {} # Unterste Ebene (ref)
self.diff_pixmaps = {} # Mittlere Ebene (diff)
self.new_pixmaps = {} # Oberste Ebene (new)
# Aktueller Zoom-Faktor # Aktueller Zoom-Faktor
self.current_zoom = 100 # 100% self.current_zoom = 100 # 100%
@@ -45,75 +47,132 @@ class MainWindow(QMainWindow):
self._connect_signals() self._connect_signals()
def _load_images(self): def _load_images(self):
"""Lädt PDF-Seiten aus der Ntbackup.pdf-Datei.""" """Lädt PDF-Seiten aus den drei Unterordnern ref, diff und new."""
# Entferne bestehende Widgets aus den Layouts # Entferne bestehende Widgets aus den Layouts
self._clear_layout(self.ui.verticalLayout_2) self._clear_layout(self.ui.verticalLayout_2)
self._clear_layout(self.ui.verticalLayout_3) self._clear_layout(self.ui.verticalLayout_3)
# Dicts zurücksetzen # Dicts zurücksetzen
self.thumbnail_to_full_image = {} self.thumbnail_to_full_image = {}
self.original_pixmaps = {} self.ref_pixmaps = {}
self.diff_pixmaps = {}
self.new_pixmaps = {}
# Pfad zur PDF-Datei # Basis-Pfad zu den PDF-Ordnern
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
pdf_path = os.path.join(base_dir, "src", "ui", "res", "pdf", "Ntbackup.pdf") pdf_base_dir = os.path.join(base_dir, "src", "ui", "res", "pdf")
if not os.path.exists(pdf_path): diff_dir = os.path.join(pdf_base_dir, "diff")
print(f"PDF-Datei nicht gefunden: {pdf_path}") ref_dir = os.path.join(pdf_base_dir, "ref")
new_dir = os.path.join(pdf_base_dir, "new")
# Prüfe ob diff-Ordner existiert und PDF-Dateien enthält
if not os.path.exists(diff_dir):
print(f"Diff-Ordner nicht gefunden: {diff_dir}")
return return
try: # Finde alle PDF-Dateien im diff-Ordner
# PDF-Datei öffnen diff_pdfs = glob.glob(os.path.join(diff_dir, "*.pdf"))
pdf_document = pymupdf.open(pdf_path) if not diff_pdfs:
print(f"PDF geladen: {pdf_path} mit {len(pdf_document)} Seiten") print("Keine PDF-Dateien im diff-Ordner gefunden")
return
# Für jede Seite der PDF: print(f"Gefundene PDF-Dateien im diff-Ordner: {diff_pdfs}")
for page_num in range(len(pdf_document)):
page = pdf_document[page_num]
# Seite in hoher Auflösung rendern # Für jede PDF-Datei im diff-Ordner
matrix = pymupdf.Matrix(2.0, 2.0) # 2x Vergrößerung für bessere Qualität for diff_pdf_path in diff_pdfs:
pix = page.get_pixmap(matrix=matrix) pdf_filename = os.path.basename(diff_pdf_path)
ref_pdf_path = os.path.join(ref_dir, pdf_filename)
new_pdf_path = os.path.join(new_dir, pdf_filename)
# PyMuPDF Pixmap zu QImage konvertieren # Prüfe ob gleichnamige PDFs in ref und new existieren
img_data = pix.tobytes("png") if not os.path.exists(ref_pdf_path):
qimg = QImage.fromData(img_data) print(f"Referenz-PDF nicht gefunden: {ref_pdf_path}")
continue
if not os.path.exists(new_pdf_path):
print(f"New-PDF nicht gefunden: {new_pdf_path}")
continue
# QImage zu QPixmap konvertieren try:
original_pixmap = QPixmap.fromImage(qimg) # Alle drei PDF-Dateien öffnen
diff_doc = pymupdf.open(diff_pdf_path)
ref_doc = pymupdf.open(ref_pdf_path)
new_doc = pymupdf.open(new_pdf_path)
# Thumbnail erstellen und zur linken Spalte hinzufügen print(f"PDFs geladen: {pdf_filename}")
thumbnail = QLabel() print(f" diff: {len(diff_doc)} Seiten")
thumbnail.setObjectName(f"thumbnail_page_{page_num + 1}") print(f" ref: {len(ref_doc)} Seiten")
thumbnail.setPixmap(original_pixmap.scaledToWidth(200, Qt.TransformationMode.SmoothTransformation)) print(f" new: {len(new_doc)} Seiten")
thumbnail.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
thumbnail.setMouseTracking(True)
self.ui.verticalLayout_2.addWidget(thumbnail)
# Vollbild-Version erstellen und zur rechten Spalte hinzufügen # Nehme die minimale Seitenzahl aller drei PDFs
fullsize = QLabel() max_pages = min(len(diff_doc), len(ref_doc), len(new_doc))
fullsize.setObjectName(f"fullsize_page_{page_num + 1}")
fullsize.setPixmap(original_pixmap)
fullsize.setAlignment(Qt.AlignmentFlag.AlignHCenter) # Horizontale Zentrierung
self.ui.verticalLayout_3.addWidget(fullsize)
# Beziehungen speichern # Für jede Seite
self.thumbnail_to_full_image[thumbnail] = fullsize for page_num in range(max_pages):
self.original_pixmaps[fullsize] = original_pixmap # Seiten aus allen drei PDFs laden
diff_page = diff_doc[page_num]
ref_page = ref_doc[page_num]
new_page = new_doc[page_num]
# Click-Event für das Thumbnail einrichten # Seiten in hoher Auflösung rendern
thumbnail.mousePressEvent = lambda event, t=thumbnail: self.on_thumbnail_clicked(event, t) matrix = pymupdf.Matrix(2.0, 2.0) # 2x Vergrößerung für bessere Qualität
# Drag-to-Scroll Events für große Bilder einrichten # Diff-Seite für Thumbnail verwenden
fullsize.mousePressEvent = lambda event, f=fullsize: self.on_fullsize_mouse_press(event, f) diff_pix = diff_page.get_pixmap(matrix=matrix)
fullsize.mouseMoveEvent = lambda event, f=fullsize: self.on_fullsize_mouse_move(event, f) diff_img_data = diff_pix.tobytes("png")
fullsize.mouseReleaseEvent = lambda event, f=fullsize: self.on_fullsize_mouse_release(event, f) diff_qimg = QImage.fromData(diff_img_data)
diff_pixmap = QPixmap.fromImage(diff_qimg)
# PDF-Dokument schließen # Ref-Seite für unterste Ebene
pdf_document.close() ref_pix = ref_page.get_pixmap(matrix=matrix)
ref_img_data = ref_pix.tobytes("png")
ref_qimg = QImage.fromData(ref_img_data)
ref_pixmap = QPixmap.fromImage(ref_qimg)
except Exception as e: # New-Seite für oberste Ebene
print(f"Fehler beim Laden der PDF: {e}") new_pix = new_page.get_pixmap(matrix=matrix)
new_img_data = new_pix.tobytes("png")
new_qimg = QImage.fromData(new_img_data)
new_pixmap = QPixmap.fromImage(new_qimg)
# Thumbnail erstellen (aus diff-PDF) und zur linken Spalte hinzufügen
thumbnail = QLabel()
thumbnail.setObjectName(f"thumbnail_{pdf_filename}_page_{page_num + 1}")
thumbnail.setPixmap(diff_pixmap.scaledToWidth(200, Qt.TransformationMode.SmoothTransformation))
thumbnail.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
thumbnail.setMouseTracking(True)
self.ui.verticalLayout_2.addWidget(thumbnail)
# Vollbild-Version erstellen (überlagerte Ebenen) und zur rechten Spalte hinzufügen
fullsize = QLabel()
fullsize.setObjectName(f"fullsize_{pdf_filename}_page_{page_num + 1}")
fullsize.setAlignment(Qt.AlignmentFlag.AlignHCenter) # Horizontale Zentrierung
self.ui.verticalLayout_3.addWidget(fullsize)
# Beziehungen speichern
self.thumbnail_to_full_image[thumbnail] = fullsize
self.ref_pixmaps[fullsize] = ref_pixmap
self.diff_pixmaps[fullsize] = diff_pixmap
self.new_pixmaps[fullsize] = new_pixmap
# Click-Event für das Thumbnail einrichten
thumbnail.mousePressEvent = lambda event, t=thumbnail: self.on_thumbnail_clicked(event, t)
# Drag-to-Scroll Events für große Bilder einrichten
fullsize.mousePressEvent = lambda event, f=fullsize: self.on_fullsize_mouse_press(event, f)
fullsize.mouseMoveEvent = lambda event, f=fullsize: self.on_fullsize_mouse_move(event, f)
fullsize.mouseReleaseEvent = lambda event, f=fullsize: self.on_fullsize_mouse_release(event, f)
# PDF-Dokumente schließen
diff_doc.close()
ref_doc.close()
new_doc.close()
except Exception as e:
print(f"Fehler beim Laden der PDFs: {e}")
# Initiale Darstellung mit aktuellem Alpha-Wert
self.update_layered_images()
def _clear_layout(self, layout): def _clear_layout(self, layout):
"""Entfernt alle Widgets aus einem Layout.""" """Entfernt alle Widgets aus einem Layout."""
@@ -132,6 +191,97 @@ class MainWindow(QMainWindow):
# Zoom-Slider verbinden # Zoom-Slider verbinden
self.ui.zoom.valueChanged.connect(self.apply_zoom) self.ui.zoom.valueChanged.connect(self.apply_zoom)
# Alpha-Slider verbinden
self.ui.alpha.valueChanged.connect(self.on_alpha_changed)
def on_alpha_changed(self, alpha_value):
"""
Wird ausgeführt, wenn der Alpha-Slider geändert wird.
Args:
alpha_value: Der neue Alpha-Wert (-100 bis 100)
"""
print(f"Alpha geändert auf {alpha_value}")
self.update_layered_images()
def update_layered_images(self):
"""Aktualisiert alle überlagerten Bilder basierend auf dem aktuellen Alpha-Wert."""
alpha_value = self.ui.alpha.value()
for fullsize_label in self.ref_pixmaps.keys():
# Hole die Original-Pixmaps für alle drei Ebenen
ref_pixmap = self.ref_pixmaps[fullsize_label]
diff_pixmap = self.diff_pixmaps[fullsize_label]
new_pixmap = self.new_pixmaps[fullsize_label]
# Erstelle das überlagerte Bild
layered_pixmap = self.create_layered_pixmap(ref_pixmap, diff_pixmap, new_pixmap, alpha_value)
# Wende aktuellen Zoom an
zoom_factor = self.current_zoom / 100.0
if zoom_factor != 1.0:
new_width = int(layered_pixmap.width() * zoom_factor)
layered_pixmap = layered_pixmap.scaledToWidth(new_width, Qt.TransformationMode.SmoothTransformation)
# Setze das überlagerte Bild
fullsize_label.setPixmap(layered_pixmap)
fullsize_label.setAlignment(Qt.AlignmentFlag.AlignHCenter)
def create_layered_pixmap(self, ref_pixmap, diff_pixmap, new_pixmap, alpha_value):
"""
Erstellt ein übergelagertes Pixmap basierend auf dem Alpha-Wert.
Args:
ref_pixmap: Unterste Ebene (ref)
diff_pixmap: Mittlere Ebene (diff)
new_pixmap: Oberste Ebene (new)
alpha_value: Alpha-Wert (-100 bis 100)
Returns:
QPixmap: Das überlagerte Bild
"""
# Verwende die Größe des größten Bildes
max_width = max(ref_pixmap.width(), diff_pixmap.width(), new_pixmap.width())
max_height = max(ref_pixmap.height(), diff_pixmap.height(), new_pixmap.height())
# Erstelle ein leeres Pixmap für das Ergebnis
result = QPixmap(max_width, max_height)
result.fill(Qt.GlobalColor.white)
painter = QPainter(result)
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
if alpha_value <= 0:
# Alpha von -100 bis 0: Übergang von ref zu diff
# ref_opacity: 1.0 bei -100, 0.0 bei 0
# diff_opacity: 0.0 bei -100, 1.0 bei 0
ref_opacity = 1.0 - (alpha_value + 100) / 100.0
diff_opacity = (alpha_value + 100) / 100.0
new_opacity = 0.0
else:
# Alpha von 0 bis 100: Übergang von diff zu new
# diff_opacity: 1.0 bei 0, 0.0 bei 100
# new_opacity: 0.0 bei 0, 1.0 bei 100
ref_opacity = 0.0
diff_opacity = 1.0 - alpha_value / 100.0
new_opacity = alpha_value / 100.0
# Zeichne die Ebenen mit entsprechender Transparenz
if ref_opacity > 0:
painter.setOpacity(ref_opacity)
painter.drawPixmap(0, 0, ref_pixmap)
if diff_opacity > 0:
painter.setOpacity(diff_opacity)
painter.drawPixmap(0, 0, diff_pixmap)
if new_opacity > 0:
painter.setOpacity(new_opacity)
painter.drawPixmap(0, 0, new_pixmap)
painter.end()
return result
def on_button_clicked(self): def on_button_clicked(self):
"""Wird ausgeführt, wenn der Button geklickt wird.""" """Wird ausgeführt, wenn der Button geklickt wird."""
print("Button wurde geklickt!") print("Button wurde geklickt!")
@@ -162,17 +312,8 @@ class MainWindow(QMainWindow):
self.current_zoom = zoom_value self.current_zoom = zoom_value
print(f"Zoom geändert auf {zoom_value}%") print(f"Zoom geändert auf {zoom_value}%")
# Wende den Zoom auf alle Bilder an # Aktualisiere alle überlagerten Bilder mit neuem Zoom
for fullsize_label, original_pixmap in self.original_pixmaps.items(): self.update_layered_images()
# Berechne die neue Größe basierend auf dem Zoom-Faktor
new_width = int(original_pixmap.width() * zoom_value / 100)
# Skaliere das Bild und setze es ins Label
scaled_pixmap = original_pixmap.scaledToWidth(new_width, Qt.TransformationMode.SmoothTransformation)
fullsize_label.setPixmap(scaled_pixmap)
# Stelle sicher, dass die horizontale Zentrierung beibehalten wird
fullsize_label.setAlignment(Qt.AlignmentFlag.AlignHCenter)
def on_fullsize_mouse_press(self, event, fullsize_label): def on_fullsize_mouse_press(self, event, fullsize_label):
""" """