mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 18:24:30 -04:00
E-book viewer: When displaying metadata for the book, also display custom column metadata
This commit is contained in:
parent
5da59094c9
commit
225a7e0723
197
src/calibre/ebooks/metadata/book/render.py
Normal file
197
src/calibre/ebooks/metadata/book/render.py
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=utf-8
|
||||||
|
from __future__ import (unicode_literals, division, absolute_import,
|
||||||
|
print_function)
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
|
||||||
|
import os
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
|
from calibre import prepare_string_for_xml, force_unicode
|
||||||
|
from calibre.ebooks.metadata import fmt_sidx
|
||||||
|
from calibre.ebooks.metadata.sources.identify import urls_from_identifiers
|
||||||
|
from calibre.constants import filesystem_encoding
|
||||||
|
from calibre.library.comments import comments_to_html
|
||||||
|
from calibre.utils.icu import sort_key
|
||||||
|
from calibre.utils.formatter import EvalFormatter
|
||||||
|
from calibre.utils.date import is_date_undefined
|
||||||
|
from calibre.utils.localization import calibre_langcode_to_name
|
||||||
|
|
||||||
|
default_sort = ('title', 'title_sort', 'authors', 'author_sort', 'series', 'rating', 'pubdate', 'tags', 'publisher', 'identifiers')
|
||||||
|
|
||||||
|
def field_sort(mi, name):
|
||||||
|
try:
|
||||||
|
title = mi.metadata_for_field(name)['name']
|
||||||
|
except:
|
||||||
|
title = 'zzz'
|
||||||
|
return {x:(i, None) for i, x in enumerate(default_sort)}.get(name, (10000, sort_key(title)))
|
||||||
|
|
||||||
|
def displayable_field_keys(mi):
|
||||||
|
for k in mi.all_field_keys():
|
||||||
|
try:
|
||||||
|
m = mi.metadata_for_field(k)
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
if (
|
||||||
|
m is not None and m['kind'] == 'field' and m['datatype'] is not None and
|
||||||
|
k not in ('au_map', 'marked', 'ondevice', 'cover', 'series_sort') and
|
||||||
|
not k.endswith('_index')
|
||||||
|
):
|
||||||
|
yield k
|
||||||
|
|
||||||
|
def get_field_list(mi):
|
||||||
|
for field in sorted(displayable_field_keys(mi), key=partial(field_sort, mi)):
|
||||||
|
yield field, True
|
||||||
|
|
||||||
|
def mi_to_html(mi, field_list=None, default_author_link=None, use_roman_numbers=True, rating_font='Liberation Serif'):
|
||||||
|
if field_list is None:
|
||||||
|
field_list = get_field_list(mi)
|
||||||
|
ans = []
|
||||||
|
comment_fields = []
|
||||||
|
isdevice = not hasattr(mi, 'id')
|
||||||
|
row = u'<td class="title">%s</td><td class="value">%s</td>'
|
||||||
|
p = prepare_string_for_xml
|
||||||
|
a = partial(prepare_string_for_xml, attribute=True)
|
||||||
|
|
||||||
|
for field in (field for field, display in field_list if display):
|
||||||
|
try:
|
||||||
|
metadata = mi.metadata_for_field(field)
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
if not metadata:
|
||||||
|
continue
|
||||||
|
if field == 'sort':
|
||||||
|
field = 'title_sort'
|
||||||
|
if metadata['datatype'] == 'bool':
|
||||||
|
isnull = mi.get(field) is None
|
||||||
|
else:
|
||||||
|
isnull = mi.is_null(field)
|
||||||
|
if isnull:
|
||||||
|
continue
|
||||||
|
name = metadata['name']
|
||||||
|
if not name:
|
||||||
|
name = field
|
||||||
|
name += ':'
|
||||||
|
if metadata['datatype'] == 'comments' or field == 'comments':
|
||||||
|
val = getattr(mi, field)
|
||||||
|
if val:
|
||||||
|
val = force_unicode(val)
|
||||||
|
comment_fields.append(comments_to_html(val))
|
||||||
|
elif metadata['datatype'] == 'rating':
|
||||||
|
val = getattr(mi, field)
|
||||||
|
if val:
|
||||||
|
val = val/2.0
|
||||||
|
ans.append((field,
|
||||||
|
u'<td class="title">%s</td><td class="rating value" '
|
||||||
|
'style=\'font-family:"%s"\'>%s</td>'%(
|
||||||
|
name, rating_font, u'\u2605'*int(val))))
|
||||||
|
elif metadata['datatype'] == 'composite' and \
|
||||||
|
metadata['display'].get('contains_html', False):
|
||||||
|
val = getattr(mi, field)
|
||||||
|
if val:
|
||||||
|
val = force_unicode(val)
|
||||||
|
ans.append((field,
|
||||||
|
row % (name, comments_to_html(val))))
|
||||||
|
elif field == 'path':
|
||||||
|
if mi.path:
|
||||||
|
path = force_unicode(mi.path, filesystem_encoding)
|
||||||
|
scheme = u'devpath' if isdevice else u'path'
|
||||||
|
url = prepare_string_for_xml(path if isdevice else
|
||||||
|
unicode(mi.id), True)
|
||||||
|
pathstr = _('Click to open')
|
||||||
|
extra = ''
|
||||||
|
if isdevice:
|
||||||
|
durl = url
|
||||||
|
if durl.startswith('mtp:::'):
|
||||||
|
durl = ':::'.join((durl.split(':::'))[2:])
|
||||||
|
extra = '<br><span style="font-size:smaller">%s</span>'%(
|
||||||
|
prepare_string_for_xml(durl))
|
||||||
|
link = u'<a href="%s:%s" title="%s">%s</a>%s' % (scheme, url,
|
||||||
|
prepare_string_for_xml(path, True), pathstr, extra)
|
||||||
|
ans.append((field, row % (name, link)))
|
||||||
|
elif field == 'formats':
|
||||||
|
if isdevice:
|
||||||
|
continue
|
||||||
|
path = ''
|
||||||
|
if mi.path:
|
||||||
|
h, t = os.path.split(mi.path)
|
||||||
|
path = '/'.join((os.path.basename(h), t))
|
||||||
|
data = ({
|
||||||
|
'fmt':x, 'path':a(path or ''), 'fname':a(mi.format_files.get(x, '')),
|
||||||
|
'ext':x.lower(), 'id':mi.id
|
||||||
|
} for x in mi.formats)
|
||||||
|
fmts = [u'<a title="{path}/{fname}.{ext}" href="format:{id}:{fmt}">{fmt}</a>'.format(**x) for x in data]
|
||||||
|
ans.append((field, row % (name, u', '.join(fmts))))
|
||||||
|
elif field == 'identifiers':
|
||||||
|
urls = urls_from_identifiers(mi.identifiers)
|
||||||
|
links = [u'<a href="%s" title="%s:%s">%s</a>' % (a(url), a(id_typ), a(id_val), p(name))
|
||||||
|
for name, id_typ, id_val, url in urls]
|
||||||
|
links = u', '.join(links)
|
||||||
|
if links:
|
||||||
|
ans.append((field, row % (_('Ids')+':', links)))
|
||||||
|
elif field == 'authors' and not isdevice:
|
||||||
|
authors = []
|
||||||
|
formatter = EvalFormatter()
|
||||||
|
for aut in mi.authors:
|
||||||
|
link = ''
|
||||||
|
if mi.author_link_map[aut]:
|
||||||
|
link = mi.author_link_map[aut]
|
||||||
|
elif default_author_link:
|
||||||
|
vals = {'author': aut.replace(' ', '+')}
|
||||||
|
try:
|
||||||
|
vals['author_sort'] = mi.author_sort_map[aut].replace(' ', '+')
|
||||||
|
except:
|
||||||
|
vals['author_sort'] = aut.replace(' ', '+')
|
||||||
|
link = formatter.safe_format(
|
||||||
|
default_author_link, vals, '', vals)
|
||||||
|
aut = p(aut)
|
||||||
|
if link:
|
||||||
|
authors.append(u'<a calibre-data="authors" href="%s">%s</a>'%(a(link), aut))
|
||||||
|
else:
|
||||||
|
authors.append(aut)
|
||||||
|
ans.append((field, row % (name, u' & '.join(authors))))
|
||||||
|
elif field == 'languages':
|
||||||
|
if not mi.languages:
|
||||||
|
continue
|
||||||
|
names = filter(None, map(calibre_langcode_to_name, mi.languages))
|
||||||
|
ans.append((field, row % (name, u', '.join(names))))
|
||||||
|
else:
|
||||||
|
val = mi.format_field(field)[-1]
|
||||||
|
if val is None:
|
||||||
|
continue
|
||||||
|
val = p(val)
|
||||||
|
if metadata['datatype'] == 'series':
|
||||||
|
sidx = mi.get(field+'_index')
|
||||||
|
if sidx is None:
|
||||||
|
sidx = 1.0
|
||||||
|
val = _('Book %(sidx)s of <span class="series_name">%(series)s</span>')%dict(
|
||||||
|
sidx=fmt_sidx(sidx, use_roman=use_roman_numbers),
|
||||||
|
series=p(getattr(mi, field)))
|
||||||
|
elif metadata['datatype'] == 'datetime':
|
||||||
|
aval = getattr(mi, field)
|
||||||
|
if is_date_undefined(aval):
|
||||||
|
continue
|
||||||
|
|
||||||
|
ans.append((field, row % (name, val)))
|
||||||
|
|
||||||
|
dc = getattr(mi, 'device_collections', [])
|
||||||
|
if dc:
|
||||||
|
dc = u', '.join(sorted(dc, key=sort_key))
|
||||||
|
ans.append(('device_collections',
|
||||||
|
row % (_('Collections')+':', dc)))
|
||||||
|
|
||||||
|
def classname(field):
|
||||||
|
try:
|
||||||
|
dt = mi.metadata_for_field(field)['datatype']
|
||||||
|
except:
|
||||||
|
dt = 'text'
|
||||||
|
return 'datatype_%s'%dt
|
||||||
|
|
||||||
|
ans = [u'<tr id="%s" class="%s">%s</tr>'%(field.replace('#', '_'),
|
||||||
|
classname(field), html) for field, html in ans]
|
||||||
|
# print '\n'.join(ans)
|
||||||
|
return u'<table class="fields">%s</table>'%(u'\n'.join(ans)), comment_fields
|
||||||
|
|
||||||
|
|
@ -5,34 +5,24 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
|
||||||
from functools import partial
|
|
||||||
|
|
||||||
from PyQt4.Qt import (QPixmap, QSize, QWidget, Qt, pyqtSignal, QUrl, QIcon,
|
from PyQt4.Qt import (QPixmap, QSize, QWidget, Qt, pyqtSignal, QUrl, QIcon,
|
||||||
QPropertyAnimation, QEasingCurve, QApplication, QFontInfo, QAction,
|
QPropertyAnimation, QEasingCurve, QApplication, QFontInfo, QAction,
|
||||||
QSizePolicy, QPainter, QRect, pyqtProperty, QLayout, QPalette, QMenu,
|
QSizePolicy, QPainter, QRect, pyqtProperty, QLayout, QPalette, QMenu,
|
||||||
QPen, QColor)
|
QPen, QColor)
|
||||||
from PyQt4.QtWebKit import QWebView
|
from PyQt4.QtWebKit import QWebView
|
||||||
|
|
||||||
from calibre import fit_image, force_unicode, prepare_string_for_xml
|
from calibre import fit_image
|
||||||
from calibre.gui2.dnd import (dnd_has_image, dnd_get_image, dnd_get_files,
|
from calibre.gui2.dnd import (dnd_has_image, dnd_get_image, dnd_get_files,
|
||||||
IMAGE_EXTENSIONS, dnd_has_extension)
|
IMAGE_EXTENSIONS, dnd_has_extension)
|
||||||
from calibre.ebooks import BOOK_EXTENSIONS
|
from calibre.ebooks import BOOK_EXTENSIONS
|
||||||
from calibre.ebooks.metadata.book.base import (field_metadata, Metadata)
|
from calibre.ebooks.metadata.book.base import (field_metadata, Metadata)
|
||||||
from calibre.ebooks.metadata import fmt_sidx
|
from calibre.ebooks.metadata.book.render import mi_to_html
|
||||||
from calibre.ebooks.metadata.sources.identify import urls_from_identifiers
|
|
||||||
from calibre.constants import filesystem_encoding
|
|
||||||
from calibre.library.comments import comments_to_html
|
|
||||||
from calibre.gui2 import (config, open_url, pixmap_to_data, gprefs,
|
from calibre.gui2 import (config, open_url, pixmap_to_data, gprefs,
|
||||||
rating_font)
|
rating_font)
|
||||||
from calibre.utils.icu import sort_key
|
|
||||||
from calibre.utils.formatter import EvalFormatter
|
|
||||||
from calibre.utils.date import is_date_undefined
|
|
||||||
from calibre.utils.localization import calibre_langcode_to_name
|
|
||||||
from calibre.utils.config import tweaks
|
from calibre.utils.config import tweaks
|
||||||
|
|
||||||
def render_html(mi, css, vertical, widget, all_fields=False): # {{{
|
def render_html(mi, css, vertical, widget, all_fields=False, render_data_func=None): # {{{
|
||||||
table, comment_fields = render_data(mi, all_fields=all_fields,
|
table, comment_fields = (render_data_func or render_data)(mi, all_fields=all_fields,
|
||||||
use_roman_numbers=config['use_roman_numerals_for_series_number'])
|
use_roman_numbers=config['use_roman_numerals_for_series_number'])
|
||||||
|
|
||||||
def color_to_string(col):
|
def color_to_string(col):
|
||||||
@ -105,149 +95,10 @@ def get_field_list(fm, use_defaults=False):
|
|||||||
return [(f, d) for f, d in fieldlist if f in available]
|
return [(f, d) for f, d in fieldlist if f in available]
|
||||||
|
|
||||||
def render_data(mi, use_roman_numbers=True, all_fields=False):
|
def render_data(mi, use_roman_numbers=True, all_fields=False):
|
||||||
ans = []
|
field_list = get_field_list(getattr(mi, 'field_metadata', field_metadata))
|
||||||
comment_fields = []
|
field_list = [(x, all_fields or display) for x, display in field_list]
|
||||||
isdevice = not hasattr(mi, 'id')
|
return mi_to_html(mi, field_list=field_list, use_roman_numbers=use_roman_numbers,
|
||||||
fm = getattr(mi, 'field_metadata', field_metadata)
|
rating_font=rating_font(), default_author_link=gprefs.get('default_author_link'))
|
||||||
row = u'<td class="title">%s</td><td class="value">%s</td>'
|
|
||||||
p = prepare_string_for_xml
|
|
||||||
a = partial(prepare_string_for_xml, attribute=True)
|
|
||||||
|
|
||||||
for field, display in get_field_list(fm):
|
|
||||||
metadata = fm.get(field, None)
|
|
||||||
if field == 'sort':
|
|
||||||
field = 'title_sort'
|
|
||||||
if all_fields:
|
|
||||||
display = True
|
|
||||||
if metadata['datatype'] == 'bool':
|
|
||||||
isnull = mi.get(field) is None
|
|
||||||
else:
|
|
||||||
isnull = mi.is_null(field)
|
|
||||||
if (not display or not metadata or isnull):
|
|
||||||
continue
|
|
||||||
name = metadata['name']
|
|
||||||
if not name:
|
|
||||||
name = field
|
|
||||||
name += ':'
|
|
||||||
if metadata['datatype'] == 'comments' or field == 'comments':
|
|
||||||
val = getattr(mi, field)
|
|
||||||
if val:
|
|
||||||
val = force_unicode(val)
|
|
||||||
comment_fields.append(comments_to_html(val))
|
|
||||||
elif metadata['datatype'] == 'rating':
|
|
||||||
val = getattr(mi, field)
|
|
||||||
if val:
|
|
||||||
val = val/2.0
|
|
||||||
ans.append((field,
|
|
||||||
u'<td class="title">%s</td><td class="rating value" '
|
|
||||||
'style=\'font-family:"%s"\'>%s</td>'%(
|
|
||||||
name, rating_font(), u'\u2605'*int(val))))
|
|
||||||
elif metadata['datatype'] == 'composite' and \
|
|
||||||
metadata['display'].get('contains_html', False):
|
|
||||||
val = getattr(mi, field)
|
|
||||||
if val:
|
|
||||||
val = force_unicode(val)
|
|
||||||
ans.append((field,
|
|
||||||
row % (name, comments_to_html(val))))
|
|
||||||
elif field == 'path':
|
|
||||||
if mi.path:
|
|
||||||
path = force_unicode(mi.path, filesystem_encoding)
|
|
||||||
scheme = u'devpath' if isdevice else u'path'
|
|
||||||
url = prepare_string_for_xml(path if isdevice else
|
|
||||||
unicode(mi.id), True)
|
|
||||||
pathstr = _('Click to open')
|
|
||||||
extra = ''
|
|
||||||
if isdevice:
|
|
||||||
durl = url
|
|
||||||
if durl.startswith('mtp:::'):
|
|
||||||
durl = ':::'.join((durl.split(':::'))[2:])
|
|
||||||
extra = '<br><span style="font-size:smaller">%s</span>'%(
|
|
||||||
prepare_string_for_xml(durl))
|
|
||||||
link = u'<a href="%s:%s" title="%s">%s</a>%s' % (scheme, url,
|
|
||||||
prepare_string_for_xml(path, True), pathstr, extra)
|
|
||||||
ans.append((field, row % (name, link)))
|
|
||||||
elif field == 'formats':
|
|
||||||
if isdevice:
|
|
||||||
continue
|
|
||||||
path = ''
|
|
||||||
if mi.path:
|
|
||||||
h, t = os.path.split(mi.path)
|
|
||||||
path = '/'.join((os.path.basename(h), t))
|
|
||||||
data = ({
|
|
||||||
'fmt':x, 'path':a(path or ''), 'fname':a(mi.format_files.get(x, '')),
|
|
||||||
'ext':x.lower(), 'id':mi.id
|
|
||||||
} for x in mi.formats)
|
|
||||||
fmts = [u'<a title="{path}/{fname}.{ext}" href="format:{id}:{fmt}">{fmt}</a>'.format(**x) for x in data]
|
|
||||||
ans.append((field, row % (name, u', '.join(fmts))))
|
|
||||||
elif field == 'identifiers':
|
|
||||||
urls = urls_from_identifiers(mi.identifiers)
|
|
||||||
links = [u'<a href="%s" title="%s:%s">%s</a>' % (a(url), a(id_typ), a(id_val), p(name))
|
|
||||||
for name, id_typ, id_val, url in urls]
|
|
||||||
links = u', '.join(links)
|
|
||||||
if links:
|
|
||||||
ans.append((field, row % (_('Ids')+':', links)))
|
|
||||||
elif field == 'authors' and not isdevice:
|
|
||||||
authors = []
|
|
||||||
formatter = EvalFormatter()
|
|
||||||
for aut in mi.authors:
|
|
||||||
link = ''
|
|
||||||
if mi.author_link_map[aut]:
|
|
||||||
link = mi.author_link_map[aut]
|
|
||||||
elif gprefs.get('default_author_link'):
|
|
||||||
vals = {'author': aut.replace(' ', '+')}
|
|
||||||
try:
|
|
||||||
vals['author_sort'] = mi.author_sort_map[aut].replace(' ', '+')
|
|
||||||
except:
|
|
||||||
vals['author_sort'] = aut.replace(' ', '+')
|
|
||||||
link = formatter.safe_format(
|
|
||||||
gprefs.get('default_author_link'), vals, '', vals)
|
|
||||||
aut = p(aut)
|
|
||||||
if link:
|
|
||||||
authors.append(u'<a calibre-data="authors" href="%s">%s</a>'%(a(link), aut))
|
|
||||||
else:
|
|
||||||
authors.append(aut)
|
|
||||||
ans.append((field, row % (name, u' & '.join(authors))))
|
|
||||||
elif field == 'languages':
|
|
||||||
if not mi.languages:
|
|
||||||
continue
|
|
||||||
names = filter(None, map(calibre_langcode_to_name, mi.languages))
|
|
||||||
ans.append((field, row % (name, u', '.join(names))))
|
|
||||||
else:
|
|
||||||
val = mi.format_field(field)[-1]
|
|
||||||
if val is None:
|
|
||||||
continue
|
|
||||||
val = p(val)
|
|
||||||
if metadata['datatype'] == 'series':
|
|
||||||
sidx = mi.get(field+'_index')
|
|
||||||
if sidx is None:
|
|
||||||
sidx = 1.0
|
|
||||||
val = _('Book %(sidx)s of <span class="series_name">%(series)s</span>')%dict(
|
|
||||||
sidx=fmt_sidx(sidx, use_roman=use_roman_numbers),
|
|
||||||
series=p(getattr(mi, field)))
|
|
||||||
elif metadata['datatype'] == 'datetime':
|
|
||||||
aval = getattr(mi, field)
|
|
||||||
if is_date_undefined(aval):
|
|
||||||
continue
|
|
||||||
|
|
||||||
ans.append((field, row % (name, val)))
|
|
||||||
|
|
||||||
dc = getattr(mi, 'device_collections', [])
|
|
||||||
if dc:
|
|
||||||
dc = u', '.join(sorted(dc, key=sort_key))
|
|
||||||
ans.append(('device_collections',
|
|
||||||
row % (_('Collections')+':', dc)))
|
|
||||||
|
|
||||||
def classname(field):
|
|
||||||
try:
|
|
||||||
dt = fm[field]['datatype']
|
|
||||||
except:
|
|
||||||
dt = 'text'
|
|
||||||
return 'datatype_%s'%dt
|
|
||||||
|
|
||||||
ans = [u'<tr id="%s" class="%s">%s</tr>'%(field.replace('#', '_'),
|
|
||||||
classname(field), html) for field, html in ans]
|
|
||||||
# print '\n'.join(ans)
|
|
||||||
return u'<table class="fields">%s</table>'%(u'\n'.join(ans)), comment_fields
|
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
@ -5,11 +5,12 @@ import traceback, os, sys, functools, textwrap
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
from PyQt4.Qt import (QApplication, Qt, QIcon, QTimer, QByteArray, QSize,
|
from PyQt4.Qt import (
|
||||||
QTime, QDoubleSpinBox, QLabel, QTextBrowser, QPropertyAnimation,
|
QApplication, Qt, QIcon, QTimer, QByteArray, QSize, QTime, QDoubleSpinBox,
|
||||||
QPainter, QBrush, QColor, pyqtSignal, QUrl, QRegExpValidator, QRegExp,
|
QLabel, QPropertyAnimation, pyqtSignal, QUrl, QRegExpValidator, QRegExp,
|
||||||
QLineEdit, QToolButton, QMenu, QInputDialog, QAction,
|
QLineEdit, QToolButton, QMenu, QInputDialog, QAction, QModelIndex, QPalette,
|
||||||
QModelIndex)
|
QPainter, QBrush, QColor)
|
||||||
|
from PyQt4.QtWebKit import QWebView
|
||||||
|
|
||||||
from calibre.gui2.viewer.main_ui import Ui_EbookViewer
|
from calibre.gui2.viewer.main_ui import Ui_EbookViewer
|
||||||
from calibre.gui2.viewer.printing import Printing
|
from calibre.gui2.viewer.printing import Printing
|
||||||
@ -17,14 +18,13 @@ from calibre.gui2.viewer.bookmarkmanager import BookmarkManager
|
|||||||
from calibre.gui2.viewer.toc import TOC
|
from calibre.gui2.viewer.toc import TOC
|
||||||
from calibre.gui2.widgets import ProgressIndicator
|
from calibre.gui2.widgets import ProgressIndicator
|
||||||
from calibre.gui2.main_window import MainWindow
|
from calibre.gui2.main_window import MainWindow
|
||||||
from calibre.gui2 import (Application, ORG_NAME, APP_UID, choose_files,
|
from calibre.gui2 import (Application, ORG_NAME, APP_UID, choose_files, rating_font,
|
||||||
info_dialog, error_dialog, open_url, available_height, setup_gui_option_parser, detach_gui)
|
info_dialog, error_dialog, open_url, available_height, setup_gui_option_parser, detach_gui)
|
||||||
from calibre.ebooks.oeb.iterator.book import EbookIterator
|
from calibre.ebooks.oeb.iterator.book import EbookIterator
|
||||||
from calibre.ebooks import DRMError
|
from calibre.ebooks import DRMError
|
||||||
from calibre.constants import islinux, filesystem_encoding
|
from calibre.constants import islinux, filesystem_encoding
|
||||||
from calibre.utils.config import Config, StringConfig, JSONConfig
|
from calibre.utils.config import Config, StringConfig, JSONConfig
|
||||||
from calibre.gui2.search_box import SearchBox2
|
from calibre.gui2.search_box import SearchBox2
|
||||||
from calibre.ebooks.metadata import MetaInformation
|
|
||||||
from calibre.customize.ui import available_input_formats
|
from calibre.customize.ui import available_input_formats
|
||||||
from calibre.gui2.viewer.dictionary import Lookup
|
from calibre.gui2.viewer.dictionary import Lookup
|
||||||
from calibre import as_unicode, force_unicode, isbytestring
|
from calibre import as_unicode, force_unicode, isbytestring
|
||||||
@ -102,31 +102,44 @@ class History(list):
|
|||||||
self.forward_pos = None
|
self.forward_pos = None
|
||||||
self.set_actions()
|
self.set_actions()
|
||||||
|
|
||||||
class Metadata(QLabel):
|
class Metadata(QWebView):
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
QTextBrowser.__init__(self, parent.centralWidget())
|
QWebView.__init__(self, parent.centralWidget())
|
||||||
|
s = self.settings()
|
||||||
|
s.setAttribute(s.JavascriptEnabled, False)
|
||||||
|
self.page().setLinkDelegationPolicy(self.page().DelegateAllLinks)
|
||||||
|
self.setAttribute(Qt.WA_OpaquePaintEvent, False)
|
||||||
|
palette = self.palette()
|
||||||
|
palette.setBrush(QPalette.Base, Qt.transparent)
|
||||||
|
self.page().setPalette(palette)
|
||||||
|
self.css = P('templates/book_details.css', data=True).decode('utf-8')
|
||||||
|
|
||||||
self.view = parent.splitter
|
self.view = parent.splitter
|
||||||
self.setGeometry(self.view.geometry())
|
self.setGeometry(self.view.geometry())
|
||||||
self.setWordWrap(True)
|
|
||||||
self.setVisible(False)
|
self.setVisible(False)
|
||||||
|
|
||||||
def show_opf(self, opf, ext=''):
|
def show_opf(self, opf, ext=''):
|
||||||
mi = MetaInformation(opf)
|
from calibre.gui2.book_details import render_html
|
||||||
html = '<h2 align="center">%s</h2>%s\n<b>%s:</b> %s'\
|
from calibre.ebooks.metadata.book.render import mi_to_html
|
||||||
%(_('Metadata'), u''.join(mi.to_html()),
|
|
||||||
_('Book format'), ext.upper())
|
def render_data(mi, use_roman_numbers=True, all_fields=False):
|
||||||
self.setText(html)
|
return mi_to_html(mi, use_roman_numbers=use_roman_numbers, rating_font=rating_font())
|
||||||
|
|
||||||
|
mi = opf.to_book_metadata()
|
||||||
|
html = render_html(mi, self.css, True, self, render_data_func=render_data)
|
||||||
|
self.setHtml(html)
|
||||||
|
|
||||||
def setVisible(self, x):
|
def setVisible(self, x):
|
||||||
self.setGeometry(self.view.geometry())
|
if x:
|
||||||
QLabel.setVisible(self, x)
|
self.setGeometry(self.view.geometry())
|
||||||
|
QWebView.setVisible(self, x)
|
||||||
|
|
||||||
def paintEvent(self, ev):
|
def paintEvent(self, ev):
|
||||||
p = QPainter(self)
|
p = QPainter(self)
|
||||||
p.fillRect(ev.region().boundingRect(), QBrush(QColor(200, 200, 200, 220), Qt.SolidPattern))
|
p.fillRect(ev.region().boundingRect(), QBrush(QColor(200, 200, 200, 220), Qt.SolidPattern))
|
||||||
p.end()
|
p.end()
|
||||||
QLabel.paintEvent(self, ev)
|
QWebView.paintEvent(self, ev)
|
||||||
|
|
||||||
|
|
||||||
class DoubleSpinBox(QDoubleSpinBox):
|
class DoubleSpinBox(QDoubleSpinBox):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user