Vergleich der PDF

This commit is contained in:
2025-05-27 18:31:45 +02:00
parent 6cd1cb8a2a
commit c2826695c7
+184 -43
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,61 +47,113 @@ 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
# Finde alle PDF-Dateien im diff-Ordner
diff_pdfs = glob.glob(os.path.join(diff_dir, "*.pdf"))
if not diff_pdfs:
print("Keine PDF-Dateien im diff-Ordner gefunden")
return
print(f"Gefundene PDF-Dateien im diff-Ordner: {diff_pdfs}")
# Für jede PDF-Datei im diff-Ordner
for diff_pdf_path in diff_pdfs:
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)
# Prüfe ob gleichnamige PDFs in ref und new existieren
if not os.path.exists(ref_pdf_path):
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
try: try:
# PDF-Datei öffnen # Alle drei PDF-Dateien öffnen
pdf_document = pymupdf.open(pdf_path) diff_doc = pymupdf.open(diff_pdf_path)
print(f"PDF geladen: {pdf_path} mit {len(pdf_document)} Seiten") ref_doc = pymupdf.open(ref_pdf_path)
new_doc = pymupdf.open(new_pdf_path)
# Für jede Seite der PDF: print(f"PDFs geladen: {pdf_filename}")
for page_num in range(len(pdf_document)): print(f" diff: {len(diff_doc)} Seiten")
page = pdf_document[page_num] print(f" ref: {len(ref_doc)} Seiten")
print(f" new: {len(new_doc)} Seiten")
# Seite in hoher Auflösung rendern # Nehme die minimale Seitenzahl aller drei PDFs
max_pages = min(len(diff_doc), len(ref_doc), len(new_doc))
# Für jede Seite
for page_num in range(max_pages):
# Seiten aus allen drei PDFs laden
diff_page = diff_doc[page_num]
ref_page = ref_doc[page_num]
new_page = new_doc[page_num]
# Seiten in hoher Auflösung rendern
matrix = pymupdf.Matrix(2.0, 2.0) # 2x Vergrößerung für bessere Qualität matrix = pymupdf.Matrix(2.0, 2.0) # 2x Vergrößerung für bessere Qualität
pix = page.get_pixmap(matrix=matrix)
# PyMuPDF Pixmap zu QImage konvertieren # Diff-Seite für Thumbnail verwenden
img_data = pix.tobytes("png") diff_pix = diff_page.get_pixmap(matrix=matrix)
qimg = QImage.fromData(img_data) diff_img_data = diff_pix.tobytes("png")
diff_qimg = QImage.fromData(diff_img_data)
diff_pixmap = QPixmap.fromImage(diff_qimg)
# QImage zu QPixmap konvertieren # Ref-Seite für unterste Ebene
original_pixmap = QPixmap.fromImage(qimg) 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)
# Thumbnail erstellen und zur linken Spalte hinzufügen # New-Seite für oberste Ebene
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 = QLabel()
thumbnail.setObjectName(f"thumbnail_page_{page_num + 1}") thumbnail.setObjectName(f"thumbnail_{pdf_filename}_page_{page_num + 1}")
thumbnail.setPixmap(original_pixmap.scaledToWidth(200, Qt.TransformationMode.SmoothTransformation)) thumbnail.setPixmap(diff_pixmap.scaledToWidth(200, Qt.TransformationMode.SmoothTransformation))
thumbnail.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) thumbnail.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
thumbnail.setMouseTracking(True) thumbnail.setMouseTracking(True)
self.ui.verticalLayout_2.addWidget(thumbnail) self.ui.verticalLayout_2.addWidget(thumbnail)
# Vollbild-Version erstellen und zur rechten Spalte hinzufügen # Vollbild-Version erstellen (überlagerte Ebenen) und zur rechten Spalte hinzufügen
fullsize = QLabel() fullsize = QLabel()
fullsize.setObjectName(f"fullsize_page_{page_num + 1}") fullsize.setObjectName(f"fullsize_{pdf_filename}_page_{page_num + 1}")
fullsize.setPixmap(original_pixmap)
fullsize.setAlignment(Qt.AlignmentFlag.AlignHCenter) # Horizontale Zentrierung fullsize.setAlignment(Qt.AlignmentFlag.AlignHCenter) # Horizontale Zentrierung
self.ui.verticalLayout_3.addWidget(fullsize) self.ui.verticalLayout_3.addWidget(fullsize)
# Beziehungen speichern # Beziehungen speichern
self.thumbnail_to_full_image[thumbnail] = fullsize self.thumbnail_to_full_image[thumbnail] = fullsize
self.original_pixmaps[fullsize] = original_pixmap 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 # Click-Event für das Thumbnail einrichten
thumbnail.mousePressEvent = lambda event, t=thumbnail: self.on_thumbnail_clicked(event, t) thumbnail.mousePressEvent = lambda event, t=thumbnail: self.on_thumbnail_clicked(event, t)
@@ -109,11 +163,16 @@ class MainWindow(QMainWindow):
fullsize.mouseMoveEvent = lambda event, f=fullsize: self.on_fullsize_mouse_move(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) fullsize.mouseReleaseEvent = lambda event, f=fullsize: self.on_fullsize_mouse_release(event, f)
# PDF-Dokument schließen # PDF-Dokumente schließen
pdf_document.close() diff_doc.close()
ref_doc.close()
new_doc.close()
except Exception as e: except Exception as e:
print(f"Fehler beim Laden der PDF: {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):
""" """