Allow setting the cover for a book from one of the book's formats by right clicking on the format in the Book details panel. See #1515411 (Extract cover via book details and edit metadata)

This commit is contained in:
Kovid Goyal 2015-11-12 18:11:36 +05:30
parent 438f5a8d88
commit 692500b852
3 changed files with 70 additions and 5 deletions

View File

@ -7,6 +7,7 @@ __docformat__ = 'restructuredtext en'
import os, shutil, copy
from functools import partial
from io import BytesIO
from PyQt5.Qt import QMenu, QModelIndex, QTimer, QIcon, QApplication
@ -785,3 +786,55 @@ class EditMetadataAction(InterfaceAction):
affected_books = db.set_field(field, {book_id:''})
if affected_books:
self.refresh_books_after_metadata_edit(affected_books)
def set_cover_from_format(self, book_id, fmt):
from calibre.utils.config import prefs
from calibre.ebooks.metadata.meta import get_metadata
fmt = fmt.lower()
cdata = None
db = self.gui.current_db.new_api
if fmt == 'pdf':
pdfpath = db.format_abspath(book_id, fmt)
if pdfpath is None:
return error_dialog(self.gui, _('Format file missing'), _(
'Cannot read cover as the %s file is missing from this book') % 'PDF', show=True)
from calibre.gui2.metadata.pdf_covers import PDFCovers
d = PDFCovers(pdfpath, parent=self.gui)
if d.exec_() == d.Accepted:
cpath = d.cover_path
if cpath:
with open(cpath, 'rb') as f:
cdata = f.read()
d.cleanup()
else:
stream = BytesIO()
try:
db.copy_format_to(book_id, fmt, stream)
except NoSuchFormat:
return error_dialog(self.gui, _('Format file missing'), _(
'Cannot read cover as the %s file is missing from this book') % fmt.upper(), show=True)
old = prefs['read_file_metadata']
if not old:
prefs['read_file_metadata'] = True
try:
stream.seek(0)
mi = get_metadata(stream, fmt)
except Exception:
import traceback
return error_dialog(self.gui, _('Could not read metadata'),
_('Could not read metadata from %s format')%fmt.upper(),
det_msg=traceback.format_exc(), show=True)
finally:
if old != prefs['read_file_metadata']:
prefs['read_file_metadata'] = old
if mi.cover and os.access(mi.cover, os.R_OK):
cdata = open(mi.cover).read()
elif mi.cover_data[1] is not None:
cdata = mi.cover_data[1]
if cdata is None:
return error_dialog(self.gui, _('Could not read cover'),
_('Could not read cover from %s format')%fmt.upper(), show=True)
db.set_cover({book_id:cdata})
current_idx = self.gui.library_view.currentIndex()
self.gui.library_view.model().current_changed(current_idx, current_idx)
self.gui.refresh_cover_browser()

View File

@ -130,10 +130,12 @@ def details_context_menu_event(view, ev, book_info): # {{{
ofmt = fmt.upper() if fmt.startswith('ORIGINAL_') else 'ORIGINAL_' + fmt
nfmt = ofmt[len('ORIGINAL_'):]
fmts = {x.upper() for x in db.formats(book_id)}
for a, t in [('remove', _('Delete the %s format')),
for a, t in [
('remove', _('Delete the %s format')),
('save', _('Save the %s format to disk')),
('restore', _('Restore the %s format')),
('compare', ''),
('set_cover', _('Set the book cover from the %s file')),
]:
if a == 'restore' and not fmt.startswith('ORIGINAL_'):
continue
@ -401,6 +403,7 @@ class BookInfo(QWebView):
save_format = pyqtSignal(int, object)
restore_format = pyqtSignal(int, object)
compare_format = pyqtSignal(int, object)
set_cover_format = pyqtSignal(int, object)
copy_link = pyqtSignal(object)
manage_author = pyqtSignal(object)
open_fmt_with = pyqtSignal(int, object, object)
@ -422,7 +425,9 @@ class BookInfo(QWebView):
for x, icon in [
('remove_format', 'trash.png'), ('save_format', 'save.png'),
('restore_format', 'edit-undo.png'), ('copy_link','edit-copy.png'),
('manage_author', 'user_profile.png'), ('compare_format', 'diff.png')]:
('manage_author', 'user_profile.png'), ('compare_format', 'diff.png'),
('set_cover_format', 'book.png'),
]:
ac = QAction(QIcon(I(icon)), '', self)
ac.current_fmt = None
ac.current_url = None
@ -459,6 +464,9 @@ class BookInfo(QWebView):
def compare_format_triggerred(self):
self.context_action_triggered('compare_format')
def set_cover_format_triggerred(self):
self.context_action_triggered('set_cover_format')
def copy_link_triggerred(self):
self.context_action_triggered('copy_link')
@ -603,6 +611,7 @@ class BookDetails(QWidget): # {{{
remove_metadata_item = pyqtSignal(int, object, object)
save_specific_format = pyqtSignal(int, object)
restore_specific_format = pyqtSignal(int, object)
set_cover_from_format = pyqtSignal(int, object)
compare_specific_format = pyqtSignal(int, object)
copy_link = pyqtSignal(object)
remote_file_dropped = pyqtSignal(object, object)
@ -680,6 +689,7 @@ class BookDetails(QWidget): # {{{
self.book_info.open_fmt_with.connect(self.open_fmt_with)
self.book_info.save_format.connect(self.save_specific_format)
self.book_info.restore_format.connect(self.restore_specific_format)
self.book_info.set_cover_format.connect(self.set_cover_from_format)
self.book_info.compare_format.connect(self.compare_specific_format)
self.book_info.copy_link.connect(self.copy_link)
self.book_info.manage_author.connect(self.manage_author)

View File

@ -528,6 +528,8 @@ class LayoutMixin(object): # {{{
self.iactions['Save To Disk'].save_library_format_by_ids)
self.book_details.restore_specific_format.connect(
self.iactions['Remove Books'].restore_format)
self.book_details.set_cover_from_format.connect(
self.iactions['Edit Metadata'].set_cover_from_format)
self.book_details.copy_link.connect(self.bd_copy_link,
type=Qt.QueuedConnection)
self.book_details.view_device_book.connect(