From 5e368ef26064cd719d05560c485dfb463f783544 Mon Sep 17 00:00:00 2001 From: Jules Date: Sat, 21 Mar 2026 16:43:32 +0100 Subject: [PATCH] =?UTF-8?q?V3.3.1=20=E2=80=94=20Impression=20directe=20via?= =?UTF-8?q?=20QPrinter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Impression directe sans passer par un lecteur PDF externe - Dialogue d'impression natif Windows (QPrintDialog) - Choix imprimante, copies, pages, orientation - Rendu haute resolution (DPI de l'imprimante) - Centrage automatique sur la page - Fonctionne sans Adobe/Edge/lecteur PDF installe Co-Authored-By: Claude Opus 4.6 (1M context) --- app/main_window.py | 86 +++++++++++++++++++++++++++++++++++----------- app/updater.py | 2 +- version.txt | 2 +- 3 files changed, 68 insertions(+), 22 deletions(-) diff --git a/app/main_window.py b/app/main_window.py index 7c3c92b..5dd84b0 100644 --- a/app/main_window.py +++ b/app/main_window.py @@ -7,8 +7,8 @@ import shutil from PyQt6.QtWidgets import (QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QFileDialog, QMessageBox, QStatusBar, QSplitter, QProgressBar, QApplication, QToolBar) -from PyQt6.QtCore import Qt, QTimer -from PyQt6.QtGui import QAction, QIcon, QDragEnterEvent, QDropEvent +from PyQt6.QtCore import Qt, QTimer, QRect +from PyQt6.QtGui import QAction, QIcon, QDragEnterEvent, QDropEvent, QPageLayout from app.pdf_viewer import PdfViewer from app.page_panel import PagePanel @@ -1012,26 +1012,72 @@ class MainWindow(QMainWindow): if not self._require_file(): return try: + from PyQt6.QtPrintSupport import QPrinter, QPrintDialog + from PyQt6.QtGui import QPainter, QImage + import pypdfium2 as pdfium + source = self._result_file or self._current_file - tmp_print = os.path.join(tempfile.gettempdir(), "copydev_print.pdf") - shutil.copy2(source, tmp_print) - if sys.platform == "win32": - # "print" envoie directement au dialogue d'impression - os.startfile(tmp_print, "print") - else: - import subprocess - subprocess.Popen(["lp", tmp_print]) - self._status_label.setText("Impression lancee...") - except OSError: - # Fallback : ouvrir le fichier normalement - try: - if sys.platform == "win32": - os.startfile(tmp_print) - self._status_label.setText("Fichier ouvert — utilisez Ctrl+P pour imprimer") - except Exception as e2: - QMessageBox.critical(self, "Erreur", f"Impossible d'imprimer :\n{e2}") + pdf = pdfium.PdfDocument(source) + + printer = QPrinter(QPrinter.PrinterMode.HighResolution) + printer.setPageOrientation( + QPageLayout.Orientation.Landscape + if pdf[0].get_size()[0] > pdf[0].get_size()[1] + else QPageLayout.Orientation.Portrait + ) + + dialog = QPrintDialog(printer, self) + dialog.setWindowTitle("Imprimer — CopyDev Imposing Tool") + if dialog.exec() != QPrintDialog.DialogCode.Accepted: + return + + self._show_progress() + self._status_label.setText("Impression en cours...") + QApplication.processEvents() + + painter = QPainter() + painter.begin(printer) + + for i in range(len(pdf)): + if i > 0: + printer.newPage() + + page = pdf[i] + # Rendu a haute resolution + dpi = printer.resolution() + scale = dpi / 72 + bitmap = page.render(scale=scale) + pil_image = bitmap.to_pil() + + data = pil_image.tobytes("raw", "RGBA") + qimage = QImage(data, pil_image.width, pil_image.height, QImage.Format.Format_RGBA8888) + + # Calculer le placement sur la page imprimee + page_rect = printer.pageRect(QPrinter.Unit.Point) + pw, ph = page.get_size() + scale_x = page_rect.width() / pil_image.width + scale_y = page_rect.height() / pil_image.height + s = min(scale_x, scale_y) + + target_w = int(pil_image.width * s) + target_h = int(pil_image.height * s) + x = int((page_rect.width() - target_w) / 2) + y = int((page_rect.height() - target_h) / 2) + + from PyQt6.QtCore import QRect + painter.drawImage(QRect(x, y, target_w, target_h), qimage) + + painter.end() + self._hide_progress() + self._status_label.setText(f"Impression terminee — {len(pdf)} page(s)") + + except ImportError: + QMessageBox.critical(self, "Erreur", + "Le module d'impression n'est pas disponible.\n" + "Installez PyQt6 avec le support impression.") except Exception as e: - QMessageBox.critical(self, "Erreur", f"Impossible d'imprimer :\n{e}") + self._hide_progress() + QMessageBox.critical(self, "Erreur", f"Erreur d'impression :\n{e}") def _do_crop_marks(self): if not self._require_file(): diff --git a/app/updater.py b/app/updater.py index 8a6459b..f568a54 100644 --- a/app/updater.py +++ b/app/updater.py @@ -14,7 +14,7 @@ REPO = "jules/copydev-imposing-tool" BRANCH = "master" # Version actuelle (incrementee a chaque release) -VERSION = "3.3.0" +VERSION = "3.3.1" def get_remote_version(): diff --git a/version.txt b/version.txt index 15a2799..bea438e 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -3.3.0 +3.3.1