Vergleich der PDF
This commit is contained in:
+202
-61
@@ -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):
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user