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:
Jules
2026-03-21 13:50:55 +01:00
parent 500309ed53
commit e7a27018e5
6 changed files with 427 additions and 5 deletions

View File

@@ -24,6 +24,8 @@ from app.dialogs.masking_dialog import MaskingDialog
from app.dialogs.bleeds_dialog import BleedsDialog
from app.dialogs.crop_marks_dialog import CropMarksDialog
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.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.crop_marks import add_crop_marks, remove_crop_marks
from app.engine.crop import crop_pages
from app.engine.add_content import add_text_to_pages, add_image_to_pages
class MainWindow(QMainWindow):
@@ -124,6 +127,9 @@ class MainWindow(QMainWindow):
# 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, "Masquage (ruban blanc)", None, self._do_masking)
annot_menu.addSeparator()
@@ -145,15 +151,16 @@ class MainWindow(QMainWindow):
act.triggered.connect(callback)
menu.addAction(act)
# ── Toolbar ──
# ── Toolbars ──
def _setup_toolbar(self):
tb = QToolBar()
# Toolbar horizontale en haut (fichier + zoom)
tb = QToolBar("Fichier")
tb.setMovable(False)
self.addToolBar(tb)
tb.addAction("Ouvrir", self._open_file)
tb.addAction("Enregistrer", self._save_result)
tb.addAction("Imprimer", self._do_print)
tb.addSeparator()
tb.addAction("Zoom +", lambda: self._viewer.zoom_in())
tb.addAction("Zoom -", lambda: self._viewer.zoom_out())
@@ -163,6 +170,57 @@ class MainWindow(QMainWindow):
self._page_label.setStyleSheet("color: #aaa; padding: 0 10px;")
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 ──
def _setup_ui(self):
@@ -499,6 +557,47 @@ class MainWindow(QMainWindow):
self._hide_progress()
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):
if not self._require_file():
return