mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
IGN:Fixes for various minor regressions and support for adding the calibre brand to EPUB files
This commit is contained in:
parent
1f1be79a46
commit
b23c04e64d
@ -50,6 +50,7 @@ def convert(opts, recipe_arg, notification=None):
|
|||||||
opts.output = os.path.join(os.getcwd(), sanitize_file_name(fname))
|
opts.output = os.path.join(os.getcwd(), sanitize_file_name(fname))
|
||||||
|
|
||||||
print 'Generating epub...'
|
print 'Generating epub...'
|
||||||
|
opts.encoding = 'utf-8'
|
||||||
html2epub(opf, opts, notification=notification)
|
html2epub(opf, opts, notification=notification)
|
||||||
|
|
||||||
|
|
||||||
|
@ -644,8 +644,14 @@ def config(defaults=None, config_name='html',
|
|||||||
metadata = c.add_group('metadata', _('Set metadata of the generated ebook'))
|
metadata = c.add_group('metadata', _('Set metadata of the generated ebook'))
|
||||||
metadata('title', ['-t', '--title'], default=None,
|
metadata('title', ['-t', '--title'], default=None,
|
||||||
help=_('Set the title. Default is to autodetect.'))
|
help=_('Set the title. Default is to autodetect.'))
|
||||||
metadata('authors', ['-a', '--authors'], default=_('Unknown'),
|
metadata('authors', ['-a', '--authors'], default=None,
|
||||||
help=_('The author(s) of the ebook, as a comma separated list.'))
|
help=_('The author(s) of the ebook, as a comma separated list.'))
|
||||||
|
metadata('tags', ['--subjects'], default=None,
|
||||||
|
help=_('The subject(s) of this book, as a comma separated list.'))
|
||||||
|
metadata('publisher', ['--publisher'], default=None,
|
||||||
|
help=_('Set the publisher of this book.'))
|
||||||
|
metadata('comments', ['--comment'], default=None,
|
||||||
|
help=_('A summary of this book.'))
|
||||||
metadata('from_opf', ['--metadata-from'], default=None,
|
metadata('from_opf', ['--metadata-from'], default=None,
|
||||||
help=_('Load metadata from the specified OPF file'))
|
help=_('Load metadata from the specified OPF file'))
|
||||||
|
|
||||||
@ -730,13 +736,13 @@ def merge_metadata(htmlfile, opf, opts):
|
|||||||
mi = MetaInformation(None, None)
|
mi = MetaInformation(None, None)
|
||||||
if opts.from_opf is not None and os.access(opts.from_opf, os.R_OK):
|
if opts.from_opf is not None and os.access(opts.from_opf, os.R_OK):
|
||||||
mi.smart_update(OPF(open(opts.from_opf, 'rb'), os.path.abspath(os.path.dirname(opts.from_opf))))
|
mi.smart_update(OPF(open(opts.from_opf, 'rb'), os.path.abspath(os.path.dirname(opts.from_opf))))
|
||||||
if opts.title:
|
for attr in ('title', 'authors', 'publisher', 'tags', 'comments'):
|
||||||
mi.title = opts.title
|
val = getattr(opts, attr, None)
|
||||||
if opts.authors != _('Unknown'):
|
if val is None or val == _('Unknown') or val == [_('Unknown')]:
|
||||||
opts.authors = opts.authors.split(',')
|
continue
|
||||||
opts.authors = [a.strip() for a in opts.authors]
|
if attr in ('authors', 'tags'):
|
||||||
mi.authors = opts.authors
|
val = [i.strip() for i in val.split(',') if i.strip()]
|
||||||
|
setattr(mi, attr, val)
|
||||||
if not mi.title:
|
if not mi.title:
|
||||||
mi.title = os.path.splitext(os.path.basename(htmlfile))[0]
|
mi.title = os.path.splitext(os.path.basename(htmlfile))[0]
|
||||||
if not mi.authors:
|
if not mi.authors:
|
||||||
|
@ -269,6 +269,8 @@ def process_pages(pages, opts, update):
|
|||||||
ans, failures = [], []
|
ans, failures = [], []
|
||||||
|
|
||||||
for job in jobs:
|
for job in jobs:
|
||||||
|
if job.result is None:
|
||||||
|
raise Exception(_('Failed to process comic: %s\n\n%s')%(job.exception, job.traceback))
|
||||||
pages, failures_ = job.result
|
pages, failures_ = job.result
|
||||||
ans += pages
|
ans += pages
|
||||||
failures += failures_
|
failures += failures_
|
||||||
|
@ -171,7 +171,7 @@ class MetaInformation(object):
|
|||||||
for attr in ('author_sort', 'title_sort', 'comments', 'category',
|
for attr in ('author_sort', 'title_sort', 'comments', 'category',
|
||||||
'publisher', 'series', 'series_index', 'rating',
|
'publisher', 'series', 'series_index', 'rating',
|
||||||
'isbn', 'tags', 'cover_data', 'application_id', 'guide',
|
'isbn', 'tags', 'cover_data', 'application_id', 'guide',
|
||||||
'manifest', 'spine', 'toc', 'cover', 'language'):
|
'manifest', 'spine', 'toc', 'cover', 'language', 'book_producer'):
|
||||||
if hasattr(mi, attr):
|
if hasattr(mi, attr):
|
||||||
setattr(ans, attr, getattr(mi, attr))
|
setattr(ans, attr, getattr(mi, attr))
|
||||||
|
|
||||||
@ -195,7 +195,8 @@ class MetaInformation(object):
|
|||||||
|
|
||||||
for x in ('author_sort', 'title_sort', 'comments', 'category', 'publisher',
|
for x in ('author_sort', 'title_sort', 'comments', 'category', 'publisher',
|
||||||
'series', 'series_index', 'rating', 'isbn', 'language',
|
'series', 'series_index', 'rating', 'isbn', 'language',
|
||||||
'application_id', 'manifest', 'toc', 'spine', 'guide', 'cover'
|
'application_id', 'manifest', 'toc', 'spine', 'guide', 'cover',
|
||||||
|
'book_producer',
|
||||||
):
|
):
|
||||||
setattr(self, x, getattr(mi, x, None))
|
setattr(self, x, getattr(mi, x, None))
|
||||||
|
|
||||||
@ -213,7 +214,7 @@ class MetaInformation(object):
|
|||||||
for attr in ('author_sort', 'title_sort', 'comments', 'category',
|
for attr in ('author_sort', 'title_sort', 'comments', 'category',
|
||||||
'publisher', 'series', 'series_index', 'rating',
|
'publisher', 'series', 'series_index', 'rating',
|
||||||
'isbn', 'application_id', 'manifest', 'spine', 'toc',
|
'isbn', 'application_id', 'manifest', 'spine', 'toc',
|
||||||
'cover', 'language', 'guide'):
|
'cover', 'language', 'guide', 'book_producer'):
|
||||||
if hasattr(mi, attr):
|
if hasattr(mi, attr):
|
||||||
val = getattr(mi, attr)
|
val = getattr(mi, attr)
|
||||||
if val is not None:
|
if val is not None:
|
||||||
@ -234,6 +235,8 @@ class MetaInformation(object):
|
|||||||
ans += ((' (' + self.author_sort + ')') if self.author_sort else '') + u'\n'
|
ans += ((' (' + self.author_sort + ')') if self.author_sort else '') + u'\n'
|
||||||
if self.publisher:
|
if self.publisher:
|
||||||
ans += u'Publisher: '+ unicode(self.publisher) + u'\n'
|
ans += u'Publisher: '+ unicode(self.publisher) + u'\n'
|
||||||
|
if self.book_producer:
|
||||||
|
ans += u'Producer : '+ unicode(self.book_producer) + u'\n'
|
||||||
if self.category:
|
if self.category:
|
||||||
ans += u'Category : ' + unicode(self.category) + u'\n'
|
ans += u'Category : ' + unicode(self.category) + u'\n'
|
||||||
if self.comments:
|
if self.comments:
|
||||||
|
@ -7,7 +7,7 @@ import cStringIO
|
|||||||
import uuid
|
import uuid
|
||||||
from urllib import unquote, quote
|
from urllib import unquote, quote
|
||||||
|
|
||||||
from calibre import __appname__
|
from calibre.constants import __appname__, __version__
|
||||||
from calibre.ebooks.metadata import MetaInformation
|
from calibre.ebooks.metadata import MetaInformation
|
||||||
from calibre.ebooks.BeautifulSoup import BeautifulStoneSoup, BeautifulSoup
|
from calibre.ebooks.BeautifulSoup import BeautifulStoneSoup, BeautifulSoup
|
||||||
from calibre.ebooks.lrf import entity_to_unicode
|
from calibre.ebooks.lrf import entity_to_unicode
|
||||||
@ -515,7 +515,7 @@ class OPFCreator(MetaInformation):
|
|||||||
self.guide.set_cover(cover)
|
self.guide.set_cover(cover)
|
||||||
self.guide.set_basedir(self.base_path)
|
self.guide.set_basedir(self.base_path)
|
||||||
|
|
||||||
opf = template.generate(__appname__=__appname__, mi=self).render('xml')
|
opf = template.generate(__appname__=__appname__, mi=self, __version__=__version__).render('xml')
|
||||||
opf_stream.write(opf)
|
opf_stream.write(opf)
|
||||||
opf_stream.flush()
|
opf_stream.flush()
|
||||||
toc = getattr(self, 'toc', None)
|
toc = getattr(self, 'toc', None)
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
|
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
|
||||||
<dc:title py:with="attrs={'opf:files-as':mi.title_sort}" py:attrs="attrs">${mi.title}</dc:title>
|
<dc:title py:with="attrs={'opf:files-as':mi.title_sort}" py:attrs="attrs">${mi.title}</dc:title>
|
||||||
<dc:creator opf:role="aut" py:for="i, author in enumerate(mi.authors)" py:with="attrs={'opf:file-as':mi.author_sort if i==0 else None}" py:attrs="attrs">${author}</dc:creator>
|
<dc:creator opf:role="aut" py:for="i, author in enumerate(mi.authors)" py:with="attrs={'opf:file-as':mi.author_sort if i==0 else None}" py:attrs="attrs">${author}</dc:creator>
|
||||||
|
<dc:contributor opf:role="bkp" py:with="attrs={'opf:files-as':__appname__}" py:attrs="attrs">${'%s (%s)'%(__appname__, __version__)} [http://${__appname__}.kovidgoyal.net]</dc:contributor>
|
||||||
<dc:identifier opf:scheme="${__appname__}" id="${__appname__}_id">${mi.application_id}</dc:identifier>
|
<dc:identifier opf:scheme="${__appname__}" id="${__appname__}_id">${mi.application_id}</dc:identifier>
|
||||||
|
|
||||||
<dc:language>${mi.language if mi.language else 'Unknown'}</dc:language>
|
<dc:language>${mi.language if mi.language else 'Unknown'}</dc:language>
|
||||||
|
@ -15,7 +15,7 @@ from lxml import etree
|
|||||||
|
|
||||||
from calibre.ebooks.chardet import xml_to_unicode
|
from calibre.ebooks.chardet import xml_to_unicode
|
||||||
from calibre import relpath
|
from calibre import relpath
|
||||||
from calibre.constants import __appname__
|
from calibre.constants import __appname__, __version__
|
||||||
from calibre.ebooks.metadata.toc import TOC
|
from calibre.ebooks.metadata.toc import TOC
|
||||||
from calibre.ebooks.metadata import MetaInformation
|
from calibre.ebooks.metadata import MetaInformation
|
||||||
|
|
||||||
@ -407,6 +407,7 @@ class OPF(object):
|
|||||||
metadata_path = XPath('descendant::*[re:match(name(), "metadata", "i")]')
|
metadata_path = XPath('descendant::*[re:match(name(), "metadata", "i")]')
|
||||||
metadata_elem_path = XPath('descendant::*[re:match(name(), $name, "i")]')
|
metadata_elem_path = XPath('descendant::*[re:match(name(), $name, "i")]')
|
||||||
authors_path = XPath('descendant::*[re:match(name(), "creator", "i") and (@role="aut" or @opf:role="aut")]')
|
authors_path = XPath('descendant::*[re:match(name(), "creator", "i") and (@role="aut" or @opf:role="aut")]')
|
||||||
|
bkp_path = XPath('descendant::*[re:match(name(), "contributor", "i") and (@role="bkp" or @opf:role="bkp")]')
|
||||||
tags_path = XPath('descendant::*[re:match(name(), "subject", "i")]')
|
tags_path = XPath('descendant::*[re:match(name(), "subject", "i")]')
|
||||||
isbn_path = XPath('descendant::*[re:match(name(), "identifier", "i") and '+
|
isbn_path = XPath('descendant::*[re:match(name(), "identifier", "i") and '+
|
||||||
'(re:match(@scheme, "isbn", "i") or re:match(@opf:scheme, "isbn", "i"))]')
|
'(re:match(@scheme, "isbn", "i") or re:match(@opf:scheme, "isbn", "i"))]')
|
||||||
@ -607,6 +608,21 @@ class OPF(object):
|
|||||||
matches[0].text = unicode(val)
|
matches[0].text = unicode(val)
|
||||||
return property(fget=fget, fset=fset)
|
return property(fget=fget, fset=fset)
|
||||||
|
|
||||||
|
@apply
|
||||||
|
def book_producer():
|
||||||
|
|
||||||
|
def fget(self):
|
||||||
|
for match in self.bkp_path(self.metadata):
|
||||||
|
return match.text if match.text else None
|
||||||
|
|
||||||
|
def fset(self, val):
|
||||||
|
matches = self.bkp_path(self.metadata)
|
||||||
|
if not matches:
|
||||||
|
matches = [self.create_metadata_element('contributor', ns='dc',
|
||||||
|
attrib={'{%s}role'%self.NAMESPACES['opf']:'bkp'})]
|
||||||
|
matches[0].text = unicode(val)
|
||||||
|
return property(fget=fget, fset=fset)
|
||||||
|
|
||||||
@apply
|
@apply
|
||||||
def cover():
|
def cover():
|
||||||
|
|
||||||
@ -758,8 +774,7 @@ class OPFCreator(MetaInformation):
|
|||||||
cover = os.path.abspath(os.path.join(self.base_path, cover))
|
cover = os.path.abspath(os.path.join(self.base_path, cover))
|
||||||
self.guide.set_cover(cover)
|
self.guide.set_cover(cover)
|
||||||
self.guide.set_basedir(self.base_path)
|
self.guide.set_basedir(self.base_path)
|
||||||
|
opf = template.generate(__appname__=__appname__, mi=self, __version__=__version__).render('xml')
|
||||||
opf = template.generate(__appname__=__appname__, mi=self).render('xml')
|
|
||||||
opf_stream.write(opf)
|
opf_stream.write(opf)
|
||||||
opf_stream.flush()
|
opf_stream.flush()
|
||||||
toc = getattr(self, 'toc', None)
|
toc = getattr(self, 'toc', None)
|
||||||
|
@ -808,7 +808,8 @@ class Main(MainWindow, Ui_MainWindow):
|
|||||||
self.job_exception(job)
|
self.job_exception(job)
|
||||||
return
|
return
|
||||||
to_device = self.device_connected and fmt.lower() in self.device_manager.device_class.FORMATS
|
to_device = self.device_connected and fmt.lower() in self.device_manager.device_class.FORMATS
|
||||||
self._add_books([pt.name], to_device, on_card=config.get('send_to_storage_card_by_default') and bool(self.device_manager.device.card_prefix()))
|
self._add_books([pt.name], to_device,
|
||||||
|
on_card=config.get('send_to_storage_card_by_default') and self.device_connected and bool(self.device_manager.device.card_prefix()))
|
||||||
if to_device:
|
if to_device:
|
||||||
self.status_bar.showMessage(_('News fetched. Uploading to device.'), 2000)
|
self.status_bar.showMessage(_('News fetched. Uploading to device.'), 2000)
|
||||||
self.persistent_files.append(pt)
|
self.persistent_files.append(pt)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user