diff --git a/src/calibre/ebooks/conversion/cli.py b/src/calibre/ebooks/conversion/cli.py index a860b75839..fb1974f93b 100644 --- a/src/calibre/ebooks/conversion/cli.py +++ b/src/calibre/ebooks/conversion/cli.py @@ -170,7 +170,7 @@ def add_pipeline_options(parser, plumber): 'chapter', 'chapter_mark', 'prefer_metadata_cover', 'remove_first_image', 'insert_metadata', 'page_breaks_before', - 'remove_fake_margins', + 'remove_fake_margins', 'start_reading_at', ] ), diff --git a/src/calibre/ebooks/conversion/plumber.py b/src/calibre/ebooks/conversion/plumber.py index 6a7b5e586b..dcb5add27e 100644 --- a/src/calibre/ebooks/conversion/plumber.py +++ b/src/calibre/ebooks/conversion/plumber.py @@ -304,6 +304,16 @@ OptionRecommendation(name='chapter_mark', 'to mark chapters.') ), +OptionRecommendation(name='start_reading_at', + recommended_value=None, level=OptionRecommendation.LOW, + help=_('An XPath expression to detect the location in the document' + ' at which to start reading. Some ebook reading programs' + ' (most prominently the Kindle) use this location as the' + ' position at which to open the book. See the XPath tutorial' + ' in the calibre User Manual for further help using this' + ' feature.') + ), + OptionRecommendation(name='extra_css', recommended_value=None, level=OptionRecommendation.LOW, help=_('Either the path to a CSS stylesheet or raw CSS. ' diff --git a/src/calibre/ebooks/oeb/transforms/structure.py b/src/calibre/ebooks/oeb/transforms/structure.py index b90774bcc7..3af4d87a13 100644 --- a/src/calibre/ebooks/oeb/transforms/structure.py +++ b/src/calibre/ebooks/oeb/transforms/structure.py @@ -6,7 +6,7 @@ __license__ = 'GPL v3' __copyright__ = '2009, Kovid Goyal ' __docformat__ = 'restructuredtext en' -import re +import re, uuid from lxml import etree from urlparse import urlparse @@ -80,6 +80,35 @@ class DetectStructure(object): if not node.title or not node.title.strip(): node.title = _('Unnamed') + if self.opts.start_reading_at: + self.detect_start_reading() + + def detect_start_reading(self): + expr = self.opts.start_reading_at + try: + expr = XPath(expr) + except: + self.log.warn( + 'Invalid start reading at XPath expression, ignoring: %s'%expr) + return + for item in self.oeb.spine: + if not hasattr(item.data, 'xpath'): continue + matches = expr(item.data) + if matches: + elem = matches[0] + eid = elem.get('id', None) + if not eid: + eid = u'start_reading_at_'+unicode(uuid.uuid4()).replace(u'-', u'') + elem.set('id', eid) + if u'text' in self.oeb.guide: + self.oeb.guide.remove(u'text') + self.oeb.guide.add(u'text', u'Start', item.href+u'#'+eid) + self.log('Setting start reading at position to %s in %s'%( + self.opts.start_reading_at, item.href)) + return + self.log.warn("Failed to find start reading at position: %s"% + self.opts.start_reading_at) + def detect_chapters(self): self.detected_chapters = [] diff --git a/src/calibre/gui2/convert/structure_detection.py b/src/calibre/gui2/convert/structure_detection.py index b58c473bd4..0946d13e46 100644 --- a/src/calibre/gui2/convert/structure_detection.py +++ b/src/calibre/gui2/convert/structure_detection.py @@ -20,7 +20,7 @@ class StructureDetectionWidget(Widget, Ui_Form): def __init__(self, parent, get_option, get_help, db=None, book_id=None): Widget.__init__(self, parent, - ['chapter', 'chapter_mark', + ['chapter', 'chapter_mark', 'start_reading_at', 'remove_first_image', 'remove_fake_margins', 'insert_metadata', 'page_breaks_before'] ) @@ -31,15 +31,18 @@ class StructureDetectionWidget(Widget, Ui_Form): self.opt_chapter.set_msg(_('Detect chapters at (XPath expression):')) self.opt_page_breaks_before.set_msg(_('Insert page breaks before ' '(XPath expression):')) + self.opt_start_reading_at.set_msg( + _('Start reading at (XPath expression):')) def break_cycles(self): Widget.break_cycles(self) def pre_commit_check(self): - for x in ('chapter', 'page_breaks_before'): + for x in ('chapter', 'page_breaks_before', 'start_reading_at'): x = getattr(self, 'opt_'+x) if not x.check(): error_dialog(self, _('Invalid XPath'), _('The XPath expression %s is invalid.')%x.text).exec_() return False return True + diff --git a/src/calibre/gui2/convert/structure_detection.ui b/src/calibre/gui2/convert/structure_detection.ui index 4ba90c1c2c..21d285fb33 100644 --- a/src/calibre/gui2/convert/structure_detection.ui +++ b/src/calibre/gui2/convert/structure_detection.ui @@ -14,10 +14,40 @@ Form - + + + + Remove &fake margins + + + + + + + The header and footer removal options have been replaced by the Search & Replace options. Click the Search & Replace category in the bar to the left to use these options. Leave the replace field blank and enter your header/footer removal regexps into the search field. + + + true + + + + + + + + + + Insert &metadata as page at start of book + + + + + + + - + Chapter &mark: @@ -27,44 +57,14 @@ - + 20 - - - - Remove first &image - - - - - - - Insert &metadata as page at start of book - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - + Qt::Horizontal @@ -77,22 +77,25 @@ - - + + - The header and footer removal options have been replaced by the Search & Replace options. Click the Search & Replace category in the bar to the left to use these options. Leave the replace field blank and enter your header/footer removal regexps into the search field. - - - true + Remove first &image - - - - Remove &fake margins + + + + Qt::Vertical - + + + 20 + 40 + + +