diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index bbe83e5b2f..9294a1f365 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -750,9 +750,11 @@ else: ans = ans[0] return ans - def choose_images(window, name, title, select_only_single_file=True, - formats=('png', 'gif', 'jpg', 'jpeg', 'svg')): + def choose_images(window, name, title, select_only_single_file=True, formats=None): mode = QFileDialog.ExistingFile if select_only_single_file else QFileDialog.ExistingFiles + if formats is None: + from calibre.gui2.dnd import image_extensions + formats = image_extensions() fd = FileDialog(title=title, name=name, filters=[(_('Images'), list(formats))], parent=window, add_all_files_filter=False, mode=mode, diff --git a/src/calibre/gui2/actions/add.py b/src/calibre/gui2/actions/add.py index 56d299df29..dcf5ad7bb5 100644 --- a/src/calibre/gui2/actions/add.py +++ b/src/calibre/gui2/actions/add.py @@ -17,7 +17,6 @@ from calibre.gui2 import (error_dialog, choose_files, choose_dir, from calibre.gui2.dialogs.add_empty_book import AddEmptyBookDialog from calibre.gui2.dialogs.confirm_delete import confirm from calibre.gui2.dialogs.progress import ProgressDialog -from calibre.gui2.widgets import IMAGE_EXTENSIONS from calibre.ebooks import BOOK_EXTENSIONS from calibre.utils.filenames import ascii_filename from calibre.utils.icu import sort_key @@ -359,11 +358,12 @@ class AddAction(InterfaceAction): return cid = db.id(current_idx.row()) if cid is None else cid formats = [] + from calibre.gui2.dnd import image_extensions for path in paths: ext = os.path.splitext(path)[1].lower() if ext: ext = ext[1:] - if ext in IMAGE_EXTENSIONS: + if ext in image_extensions(): pmap = QPixmap() pmap.load(path) if not pmap.isNull(): diff --git a/src/calibre/gui2/book_details.py b/src/calibre/gui2/book_details.py index 8ce18b7dc8..7633c49010 100644 --- a/src/calibre/gui2/book_details.py +++ b/src/calibre/gui2/book_details.py @@ -17,7 +17,7 @@ from PyQt5.QtWebKitWidgets import QWebView from calibre import fit_image from calibre.gui2.dnd import (dnd_has_image, dnd_get_image, dnd_get_files, - IMAGE_EXTENSIONS, dnd_has_extension) + dnd_has_extension, image_extensions) from calibre.ebooks import BOOK_EXTENSIONS from calibre.ebooks.metadata.book.base import (field_metadata, Metadata) from calibre.ebooks.metadata.book.render import mi_to_html @@ -639,11 +639,10 @@ class BookDetails(QWidget): # {{{ open_fmt_with = pyqtSignal(int, object, object) # Drag 'n drop {{{ - DROPABBLE_EXTENSIONS = IMAGE_EXTENSIONS+BOOK_EXTENSIONS def dragEnterEvent(self, event): md = event.mimeData() - if dnd_has_extension(md, self.DROPABBLE_EXTENSIONS, allow_all_extensions=True) or \ + if dnd_has_extension(md, image_extensions() + BOOK_EXTENSIONS, allow_all_extensions=True) or \ dnd_has_image(md): event.acceptProposedAction() diff --git a/src/calibre/gui2/dnd.py b/src/calibre/gui2/dnd.py index 01f4a356e9..e3828ff46a 100644 --- a/src/calibre/gui2/dnd.py +++ b/src/calibre/gui2/dnd.py @@ -13,7 +13,7 @@ from threading import Thread from Queue import Queue, Empty from PyQt5.Qt import QPixmap, Qt, QDialog, QLabel, QVBoxLayout, \ - QDialogButtonBox, QProgressBar, QTimer, QUrl + QDialogButtonBox, QProgressBar, QTimer, QUrl, QImageReader from calibre.constants import DEBUG, iswindows from calibre.ptempfile import PersistentTemporaryFile @@ -21,6 +21,12 @@ from calibre import browser, as_unicode, prints from calibre.gui2 import error_dialog from calibre.utils.imghdr import what +def image_extensions(): + if not hasattr(image_extensions, 'ans'): + image_extensions.ans = [bytes(x).decode('utf-8') for x in QImageReader.supportedImageFormats()] + return image_extensions.ans + +# This is present for compatibility with old plugins, do not use IMAGE_EXTENSIONS = ['jpg', 'jpeg', 'gif', 'png', 'bmp'] class Worker(Thread): # {{{ @@ -121,7 +127,7 @@ class DownloadDialog(QDialog): # {{{ def dnd_has_image(md): # Chromium puts image data into application/octet-stream - return md.hasImage() or md.hasFormat('application/octet-stream') and what(None, bytes(md.data('application/octet-stream'))) in IMAGE_EXTENSIONS + return md.hasImage() or md.hasFormat('application/octet-stream') and what(None, bytes(md.data('application/octet-stream'))) in image_extensions() def data_as_string(f, md): raw = bytes(md.data(f)) @@ -181,13 +187,12 @@ def dnd_has_extension(md, extensions, allow_all_extensions=False): return bool(exts) return bool(exts.intersection(frozenset(extensions))) -def dnd_get_image(md, image_exts=IMAGE_EXTENSIONS): +def dnd_get_image(md, image_exts=None): ''' Get the image in the QMimeData object md. :return: None, None if no image is found - QPixmap, None if an image is found, the pixmap is guaranteed not - null + QPixmap, None if an image is found, the pixmap is guaranteed not null url, filename if a URL that points to an image is found ''' if md.hasImage(): @@ -207,6 +212,9 @@ def dnd_get_image(md, image_exts=IMAGE_EXTENSIONS): if not pmap.isNull(): return pmap, None + if image_exts is None: + image_exts = image_extensions() + # No image, look for an URL pointing to an image urls = urls_from_md(md) paths = [path_from_qurl(u) for u in urls] diff --git a/src/calibre/gui2/metadata/basic_widgets.py b/src/calibre/gui2/metadata/basic_widgets.py index 08f0149e78..117c316925 100644 --- a/src/calibre/gui2/metadata/basic_widgets.py +++ b/src/calibre/gui2/metadata/basic_widgets.py @@ -1071,8 +1071,7 @@ class Cover(ImageView): # {{{ def select_cover(self, *args): files = choose_images( - self, 'change cover dialog', _('Choose cover for ') + self.dialog.title.current_val, - formats=('png', 'gif', 'jpg', 'jpeg')) + self, 'change cover dialog', _('Choose cover for ') + self.dialog.title.current_val) if not files: return _file = files[0] diff --git a/src/calibre/gui2/tweak_book/editor/canvas.py b/src/calibre/gui2/tweak_book/editor/canvas.py index 8278d1f25f..99355491e8 100644 --- a/src/calibre/gui2/tweak_book/editor/canvas.py +++ b/src/calibre/gui2/tweak_book/editor/canvas.py @@ -18,7 +18,7 @@ from PyQt5.Qt import ( from calibre import fit_image from calibre.gui2 import error_dialog, pixmap_to_data from calibre.gui2.dnd import ( - IMAGE_EXTENSIONS, dnd_has_extension, dnd_has_image, dnd_get_image, DownloadDialog) + image_extensions, dnd_has_extension, dnd_has_image, dnd_get_image, DownloadDialog) from calibre.gui2.tweak_book import capitalize from calibre.utils.imghdr import identify from calibre.utils.img import ( @@ -224,11 +224,10 @@ class Canvas(QWidget): return self.current_image is not self.original_image # Drag 'n drop {{{ - DROPABBLE_EXTENSIONS = IMAGE_EXTENSIONS def dragEnterEvent(self, event): md = event.mimeData() - if dnd_has_extension(md, self.DROPABBLE_EXTENSIONS) or dnd_has_image(md): + if dnd_has_extension(md, image_extensions()) or dnd_has_image(md): event.acceptProposedAction() def dropEvent(self, event): diff --git a/src/calibre/gui2/widgets.py b/src/calibre/gui2/widgets.py index 7cf363453a..428a31fb29 100644 --- a/src/calibre/gui2/widgets.py +++ b/src/calibre/gui2/widgets.py @@ -20,7 +20,7 @@ from calibre.ebooks import BOOK_EXTENSIONS from calibre.utils.config import prefs, XMLConfig from calibre.gui2.progress_indicator import ProgressIndicator as _ProgressIndicator from calibre.gui2.dnd import (dnd_has_image, dnd_get_image, dnd_get_files, - IMAGE_EXTENSIONS, dnd_has_extension, DownloadDialog) + image_extensions, dnd_has_extension, DownloadDialog) from calibre.utils.localization import localize_user_manual_link history = XMLConfig('history') @@ -215,14 +215,15 @@ class ImageDropMixin(object): # {{{ Adds support for dropping images onto widgets and a context menu for copy/pasting images. ''' - DROPABBLE_EXTENSIONS = IMAGE_EXTENSIONS + DROPABBLE_EXTENSIONS = None def __init__(self): self.setAcceptDrops(True) def dragEnterEvent(self, event): md = event.mimeData() - if dnd_has_extension(md, self.DROPABBLE_EXTENSIONS) or \ + exts = self.DROPABBLE_EXTENSIONS or image_extensions() + if dnd_has_extension(md, exts) or \ dnd_has_image(md): event.acceptProposedAction() diff --git a/src/calibre/gui2/win_file_dialogs.py b/src/calibre/gui2/win_file_dialogs.py index 2e4a2df304..11001c0552 100644 --- a/src/calibre/gui2/win_file_dialogs.py +++ b/src/calibre/gui2/win_file_dialogs.py @@ -225,8 +225,10 @@ def choose_files(window, name, title, return ans return None -def choose_images(window, name, title, select_only_single_file=True, - formats=('png', 'gif', 'jpg', 'jpeg', 'svg')): +def choose_images(window, name, title, select_only_single_file=True, formats=None): + if formats is None: + from calibre.gui2.dnd import image_extensions + formats = image_extensions() file_types = [(_('Images'), list(formats))] return choose_files(window, name, title, select_only_single_file=select_only_single_file, filters=file_types)