"""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.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.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 _context_menu(self, pos): item = self._list.itemAt(pos) if not item: return row = self._list.row(item) 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("Pivoter +90°") act_rot_left = menu.addAction("Pivoter -90°") act_rot_180 = menu.addAction("Pivoter 180°") menu.addSeparator() act_insert = menu.addAction("Inserer une page blanche apres") act_delete = menu.addAction("Supprimer cette page") action = menu.exec(self._list.mapToGlobal(pos)) if action == act_delete: self.page_delete_requested.emit(row) elif action == act_insert: self.page_insert_requested.emit(row) elif action == act_rot_right: self.page_rotate_requested.emit(row, 90) elif action == act_rot_left: self.page_rotate_requested.emit(row, -90) elif action == act_rot_180: self.page_rotate_requested.emit(row, 180)