mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
Implement marking of images as covers
This commit is contained in:
parent
c306458357
commit
c1ae0a275f
@ -697,6 +697,10 @@ class Container(object): # {{{
|
||||
mdata.remove(child)
|
||||
if len(mdata) > 0:
|
||||
mdata[-1].tail = '\n '
|
||||
# Ensure name comes before content, needed for Nooks
|
||||
for meta in self.opf_xpath('//opf:meta[@name="cover"]'):
|
||||
if 'content' in meta.attrib:
|
||||
meta.set('content', meta.attrib.pop('content'))
|
||||
|
||||
def serialize_item(self, name):
|
||||
data = self.parsed(name)
|
||||
|
@ -38,6 +38,12 @@ def get_azw3_raster_cover_name(container):
|
||||
if items:
|
||||
return container.href_to_name(items[0].get('href'))
|
||||
|
||||
def mark_as_cover_azw3(container, name):
|
||||
href = container.name_to_href(name, container.opf_name)
|
||||
for item in container.opf_xpath('//opf:guide/opf:reference[@href and contains(@type, "cover")]'):
|
||||
item.set('href', href)
|
||||
container.dirty(container.opf_name)
|
||||
|
||||
def get_raster_cover_name(container):
|
||||
if container.book_type == 'azw3':
|
||||
return get_azw3_raster_cover_name(container)
|
||||
@ -54,6 +60,17 @@ def set_cover(container, cover_path, report):
|
||||
else:
|
||||
set_epub_cover(container, cover_path, report)
|
||||
|
||||
def mark_as_cover(container, name):
|
||||
if name not in container.mime_map:
|
||||
raise ValueError('Cannot mark %s as cover as it does not exist' % name)
|
||||
mt = container.mime_map[name]
|
||||
if not is_raster_image(mt):
|
||||
raise ValueError('Cannot mark %s as the cover image as it is not a raster image' % name)
|
||||
if container.book_type == 'azw3':
|
||||
mark_as_cover_azw3(container, name)
|
||||
else:
|
||||
mark_as_cover_epub(container, name)
|
||||
|
||||
###############################################################################
|
||||
# The delightful EPUB cover processing
|
||||
|
||||
@ -100,6 +117,37 @@ def find_cover_image(container, strict=False):
|
||||
if largest_cover[0]:
|
||||
return largest_cover[0]
|
||||
|
||||
def mark_as_cover_epub(container, name):
|
||||
mmap = {v:k for k, v in container.manifest_id_map.iteritems()}
|
||||
if name not in mmap:
|
||||
raise ValueError('Cannot mark %s as cover as it is not in manifest' % name)
|
||||
mid = mmap[name]
|
||||
|
||||
# Remove all entries from the opf that identify a raster image as cover
|
||||
for meta in container.opf_xpath('//opf:meta[@name="cover" and @content]'):
|
||||
container.remove_from_xml(meta)
|
||||
for ref in container.opf_xpath('//opf:guide/opf:reference[@href and @type]'):
|
||||
if ref.get('type').lower() not in COVER_TYPES:
|
||||
continue
|
||||
name = container.href_to_name(ref.get('href'), container.opf_name)
|
||||
mt = container.mime_map.get(name, None)
|
||||
if is_raster_image(mt):
|
||||
container.remove_from_xml(ref)
|
||||
|
||||
# Add reference to image in <metadata>
|
||||
for metadata in container.opf_xpath('//opf:metadata'):
|
||||
m = metadata.makeelement(OPF('meta'), name='cover', content=mid)
|
||||
container.insert_into_xml(metadata, m)
|
||||
|
||||
# If no entry for titlepage exists in guide, insert one that points to this
|
||||
# image
|
||||
if not container.opf_xpath('//opf:guide/opf:reference[@type="cover"]'):
|
||||
for guide in container.opf_xpath('//opf:guide'):
|
||||
container.insert_into_xml(guide, guide.makeelement(
|
||||
OPF('reference', type='cover', href=container.name_to_href(name, container.opf_name))))
|
||||
|
||||
container.dirty(container.opf_name)
|
||||
|
||||
def find_cover_page(container):
|
||||
'Find a document marked as a cover in the OPF'
|
||||
mm = container.mime_map
|
||||
|
@ -19,6 +19,7 @@ from calibre.ptempfile import PersistentTemporaryDirectory
|
||||
from calibre.ebooks.oeb.base import urlnormalize
|
||||
from calibre.ebooks.oeb.polish.main import SUPPORTED, tweak_polish
|
||||
from calibre.ebooks.oeb.polish.container import get_container as _gc, clone_container, guess_type
|
||||
from calibre.ebooks.oeb.polish.cover import mark_as_cover
|
||||
from calibre.ebooks.oeb.polish.pretty import fix_all_html, pretty_all
|
||||
from calibre.ebooks.oeb.polish.replace import rename_files
|
||||
from calibre.ebooks.oeb.polish.split import split, merge, AbortError
|
||||
@ -57,6 +58,7 @@ class Boss(QObject):
|
||||
fl.rename_requested.connect(self.rename_requested)
|
||||
fl.edit_file.connect(self.edit_file_requested)
|
||||
fl.merge_requested.connect(self.merge_requested)
|
||||
fl.mark_requested.connect(self.mark_requested)
|
||||
self.gui.central.current_editor_changed.connect(self.apply_current_editor_state)
|
||||
self.gui.central.close_requested.connect(self.editor_close_requested)
|
||||
self.gui.central.search_panel.search_triggered.connect(self.search)
|
||||
@ -70,6 +72,18 @@ class Boss(QObject):
|
||||
for ed in editors.itervalues():
|
||||
ed.apply_settings()
|
||||
|
||||
def mark_requested(self, name, action):
|
||||
if not self.check_opf_dirtied():
|
||||
return
|
||||
c = current_container()
|
||||
if action == 'cover':
|
||||
mark_as_cover(current_container(), name)
|
||||
|
||||
if c.opf_name in editors:
|
||||
editors[c.opf_name].replace_data(c.raw_data(c.opf_name))
|
||||
self.gui.file_list.build(c)
|
||||
self.set_modified()
|
||||
|
||||
def mkdtemp(self, prefix=''):
|
||||
self.container_count += 1
|
||||
return tempfile.mkdtemp(prefix='%s%05d-' % (prefix, self.container_count), dir=self.tdir)
|
||||
|
@ -18,7 +18,8 @@ from PyQt4.Qt import (
|
||||
from calibre import human_readable, sanitize_file_name_unicode
|
||||
from calibre.ebooks.oeb.base import OEB_STYLES, OEB_DOCS
|
||||
from calibre.ebooks.oeb.polish.container import guess_type, OEB_FONTS
|
||||
from calibre.ebooks.oeb.polish.cover import get_cover_page_name, get_raster_cover_name
|
||||
from calibre.ebooks.oeb.polish.cover import (
|
||||
get_cover_page_name, get_raster_cover_name, is_raster_image)
|
||||
from calibre.gui2 import error_dialog, choose_files
|
||||
from calibre.gui2.tweak_book import current_container, elided_text
|
||||
from calibre.gui2.tweak_book.editor import syntax_from_mime
|
||||
@ -83,6 +84,7 @@ class FileList(QTreeWidget):
|
||||
rename_requested = pyqtSignal(object, object)
|
||||
edit_file = pyqtSignal(object, object, object)
|
||||
merge_requested = pyqtSignal(object, object, object)
|
||||
mark_requested = pyqtSignal(object, object)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QTreeWidget.__init__(self, parent)
|
||||
@ -306,7 +308,10 @@ class FileList(QTreeWidget):
|
||||
ci = self.currentItem()
|
||||
if ci is not None:
|
||||
cn = unicode(ci.data(0, NAME_ROLE).toString())
|
||||
mt = unicode(ci.data(0, MIME_ROLE).toString())
|
||||
m.addAction(QIcon(I('modified.png')), _('&Rename %s') % (elided_text(self.font(), cn)), self.edit_current_item)
|
||||
if is_raster_image(mt):
|
||||
m.addAction(QIcon(I('default_cover.png')), _('Mark %s as cover image') % elided_text(self.font(), cn), partial(self.mark_as_cover, cn))
|
||||
|
||||
selected_map = defaultdict(list)
|
||||
for item in sel:
|
||||
@ -340,6 +345,9 @@ class FileList(QTreeWidget):
|
||||
if self.currentItem() is not None:
|
||||
self.editItem(self.currentItem())
|
||||
|
||||
def mark_as_cover(self, name):
|
||||
self.mark_requested.emit(name, 'cover')
|
||||
|
||||
def keyPressEvent(self, ev):
|
||||
if ev.key() in (Qt.Key_Delete, Qt.Key_Backspace):
|
||||
ev.accept()
|
||||
@ -544,6 +552,7 @@ class FileListWidget(QWidget):
|
||||
rename_requested = pyqtSignal(object, object)
|
||||
edit_file = pyqtSignal(object, object, object)
|
||||
merge_requested = pyqtSignal(object, object, object)
|
||||
mark_requested = pyqtSignal(object, object)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QWidget.__init__(self, parent)
|
||||
@ -551,7 +560,7 @@ class FileListWidget(QWidget):
|
||||
self.file_list = FileList(self)
|
||||
self.layout().addWidget(self.file_list)
|
||||
self.layout().setContentsMargins(0, 0, 0, 0)
|
||||
for x in ('delete_requested', 'reorder_spine', 'rename_requested', 'edit_file', 'merge_requested'):
|
||||
for x in ('delete_requested', 'reorder_spine', 'rename_requested', 'edit_file', 'merge_requested', 'mark_requested'):
|
||||
getattr(self.file_list, x).connect(getattr(self, x))
|
||||
for x in ('delete_done', 'select_name'):
|
||||
setattr(self, x, getattr(self.file_list, x))
|
||||
|
Loading…
x
Reference in New Issue
Block a user