mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Implement multiple emblems for the file browser
This commit is contained in:
parent
962663c1de
commit
a9a24f316a
@ -33,6 +33,21 @@ def set_azw3_cover(container, cover_path, report):
|
|||||||
container.dirty(container.opf_name)
|
container.dirty(container.opf_name)
|
||||||
report('Cover updated' if found else 'Cover inserted')
|
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):
|
def set_cover(container, cover_path, report):
|
||||||
if container.book_type == 'azw3':
|
if container.book_type == 'azw3':
|
||||||
set_azw3_cover(container, cover_path, report)
|
set_azw3_cover(container, cover_path, report)
|
||||||
@ -52,7 +67,7 @@ COVER_TYPES = {
|
|||||||
'other.ms-coverimage', 'other.ms-thumbimage-standard',
|
'other.ms-coverimage', 'other.ms-thumbimage-standard',
|
||||||
'other.ms-thumbimage', 'thumbimagestandard', 'cover'}
|
'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'
|
'Find a raster image marked as a cover in the OPF'
|
||||||
manifest_id_map = container.manifest_id_map
|
manifest_id_map = container.manifest_id_map
|
||||||
mm = container.mime_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)):
|
if ref_type.lower() == 'cover' and is_raster_image(mm.get(name, None)):
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
if strict:
|
||||||
|
return
|
||||||
|
|
||||||
# Find the largest image from all possible guide cover items
|
# Find the largest image from all possible guide cover items
|
||||||
largest_cover = (None, 0)
|
largest_cover = (None, 0)
|
||||||
for ref_type, name in guide_type_map.iteritems():
|
for ref_type, name in guide_type_map.iteritems():
|
||||||
|
@ -8,10 +8,11 @@ __copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
|
|
||||||
from PyQt4.Qt import (
|
from PyQt4.Qt import (
|
||||||
QWidget, QTreeWidget, QGridLayout, QSize, Qt, QTreeWidgetItem, QIcon,
|
QWidget, QTreeWidget, QGridLayout, QSize, Qt, QTreeWidgetItem, QIcon,
|
||||||
QStyledItemDelegate, QStyle)
|
QStyledItemDelegate, QStyle, QPixmap, QPainter)
|
||||||
|
|
||||||
from calibre import guess_type, human_readable
|
from calibre import guess_type, human_readable
|
||||||
from calibre.ebooks.oeb.base import OEB_STYLES
|
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
|
from calibre.gui2.tweak_book import current_container
|
||||||
|
|
||||||
TOP_ICON_SIZE = 24
|
TOP_ICON_SIZE = 24
|
||||||
@ -20,12 +21,6 @@ NBSP = '\xa0'
|
|||||||
|
|
||||||
class ItemDelegate(QStyledItemDelegate): # {{{
|
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):
|
def sizeHint(self, option, index):
|
||||||
ans = QStyledItemDelegate.sizeHint(self, option, index)
|
ans = QStyledItemDelegate.sizeHint(self, option, index)
|
||||||
top_level = not index.parent().isValid()
|
top_level = not index.parent().isValid()
|
||||||
@ -60,6 +55,7 @@ class FileList(QTreeWidget):
|
|||||||
self.delegate = ItemDelegate(self)
|
self.delegate = ItemDelegate(self)
|
||||||
self.setTextElideMode(Qt.ElideMiddle)
|
self.setTextElideMode(Qt.ElideMiddle)
|
||||||
self.setItemDelegate(self.delegate)
|
self.setItemDelegate(self.delegate)
|
||||||
|
self.setIconSize(QSize(16, 16))
|
||||||
self.header().close()
|
self.header().close()
|
||||||
self.setDragEnabled(True)
|
self.setDragEnabled(True)
|
||||||
self.setSelectionMode(self.ExtendedSelection)
|
self.setSelectionMode(self.ExtendedSelection)
|
||||||
@ -76,22 +72,33 @@ class FileList(QTreeWidget):
|
|||||||
self.setContextMenuPolicy(Qt.CustomContextMenu)
|
self.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||||
self.customContextMenuRequested.connect(self.show_context_menu)
|
self.customContextMenuRequested.connect(self.show_context_menu)
|
||||||
self.root = self.invisibleRootItem()
|
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):
|
def build(self, container):
|
||||||
self.clear()
|
self.clear()
|
||||||
self.root = self.invisibleRootItem()
|
self.root = self.invisibleRootItem()
|
||||||
self.root.setFlags(Qt.ItemIsDragEnabled)
|
self.root.setFlags(Qt.ItemIsDragEnabled)
|
||||||
self.categories = {}
|
self.categories = {}
|
||||||
for category, text, icon in (
|
for category, text in (
|
||||||
('text', _('Text'), 'keyboard-prefs.png'),
|
('text', _('Text')),
|
||||||
('styles', _('Styles'), 'lookfeel.png'),
|
('styles', _('Styles')),
|
||||||
('images', _('Images'), 'view-image.png'),
|
('images', _('Images')),
|
||||||
('fonts', _('Fonts'), 'font.png'),
|
('fonts', _('Fonts')),
|
||||||
('misc', _('Miscellaneous'), 'mimetypes/dir.png'),
|
('misc', _('Miscellaneous')),
|
||||||
):
|
):
|
||||||
self.categories[category] = i = QTreeWidgetItem(self.root, 0)
|
self.categories[category] = i = QTreeWidgetItem(self.root, 0)
|
||||||
i.setText(0, text)
|
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 = i.font(0)
|
||||||
f.setBold(True)
|
f.setBold(True)
|
||||||
i.setFont(0, f)
|
i.setFont(0, f)
|
||||||
@ -111,16 +118,55 @@ class FileList(QTreeWidget):
|
|||||||
seen[text] = item
|
seen[text] = item
|
||||||
return text
|
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:
|
for name, linear in container.spine_names:
|
||||||
processed.add(name)
|
processed.add(name)
|
||||||
i = QTreeWidgetItem(self.categories['text'], 1)
|
i = QTreeWidgetItem(self.categories['text'], 1)
|
||||||
prefix = '' if linear else '[nl] '
|
prefix = '' if linear else '[nl] '
|
||||||
if not linear:
|
|
||||||
i.setIcon(self.non_linear_icon)
|
|
||||||
i.setText(0, prefix + get_display_name(name, i))
|
i.setText(0, prefix + get_display_name(name, i))
|
||||||
i.setStatusTip(0, _('Full path: ') + name)
|
i.setStatusTip(0, _('Full path: ') + name)
|
||||||
i.setFlags(Qt.ItemIsEnabled | Qt.ItemIsDragEnabled | Qt.ItemIsSelectable)
|
i.setFlags(Qt.ItemIsEnabled | Qt.ItemIsDragEnabled | Qt.ItemIsSelectable)
|
||||||
i.setData(0, NAME_ROLE, name)
|
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')}
|
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.setStatusTip(0, _('Full path: ') + name)
|
||||||
i.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
|
i.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
|
||||||
i.setData(0, NAME_ROLE, name)
|
i.setData(0, NAME_ROLE, name)
|
||||||
|
add_emblems(i, name)
|
||||||
|
|
||||||
for c in self.categories.itervalues():
|
for c in self.categories.itervalues():
|
||||||
self.expandItem(c)
|
self.expandItem(c)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user