Files
copydev-imposing-tool/app/page_panel.py
Jules 202a4fc536 V3.2.0 — Macros, grille vignettes, progression fun, shuffle, sample doc
- Macros : enregistrer la derniere action sous un nom, rejouer, supprimer
  Menu Macros avec liste des macros enregistrees
- Grille adaptive dans le panneau de vignettes (s'adapte a la largeur)
- Barre de progression avec messages fun/rigolos
  (Pliage des pages en origami, Consultation des esprits de Gutenberg...)
- Separer paires/impaires en 2 fichiers
- Creer un document test numerote (Pages > Creer un document test)
- _last_action sauvegardee pour booklet, nup, step_repeat, trim_shift

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 16:22:48 +01:00

149 lines
5.6 KiB
Python

"""Panneau lateral de vignettes des pages — V2."""
from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QListWidget, QListWidgetItem,
QAbstractItemView, QMenu, QSizePolicy)
from PyQt6.QtGui import QIcon, QPixmap
from PyQt6.QtCore import Qt, pyqtSignal, QSize
class PagePanel(QWidget):
"""Panneau de vignettes avec drag & drop, suppression, insertion."""
page_selected = pyqtSignal(int)
pages_reordered = pyqtSignal(list)
page_delete_requested = pyqtSignal(int)
page_insert_requested = pyqtSignal(int)
page_rotate_requested = pyqtSignal(int, int) # page_index, degrees (90, -90, 180)
def __init__(self, parent=None):
super().__init__(parent)
self.setMinimumWidth(100)
self.setSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Expanding)
self._setup_ui()
def _setup_ui(self):
layout = QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
self._list = QListWidget()
self._list.setIconSize(QSize(120, 170))
self._list.setSpacing(4)
self._list.setViewMode(QListWidget.ViewMode.IconMode)
self._list.setResizeMode(QListWidget.ResizeMode.Adjust)
self._list.setWrapping(True)
self._list.setGridSize(QSize(140, 190))
self._list.setUniformItemSizes(True)
self._list.setMovement(QListWidget.Movement.Free)
self._list.setStyleSheet("""
QListWidget {
background: #e0e0e0;
border: none;
border-right: 1px solid #d0d0d0;
padding: 4px;
}
QListWidget::item {
background: #ffffff;
border: 1px solid #d0d0d0;
border-radius: 6px;
padding: 4px;
color: #555;
font-size: 10px;
margin: 2px 0;
}
QListWidget::item:hover {
background: #e0f4ff;
border-color: #00b4d8;
}
QListWidget::item:selected {
background: #d8f0f8;
border: 2px solid #00b4d8;
color: #006fa6;
}
""")
self._list.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection)
self._list.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove)
self._list.setDefaultDropAction(Qt.DropAction.MoveAction)
self._list.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self._list.customContextMenuRequested.connect(self._context_menu)
self._list.currentRowChanged.connect(self._on_row_changed)
self._list.model().rowsMoved.connect(self._on_rows_moved)
layout.addWidget(self._list)
def load_thumbnails(self, viewer):
"""Charger les miniatures depuis le viewer."""
self._list.clear()
for i in range(viewer.total_pages):
thumb = viewer.get_page_thumbnail(i, 120)
item = QListWidgetItem()
item.setText(f" Page {i + 1}")
item.setData(Qt.ItemDataRole.UserRole, i)
if thumb:
item.setIcon(QIcon(thumb))
self._list.addItem(item)
def select_page(self, index):
"""Selectionner une page sans emettre le signal."""
self._list.blockSignals(True)
self._list.setCurrentRow(index)
self._list.blockSignals(False)
def _on_row_changed(self, row):
if row >= 0:
self.page_selected.emit(row)
def _on_rows_moved(self):
indices = []
for i in range(self._list.count()):
item = self._list.item(i)
original_index = item.data(Qt.ItemDataRole.UserRole)
indices.append(original_index)
self.pages_reordered.emit(indices)
def get_selected_indices(self):
"""Retourne les indices des pages selectionnees."""
return sorted(set(self._list.row(item) for item in self._list.selectedItems()))
def _context_menu(self, pos):
item = self._list.itemAt(pos)
if not item:
return
row = self._list.row(item)
selected = self.get_selected_indices()
if row not in selected:
selected = [row]
count = len(selected)
label_pages = f"{count} page(s)" if count > 1 else "cette page"
menu = QMenu(self)
menu.setStyleSheet("""
QMenu { background: #fff; color: #2d2d2d; border: 1px solid #d0d0d0; border-radius: 8px; padding: 4px; }
QMenu::item { padding: 6px 20px; border-radius: 4px; }
QMenu::item:selected { background: #e0f4ff; color: #006fa6; }
""")
act_rot_right = menu.addAction(f"Pivoter +90° ({label_pages})")
act_rot_left = menu.addAction(f"Pivoter -90° ({label_pages})")
act_rot_180 = menu.addAction(f"Pivoter 180° ({label_pages})")
menu.addSeparator()
act_insert = menu.addAction("Inserer une page blanche apres")
act_delete = menu.addAction(f"Supprimer {label_pages}")
action = menu.exec(self._list.mapToGlobal(pos))
if action == act_delete:
for idx in reversed(selected):
self.page_delete_requested.emit(idx)
elif action == act_insert:
self.page_insert_requested.emit(row)
elif action == act_rot_right:
for idx in selected:
self.page_rotate_requested.emit(idx, 90)
elif action == act_rot_left:
for idx in selected:
self.page_rotate_requested.emit(idx, -90)
elif action == act_rot_180:
for idx in selected:
self.page_rotate_requested.emit(idx, 180)