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 import os, shutil, copy
from functools import partial from functools import partial
from io import BytesIO
from PyQt5.Qt import QMenu, QModelIndex, QTimer, QIcon, QApplication from PyQt5.Qt import QMenu, QModelIndex, QTimer, QIcon, QApplication
@ -785,3 +786,55 @@ class EditMetadataAction(InterfaceAction):
affected_books = db.set_field(field, {book_id:''}) affected_books = db.set_field(field, {book_id:''})
if affected_books: if affected_books:
self.refresh_books_after_metadata_edit(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 ofmt = fmt.upper() if fmt.startswith('ORIGINAL_') else 'ORIGINAL_' + fmt
nfmt = ofmt[len('ORIGINAL_'):] nfmt = ofmt[len('ORIGINAL_'):]
fmts = {x.upper() for x in db.formats(book_id)} fmts = {x.upper() for x in db.formats(book_id)}
for a, t in [('remove', _('Delete the %s format')), for a, t in [
('save', _('Save the %s format to disk')), ('remove', _('Delete the %s format')),
('restore', _('Restore the %s format')), ('save', _('Save the %s format to disk')),
('compare', ''), ('restore', _('Restore the %s format')),
('compare', ''),
('set_cover', _('Set the book cover from the %s file')),
]: ]:
if a == 'restore' and not fmt.startswith('ORIGINAL_'): if a == 'restore' and not fmt.startswith('ORIGINAL_'):
continue continue
@ -401,6 +403,7 @@ class BookInfo(QWebView):
save_format = pyqtSignal(int, object) save_format = pyqtSignal(int, object)
restore_format = pyqtSignal(int, object) restore_format = pyqtSignal(int, object)
compare_format = pyqtSignal(int, object) compare_format = pyqtSignal(int, object)
set_cover_format = pyqtSignal(int, object)
copy_link = pyqtSignal(object) copy_link = pyqtSignal(object)
manage_author = pyqtSignal(object) manage_author = pyqtSignal(object)
open_fmt_with = pyqtSignal(int, object, object) open_fmt_with = pyqtSignal(int, object, object)
@ -422,7 +425,9 @@ class BookInfo(QWebView):
for x, icon in [ for x, icon in [
('remove_format', 'trash.png'), ('save_format', 'save.png'), ('remove_format', 'trash.png'), ('save_format', 'save.png'),
('restore_format', 'edit-undo.png'), ('copy_link','edit-copy.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 = QAction(QIcon(I(icon)), '', self)
ac.current_fmt = None ac.current_fmt = None
ac.current_url = None ac.current_url = None
@ -459,6 +464,9 @@ class BookInfo(QWebView):
def compare_format_triggerred(self): def compare_format_triggerred(self):
self.context_action_triggered('compare_format') self.context_action_triggered('compare_format')
def set_cover_format_triggerred(self):
self.context_action_triggered('set_cover_format')
def copy_link_triggerred(self): def copy_link_triggerred(self):
self.context_action_triggered('copy_link') self.context_action_triggered('copy_link')
@ -603,6 +611,7 @@ class BookDetails(QWidget): # {{{
remove_metadata_item = pyqtSignal(int, object, object) remove_metadata_item = pyqtSignal(int, object, object)
save_specific_format = pyqtSignal(int, object) save_specific_format = pyqtSignal(int, object)
restore_specific_format = pyqtSignal(int, object) restore_specific_format = pyqtSignal(int, object)
set_cover_from_format = pyqtSignal(int, object)
compare_specific_format = pyqtSignal(int, object) compare_specific_format = pyqtSignal(int, object)
copy_link = pyqtSignal(object) copy_link = pyqtSignal(object)
remote_file_dropped = pyqtSignal(object, 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.open_fmt_with.connect(self.open_fmt_with)
self.book_info.save_format.connect(self.save_specific_format) self.book_info.save_format.connect(self.save_specific_format)
self.book_info.restore_format.connect(self.restore_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.compare_format.connect(self.compare_specific_format)
self.book_info.copy_link.connect(self.copy_link) self.book_info.copy_link.connect(self.copy_link)
self.book_info.manage_author.connect(self.manage_author) 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.iactions['Save To Disk'].save_library_format_by_ids)
self.book_details.restore_specific_format.connect( self.book_details.restore_specific_format.connect(
self.iactions['Remove Books'].restore_format) 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, self.book_details.copy_link.connect(self.bd_copy_link,
type=Qt.QueuedConnection) type=Qt.QueuedConnection)
self.book_details.view_device_book.connect( self.book_details.view_device_book.connect(