V2.5.2 — Selection redimensionnable + fix crop + bouton Effacer
- Rectangle de selection redimensionnable par les 8 poignees (angles + cotes) - Curseurs adaptes selon la poignee survolee - Deplacement du rectangle entier en cliquant a l'interieur - Zone sombre en dehors, cadre cyan, poignees blanches - Bouton Effacer dans le dialogue recadrage - Fix remontee des valeurs de selection dans les spinbox Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -39,14 +39,24 @@ class CropDialog(QDialog):
|
|||||||
self.btn_select = QPushButton("Selectionner sur l'apercu")
|
self.btn_select = QPushButton("Selectionner sur l'apercu")
|
||||||
self.btn_select.setCheckable(True)
|
self.btn_select.setCheckable(True)
|
||||||
self.btn_select.setStyleSheet("""
|
self.btn_select.setStyleSheet("""
|
||||||
QPushButton { background: #0066cc; color: white; padding: 8px 16px;
|
QPushButton { background: #00b4d8; color: white; padding: 6px 14px;
|
||||||
border-radius: 4px; font-weight: bold; }
|
border-radius: 6px; font-weight: bold; font-size: 11px; }
|
||||||
QPushButton:checked { background: #cc3300; }
|
QPushButton:checked { background: #e74c3c; }
|
||||||
QPushButton:hover { background: #0055aa; }
|
QPushButton:hover { background: #0096b7; }
|
||||||
QPushButton:checked:hover { background: #aa2200; }
|
QPushButton:checked:hover { background: #c0392b; }
|
||||||
""")
|
""")
|
||||||
self.btn_select.toggled.connect(self._toggle_select_mode)
|
self.btn_select.toggled.connect(self._toggle_select_mode)
|
||||||
sel_layout.addWidget(self.btn_select)
|
sel_layout.addWidget(self.btn_select)
|
||||||
|
|
||||||
|
self.btn_clear = QPushButton("Effacer")
|
||||||
|
self.btn_clear.setStyleSheet("""
|
||||||
|
QPushButton { background: #e8e8e8; color: #555; padding: 6px 14px;
|
||||||
|
border-radius: 6px; font-size: 11px; border: 1px solid #ccc; }
|
||||||
|
QPushButton:hover { background: #ddd; }
|
||||||
|
""")
|
||||||
|
self.btn_clear.clicked.connect(self._clear_selection)
|
||||||
|
sel_layout.addWidget(self.btn_clear)
|
||||||
|
|
||||||
sel_layout.addStretch()
|
sel_layout.addStretch()
|
||||||
layout.addLayout(sel_layout)
|
layout.addLayout(sel_layout)
|
||||||
|
|
||||||
@@ -173,10 +183,19 @@ class CropDialog(QDialog):
|
|||||||
if self._viewer:
|
if self._viewer:
|
||||||
self._viewer.set_select_mode(checked)
|
self._viewer.set_select_mode(checked)
|
||||||
if checked:
|
if checked:
|
||||||
self.btn_select.setText("Cliquez et tracez sur l'apercu...")
|
self.btn_select.setText("Mode selection actif")
|
||||||
else:
|
else:
|
||||||
self.btn_select.setText("Selectionner sur l'apercu")
|
self.btn_select.setText("Selectionner sur l'apercu")
|
||||||
|
|
||||||
|
def _clear_selection(self):
|
||||||
|
if self._viewer:
|
||||||
|
self._viewer.clear_selection()
|
||||||
|
for spin in self.margin_spins.values():
|
||||||
|
spin.blockSignals(True)
|
||||||
|
spin.setValue(0)
|
||||||
|
spin.blockSignals(False)
|
||||||
|
self._update_preview()
|
||||||
|
|
||||||
def _on_selection_changed(self, left, top, right, bottom):
|
def _on_selection_changed(self, left, top, right, bottom):
|
||||||
"""Recoit les ratios de selection du viewer et met a jour les marges."""
|
"""Recoit les ratios de selection du viewer et met a jour les marges."""
|
||||||
if not self.rb_margins.isChecked():
|
if not self.rb_margins.isChecked():
|
||||||
|
|||||||
@@ -1,147 +1,241 @@
|
|||||||
"""Widget de visualisation PDF avec pypdfium2 — V2.3.1 avec selection."""
|
"""Widget de visualisation PDF avec pypdfium2 — V2.5 avec selection redimensionnable."""
|
||||||
|
|
||||||
from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QLabel,
|
from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QLabel,
|
||||||
QScrollArea, QSizePolicy, QApplication)
|
QScrollArea, QSizePolicy, QApplication)
|
||||||
from PyQt6.QtGui import (QImage, QPixmap, QWheelEvent, QPainter, QPen, QColor,
|
from PyQt6.QtGui import (QImage, QPixmap, QWheelEvent, QPainter, QPen, QColor,
|
||||||
QMouseEvent, QCursor)
|
QMouseEvent, QCursor, QBrush)
|
||||||
from PyQt6.QtCore import Qt, pyqtSignal, QRect, QPoint
|
from PyQt6.QtCore import Qt, pyqtSignal, QRect, QPoint, QSize
|
||||||
import pypdfium2 as pdfium
|
import pypdfium2 as pdfium
|
||||||
|
|
||||||
|
HANDLE_SIZE = 8 # taille des poignees de redimensionnement
|
||||||
|
|
||||||
|
|
||||||
class SelectableImageLabel(QLabel):
|
class SelectableImageLabel(QLabel):
|
||||||
"""QLabel avec possibilite de dessiner un rectangle de selection."""
|
"""QLabel avec rectangle de selection redimensionnable par les angles."""
|
||||||
|
|
||||||
selection_changed = pyqtSignal(float, float, float, float) # left, top, right, bottom en ratio (0-1)
|
selection_changed = pyqtSignal(float, float, float, float)
|
||||||
selection_done = pyqtSignal()
|
selection_done = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self._selecting = False
|
|
||||||
self._select_mode = False
|
self._select_mode = False
|
||||||
self._start = QPoint()
|
|
||||||
self._end = QPoint()
|
|
||||||
self._rect = QRect()
|
|
||||||
self._has_selection = False
|
self._has_selection = False
|
||||||
self._img_rect = QRect() # zone de l'image dans le label
|
self._rect = QRect()
|
||||||
|
self._drag_mode = None # None, "create", "move", "tl", "tr", "bl", "br", "t", "b", "l", "r"
|
||||||
|
self._drag_start = QPoint()
|
||||||
|
self._drag_rect_start = QRect()
|
||||||
|
|
||||||
def set_select_mode(self, enabled):
|
def set_select_mode(self, enabled):
|
||||||
self._select_mode = enabled
|
self._select_mode = enabled
|
||||||
self.setCursor(QCursor(Qt.CursorShape.CrossCursor if enabled else Qt.CursorShape.ArrowCursor))
|
if enabled:
|
||||||
if not enabled:
|
self.setCursor(Qt.CursorShape.CrossCursor)
|
||||||
self._has_selection = False
|
else:
|
||||||
self.update()
|
self.setCursor(Qt.CursorShape.ArrowCursor)
|
||||||
|
|
||||||
def clear_selection(self):
|
def clear_selection(self):
|
||||||
self._has_selection = False
|
self._has_selection = False
|
||||||
|
self._rect = QRect()
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
def set_selection_from_margins(self, left_ratio, top_ratio, right_ratio, bottom_ratio):
|
def set_selection_from_margins(self, left_ratio, top_ratio, right_ratio, bottom_ratio):
|
||||||
"""Afficher un rectangle de selection a partir de ratios (0-1)."""
|
|
||||||
if not self.pixmap():
|
if not self.pixmap():
|
||||||
return
|
return
|
||||||
pm = self.pixmap()
|
pm = self.pixmap()
|
||||||
img_w, img_h = pm.width(), pm.height()
|
img_w, img_h = pm.width(), pm.height()
|
||||||
# Calculer la position de l'image dans le label (centree)
|
off_x, off_y = self._img_offset()
|
||||||
lbl_w, lbl_h = self.width(), self.height()
|
|
||||||
off_x = max(0, (lbl_w - img_w) // 2)
|
|
||||||
off_y = max(0, (lbl_h - img_h) // 2)
|
|
||||||
|
|
||||||
x1 = off_x + int(left_ratio * img_w)
|
x1 = off_x + int(left_ratio * img_w)
|
||||||
y1 = off_y + int(top_ratio * img_h)
|
y1 = off_y + int(top_ratio * img_h)
|
||||||
x2 = off_x + int(right_ratio * img_w)
|
x2 = off_x + int(right_ratio * img_w)
|
||||||
y2 = off_y + int(bottom_ratio * img_h)
|
y2 = off_y + int(bottom_ratio * img_h)
|
||||||
self._rect = QRect(QPoint(x1, y1), QPoint(x2, y2))
|
self._rect = QRect(QPoint(x1, y1), QPoint(x2, y2)).normalized()
|
||||||
self._has_selection = True
|
self._has_selection = True
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
def mousePressEvent(self, event: QMouseEvent):
|
def _img_offset(self):
|
||||||
if self._select_mode and event.button() == Qt.MouseButton.LeftButton:
|
if not self.pixmap():
|
||||||
self._selecting = True
|
return 0, 0
|
||||||
self._start = event.pos()
|
pm = self.pixmap()
|
||||||
self._end = event.pos()
|
return max(0, (self.width() - pm.width()) // 2), max(0, (self.height() - pm.height()) // 2)
|
||||||
self._rect = QRect(self._start, self._end).normalized()
|
|
||||||
self._has_selection = True
|
|
||||||
self.update()
|
|
||||||
else:
|
|
||||||
super().mousePressEvent(event)
|
|
||||||
|
|
||||||
def mouseMoveEvent(self, event: QMouseEvent):
|
def _handle_rects(self):
|
||||||
if self._selecting:
|
"""Retourne les rectangles des 8 poignees."""
|
||||||
self._end = event.pos()
|
if not self._has_selection:
|
||||||
self._rect = QRect(self._start, self._end).normalized()
|
return {}
|
||||||
self.update()
|
r = self._rect.normalized()
|
||||||
self._emit_ratios()
|
hs = HANDLE_SIZE
|
||||||
else:
|
return {
|
||||||
super().mouseMoveEvent(event)
|
"tl": QRect(r.left() - hs, r.top() - hs, hs * 2, hs * 2),
|
||||||
|
"tr": QRect(r.right() - hs, r.top() - hs, hs * 2, hs * 2),
|
||||||
|
"bl": QRect(r.left() - hs, r.bottom() - hs, hs * 2, hs * 2),
|
||||||
|
"br": QRect(r.right() - hs, r.bottom() - hs, hs * 2, hs * 2),
|
||||||
|
"t": QRect(r.center().x() - hs, r.top() - hs, hs * 2, hs * 2),
|
||||||
|
"b": QRect(r.center().x() - hs, r.bottom() - hs, hs * 2, hs * 2),
|
||||||
|
"l": QRect(r.left() - hs, r.center().y() - hs, hs * 2, hs * 2),
|
||||||
|
"r": QRect(r.right() - hs, r.center().y() - hs, hs * 2, hs * 2),
|
||||||
|
}
|
||||||
|
|
||||||
def mouseReleaseEvent(self, event: QMouseEvent):
|
def _cursor_for_handle(self, handle):
|
||||||
if self._selecting:
|
cursors = {
|
||||||
self._selecting = False
|
"tl": Qt.CursorShape.SizeFDiagCursor,
|
||||||
self._end = event.pos()
|
"br": Qt.CursorShape.SizeFDiagCursor,
|
||||||
self._rect = QRect(self._start, self._end).normalized()
|
"tr": Qt.CursorShape.SizeBDiagCursor,
|
||||||
self.update()
|
"bl": Qt.CursorShape.SizeBDiagCursor,
|
||||||
|
"t": Qt.CursorShape.SizeVerCursor,
|
||||||
|
"b": Qt.CursorShape.SizeVerCursor,
|
||||||
|
"l": Qt.CursorShape.SizeHorCursor,
|
||||||
|
"r": Qt.CursorShape.SizeHorCursor,
|
||||||
|
}
|
||||||
|
return cursors.get(handle, Qt.CursorShape.CrossCursor)
|
||||||
|
|
||||||
|
def mousePressEvent(self, event):
|
||||||
|
if not self._select_mode or event.button() != Qt.MouseButton.LeftButton:
|
||||||
|
return super().mousePressEvent(event)
|
||||||
|
|
||||||
|
pos = event.pos()
|
||||||
|
self._drag_start = pos
|
||||||
|
self._drag_rect_start = QRect(self._rect)
|
||||||
|
|
||||||
|
# Verifier si on clique sur une poignee
|
||||||
|
if self._has_selection:
|
||||||
|
for name, hr in self._handle_rects().items():
|
||||||
|
if hr.contains(pos):
|
||||||
|
self._drag_mode = name
|
||||||
|
return
|
||||||
|
# Clic dans le rectangle = deplacer
|
||||||
|
if self._rect.normalized().contains(pos):
|
||||||
|
self._drag_mode = "move"
|
||||||
|
return
|
||||||
|
|
||||||
|
# Nouveau rectangle
|
||||||
|
self._drag_mode = "create"
|
||||||
|
self._rect = QRect(pos, pos)
|
||||||
|
self._has_selection = True
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def mouseMoveEvent(self, event):
|
||||||
|
pos = event.pos()
|
||||||
|
|
||||||
|
if not self._select_mode:
|
||||||
|
return super().mouseMoveEvent(event)
|
||||||
|
|
||||||
|
# Hover : changer le curseur sur les poignees
|
||||||
|
if not self._drag_mode and self._has_selection:
|
||||||
|
for name, hr in self._handle_rects().items():
|
||||||
|
if hr.contains(pos):
|
||||||
|
self.setCursor(self._cursor_for_handle(name))
|
||||||
|
return
|
||||||
|
if self._rect.normalized().contains(pos):
|
||||||
|
self.setCursor(Qt.CursorShape.SizeAllCursor)
|
||||||
|
return
|
||||||
|
self.setCursor(Qt.CursorShape.CrossCursor)
|
||||||
|
return
|
||||||
|
|
||||||
|
if not self._drag_mode:
|
||||||
|
return
|
||||||
|
|
||||||
|
dx = pos.x() - self._drag_start.x()
|
||||||
|
dy = pos.y() - self._drag_start.y()
|
||||||
|
r = QRect(self._drag_rect_start)
|
||||||
|
|
||||||
|
if self._drag_mode == "create":
|
||||||
|
self._rect = QRect(self._drag_start, pos).normalized()
|
||||||
|
elif self._drag_mode == "move":
|
||||||
|
self._rect = r.translated(dx, dy)
|
||||||
|
elif self._drag_mode == "tl":
|
||||||
|
self._rect = QRect(QPoint(r.left() + dx, r.top() + dy), r.bottomRight()).normalized()
|
||||||
|
elif self._drag_mode == "tr":
|
||||||
|
self._rect = QRect(QPoint(r.left(), r.top() + dy), QPoint(r.right() + dx, r.bottom())).normalized()
|
||||||
|
elif self._drag_mode == "bl":
|
||||||
|
self._rect = QRect(QPoint(r.left() + dx, r.top()), QPoint(r.right(), r.bottom() + dy)).normalized()
|
||||||
|
elif self._drag_mode == "br":
|
||||||
|
self._rect = QRect(r.topLeft(), QPoint(r.right() + dx, r.bottom() + dy)).normalized()
|
||||||
|
elif self._drag_mode == "t":
|
||||||
|
self._rect = QRect(QPoint(r.left(), r.top() + dy), r.bottomRight()).normalized()
|
||||||
|
elif self._drag_mode == "b":
|
||||||
|
self._rect = QRect(r.topLeft(), QPoint(r.right(), r.bottom() + dy)).normalized()
|
||||||
|
elif self._drag_mode == "l":
|
||||||
|
self._rect = QRect(QPoint(r.left() + dx, r.top()), r.bottomRight()).normalized()
|
||||||
|
elif self._drag_mode == "r":
|
||||||
|
self._rect = QRect(r.topLeft(), QPoint(r.right() + dx, r.bottom())).normalized()
|
||||||
|
|
||||||
|
self.update()
|
||||||
|
self._emit_ratios()
|
||||||
|
|
||||||
|
def mouseReleaseEvent(self, event):
|
||||||
|
if self._drag_mode:
|
||||||
|
self._drag_mode = None
|
||||||
self._emit_ratios()
|
self._emit_ratios()
|
||||||
self.selection_done.emit()
|
self.selection_done.emit()
|
||||||
|
self.update()
|
||||||
else:
|
else:
|
||||||
super().mouseReleaseEvent(event)
|
super().mouseReleaseEvent(event)
|
||||||
|
|
||||||
def _emit_ratios(self):
|
def _emit_ratios(self):
|
||||||
if not self.pixmap():
|
if not self.pixmap() or not self._has_selection:
|
||||||
return
|
return
|
||||||
pm = self.pixmap()
|
pm = self.pixmap()
|
||||||
img_w, img_h = pm.width(), pm.height()
|
img_w, img_h = pm.width(), pm.height()
|
||||||
lbl_w, lbl_h = self.width(), self.height()
|
if img_w <= 0 or img_h <= 0:
|
||||||
off_x = max(0, (lbl_w - img_w) // 2)
|
return
|
||||||
off_y = max(0, (lbl_h - img_h) // 2)
|
off_x, off_y = self._img_offset()
|
||||||
|
r = self._rect.normalized()
|
||||||
|
|
||||||
left = max(0, (self._rect.left() - off_x)) / img_w
|
left = max(0, min(1, (r.left() - off_x) / img_w))
|
||||||
top = max(0, (self._rect.top() - off_y)) / img_h
|
top = max(0, min(1, (r.top() - off_y) / img_h))
|
||||||
right = min(1, (self._rect.right() - off_x)) / img_w
|
right = max(0, min(1, (r.right() - off_x) / img_w))
|
||||||
bottom = min(1, (self._rect.bottom() - off_y)) / img_h
|
bottom = max(0, min(1, (r.bottom() - off_y) / img_h))
|
||||||
|
|
||||||
left = max(0, min(1, left))
|
|
||||||
top = max(0, min(1, top))
|
|
||||||
right = max(0, min(1, right))
|
|
||||||
bottom = max(0, min(1, bottom))
|
|
||||||
|
|
||||||
self.selection_changed.emit(left, top, right, bottom)
|
self.selection_changed.emit(left, top, right, bottom)
|
||||||
|
|
||||||
def paintEvent(self, event):
|
def paintEvent(self, event):
|
||||||
super().paintEvent(event)
|
super().paintEvent(event)
|
||||||
if self._has_selection and not self._rect.isNull():
|
if not self._has_selection or self._rect.isNull():
|
||||||
painter = QPainter(self)
|
return
|
||||||
# Zone sombre en dehors de la selection
|
|
||||||
painter.setBrush(QColor(0, 0, 0, 100))
|
|
||||||
painter.setPen(Qt.PenStyle.NoPen)
|
|
||||||
full = self.rect()
|
|
||||||
r = self._rect.normalized()
|
|
||||||
# Haut
|
|
||||||
painter.drawRect(full.left(), full.top(), full.width(), r.top() - full.top())
|
|
||||||
# Bas
|
|
||||||
painter.drawRect(full.left(), r.bottom(), full.width(), full.bottom() - r.bottom())
|
|
||||||
# Gauche
|
|
||||||
painter.drawRect(full.left(), r.top(), r.left() - full.left(), r.height())
|
|
||||||
# Droite
|
|
||||||
painter.drawRect(r.right(), r.top(), full.right() - r.right(), r.height())
|
|
||||||
|
|
||||||
# Cadre de selection
|
painter = QPainter(self)
|
||||||
pen = QPen(QColor(0, 120, 255), 2, Qt.PenStyle.DashLine)
|
r = self._rect.normalized()
|
||||||
painter.setPen(pen)
|
full = self.rect()
|
||||||
painter.setBrush(Qt.BrushStyle.NoBrush)
|
|
||||||
painter.drawRect(r)
|
|
||||||
|
|
||||||
# Dimensions en mm (affichees dans le coin)
|
# Zone sombre en dehors
|
||||||
painter.setPen(QColor(0, 120, 255))
|
painter.setBrush(QColor(0, 0, 0, 80))
|
||||||
painter.drawText(r.left() + 4, r.top() - 4,
|
painter.setPen(Qt.PenStyle.NoPen)
|
||||||
f"{r.width()}x{r.height()} px")
|
painter.drawRect(full.left(), full.top(), full.width(), r.top() - full.top())
|
||||||
painter.end()
|
painter.drawRect(full.left(), r.bottom(), full.width(), full.bottom() - r.bottom())
|
||||||
|
painter.drawRect(full.left(), r.top(), r.left() - full.left(), r.height())
|
||||||
|
painter.drawRect(r.right(), r.top(), full.right() - r.right(), r.height())
|
||||||
|
|
||||||
|
# Cadre
|
||||||
|
pen = QPen(QColor(0, 180, 216), 2, Qt.PenStyle.SolidLine)
|
||||||
|
painter.setPen(pen)
|
||||||
|
painter.setBrush(Qt.BrushStyle.NoBrush)
|
||||||
|
painter.drawRect(r)
|
||||||
|
|
||||||
|
# Poignees
|
||||||
|
painter.setBrush(QColor(255, 255, 255))
|
||||||
|
painter.setPen(QPen(QColor(0, 180, 216), 1))
|
||||||
|
for hr in self._handle_rects().values():
|
||||||
|
painter.drawRect(hr)
|
||||||
|
|
||||||
|
# Dimensions
|
||||||
|
if self.pixmap():
|
||||||
|
pm = self.pixmap()
|
||||||
|
img_w, img_h = pm.width(), pm.height()
|
||||||
|
off_x, off_y = self._img_offset()
|
||||||
|
if img_w > 0 and img_h > 0:
|
||||||
|
w_pct = r.width() / img_w * 100
|
||||||
|
h_pct = r.height() / img_h * 100
|
||||||
|
painter.setPen(QColor(0, 180, 216))
|
||||||
|
painter.drawText(r.left() + 4, r.top() - 6,
|
||||||
|
f"{w_pct:.0f}% x {h_pct:.0f}%")
|
||||||
|
|
||||||
|
painter.end()
|
||||||
|
|
||||||
|
|
||||||
class PdfViewer(QWidget):
|
class PdfViewer(QWidget):
|
||||||
"""Widget d'apercu PDF avec zoom molette, navigation et selection."""
|
"""Widget d'apercu PDF avec zoom molette, navigation et selection."""
|
||||||
|
|
||||||
page_changed = pyqtSignal(int, int)
|
page_changed = pyqtSignal(int, int)
|
||||||
selection_changed = pyqtSignal(float, float, float, float) # ratios
|
selection_changed = pyqtSignal(float, float, float, float)
|
||||||
selection_done = pyqtSignal()
|
selection_done = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
@@ -185,7 +279,7 @@ class PdfViewer(QWidget):
|
|||||||
def show_selection(self, left_ratio, top_ratio, right_ratio, bottom_ratio):
|
def show_selection(self, left_ratio, top_ratio, right_ratio, bottom_ratio):
|
||||||
self._image_label.set_selection_from_margins(left_ratio, top_ratio, right_ratio, bottom_ratio)
|
self._image_label.set_selection_from_margins(left_ratio, top_ratio, right_ratio, bottom_ratio)
|
||||||
|
|
||||||
def _on_wheel(self, event: QWheelEvent):
|
def _on_wheel(self, event):
|
||||||
if event.modifiers() & Qt.KeyboardModifier.ControlModifier:
|
if event.modifiers() & Qt.KeyboardModifier.ControlModifier:
|
||||||
delta = event.angleDelta().y()
|
delta = event.angleDelta().y()
|
||||||
if delta > 0:
|
if delta > 0:
|
||||||
@@ -194,10 +288,9 @@ class PdfViewer(QWidget):
|
|||||||
self._zoom = max(self._zoom / 1.15, 0.2)
|
self._zoom = max(self._zoom / 1.15, 0.2)
|
||||||
self._render_page()
|
self._render_page()
|
||||||
else:
|
else:
|
||||||
delta = event.angleDelta().y()
|
if event.angleDelta().y() < 0:
|
||||||
if delta < 0:
|
|
||||||
self.next_page()
|
self.next_page()
|
||||||
elif delta > 0:
|
elif event.angleDelta().y() > 0:
|
||||||
self.prev_page()
|
self.prev_page()
|
||||||
|
|
||||||
def load_pdf(self, path):
|
def load_pdf(self, path):
|
||||||
@@ -246,9 +339,7 @@ class PdfViewer(QWidget):
|
|||||||
if vw <= 0 or vh <= 0:
|
if vw <= 0 or vh <= 0:
|
||||||
self._zoom = 1.0
|
self._zoom = 1.0
|
||||||
return
|
return
|
||||||
scale_x = vw / pw
|
self._zoom = min(vw / pw, vh / ph) * (72 / 150)
|
||||||
scale_y = vh / ph
|
|
||||||
self._zoom = min(scale_x, scale_y) * (72 / 150)
|
|
||||||
|
|
||||||
def prev_page(self):
|
def prev_page(self):
|
||||||
if self._current_page > 0:
|
if self._current_page > 0:
|
||||||
|
|||||||
@@ -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.5.1"
|
VERSION = "2.5.2"
|
||||||
|
|
||||||
|
|
||||||
def get_remote_version():
|
def get_remote_version():
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
2.5.1
|
2.5.2
|
||||||
|
|||||||
Reference in New Issue
Block a user