Save single format to disk: Allow choosing the book cover as the format to save. Fixes #2092395 [[Enhancement] Add cover image to 'Save single format' dialog](https://bugs.launchpad.net/calibre/+bug/2092395)

This commit is contained in:
Kovid Goyal 2025-01-07 11:12:05 +05:30
parent 4b00f39ef0
commit b36a3bb497
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 28 additions and 11 deletions

View File

@ -121,15 +121,17 @@ class DeleteAction(InterfaceActionWithLibraryDrop):
for action in list(self.delete_menu.actions())[1:]: for action in list(self.delete_menu.actions())[1:]:
action.setEnabled(enabled) action.setEnabled(enabled)
def _get_selected_formats(self, msg, ids, exclude=False, single=False): def _get_selected_formats(self, msg, ids, exclude=False, single=False, add_cover=False):
from calibre.gui2.dialogs.select_formats import SelectFormats from calibre.gui2.dialogs.select_formats import SelectFormats
c = Counter() c = Counter()
db = self.gui.library_view.model().db db = self.gui.library_view.model().db
for x in ids: for book_id in ids:
fmts_ = db.formats(x, index_is_id=True, verify_formats=False) fmts_ = db.formats(book_id, index_is_id=True, verify_formats=False)
if fmts_: if fmts_:
for x in frozenset(x.lower() for x in fmts_.split(',')): for x in frozenset(x.lower() for x in fmts_.split(',')):
c[x] += 1 c[x] += 1
if add_cover and db.new_api.field_for('cover', book_id, default_value=False):
c['..cover..'] += 1
d = SelectFormats(c, msg, parent=self.gui, exclude=exclude, d = SelectFormats(c, msg, parent=self.gui, exclude=exclude,
single=single) single=single)
if d.exec() != QDialog.DialogCode.Accepted: if d.exec() != QDialog.DialogCode.Accepted:

View File

@ -63,10 +63,11 @@ class SaveToDiskAction(InterfaceAction):
return return
fmts = rb._get_selected_formats( fmts = rb._get_selected_formats(
_('Choose format to save to disk'), ids, _('Choose format to save to disk'), ids,
single=True) single=True, add_cover=True)
if not fmts: if not fmts:
return return
self.save_to_disk(False, False, list(fmts)[0]) fmt = list(fmts)[0]
self.save_to_disk(False, False, fmt)
def save_to_single_dir(self, checked): def save_to_single_dir(self, checked):
self.save_to_disk(checked, True) self.save_to_disk(checked, True)
@ -107,7 +108,10 @@ class SaveToDiskAction(InterfaceAction):
opts.to_lowercase = False opts.to_lowercase = False
opts.save_cover = False opts.save_cover = False
opts.write_opf = False opts.write_opf = False
opts.save_extra_files = False
opts.template = opts.send_template opts.template = opts.send_template
elif single_format == '..cover..':
opts.save_cover = True
opts.single_dir = single_dir opts.single_dir = single_dir
if write_opf is not None: if write_opf is not None:
opts.write_opf = write_opf opts.write_opf = write_opf

View File

@ -27,12 +27,20 @@ class Formats(QAbstractListModel):
if role == Qt.ItemDataRole.DisplayRole: if role == Qt.ItemDataRole.DisplayRole:
fmt = self.fmts[row] fmt = self.fmts[row]
count = self.counts[fmt] count = self.counts[fmt]
return ('%s [%d]'%(fmt.upper(), count)) if fmt == '..cover..':
fmt = _('Book cover')
else:
fmt = fmt.upper()
return f'{fmt} [{count}]'
if role == Qt.ItemDataRole.DecorationRole: if role == Qt.ItemDataRole.DecorationRole:
return (self.fi.icon_from_ext(self.fmts[row].lower())) return (self.fi.icon_from_ext(self.fmts[row].lower()))
if role == Qt.ItemDataRole.ToolTipRole: if role == Qt.ItemDataRole.ToolTipRole:
fmt = self.fmts[row] fmt = self.fmts[row]
count = self.counts[fmt] count = self.counts[fmt]
if fmt == '..cover..':
if count == 1:
return _('There is only one book with a cover')
return _('There are {} books with a cover').format(count)
return _('There is one book with the {} format').format(fmt.upper()) if count == 1 else _( return _('There is one book with the {} format').format(fmt.upper()) if count == 1 else _(
'There are {count} books with the {fmt} format').format( 'There are {count} books with the {fmt} format').format(
count=count, fmt=fmt.upper()) count=count, fmt=fmt.upper())

View File

@ -213,11 +213,14 @@ class Saver(QObject):
base_path = os.path.join(self.root, *components) base_path = os.path.join(self.root, *components)
base_dir = os.path.dirname(base_path) base_dir = os.path.dirname(base_path)
if self.opts.formats and self.opts.formats != 'all': if self.opts.formats and self.opts.formats != 'all':
asked_formats = {x.lower().strip() for x in self.opts.formats.split(',')} if self.opts.formats == '..cover..':
fmts = asked_formats.intersection(fmts) fmts = set()
if not fmts: else:
self.errors[book_id].append(('critical', _('Requested formats not available'))) asked_formats = {x.lower().strip() for x in self.opts.formats.split(',')}
return fmts = asked_formats.intersection(fmts)
if not fmts:
self.errors[book_id].append(('critical', _('Requested formats not available')))
return
extra_files = {} extra_files = {}
if self.opts.save_extra_files: if self.opts.save_extra_files: