Perf: PDF-Thumbnails progressiv rendern statt alle auf einmal
Placeholder-Labels werden sofort erstellt, das eigentliche Rendern erfolgt asynchron über QTimer.singleShot(0) — ein Thumbnail pro Event-Loop-Iteration. UI friert nicht mehr ein; RAM-Spitze wird verteilt. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+32
-24
@@ -14,7 +14,7 @@ import logging
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
from PySide6.QtCore import Qt, QSize, QUrl
|
||||
from PySide6.QtCore import Qt, QSize, QTimer, QUrl
|
||||
from PySide6.QtGui import QCursor, QPixmap, QPainter, QDesktopServices
|
||||
from PySide6.QtWidgets import QLabel, QMessageBox, QSpacerItem, QSizePolicy
|
||||
from PySide6.QtPdf import QPdfDocument
|
||||
@@ -206,6 +206,27 @@ class PdfViewerMixin:
|
||||
painter.end()
|
||||
return result
|
||||
|
||||
def _schedule_thumbnail_rendering(self, diff_doc, pdf_basename, thumbnail_labels, page_num):
|
||||
"""Rendert Thumbnails progressiv — ein Thumbnail pro Event-Loop-Iteration."""
|
||||
if page_num >= len(thumbnail_labels):
|
||||
return
|
||||
|
||||
thumbnail = thumbnail_labels[page_num]
|
||||
# Prüfe ob das Label noch existiert (Benutzer könnte inzwischen anderes PDF geöffnet haben)
|
||||
if thumbnail_labels[page_num] not in self.thumbnail_to_page:
|
||||
return
|
||||
|
||||
page_size = diff_doc.pagePointSize(page_num)
|
||||
scale_factor = 200.0 / page_size.width()
|
||||
page_image = diff_doc.render(
|
||||
page_num,
|
||||
QSize(int(page_size.width() * scale_factor), int(page_size.height() * scale_factor)),
|
||||
)
|
||||
thumbnail.setPixmap(QPixmap.fromImage(page_image).scaledToWidth(200, Qt.TransformationMode.SmoothTransformation))
|
||||
thumbnail.setMinimumHeight(0)
|
||||
|
||||
QTimer.singleShot(0, lambda: self._schedule_thumbnail_rendering(diff_doc, pdf_basename, thumbnail_labels, page_num + 1))
|
||||
|
||||
def _clear_layout(self, layout):
|
||||
"""Entfernt alle Widgets aus einem Layout."""
|
||||
if layout is not None:
|
||||
@@ -395,43 +416,30 @@ class PdfViewerMixin:
|
||||
# Nehme die Seitenzahl der diff-PDF als Basis
|
||||
max_pages = diff_doc.pageCount()
|
||||
|
||||
# Erstelle Thumbnails für alle Seiten
|
||||
# Erstelle Placeholder-Labels für alle Seiten (sofort, ohne Rendern)
|
||||
thumbnail_labels = []
|
||||
for page_num in range(max_pages):
|
||||
# Nur diff-Seite für Thumbnail rendern
|
||||
page_size = diff_doc.pagePointSize(page_num)
|
||||
|
||||
# Skalierung für Thumbnail
|
||||
scale_factor = 200.0 / page_size.width() # 200 Pixel Breite
|
||||
|
||||
# Seite rendern
|
||||
page_image = diff_doc.render(
|
||||
page_num,
|
||||
QSize(int(page_size.width() * scale_factor), int(page_size.height() * scale_factor)),
|
||||
)
|
||||
|
||||
diff_pixmap = QPixmap.fromImage(page_image)
|
||||
|
||||
# Thumbnail erstellen und zur linken Spalte hinzufügen
|
||||
thumbnail = QLabel()
|
||||
thumbnail.setObjectName(f"thumbnail_{pdf_basename}_page_{page_num + 1}")
|
||||
thumbnail.setPixmap(diff_pixmap.scaledToWidth(200, Qt.TransformationMode.SmoothTransformation))
|
||||
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)
|
||||
|
||||
# Seitennummer für Thumbnail anzeigen
|
||||
thumbnail_info = QLabel(f"Seite {page_num + 1}")
|
||||
thumbnail_info.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
thumbnail_info.setMaximumHeight(18) # Kompakte Höhe
|
||||
thumbnail_info.setContentsMargins(0, 0, 0, 0) # Keine Ränder
|
||||
thumbnail_info.setMaximumHeight(18)
|
||||
thumbnail_info.setContentsMargins(0, 0, 0, 0)
|
||||
self.ui.verticalLayout_2.addWidget(thumbnail_info)
|
||||
|
||||
# Beziehung zwischen Thumbnail und Seitennummer speichern
|
||||
self.thumbnail_to_page[thumbnail] = {"pdf_filename": pdf_basename, "page_num": page_num}
|
||||
|
||||
# Click-Event für das Thumbnail einrichten
|
||||
thumbnail.mousePressEvent = lambda event, t=thumbnail: self.on_thumbnail_clicked(event, t)
|
||||
thumbnail_labels.append(thumbnail)
|
||||
|
||||
# Thumbnails progressiv rendern (nicht blockierend)
|
||||
self._schedule_thumbnail_rendering(diff_doc, pdf_basename, thumbnail_labels, 0)
|
||||
|
||||
# Füge expandierenden Spacer am Ende hinzu, damit Thumbnails oben bleiben
|
||||
spacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
|
||||
|
||||
Reference in New Issue
Block a user