diff --git a/src/calibre/gui2/viewer/ui.py b/src/calibre/gui2/viewer/ui.py index 15c55680ed..dd279d10c0 100644 --- a/src/calibre/gui2/viewer/ui.py +++ b/src/calibre/gui2/viewer/ui.py @@ -12,8 +12,8 @@ from hashlib import sha256 from threading import Thread from PyQt5.Qt import ( - QDockWidget, QEvent, QModelIndex, QPixmap, Qt, QUrl, QVBoxLayout, QWidget, - pyqtSignal + QApplication, QDockWidget, QEvent, QMimeData, QModelIndex, QPixmap, Qt, QUrl, + QVBoxLayout, QWidget, pyqtSignal ) from calibre import prints @@ -33,6 +33,7 @@ from calibre.gui2.viewer.web_view import ( vprefs ) from calibre.utils.date import utcnow +from calibre.utils.img import image_from_path from calibre.utils.ipc.simple_worker import WorkerError from calibre.utils.serialize import json_loads from polyglot.builtins import as_bytes, itervalues @@ -125,6 +126,7 @@ class EbookViewer(MainWindow): self.web_view.ask_for_open.connect(self.ask_for_open, type=Qt.QueuedConnection) self.web_view.selection_changed.connect(self.lookup_widget.selected_text_changed, type=Qt.QueuedConnection) self.web_view.view_image.connect(self.view_image, type=Qt.QueuedConnection) + self.web_view.copy_image.connect(self.copy_image, type=Qt.QueuedConnection) self.setCentralWidget(self.web_view) self.restore_state() if continue_reading: @@ -213,6 +215,22 @@ class EbookViewer(MainWindow): else: error_dialog(self, _('Image not found'), _( "Failed to find the image {}").format(name), show=True) + + def copy_image(self, name): + path = get_path_for_name(name) + if not path: + return error_dialog(self, _('Image not found'), _( + "Failed to find the image {}").format(name), show=True) + try: + img = image_from_path(path) + except Exception: + return error_dialog(self, _('Invalid image'), _( + "Failed to load the image {}").format(name), show=True) + url = QUrl.fromLocalFile(path) + md = QMimeData() + md.setImageData(img) + md.setUrls([url]) + QApplication.instance().clipboard().setMimeData(md) # }}} # Load book {{{ diff --git a/src/calibre/gui2/viewer/web_view.py b/src/calibre/gui2/viewer/web_view.py index c53a33a1a3..630ff4949f 100644 --- a/src/calibre/gui2/viewer/web_view.py +++ b/src/calibre/gui2/viewer/web_view.py @@ -230,6 +230,7 @@ class ViewerBridge(Bridge): selection_changed = from_js(object) copy_selection = from_js(object) view_image = from_js(object) + copy_image = from_js(object) change_background_image = from_js(object) create_view = to_js() @@ -371,6 +372,7 @@ class WebView(RestartingWebEngineView): ask_for_open = pyqtSignal(object) selection_changed = pyqtSignal(object) view_image = pyqtSignal(object) + copy_image = pyqtSignal(object) def __init__(self, parent=None): self._host_widget = None @@ -396,6 +398,7 @@ class WebView(RestartingWebEngineView): self.bridge.ask_for_open.connect(self.ask_for_open) self.bridge.selection_changed.connect(self.selection_changed) self.bridge.view_image.connect(self.view_image) + self.bridge.copy_image.connect(self.copy_image) self.bridge.report_cfi.connect(self.call_callback) self.bridge.change_background_image.connect(self.change_background_image) self.pending_bridge_ready_actions = {} diff --git a/src/pyj/read_book/overlay.pyj b/src/pyj/read_book/overlay.pyj index e9cd6f56e0..8c6dafeddb 100644 --- a/src/pyj/read_book/overlay.pyj +++ b/src/pyj/read_book/overlay.pyj @@ -303,6 +303,9 @@ class MainOverlay: # {{{ copy_actions.appendChild(ac(_('View image'), _('View the current image'), def(): self.overlay.hide(), ui_operations.view_image(self.elements.img) , 'image')) + copy_actions.appendChild(ac(_('Copy image'), _('View the current image'), def(): + self.overlay.hide(), ui_operations.copy_image(self.elements.img) + , 'copy')) if copy_actions.childNodes.length: actions_div.appendChild(copy_actions) diff --git a/src/pyj/viewer-main.pyj b/src/pyj/viewer-main.pyj index 111d8961f3..faae045997 100644 --- a/src/pyj/viewer-main.pyj +++ b/src/pyj/viewer-main.pyj @@ -302,6 +302,8 @@ if window is window.top: to_python.copy_selection(text or None) ui_operations.view_image = def(name): to_python.view_image(name) + ui_operations.copy_image = def(name): + to_python.copy_image(name) ui_operations.change_background_image = def(img_id): to_python.change_background_image(img_id) ui_operations.quit = def():