From f4a4f197867ad67810d38b8685f94137db3e41af Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 11 Sep 2024 16:33:55 +0530 Subject: [PATCH] Image popup: Add a context menu with an option to reset the current zoom. Fixes #2080315 [[Enhancement] Image viewer: View image at 100%](https://bugs.launchpad.net/calibre/+bug/2080315) --- src/calibre/gui2/image_popup.py | 63 +++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 18 deletions(-) diff --git a/src/calibre/gui2/image_popup.py b/src/calibre/gui2/image_popup.py index 95bcda9a82..cd43809f2d 100644 --- a/src/calibre/gui2/image_popup.py +++ b/src/calibre/gui2/image_popup.py @@ -16,6 +16,7 @@ from qt.core import ( QImage, QKeySequence, QLabel, + QMenu, QPainter, QPalette, QPixmap, @@ -140,14 +141,25 @@ class ImageView(QDialog): self.current_url = current_url self.factor = 1.0 self.geom_name = geom_name - self.zoom_in_action = ac = QAction(self) + self.zoom_in_action = ac = QAction(QIcon.ic('plus.png'), _('Zoom &in'), self) ac.triggered.connect(self.zoom_in) ac.setShortcuts([QKeySequence(QKeySequence.StandardKey.ZoomIn), QKeySequence('+', QKeySequence.SequenceFormat.PortableText)]) self.addAction(ac) - self.zoom_out_action = ac = QAction(self) + self.zoom_out_action = ac = QAction(QIcon.ic('minus.png'), _('Zoom &out'), self) ac.triggered.connect(self.zoom_out) ac.setShortcuts([QKeySequence(QKeySequence.StandardKey.ZoomOut), QKeySequence('-', QKeySequence.SequenceFormat.PortableText)]) self.addAction(ac) + self.reset_zoom_action = ac = QAction(QIcon.ic('edit-undo.png'), _('Reset &zoom'), self) + ac.triggered.connect(self.reset_zoom) + ac.setShortcuts([QKeySequence('=', QKeySequence.SequenceFormat.PortableText)]) + self.addAction(ac) + self.copy_action = ac = QAction(QIcon.ic('edit-copy.png'), _('&Copy'), self) + ac.setShortcuts([QKeySequence(QKeySequence.StandardKey.Copy)]) + self.addAction(ac) + ac.triggered.connect(self.copy_image) + self.rotate_action = ac = QAction(QIcon.ic('rotate-right.png'), _('&Rotate'), self) + self.addAction(ac) + ac.triggered.connect(self.rotate_image) self.scrollarea = sa = ScrollArea() sa.setAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter) @@ -160,26 +172,22 @@ class ImageView(QDialog): self.bb = bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Close) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) - self.zi_button = zi = bb.addButton(_('Zoom &in'), QDialogButtonBox.ButtonRole.ActionRole) - self.zo_button = zo = bb.addButton(_('Zoom &out'), QDialogButtonBox.ButtonRole.ActionRole) + self.zi_button = zi = bb.addButton(self.zoom_in_action.text(), QDialogButtonBox.ButtonRole.ActionRole) + self.zo_button = zo = bb.addButton(self.zoom_out_action.text(), QDialogButtonBox.ButtonRole.ActionRole) self.save_button = so = bb.addButton(_('&Save as'), QDialogButtonBox.ButtonRole.ActionRole) - self.copy_button = co = bb.addButton(_('&Copy'), QDialogButtonBox.ButtonRole.ActionRole) - self.rotate_button = ro = bb.addButton(_('&Rotate'), QDialogButtonBox.ButtonRole.ActionRole) + self.copy_button = co = bb.addButton(self.copy_action.text(), QDialogButtonBox.ButtonRole.ActionRole) + self.rotate_button = ro = bb.addButton(self.rotate_action.text(), QDialogButtonBox.ButtonRole.ActionRole) self.fullscreen_button = fo = bb.addButton(_('F&ull screen'), QDialogButtonBox.ButtonRole.ActionRole) - zi.setIcon(QIcon.ic('plus.png')) - zo.setIcon(QIcon.ic('minus.png')) + zi.setIcon(self.zoom_in_action.icon()) + zo.setIcon(self.zoom_out_action.icon()) so.setIcon(QIcon.ic('save.png')) - co.setIcon(QIcon.ic('edit-copy.png')) - ro.setIcon(QIcon.ic('rotate-right.png')) + co.setIcon(self.copy_action.icon()) + ro.setIcon(self.rotate_action.icon()) fo.setIcon(QIcon.ic('page.png')) - zi.clicked.connect(self.zoom_in) - zo.clicked.connect(self.zoom_out) + zi.clicked.connect(self.zoom_in_action.trigger) + zo.clicked.connect(self.zoom_out_action.trigger) so.clicked.connect(self.save_image) - co.clicked.connect(self.copy_image) - self.copy_action = QAction(self) - self.addAction(self.copy_action) - self.copy_action.triggered.connect(self.copy_button.click) - self.copy_action.setShortcut(QKeySequence.StandardKey.Copy) + co.clicked.connect(self.copy_action.trigger) ro.clicked.connect(self.rotate_image) fo.setCheckable(True) @@ -205,6 +213,17 @@ class ImageView(QDialog): self.restore_geometry(self.prefs, self.geom_name) fo.setChecked(self.isFullScreen()) fo.toggled.connect(self.toggle_fullscreen) + self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) + self.customContextMenuRequested.connect(self.context_menu) + + def context_menu(self, pos): + m = QMenu(self) + m.addAction(self.reset_zoom_action) + m.addAction(self.zoom_in_action) + m.addAction(self.zoom_out_action) + m.addAction(self.copy_action) + m.addAction(self.rotate_action) + m.exec(self.mapToGlobal(pos)) def set_to_viewport_size(self): page_size = self.scrollarea.size() @@ -226,12 +245,17 @@ class ImageView(QDialog): actual_height = self.current_img.size().height() if actual_height: return scaled_height / actual_height - return 1 + return 1.0 def zoom_requested(self, zoom_out): if (zoom_out and self.zo_button.isEnabled()) or (not zoom_out and self.zi_button.isEnabled()): (self.zoom_out if zoom_out else self.zoom_in)() + def reset_zoom(self): + self.factor = 1.0 + self.prefs.set('image_popup_zoom_factor', self.factor) + self.adjust_image(1.0) + def zoom_in(self): if self.fit_image.isChecked(): factor = self.factor_from_fit() @@ -288,6 +312,9 @@ class ImageView(QDialog): self.label.resize(self.factor * self.current_img.size()) self.zi_button.setEnabled(self.factor <= 3) self.zo_button.setEnabled(self.factor >= 0.3333) + self.zoom_in_action.setEnabled(self.zi_button.isEnabled()) + self.zoom_out_action.setEnabled(self.zo_button.isEnabled()) + self.reset_zoom_action.setEnabled(self.factor != 1) self.adjust_scrollbars(factor) def adjust_scrollbars(self, factor):