From e7b39e91584dede387cf4c23a7c5c8b39d6ca1fe Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 28 Mar 2011 10:14:53 -0600 Subject: [PATCH 1/6] MOBI Output: Workaround for Amazon's MOBI renderer not rendering top margins on ul and ol tags. Fixes 744365 --- src/calibre/ebooks/mobi/mobiml.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/calibre/ebooks/mobi/mobiml.py b/src/calibre/ebooks/mobi/mobiml.py index 189739986d..ffb19d5fce 100644 --- a/src/calibre/ebooks/mobi/mobiml.py +++ b/src/calibre/ebooks/mobi/mobiml.py @@ -206,7 +206,11 @@ class MobiMLizer(object): vspace = bstate.vpadding + bstate.vmargin bstate.vpadding = bstate.vmargin = 0 if tag not in TABLE_TAGS: - wrapper.attrib['height'] = self.mobimlize_measure(vspace) + if tag in ('ul', 'ol') and vspace > 0: + wrapper.addprevious(etree.Element(XHTML('div'), + height=self.mobimlize_measure(vspace))) + else: + wrapper.attrib['height'] = self.mobimlize_measure(vspace) para.attrib['width'] = self.mobimlize_measure(indent) elif tag == 'table' and vspace > 0: vspace = int(round(vspace / self.profile.fbase)) From 42529417ca43dceedc7448ae46cb980ffa566c79 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Mon, 28 Mar 2011 18:18:14 +0100 Subject: [PATCH 2/6] Ensure that custcol['display'] is never None. --- src/calibre/library/custom_columns.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/calibre/library/custom_columns.py b/src/calibre/library/custom_columns.py index 48960ac871..8eed121b21 100644 --- a/src/calibre/library/custom_columns.py +++ b/src/calibre/library/custom_columns.py @@ -76,6 +76,8 @@ class CustomColumns(object): 'num':record[6], 'is_multiple':record[7], } + if data['display'] is None: + data['display'] = {} table, lt = self.custom_table_names(data['num']) if table not in custom_tables or (data['normalized'] and lt not in custom_tables): From 6958a6f907dc2043b2b9ae9f0f2d6bc887af158d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 28 Mar 2011 11:20:12 -0600 Subject: [PATCH 3/6] Add warning when MOBI output plugin detects and removes an HTML cover --- src/calibre/ebooks/mobi/mobiml.py | 5 +++++ src/calibre/trac/bzr_commit_plugin.py | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/calibre/ebooks/mobi/mobiml.py b/src/calibre/ebooks/mobi/mobiml.py index ffb19d5fce..40ad5e9e78 100644 --- a/src/calibre/ebooks/mobi/mobiml.py +++ b/src/calibre/ebooks/mobi/mobiml.py @@ -102,6 +102,7 @@ class MobiMLizer(object): def __call__(self, oeb, context): oeb.logger.info('Converting XHTML to Mobipocket markup...') self.oeb = oeb + self.log = self.oeb.logger self.opts = context self.profile = profile = context.dest self.fnums = fnums = dict((v, k) for k, v in profile.fnums.items()) @@ -118,6 +119,10 @@ class MobiMLizer(object): del oeb.guide['cover'] item = oeb.manifest.hrefs[href] if item.spine_position is not None: + self.log.warn('Found an HTML cover,', item.href, 'removing it.', + 'If you find some content missing from the output MOBI, it ' + 'is because you misidentified the HTML cover in the input ' + 'document') oeb.spine.remove(item) if item.media_type in OEB_DOCS: self.oeb.manifest.remove(item) diff --git a/src/calibre/trac/bzr_commit_plugin.py b/src/calibre/trac/bzr_commit_plugin.py index 7e5a1367cb..c596425a68 100644 --- a/src/calibre/trac/bzr_commit_plugin.py +++ b/src/calibre/trac/bzr_commit_plugin.py @@ -31,8 +31,11 @@ class cmd_commit(_cmd_commit): summary = '' raw = urllib.urlopen('https://bugs.launchpad.net/calibre/+bug/' + bug).read() - h1 = html.fromstring(raw).xpath('//h1[@id="edit-title"]')[0] - summary = html.tostring(h1, method='text', encoding=unicode).strip() + try: + h1 = html.fromstring(raw).xpath('//h1[@id="edit-title"]')[0] + summary = html.tostring(h1, method='text', encoding=unicode).strip() + except: + summary = 'Private bug' print 'Working on bug:', summary if summary: msg = msg.replace('#%s'%bug, '#%s (%s)'%(bug, summary)) From 3d63ef67ddddb7d45c5c7044354976d0dc493b8f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 28 Mar 2011 11:39:54 -0600 Subject: [PATCH 4/6] Implement #744020 (Add Publisher and Publication Date to Adding Books Possible Fields) --- src/calibre/ebooks/metadata/meta.py | 13 +++++++++ src/calibre/gui2/filename_pattern.ui | 40 ++++++++++++++++++++++++++++ src/calibre/gui2/widgets.py | 6 +++++ 3 files changed, 59 insertions(+) diff --git a/src/calibre/ebooks/metadata/meta.py b/src/calibre/ebooks/metadata/meta.py index cbd9db3f04..b0c43a8182 100644 --- a/src/calibre/ebooks/metadata/meta.py +++ b/src/calibre/ebooks/metadata/meta.py @@ -182,6 +182,19 @@ def metadata_from_filename(name, pat=None): mi.isbn = si except (IndexError, ValueError): pass + try: + publisher = match.group('publisher') + mi.publisher = publisher + except (IndexError, ValueError): + pass + try: + pubdate = match.group('published') + if pubdate: + from calibre.utils.date import parse_date + mi.pubdate = parse_date(pubdate) + except: + pass + if mi.is_null('title'): mi.title = name return mi diff --git a/src/calibre/gui2/filename_pattern.ui b/src/calibre/gui2/filename_pattern.ui index 68b3108e06..c8a9b4f6f6 100644 --- a/src/calibre/gui2/filename_pattern.ui +++ b/src/calibre/gui2/filename_pattern.ui @@ -206,6 +206,46 @@ + + + + Publisher: + + + + + + + Regular expression (?P<publisher>) + + + No match + + + true + + + + + + + Published: + + + + + + + Regular expression (?P<published>) + + + No match + + + true + + + diff --git a/src/calibre/gui2/widgets.py b/src/calibre/gui2/widgets.py index ea0509b51a..e5f1c94342 100644 --- a/src/calibre/gui2/widgets.py +++ b/src/calibre/gui2/widgets.py @@ -121,6 +121,12 @@ class FilenamePattern(QWidget, Ui_Form): else: self.series_index.setText(_('No match')) + if mi.publisher: + self.publisher.setText(mi.publisher) + + if mi.pubdate: + self.pubdate.setText(mi.pubdate.strftime('%Y-%m-%d')) + self.isbn.setText(_('No match') if mi.isbn is None else str(mi.isbn)) From 71d038d975f6605bea97eca555c48ad756a48c69 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 28 Mar 2011 15:29:17 -0600 Subject: [PATCH 5/6] EPUB Output: Remove any margins specified via an Adobe page template in the input document --- src/calibre/ebooks/conversion/plumber.py | 4 +- src/calibre/ebooks/oeb/transforms/margins.py | 56 ------------------- .../ebooks/oeb/transforms/page_margin.py | 20 +++++++ 3 files changed, 23 insertions(+), 57 deletions(-) delete mode 100644 src/calibre/ebooks/oeb/transforms/margins.py diff --git a/src/calibre/ebooks/conversion/plumber.py b/src/calibre/ebooks/conversion/plumber.py index 6272e7b10b..b26befe075 100644 --- a/src/calibre/ebooks/conversion/plumber.py +++ b/src/calibre/ebooks/conversion/plumber.py @@ -1003,8 +1003,10 @@ OptionRecommendation(name='sr3_replace', self.opts.insert_blank_line = oibl self.opts.remove_paragraph_spacing = orps - from calibre.ebooks.oeb.transforms.page_margin import RemoveFakeMargins + from calibre.ebooks.oeb.transforms.page_margin import \ + RemoveFakeMargins, RemoveAdobeMargins RemoveFakeMargins()(self.oeb, self.log, self.opts) + RemoveAdobeMargins()(self.oeb, self.log, self.opts) pr(0.9) self.flush() diff --git a/src/calibre/ebooks/oeb/transforms/margins.py b/src/calibre/ebooks/oeb/transforms/margins.py deleted file mode 100644 index fbdf2e63fd..0000000000 --- a/src/calibre/ebooks/oeb/transforms/margins.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python -# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai - -__license__ = 'GPL v3' -__copyright__ = '2010, Kovid Goyal ' -__docformat__ = 'restructuredtext en' - - -class RemoveFakeMargins(object): - ''' - Try to detect and remove fake margins inserted by asinine ebook creation - software on each paragraph/wrapper div. Can be used only after CSS - flattening. - ''' - - def __call__(self, oeb, opts, log): - self.oeb, self.opts, self.log = oeb, opts, log - - from calibre.ebooks.oeb.base import XPath, OEB_STYLES - - stylesheet = None - for item in self.oeb.manifest: - if item.media_type.lower() in OEB_STYLES: - stylesheet = item.data - break - - if stylesheet is None: - return - - - top_level_elements = {} - second_level_elements = {} - - for x in self.oeb.spine: - root = x.data - body = XPath('//h:body')(root) - if body: - body = body[0] - - if not hasattr(body, 'xpath'): - continue - - # Check for margins on top level elements - for lb in XPath('./h:div|./h:p|./*/h:div|./*/h:p')(body): - cls = lb.get('class', '') - level = top_level_elements if lb.getparent() is body else \ - second_level_elements - if cls not in level: - level[cls] = [] - top_level_elements[cls] = [] - level[cls].append(lb) - - - def get_margins(self, stylesheet, cls): - pass - diff --git a/src/calibre/ebooks/oeb/transforms/page_margin.py b/src/calibre/ebooks/oeb/transforms/page_margin.py index 589f004dd1..c415dda0e0 100644 --- a/src/calibre/ebooks/oeb/transforms/page_margin.py +++ b/src/calibre/ebooks/oeb/transforms/page_margin.py @@ -11,6 +11,26 @@ from collections import Counter from calibre.ebooks.oeb.base import OEB_STYLES, barename, XPath +class RemoveAdobeMargins(object): + ''' + Remove margins specified in Adobe's page templates. + ''' + + def __call__(self, oeb, log, opts): + self.oeb, self.opts, self.log = oeb, opts, log + + for item in self.oeb.manifest: + if item.media_type == 'application/vnd.adobe-page-template+xml': + self.log('Removing page margins specified in the' + ' Adobe page template') + for elem in item.data.xpath( + '//*[@margin-bottom or @margin-top ' + 'or @margin-left or @margin-right]'): + for margin in ('left', 'right', 'top', 'bottom'): + attr = 'margin-'+margin + elem.attrib.pop(attr, None) + + class RemoveFakeMargins(object): ''' From 833f46b1496ba6daaee527cbcc3f4eae6d919ea6 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 28 Mar 2011 16:26:54 -0600 Subject: [PATCH 6/6] ... --- src/calibre/ebooks/metadata/sources/identify.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/ebooks/metadata/sources/identify.py b/src/calibre/ebooks/metadata/sources/identify.py index 53fb3a9ea4..5bc0c5b256 100644 --- a/src/calibre/ebooks/metadata/sources/identify.py +++ b/src/calibre/ebooks/metadata/sources/identify.py @@ -79,7 +79,7 @@ def identify(log, abort, title=None, authors=None, identifiers=[], timeout=30): time.sleep(0.2) if get_results() and first_result_at is None: - first_result_at = time.time() + first_result_at = time.time() if not is_worker_alive(workers): break