mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Allow reading more image formats as covers (All images will be converted to JPEG when stored). Fixes #1619993 [Request: Support for dragging TIFF files into Cover area](https://bugs.launchpad.net/calibre/+bug/1619993)
This commit is contained in:
parent
72d735b41d
commit
5088a023c7
@ -750,9 +750,11 @@ else:
|
|||||||
ans = ans[0]
|
ans = ans[0]
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
def choose_images(window, name, title, select_only_single_file=True,
|
def choose_images(window, name, title, select_only_single_file=True, formats=None):
|
||||||
formats=('png', 'gif', 'jpg', 'jpeg', 'svg')):
|
|
||||||
mode = QFileDialog.ExistingFile if select_only_single_file else QFileDialog.ExistingFiles
|
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,
|
fd = FileDialog(title=title, name=name,
|
||||||
filters=[(_('Images'), list(formats))],
|
filters=[(_('Images'), list(formats))],
|
||||||
parent=window, add_all_files_filter=False, mode=mode,
|
parent=window, add_all_files_filter=False, mode=mode,
|
||||||
|
@ -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.add_empty_book import AddEmptyBookDialog
|
||||||
from calibre.gui2.dialogs.confirm_delete import confirm
|
from calibre.gui2.dialogs.confirm_delete import confirm
|
||||||
from calibre.gui2.dialogs.progress import ProgressDialog
|
from calibre.gui2.dialogs.progress import ProgressDialog
|
||||||
from calibre.gui2.widgets import IMAGE_EXTENSIONS
|
|
||||||
from calibre.ebooks import BOOK_EXTENSIONS
|
from calibre.ebooks import BOOK_EXTENSIONS
|
||||||
from calibre.utils.filenames import ascii_filename
|
from calibre.utils.filenames import ascii_filename
|
||||||
from calibre.utils.icu import sort_key
|
from calibre.utils.icu import sort_key
|
||||||
@ -359,11 +358,12 @@ class AddAction(InterfaceAction):
|
|||||||
return
|
return
|
||||||
cid = db.id(current_idx.row()) if cid is None else cid
|
cid = db.id(current_idx.row()) if cid is None else cid
|
||||||
formats = []
|
formats = []
|
||||||
|
from calibre.gui2.dnd import image_extensions
|
||||||
for path in paths:
|
for path in paths:
|
||||||
ext = os.path.splitext(path)[1].lower()
|
ext = os.path.splitext(path)[1].lower()
|
||||||
if ext:
|
if ext:
|
||||||
ext = ext[1:]
|
ext = ext[1:]
|
||||||
if ext in IMAGE_EXTENSIONS:
|
if ext in image_extensions():
|
||||||
pmap = QPixmap()
|
pmap = QPixmap()
|
||||||
pmap.load(path)
|
pmap.load(path)
|
||||||
if not pmap.isNull():
|
if not pmap.isNull():
|
||||||
|
@ -17,7 +17,7 @@ from PyQt5.QtWebKitWidgets import QWebView
|
|||||||
|
|
||||||
from calibre import fit_image
|
from calibre import fit_image
|
||||||
from calibre.gui2.dnd import (dnd_has_image, dnd_get_image, dnd_get_files,
|
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 import BOOK_EXTENSIONS
|
||||||
from calibre.ebooks.metadata.book.base import (field_metadata, Metadata)
|
from calibre.ebooks.metadata.book.base import (field_metadata, Metadata)
|
||||||
from calibre.ebooks.metadata.book.render import mi_to_html
|
from calibre.ebooks.metadata.book.render import mi_to_html
|
||||||
@ -639,11 +639,10 @@ class BookDetails(QWidget): # {{{
|
|||||||
open_fmt_with = pyqtSignal(int, object, object)
|
open_fmt_with = pyqtSignal(int, object, object)
|
||||||
|
|
||||||
# Drag 'n drop {{{
|
# Drag 'n drop {{{
|
||||||
DROPABBLE_EXTENSIONS = IMAGE_EXTENSIONS+BOOK_EXTENSIONS
|
|
||||||
|
|
||||||
def dragEnterEvent(self, event):
|
def dragEnterEvent(self, event):
|
||||||
md = event.mimeData()
|
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):
|
dnd_has_image(md):
|
||||||
event.acceptProposedAction()
|
event.acceptProposedAction()
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ from threading import Thread
|
|||||||
from Queue import Queue, Empty
|
from Queue import Queue, Empty
|
||||||
|
|
||||||
from PyQt5.Qt import QPixmap, Qt, QDialog, QLabel, QVBoxLayout, \
|
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.constants import DEBUG, iswindows
|
||||||
from calibre.ptempfile import PersistentTemporaryFile
|
from calibre.ptempfile import PersistentTemporaryFile
|
||||||
@ -21,6 +21,12 @@ from calibre import browser, as_unicode, prints
|
|||||||
from calibre.gui2 import error_dialog
|
from calibre.gui2 import error_dialog
|
||||||
from calibre.utils.imghdr import what
|
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']
|
IMAGE_EXTENSIONS = ['jpg', 'jpeg', 'gif', 'png', 'bmp']
|
||||||
|
|
||||||
class Worker(Thread): # {{{
|
class Worker(Thread): # {{{
|
||||||
@ -121,7 +127,7 @@ class DownloadDialog(QDialog): # {{{
|
|||||||
|
|
||||||
def dnd_has_image(md):
|
def dnd_has_image(md):
|
||||||
# Chromium puts image data into application/octet-stream
|
# 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):
|
def data_as_string(f, md):
|
||||||
raw = bytes(md.data(f))
|
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)
|
||||||
return bool(exts.intersection(frozenset(extensions)))
|
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.
|
Get the image in the QMimeData object md.
|
||||||
|
|
||||||
:return: None, None if no image is found
|
:return: None, None if no image is found
|
||||||
QPixmap, None if an image is found, the pixmap is guaranteed not
|
QPixmap, None if an image is found, the pixmap is guaranteed not null
|
||||||
null
|
|
||||||
url, filename if a URL that points to an image is found
|
url, filename if a URL that points to an image is found
|
||||||
'''
|
'''
|
||||||
if md.hasImage():
|
if md.hasImage():
|
||||||
@ -207,6 +212,9 @@ def dnd_get_image(md, image_exts=IMAGE_EXTENSIONS):
|
|||||||
if not pmap.isNull():
|
if not pmap.isNull():
|
||||||
return pmap, None
|
return pmap, None
|
||||||
|
|
||||||
|
if image_exts is None:
|
||||||
|
image_exts = image_extensions()
|
||||||
|
|
||||||
# No image, look for an URL pointing to an image
|
# No image, look for an URL pointing to an image
|
||||||
urls = urls_from_md(md)
|
urls = urls_from_md(md)
|
||||||
paths = [path_from_qurl(u) for u in urls]
|
paths = [path_from_qurl(u) for u in urls]
|
||||||
|
@ -1071,8 +1071,7 @@ class Cover(ImageView): # {{{
|
|||||||
|
|
||||||
def select_cover(self, *args):
|
def select_cover(self, *args):
|
||||||
files = choose_images(
|
files = choose_images(
|
||||||
self, 'change cover dialog', _('Choose cover for ') + self.dialog.title.current_val,
|
self, 'change cover dialog', _('Choose cover for ') + self.dialog.title.current_val)
|
||||||
formats=('png', 'gif', 'jpg', 'jpeg'))
|
|
||||||
if not files:
|
if not files:
|
||||||
return
|
return
|
||||||
_file = files[0]
|
_file = files[0]
|
||||||
|
@ -18,7 +18,7 @@ from PyQt5.Qt import (
|
|||||||
from calibre import fit_image
|
from calibre import fit_image
|
||||||
from calibre.gui2 import error_dialog, pixmap_to_data
|
from calibre.gui2 import error_dialog, pixmap_to_data
|
||||||
from calibre.gui2.dnd import (
|
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.gui2.tweak_book import capitalize
|
||||||
from calibre.utils.imghdr import identify
|
from calibre.utils.imghdr import identify
|
||||||
from calibre.utils.img import (
|
from calibre.utils.img import (
|
||||||
@ -224,11 +224,10 @@ class Canvas(QWidget):
|
|||||||
return self.current_image is not self.original_image
|
return self.current_image is not self.original_image
|
||||||
|
|
||||||
# Drag 'n drop {{{
|
# Drag 'n drop {{{
|
||||||
DROPABBLE_EXTENSIONS = IMAGE_EXTENSIONS
|
|
||||||
|
|
||||||
def dragEnterEvent(self, event):
|
def dragEnterEvent(self, event):
|
||||||
md = event.mimeData()
|
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()
|
event.acceptProposedAction()
|
||||||
|
|
||||||
def dropEvent(self, event):
|
def dropEvent(self, event):
|
||||||
|
@ -20,7 +20,7 @@ from calibre.ebooks import BOOK_EXTENSIONS
|
|||||||
from calibre.utils.config import prefs, XMLConfig
|
from calibre.utils.config import prefs, XMLConfig
|
||||||
from calibre.gui2.progress_indicator import ProgressIndicator as _ProgressIndicator
|
from calibre.gui2.progress_indicator import ProgressIndicator as _ProgressIndicator
|
||||||
from calibre.gui2.dnd import (dnd_has_image, dnd_get_image, dnd_get_files,
|
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
|
from calibre.utils.localization import localize_user_manual_link
|
||||||
|
|
||||||
history = XMLConfig('history')
|
history = XMLConfig('history')
|
||||||
@ -215,14 +215,15 @@ class ImageDropMixin(object): # {{{
|
|||||||
Adds support for dropping images onto widgets and a context menu for
|
Adds support for dropping images onto widgets and a context menu for
|
||||||
copy/pasting images.
|
copy/pasting images.
|
||||||
'''
|
'''
|
||||||
DROPABBLE_EXTENSIONS = IMAGE_EXTENSIONS
|
DROPABBLE_EXTENSIONS = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.setAcceptDrops(True)
|
self.setAcceptDrops(True)
|
||||||
|
|
||||||
def dragEnterEvent(self, event):
|
def dragEnterEvent(self, event):
|
||||||
md = event.mimeData()
|
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):
|
dnd_has_image(md):
|
||||||
event.acceptProposedAction()
|
event.acceptProposedAction()
|
||||||
|
|
||||||
|
@ -225,8 +225,10 @@ def choose_files(window, name, title,
|
|||||||
return ans
|
return ans
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def choose_images(window, name, title, select_only_single_file=True,
|
def choose_images(window, name, title, select_only_single_file=True, formats=None):
|
||||||
formats=('png', 'gif', 'jpg', 'jpeg', 'svg')):
|
if formats is None:
|
||||||
|
from calibre.gui2.dnd import image_extensions
|
||||||
|
formats = image_extensions()
|
||||||
file_types = [(_('Images'), list(formats))]
|
file_types = [(_('Images'), list(formats))]
|
||||||
return choose_files(window, name, title, select_only_single_file=select_only_single_file, filters=file_types)
|
return choose_files(window, name, title, select_only_single_file=select_only_single_file, filters=file_types)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user