V2.3.0 — Ajout texte/image + barre outils verticale
- Ajout de texte libre sur les pages (Annotations > Ajouter du texte) - Texte multi-ligne, police, taille, couleur au choix - Position X/Y en mm, appliquer a page courante/toutes/paires/impaires - Ajout d'image sur les pages (Annotations > Ajouter une image) - PNG/JPG/BMP/GIF/TIFF, position, taille, ratio auto - Memes options d'application - Barre d'outils verticale a droite avec toutes les fonctions : - IMPOSITION : Livret, N-Up, Repetition, Manuel, Joindre - PAGES : Recadrer, Pg blanche, Fusionner - ANNOTATIONS : Texte, Image, Numeros, Masquer - REPERES : Coupe +/-, Bleed +/- - Toolbar horizontale : Ouvrir, Enregistrer, Imprimer, Zoom Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
120
app/dialogs/add_image_dialog.py
Normal file
120
app/dialogs/add_image_dialog.py
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
"""Dialogue Ajouter une image sur une page."""
|
||||||
|
|
||||||
|
from PyQt6.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout, QLabel,
|
||||||
|
QGroupBox, QComboBox, QDoubleSpinBox,
|
||||||
|
QDialogButtonBox, QPushButton, QFileDialog)
|
||||||
|
from reportlab.lib.units import mm
|
||||||
|
|
||||||
|
|
||||||
|
class AddImageDialog(QDialog):
|
||||||
|
def __init__(self, total_pages=1, current_page=0, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setWindowTitle("Ajouter une image")
|
||||||
|
self.setMinimumWidth(400)
|
||||||
|
self._total_pages = total_pages
|
||||||
|
self._current_page = current_page
|
||||||
|
self._image_path = None
|
||||||
|
self._setup_ui()
|
||||||
|
|
||||||
|
def _setup_ui(self):
|
||||||
|
layout = QVBoxLayout(self)
|
||||||
|
|
||||||
|
# Image
|
||||||
|
grp_img = QGroupBox("Image")
|
||||||
|
il = QHBoxLayout(grp_img)
|
||||||
|
self.btn_choose = QPushButton("Choisir une image...")
|
||||||
|
self.btn_choose.clicked.connect(self._choose_image)
|
||||||
|
il.addWidget(self.btn_choose)
|
||||||
|
self.lbl_file = QLabel("Aucun fichier")
|
||||||
|
self.lbl_file.setStyleSheet("color: #888;")
|
||||||
|
il.addWidget(self.lbl_file)
|
||||||
|
layout.addWidget(grp_img)
|
||||||
|
|
||||||
|
# Position et taille
|
||||||
|
grp_pos = QGroupBox("Position et taille (mm)")
|
||||||
|
pl = QVBoxLayout(grp_pos)
|
||||||
|
|
||||||
|
row1 = QHBoxLayout()
|
||||||
|
row1.addWidget(QLabel("X :"))
|
||||||
|
self.spin_x = QDoubleSpinBox()
|
||||||
|
self.spin_x.setRange(0, 2000)
|
||||||
|
self.spin_x.setValue(20)
|
||||||
|
self.spin_x.setSuffix(" mm")
|
||||||
|
row1.addWidget(self.spin_x)
|
||||||
|
row1.addWidget(QLabel("Y :"))
|
||||||
|
self.spin_y = QDoubleSpinBox()
|
||||||
|
self.spin_y.setRange(0, 2000)
|
||||||
|
self.spin_y.setValue(20)
|
||||||
|
self.spin_y.setSuffix(" mm")
|
||||||
|
row1.addWidget(self.spin_y)
|
||||||
|
pl.addLayout(row1)
|
||||||
|
|
||||||
|
row2 = QHBoxLayout()
|
||||||
|
row2.addWidget(QLabel("Largeur :"))
|
||||||
|
self.spin_w = QDoubleSpinBox()
|
||||||
|
self.spin_w.setRange(1, 2000)
|
||||||
|
self.spin_w.setValue(50)
|
||||||
|
self.spin_w.setSuffix(" mm")
|
||||||
|
row2.addWidget(self.spin_w)
|
||||||
|
row2.addWidget(QLabel("Hauteur :"))
|
||||||
|
self.spin_h = QDoubleSpinBox()
|
||||||
|
self.spin_h.setRange(0, 2000)
|
||||||
|
self.spin_h.setValue(0)
|
||||||
|
self.spin_h.setSuffix(" mm")
|
||||||
|
self.spin_h.setSpecialValueText("Auto")
|
||||||
|
row2.addWidget(self.spin_h)
|
||||||
|
pl.addLayout(row2)
|
||||||
|
|
||||||
|
pl.addWidget(QLabel("Hauteur 0 = proportionnelle a la largeur"))
|
||||||
|
layout.addWidget(grp_pos)
|
||||||
|
|
||||||
|
# Appliquer a
|
||||||
|
grp_apply = QGroupBox("Appliquer a")
|
||||||
|
al = QHBoxLayout(grp_apply)
|
||||||
|
self.combo_apply = QComboBox()
|
||||||
|
self.combo_apply.addItems([
|
||||||
|
f"Page courante ({self._current_page + 1})",
|
||||||
|
"Toutes les pages",
|
||||||
|
"Pages paires",
|
||||||
|
"Pages impaires"
|
||||||
|
])
|
||||||
|
al.addWidget(self.combo_apply)
|
||||||
|
layout.addWidget(grp_apply)
|
||||||
|
|
||||||
|
buttons = QDialogButtonBox(
|
||||||
|
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
|
||||||
|
)
|
||||||
|
buttons.accepted.connect(self.accept)
|
||||||
|
buttons.rejected.connect(self.reject)
|
||||||
|
layout.addWidget(buttons)
|
||||||
|
|
||||||
|
def _choose_image(self):
|
||||||
|
path, _ = QFileDialog.getOpenFileName(
|
||||||
|
self, "Choisir une image", "",
|
||||||
|
"Images (*.png *.jpg *.jpeg *.bmp *.gif *.tiff)"
|
||||||
|
)
|
||||||
|
if path:
|
||||||
|
self._image_path = path
|
||||||
|
self.lbl_file.setText(path.split("/")[-1].split("\\")[-1])
|
||||||
|
self.lbl_file.setStyleSheet("color: #0066cc;")
|
||||||
|
|
||||||
|
def get_settings(self):
|
||||||
|
apply_text = self.combo_apply.currentText()
|
||||||
|
if "courante" in apply_text:
|
||||||
|
apply_to = "current"
|
||||||
|
elif "paires" in apply_text.lower():
|
||||||
|
apply_to = "even"
|
||||||
|
elif "impaires" in apply_text.lower():
|
||||||
|
apply_to = "odd"
|
||||||
|
else:
|
||||||
|
apply_to = "all"
|
||||||
|
|
||||||
|
return {
|
||||||
|
"image_path": self._image_path,
|
||||||
|
"x": self.spin_x.value() * mm,
|
||||||
|
"y": self.spin_y.value() * mm,
|
||||||
|
"width": self.spin_w.value() * mm,
|
||||||
|
"height": self.spin_h.value() * mm if self.spin_h.value() > 0 else None,
|
||||||
|
"apply_to": apply_to,
|
||||||
|
"current_page": self._current_page,
|
||||||
|
}
|
||||||
117
app/dialogs/add_text_dialog.py
Normal file
117
app/dialogs/add_text_dialog.py
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
"""Dialogue Ajouter du texte sur une page."""
|
||||||
|
|
||||||
|
from PyQt6.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout, QLabel,
|
||||||
|
QGroupBox, QComboBox, QSpinBox, QLineEdit,
|
||||||
|
QDialogButtonBox, QDoubleSpinBox, QTextEdit,
|
||||||
|
QColorDialog, QPushButton)
|
||||||
|
from PyQt6.QtGui import QColor
|
||||||
|
from PyQt6.QtCore import Qt
|
||||||
|
from reportlab.lib.units import mm
|
||||||
|
|
||||||
|
|
||||||
|
class AddTextDialog(QDialog):
|
||||||
|
def __init__(self, total_pages=1, current_page=0, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setWindowTitle("Ajouter du texte")
|
||||||
|
self.setMinimumWidth(450)
|
||||||
|
self._total_pages = total_pages
|
||||||
|
self._current_page = current_page
|
||||||
|
self._color = QColor(0, 0, 0)
|
||||||
|
self._setup_ui()
|
||||||
|
|
||||||
|
def _setup_ui(self):
|
||||||
|
layout = QVBoxLayout(self)
|
||||||
|
|
||||||
|
# Texte
|
||||||
|
grp_text = QGroupBox("Texte")
|
||||||
|
tl = QVBoxLayout(grp_text)
|
||||||
|
self.edit_text = QTextEdit()
|
||||||
|
self.edit_text.setPlaceholderText("Saisissez le texte a ajouter...")
|
||||||
|
self.edit_text.setMaximumHeight(80)
|
||||||
|
tl.addWidget(self.edit_text)
|
||||||
|
layout.addWidget(grp_text)
|
||||||
|
|
||||||
|
# Police
|
||||||
|
grp_font = QGroupBox("Police")
|
||||||
|
fl = QHBoxLayout(grp_font)
|
||||||
|
self.combo_font = QComboBox()
|
||||||
|
self.combo_font.addItems(["Helvetica", "Helvetica-Bold", "Times-Roman",
|
||||||
|
"Times-Bold", "Courier", "Courier-Bold"])
|
||||||
|
fl.addWidget(self.combo_font)
|
||||||
|
fl.addWidget(QLabel("Taille :"))
|
||||||
|
self.spin_size = QSpinBox()
|
||||||
|
self.spin_size.setRange(4, 200)
|
||||||
|
self.spin_size.setValue(12)
|
||||||
|
fl.addWidget(self.spin_size)
|
||||||
|
self.btn_color = QPushButton("Couleur")
|
||||||
|
self.btn_color.setStyleSheet("background: black; color: white; padding: 4px 12px;")
|
||||||
|
self.btn_color.clicked.connect(self._choose_color)
|
||||||
|
fl.addWidget(self.btn_color)
|
||||||
|
layout.addWidget(grp_font)
|
||||||
|
|
||||||
|
# Position
|
||||||
|
grp_pos = QGroupBox("Position (mm depuis le bas-gauche)")
|
||||||
|
pl = QHBoxLayout(grp_pos)
|
||||||
|
pl.addWidget(QLabel("X :"))
|
||||||
|
self.spin_x = QDoubleSpinBox()
|
||||||
|
self.spin_x.setRange(0, 2000)
|
||||||
|
self.spin_x.setValue(20)
|
||||||
|
self.spin_x.setSuffix(" mm")
|
||||||
|
pl.addWidget(self.spin_x)
|
||||||
|
pl.addWidget(QLabel("Y :"))
|
||||||
|
self.spin_y = QDoubleSpinBox()
|
||||||
|
self.spin_y.setRange(0, 2000)
|
||||||
|
self.spin_y.setValue(20)
|
||||||
|
self.spin_y.setSuffix(" mm")
|
||||||
|
pl.addWidget(self.spin_y)
|
||||||
|
layout.addWidget(grp_pos)
|
||||||
|
|
||||||
|
# Appliquer a
|
||||||
|
grp_apply = QGroupBox("Appliquer a")
|
||||||
|
al = QHBoxLayout(grp_apply)
|
||||||
|
self.combo_apply = QComboBox()
|
||||||
|
self.combo_apply.addItems([
|
||||||
|
f"Page courante ({self._current_page + 1})",
|
||||||
|
"Toutes les pages",
|
||||||
|
"Pages paires",
|
||||||
|
"Pages impaires"
|
||||||
|
])
|
||||||
|
al.addWidget(self.combo_apply)
|
||||||
|
layout.addWidget(grp_apply)
|
||||||
|
|
||||||
|
buttons = QDialogButtonBox(
|
||||||
|
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
|
||||||
|
)
|
||||||
|
buttons.accepted.connect(self.accept)
|
||||||
|
buttons.rejected.connect(self.reject)
|
||||||
|
layout.addWidget(buttons)
|
||||||
|
|
||||||
|
def _choose_color(self):
|
||||||
|
color = QColorDialog.getColor(self._color, self)
|
||||||
|
if color.isValid():
|
||||||
|
self._color = color
|
||||||
|
self.btn_color.setStyleSheet(
|
||||||
|
f"background: {color.name()}; color: {'white' if color.lightness() < 128 else 'black'}; padding: 4px 12px;"
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_settings(self):
|
||||||
|
apply_text = self.combo_apply.currentText()
|
||||||
|
if "courante" in apply_text:
|
||||||
|
apply_to = "current"
|
||||||
|
elif "paires" in apply_text.lower():
|
||||||
|
apply_to = "even"
|
||||||
|
elif "impaires" in apply_text.lower():
|
||||||
|
apply_to = "odd"
|
||||||
|
else:
|
||||||
|
apply_to = "all"
|
||||||
|
|
||||||
|
return {
|
||||||
|
"text": self.edit_text.toPlainText(),
|
||||||
|
"font_name": self.combo_font.currentText(),
|
||||||
|
"font_size": self.spin_size.value(),
|
||||||
|
"color": (self._color.redF(), self._color.greenF(), self._color.blueF()),
|
||||||
|
"x": self.spin_x.value() * mm,
|
||||||
|
"y": self.spin_y.value() * mm,
|
||||||
|
"apply_to": apply_to,
|
||||||
|
"current_page": self._current_page,
|
||||||
|
}
|
||||||
86
app/engine/add_content.py
Normal file
86
app/engine/add_content.py
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
"""Moteur ajout de contenu (texte, image) sur les pages."""
|
||||||
|
|
||||||
|
from pypdf import PdfReader, PdfWriter
|
||||||
|
from reportlab.pdfgen import canvas
|
||||||
|
from reportlab.lib.utils import ImageReader
|
||||||
|
from .pdf_utils import get_page_size
|
||||||
|
import io
|
||||||
|
|
||||||
|
|
||||||
|
def add_text_to_pages(input_path, output_path, text, font_name="Helvetica",
|
||||||
|
font_size=12, color=(0, 0, 0), x=0, y=0,
|
||||||
|
apply_to="all", current_page=0):
|
||||||
|
"""Ajouter du texte sur les pages."""
|
||||||
|
reader = PdfReader(input_path)
|
||||||
|
writer = PdfWriter()
|
||||||
|
|
||||||
|
for i, page in enumerate(reader.pages):
|
||||||
|
if _should_apply(i, apply_to, current_page):
|
||||||
|
w, h = get_page_size(page)
|
||||||
|
packet = io.BytesIO()
|
||||||
|
c = canvas.Canvas(packet, pagesize=(w, h))
|
||||||
|
c.setFont(font_name, font_size)
|
||||||
|
c.setFillColorRGB(*color)
|
||||||
|
|
||||||
|
# Multi-ligne
|
||||||
|
lines = text.split("\n")
|
||||||
|
line_height = font_size * 1.3
|
||||||
|
for j, line in enumerate(lines):
|
||||||
|
c.drawString(x, y - j * line_height, line)
|
||||||
|
|
||||||
|
c.showPage()
|
||||||
|
c.save()
|
||||||
|
packet.seek(0)
|
||||||
|
overlay = PdfReader(packet)
|
||||||
|
page.merge_page(overlay.pages[0])
|
||||||
|
|
||||||
|
writer.add_page(page)
|
||||||
|
|
||||||
|
with open(output_path, "wb") as f:
|
||||||
|
writer.write(f)
|
||||||
|
return output_path
|
||||||
|
|
||||||
|
|
||||||
|
def add_image_to_pages(input_path, output_path, image_path, x=0, y=0,
|
||||||
|
width=100, height=None, apply_to="all", current_page=0):
|
||||||
|
"""Ajouter une image sur les pages."""
|
||||||
|
reader = PdfReader(input_path)
|
||||||
|
writer = PdfWriter()
|
||||||
|
|
||||||
|
img = ImageReader(image_path)
|
||||||
|
img_w, img_h = img.getSize()
|
||||||
|
|
||||||
|
if height is None or height <= 0:
|
||||||
|
height = width * (img_h / img_w)
|
||||||
|
|
||||||
|
for i, page in enumerate(reader.pages):
|
||||||
|
if _should_apply(i, apply_to, current_page):
|
||||||
|
w, h = get_page_size(page)
|
||||||
|
packet = io.BytesIO()
|
||||||
|
c = canvas.Canvas(packet, pagesize=(w, h))
|
||||||
|
c.drawImage(image_path, x, y, width=width, height=height,
|
||||||
|
preserveAspectRatio=True, mask='auto')
|
||||||
|
c.showPage()
|
||||||
|
c.save()
|
||||||
|
packet.seek(0)
|
||||||
|
overlay = PdfReader(packet)
|
||||||
|
page.merge_page(overlay.pages[0])
|
||||||
|
|
||||||
|
writer.add_page(page)
|
||||||
|
|
||||||
|
with open(output_path, "wb") as f:
|
||||||
|
writer.write(f)
|
||||||
|
return output_path
|
||||||
|
|
||||||
|
|
||||||
|
def _should_apply(page_index, apply_to, current_page):
|
||||||
|
page_num = page_index + 1
|
||||||
|
if apply_to == "all":
|
||||||
|
return True
|
||||||
|
elif apply_to == "current":
|
||||||
|
return page_index == current_page
|
||||||
|
elif apply_to == "even":
|
||||||
|
return page_num % 2 == 0
|
||||||
|
elif apply_to == "odd":
|
||||||
|
return page_num % 2 != 0
|
||||||
|
return False
|
||||||
@@ -24,6 +24,8 @@ from app.dialogs.masking_dialog import MaskingDialog
|
|||||||
from app.dialogs.bleeds_dialog import BleedsDialog
|
from app.dialogs.bleeds_dialog import BleedsDialog
|
||||||
from app.dialogs.crop_marks_dialog import CropMarksDialog
|
from app.dialogs.crop_marks_dialog import CropMarksDialog
|
||||||
from app.dialogs.crop_dialog import CropDialog
|
from app.dialogs.crop_dialog import CropDialog
|
||||||
|
from app.dialogs.add_text_dialog import AddTextDialog
|
||||||
|
from app.dialogs.add_image_dialog import AddImageDialog
|
||||||
|
|
||||||
from app.engine.booklet import create_booklet
|
from app.engine.booklet import create_booklet
|
||||||
from app.engine.nup import nup_pages
|
from app.engine.nup import nup_pages
|
||||||
@@ -36,6 +38,7 @@ from app.engine.masking import apply_masking
|
|||||||
from app.engine.bleeds import define_bleeds
|
from app.engine.bleeds import define_bleeds
|
||||||
from app.engine.crop_marks import add_crop_marks, remove_crop_marks
|
from app.engine.crop_marks import add_crop_marks, remove_crop_marks
|
||||||
from app.engine.crop import crop_pages
|
from app.engine.crop import crop_pages
|
||||||
|
from app.engine.add_content import add_text_to_pages, add_image_to_pages
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(QMainWindow):
|
class MainWindow(QMainWindow):
|
||||||
@@ -124,6 +127,9 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
# Annotations
|
# Annotations
|
||||||
annot_menu = menubar.addMenu("Annotations")
|
annot_menu = menubar.addMenu("Annotations")
|
||||||
|
self._add_action(annot_menu, "Ajouter du texte...", None, self._do_add_text)
|
||||||
|
self._add_action(annot_menu, "Ajouter une image...", None, self._do_add_image)
|
||||||
|
annot_menu.addSeparator()
|
||||||
self._add_action(annot_menu, "Numerotation de pages", None, self._do_page_numbers)
|
self._add_action(annot_menu, "Numerotation de pages", None, self._do_page_numbers)
|
||||||
self._add_action(annot_menu, "Masquage (ruban blanc)", None, self._do_masking)
|
self._add_action(annot_menu, "Masquage (ruban blanc)", None, self._do_masking)
|
||||||
annot_menu.addSeparator()
|
annot_menu.addSeparator()
|
||||||
@@ -145,15 +151,16 @@ class MainWindow(QMainWindow):
|
|||||||
act.triggered.connect(callback)
|
act.triggered.connect(callback)
|
||||||
menu.addAction(act)
|
menu.addAction(act)
|
||||||
|
|
||||||
# ── Toolbar ──
|
# ── Toolbars ──
|
||||||
|
|
||||||
def _setup_toolbar(self):
|
def _setup_toolbar(self):
|
||||||
tb = QToolBar()
|
# Toolbar horizontale en haut (fichier + zoom)
|
||||||
|
tb = QToolBar("Fichier")
|
||||||
tb.setMovable(False)
|
tb.setMovable(False)
|
||||||
self.addToolBar(tb)
|
self.addToolBar(tb)
|
||||||
|
|
||||||
tb.addAction("Ouvrir", self._open_file)
|
tb.addAction("Ouvrir", self._open_file)
|
||||||
tb.addAction("Enregistrer", self._save_result)
|
tb.addAction("Enregistrer", self._save_result)
|
||||||
|
tb.addAction("Imprimer", self._do_print)
|
||||||
tb.addSeparator()
|
tb.addSeparator()
|
||||||
tb.addAction("Zoom +", lambda: self._viewer.zoom_in())
|
tb.addAction("Zoom +", lambda: self._viewer.zoom_in())
|
||||||
tb.addAction("Zoom -", lambda: self._viewer.zoom_out())
|
tb.addAction("Zoom -", lambda: self._viewer.zoom_out())
|
||||||
@@ -163,6 +170,57 @@ class MainWindow(QMainWindow):
|
|||||||
self._page_label.setStyleSheet("color: #aaa; padding: 0 10px;")
|
self._page_label.setStyleSheet("color: #aaa; padding: 0 10px;")
|
||||||
tb.addWidget(self._page_label)
|
tb.addWidget(self._page_label)
|
||||||
|
|
||||||
|
# Toolbar verticale a droite (outils)
|
||||||
|
rtb = QToolBar("Outils")
|
||||||
|
rtb.setMovable(False)
|
||||||
|
rtb.setOrientation(Qt.Orientation.Vertical)
|
||||||
|
rtb.setStyleSheet("""
|
||||||
|
QToolBar { background: #12122a; border-left: 1px solid #333; padding: 4px 2px; spacing: 2px; }
|
||||||
|
QToolBar QToolButton {
|
||||||
|
color: #ccc; padding: 6px; border-radius: 4px;
|
||||||
|
font-size: 10px; min-width: 60px;
|
||||||
|
}
|
||||||
|
QToolBar QToolButton:hover { background: #0f3460; color: white; }
|
||||||
|
""")
|
||||||
|
self.addToolBar(Qt.ToolBarArea.RightToolBarArea, rtb)
|
||||||
|
|
||||||
|
# Section Imposition
|
||||||
|
rtb.addWidget(self._make_section_label("IMPOSITION"))
|
||||||
|
rtb.addAction("Livret", self._do_booklet)
|
||||||
|
rtb.addAction("N-Up", self._do_nup)
|
||||||
|
rtb.addAction("Repetition", self._do_step_repeat)
|
||||||
|
rtb.addAction("Manuel", self._do_manual_impose)
|
||||||
|
rtb.addAction("Joindre", self._do_join_pages)
|
||||||
|
rtb.addSeparator()
|
||||||
|
|
||||||
|
# Section Pages
|
||||||
|
rtb.addWidget(self._make_section_label("PAGES"))
|
||||||
|
rtb.addAction("Recadrer", self._do_crop)
|
||||||
|
rtb.addAction("Pg blanche", self._do_insert_blank)
|
||||||
|
rtb.addAction("Fusionner", self._do_merge)
|
||||||
|
rtb.addSeparator()
|
||||||
|
|
||||||
|
# Section Annotations
|
||||||
|
rtb.addWidget(self._make_section_label("ANNOTATIONS"))
|
||||||
|
rtb.addAction("Texte", self._do_add_text)
|
||||||
|
rtb.addAction("Image", self._do_add_image)
|
||||||
|
rtb.addAction("Numeros", self._do_page_numbers)
|
||||||
|
rtb.addAction("Masquer", self._do_masking)
|
||||||
|
rtb.addSeparator()
|
||||||
|
|
||||||
|
# Section Reperes
|
||||||
|
rtb.addWidget(self._make_section_label("REPERES"))
|
||||||
|
rtb.addAction("Coupe +", self._do_crop_marks)
|
||||||
|
rtb.addAction("Coupe -", self._do_remove_crop_marks)
|
||||||
|
rtb.addAction("Bleed +", self._do_bleeds)
|
||||||
|
rtb.addAction("Bleed -", self._do_remove_bleeds)
|
||||||
|
|
||||||
|
def _make_section_label(self, text):
|
||||||
|
lbl = QLabel(text)
|
||||||
|
lbl.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||||
|
lbl.setStyleSheet("color: #555; font-size: 9px; font-weight: bold; letter-spacing: 1px; padding: 4px 0 2px 0;")
|
||||||
|
return lbl
|
||||||
|
|
||||||
# ── UI principale ──
|
# ── UI principale ──
|
||||||
|
|
||||||
def _setup_ui(self):
|
def _setup_ui(self):
|
||||||
@@ -499,6 +557,47 @@ class MainWindow(QMainWindow):
|
|||||||
self._hide_progress()
|
self._hide_progress()
|
||||||
QMessageBox.critical(self, "Erreur", str(e))
|
QMessageBox.critical(self, "Erreur", str(e))
|
||||||
|
|
||||||
|
def _do_add_text(self):
|
||||||
|
if not self._require_file():
|
||||||
|
return
|
||||||
|
from pypdf import PdfReader
|
||||||
|
reader = PdfReader(self._current_file)
|
||||||
|
dlg = AddTextDialog(total_pages=len(reader.pages),
|
||||||
|
current_page=self._viewer.current_page, parent=self)
|
||||||
|
if dlg.exec():
|
||||||
|
settings = dlg.get_settings()
|
||||||
|
if not settings["text"].strip():
|
||||||
|
return
|
||||||
|
self._show_progress()
|
||||||
|
output = self._make_temp()
|
||||||
|
try:
|
||||||
|
add_text_to_pages(self._current_file, output, **settings)
|
||||||
|
self._show_result(output)
|
||||||
|
except Exception as e:
|
||||||
|
self._hide_progress()
|
||||||
|
QMessageBox.critical(self, "Erreur", str(e))
|
||||||
|
|
||||||
|
def _do_add_image(self):
|
||||||
|
if not self._require_file():
|
||||||
|
return
|
||||||
|
from pypdf import PdfReader
|
||||||
|
reader = PdfReader(self._current_file)
|
||||||
|
dlg = AddImageDialog(total_pages=len(reader.pages),
|
||||||
|
current_page=self._viewer.current_page, parent=self)
|
||||||
|
if dlg.exec():
|
||||||
|
settings = dlg.get_settings()
|
||||||
|
if not settings.get("image_path"):
|
||||||
|
QMessageBox.warning(self, "Erreur", "Aucune image selectionnee.")
|
||||||
|
return
|
||||||
|
self._show_progress()
|
||||||
|
output = self._make_temp()
|
||||||
|
try:
|
||||||
|
add_image_to_pages(self._current_file, output, **settings)
|
||||||
|
self._show_result(output)
|
||||||
|
except Exception as e:
|
||||||
|
self._hide_progress()
|
||||||
|
QMessageBox.critical(self, "Erreur", str(e))
|
||||||
|
|
||||||
def _do_crop(self):
|
def _do_crop(self):
|
||||||
if not self._require_file():
|
if not self._require_file():
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ REPO = "jules/copydev-imposing-tool"
|
|||||||
BRANCH = "master"
|
BRANCH = "master"
|
||||||
|
|
||||||
# Version actuelle (incrementee a chaque release)
|
# Version actuelle (incrementee a chaque release)
|
||||||
VERSION = "2.2.0"
|
VERSION = "2.3.0"
|
||||||
|
|
||||||
|
|
||||||
def get_remote_version():
|
def get_remote_version():
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
2.2.0
|
2.3.0
|
||||||
|
|||||||
Reference in New Issue
Block a user