diff --git a/src/calibre/ebooks/oeb/polish/cover.py b/src/calibre/ebooks/oeb/polish/cover.py index 5cee827d72..3104cff38d 100644 --- a/src/calibre/ebooks/oeb/polish/cover.py +++ b/src/calibre/ebooks/oeb/polish/cover.py @@ -33,6 +33,21 @@ def set_azw3_cover(container, cover_path, report): container.dirty(container.opf_name) report('Cover updated' if found else 'Cover inserted') +def get_azw3_raster_cover_name(container): + items = container.opf_xpath('//opf:guide/opf:reference[@href and contains(@type, "cover")]') + if items: + return container.href_to_name(items[0].get('href')) + +def get_raster_cover_name(container): + if container.book_type == 'azw3': + return get_azw3_raster_cover_name(container) + return find_cover_image(container, strict=True) + +def get_cover_page_name(container): + if container.book_type == 'azw3': + return + return find_cover_page(container) + def set_cover(container, cover_path, report): if container.book_type == 'azw3': set_azw3_cover(container, cover_path, report) @@ -52,7 +67,7 @@ COVER_TYPES = { 'other.ms-coverimage', 'other.ms-thumbimage-standard', 'other.ms-thumbimage', 'thumbimagestandard', 'cover'} -def find_cover_image(container): +def find_cover_image(container, strict=False): 'Find a raster image marked as a cover in the OPF' manifest_id_map = container.manifest_id_map mm = container.mime_map @@ -69,6 +84,9 @@ def find_cover_image(container): if ref_type.lower() == 'cover' and is_raster_image(mm.get(name, None)): return name + if strict: + return + # Find the largest image from all possible guide cover items largest_cover = (None, 0) for ref_type, name in guide_type_map.iteritems(): diff --git a/src/calibre/gui2/tweak_book/file_list.py b/src/calibre/gui2/tweak_book/file_list.py index 6c5765e7b3..dc533307ff 100644 --- a/src/calibre/gui2/tweak_book/file_list.py +++ b/src/calibre/gui2/tweak_book/file_list.py @@ -8,10 +8,11 @@ __copyright__ = '2013, Kovid Goyal ' from PyQt4.Qt import ( QWidget, QTreeWidget, QGridLayout, QSize, Qt, QTreeWidgetItem, QIcon, - QStyledItemDelegate, QStyle) + QStyledItemDelegate, QStyle, QPixmap, QPainter) from calibre import guess_type, human_readable from calibre.ebooks.oeb.base import OEB_STYLES +from calibre.ebooks.oeb.polish.cover import get_cover_page_name, get_raster_cover_name from calibre.gui2.tweak_book import current_container TOP_ICON_SIZE = 24 @@ -20,12 +21,6 @@ NBSP = '\xa0' class ItemDelegate(QStyledItemDelegate): # {{{ - def initStyleOption(self, option, index): - QStyledItemDelegate.initStyleOption(self, option, index) - top_level = not index.parent().isValid() - if top_level: - option.decorationSize = QSize(TOP_ICON_SIZE, TOP_ICON_SIZE) - def sizeHint(self, option, index): ans = QStyledItemDelegate.sizeHint(self, option, index) top_level = not index.parent().isValid() @@ -60,6 +55,7 @@ class FileList(QTreeWidget): self.delegate = ItemDelegate(self) self.setTextElideMode(Qt.ElideMiddle) self.setItemDelegate(self.delegate) + self.setIconSize(QSize(16, 16)) self.header().close() self.setDragEnabled(True) self.setSelectionMode(self.ExtendedSelection) @@ -76,22 +72,33 @@ class FileList(QTreeWidget): self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.show_context_menu) self.root = self.invisibleRootItem() + self.emblem_cache = {} + self.rendered_emblem_cache = {} + self.top_level_pixmap_cache = { + name : QPixmap(I(icon)).scaled(TOP_ICON_SIZE, TOP_ICON_SIZE, transformMode=Qt.SmoothTransformation) + for name, icon in { + 'text':'keyboard-prefs.png', + 'styles':'lookfeel.png', + 'fonts':'font.png', + 'misc':'mimetypes/dir.png', + 'images':'view-image.png', + }.iteritems()} def build(self, container): self.clear() self.root = self.invisibleRootItem() self.root.setFlags(Qt.ItemIsDragEnabled) self.categories = {} - for category, text, icon in ( - ('text', _('Text'), 'keyboard-prefs.png'), - ('styles', _('Styles'), 'lookfeel.png'), - ('images', _('Images'), 'view-image.png'), - ('fonts', _('Fonts'), 'font.png'), - ('misc', _('Miscellaneous'), 'mimetypes/dir.png'), + for category, text in ( + ('text', _('Text')), + ('styles', _('Styles')), + ('images', _('Images')), + ('fonts', _('Fonts')), + ('misc', _('Miscellaneous')), ): self.categories[category] = i = QTreeWidgetItem(self.root, 0) i.setText(0, text) - i.setIcon(0, QIcon(I(icon))) + i.setData(0, Qt.DecorationRole, self.top_level_pixmap_cache[category]) f = i.font(0) f.setBold(True) i.setFont(0, f) @@ -111,16 +118,55 @@ class FileList(QTreeWidget): seen[text] = item return text + cover_page_name = get_cover_page_name(container) + cover_image_name = get_raster_cover_name(container) + manifested_names = set() + for names in container.manifest_type_map.itervalues(): + manifested_names |= set(names) + + def add_emblems(item, name, linear=True): + emblems = [] + if name in {cover_page_name, cover_image_name}: + emblems.append('default_cover.png') + if name not in manifested_names and name not in {container.opf_name, 'META_INF/container.xml', 'META_INF/encryption.xml'}: + emblems.append('dialog_question.png') + if not linear: + emblems.append('arrow-down.png') + emblems = tuple(emblems) + if not emblems: + return + icon = self.rendered_emblem_cache.get(emblems, None) + if icon is None: + pixmaps = [] + for emblem in emblems: + pm = self.emblem_cache.get(emblem, None) + if pm is None: + pm = self.emblem_cache[emblem] = QPixmap( + I(emblem)).scaled(self.iconSize(), transformMode=Qt.SmoothTransformation) + pixmaps.append(pm) + num = len(pixmaps) + w, h = pixmaps[0].width(), pixmaps[0].height() + if num == 1: + icon = self.rendered_emblem_cache[emblems] = QIcon(pixmaps[0]) + else: + canvas = QPixmap((num * w) + ((num-1)*2), h) + canvas.fill(Qt.transparent) + painter = QPainter(canvas) + for i, pm in enumerate(pixmaps): + painter.drawPixmap(i * (w + 2), 0, pm) + painter.end() + icon = self.rendered_emblem_cache[emblems] = canvas + item.setData(0, Qt.DecorationRole, icon) + for name, linear in container.spine_names: processed.add(name) i = QTreeWidgetItem(self.categories['text'], 1) prefix = '' if linear else '[nl] ' - if not linear: - i.setIcon(self.non_linear_icon) i.setText(0, prefix + get_display_name(name, i)) i.setStatusTip(0, _('Full path: ') + name) i.setFlags(Qt.ItemIsEnabled | Qt.ItemIsDragEnabled | Qt.ItemIsSelectable) i.setData(0, NAME_ROLE, name) + add_emblems(i, name, linear=linear) font_types = {guess_type('a.'+x)[0] for x in ('ttf', 'otf', 'woff')} @@ -148,6 +194,7 @@ class FileList(QTreeWidget): i.setStatusTip(0, _('Full path: ') + name) i.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) i.setData(0, NAME_ROLE, name) + add_emblems(i, name) for c in self.categories.itervalues(): self.expandItem(c)