From 8535e2169474a97a294b6839d08f06732999bd8c Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 24 Mar 2013 13:43:16 +0530 Subject: [PATCH] Conversion: When converting a single book to EPUB or AZW3, add an option to automatically launch the Table of Contents editor after the conversion completes. Found under the Table of Contents section of the conversion dialog. --- manual/conversion.rst | 14 ++- src/calibre/gui2/actions/convert.py | 11 +- src/calibre/gui2/convert/bulk.py | 1 + src/calibre/gui2/convert/single.py | 8 ++ src/calibre/gui2/convert/toc.ui | 111 +++++++++++++-------- src/calibre/gui2/preferences/conversion.py | 2 + src/calibre/gui2/tools.py | 7 +- 7 files changed, 106 insertions(+), 48 deletions(-) diff --git a/manual/conversion.rst b/manual/conversion.rst index 817821a9b1..bf451d0980 100644 --- a/manual/conversion.rst +++ b/manual/conversion.rst @@ -434,6 +434,18 @@ a number of older formats either do not support a metadata based Table of Conten documents do not have one. In these cases, the options in this section can help you automatically generate a Table of Contents in the converted ebook, based on the actual content in the input document. +.. note:: Using these options can be a little challenging to get exactly right. + If you prefer creating/editing the Table of Contents by hand, convert to + the EPUB or AZW3 formats and select the checkbox at the bottom of the + screen that says + :guilabel:`Manually fine-tune the Table of Contents after conversion`. + This will launch the ToC Editor tool after the conversion. It allows you to + create entries in the Table of Contents by simply clicking the place in the + book where you want the entry to point. You can also use the ToC Editor by + itself, without doing a conversion. Go to :guilabel:`Preferences->Toolbars` + and add the ToC Editor to the main toolbar. Then just select the book you + want to edit and click the ToC Editor button. + The first option is :guilabel:`Force use of auto-generated Table of Contents`. By checking this option you can have |app| override any Table of Contents found in the metadata of the input document with the auto generated one. @@ -456,7 +468,7 @@ For example, to remove all entries titles "Next" or "Previous" use:: Next|Previous -Finally, the :guilabel:`Level 1,2,3 TOC` options allow you to create a sophisticated multi-level Table of Contents. +The :guilabel:`Level 1,2,3 TOC` options allow you to create a sophisticated multi-level Table of Contents. They are XPath expressions that match tags in the intermediate XHTML produced by the conversion pipeline. See the :ref:`conversion-introduction` for how to get access to this XHTML. Also read the :ref:`xpath-tutorial`, to learn how to construct XPath expressions. Next to each option is a button that launches a wizard to help with the creation diff --git a/src/calibre/gui2/actions/convert.py b/src/calibre/gui2/actions/convert.py index 68415db748..c5e1580c6d 100644 --- a/src/calibre/gui2/actions/convert.py +++ b/src/calibre/gui2/actions/convert.py @@ -167,8 +167,8 @@ class ConvertAction(InterfaceAction): def queue_convert_jobs(self, jobs, changed, bad, rows, previous, converted_func, extra_job_args=[], rows_are_ids=False): for func, args, desc, fmt, id, temp_files in jobs: - func, _, same_fmt = func.partition(':') - same_fmt = same_fmt == 'same_fmt' + func, _, parts = func.partition(':') + parts = {x for x in parts.split(';')} input_file = args[0] input_fmt = os.path.splitext(input_file)[1] core_usage = 1 @@ -182,7 +182,8 @@ class ConvertAction(InterfaceAction): job = self.gui.job_manager.run_job(Dispatcher(converted_func), func, args=args, description=desc, core_usage=core_usage) - job.conversion_of_same_fmt = same_fmt + job.conversion_of_same_fmt = 'same_fmt' in parts + job.manually_fine_tune_toc = 'manually_fine_tune_toc' in parts args = [temp_files, fmt, id]+extra_job_args self.conversion_jobs[job] = tuple(args) @@ -223,6 +224,7 @@ class ConvertAction(InterfaceAction): self.gui.job_exception(job) return same_fmt = getattr(job, 'conversion_of_same_fmt', False) + manually_fine_tune_toc = getattr(job, 'manually_fine_tune_toc', False) fmtf = temp_files[-1].name if os.stat(fmtf).st_size < 1: raise Exception(_('Empty output file, ' @@ -248,4 +250,7 @@ class ConvertAction(InterfaceAction): current = self.gui.library_view.currentIndex() if current.isValid(): self.gui.library_view.model().current_changed(current, QModelIndex()) + if manually_fine_tune_toc: + self.gui.iactions['Edit ToC'].do_one(book_id, fmt.upper()) + diff --git a/src/calibre/gui2/convert/bulk.py b/src/calibre/gui2/convert/bulk.py index 213f23ced2..b1c3de122b 100644 --- a/src/calibre/gui2/convert/bulk.py +++ b/src/calibre/gui2/convert/bulk.py @@ -88,6 +88,7 @@ class BulkConfig(Config): ps = widget_factory(PageSetupWidget) sd = widget_factory(StructureDetectionWidget) toc = widget_factory(TOCWidget) + toc.manually_fine_tune_toc.hide() output_widget = self.plumber.output_plugin.gui_configuration_widget( self.stack, self.plumber.get_option_by_name, diff --git a/src/calibre/gui2/convert/single.py b/src/calibre/gui2/convert/single.py index cff7ee8c3d..469091162b 100644 --- a/src/calibre/gui2/convert/single.py +++ b/src/calibre/gui2/convert/single.py @@ -165,6 +165,12 @@ class Config(ResizableDialog, Ui_Dialog): def output_format(self): return unicode(self.output_formats.currentText()).lower() + @property + def manually_fine_tune_toc(self): + for i in xrange(self.stack.count()): + w = self.stack.widget(i) + if hasattr(w, 'manually_fine_tune_toc'): + return w.manually_fine_tune_toc.isChecked() def setup_pipeline(self, *args): oidx = self.groups.currentIndex().row() @@ -191,6 +197,8 @@ class Config(ResizableDialog, Ui_Dialog): ps = widget_factory(PageSetupWidget) sd = widget_factory(StructureDetectionWidget) toc = widget_factory(TOCWidget) + from calibre.gui2.actions.toc_edit import SUPPORTED + toc.manually_fine_tune_toc.setVisible(output_format.upper() in SUPPORTED) debug = widget_factory(DebugWidget) output_widget = self.plumber.output_plugin.gui_configuration_widget( diff --git a/src/calibre/gui2/convert/toc.ui b/src/calibre/gui2/convert/toc.ui index da15551f80..6140816804 100644 --- a/src/calibre/gui2/convert/toc.ui +++ b/src/calibre/gui2/convert/toc.ui @@ -6,22 +6,32 @@ 0 0 - 436 - 382 + 596 + 493 Form + + + + + + &Force use of auto-generated Table of Contents + + + + Do not add &detected chapters to the Table of Contents - + Number of &links to add to Table of Contents @@ -31,34 +41,7 @@ - - - - 10000 - - - - - - - Chapter &threshold - - - opt_toc_threshold - - - - - - - - - - &Force use of auto-generated Table of Contents - - - - + TOC &Filter: @@ -68,19 +51,27 @@ - - - - - - - - - - + - + + + + 10000 + + + + + + + Chapter &threshold + + + opt_toc_threshold + + + + Qt::Vertical @@ -93,13 +84,47 @@ - + Allow &duplicate links when creating the Table of Contents + + + + + + + + + + + + + <a href="http://manual.calibre-ebook.com/conversion.html#table-of-contents">Help with using these options to generate a Table of Contents</a> + + + true + + + true + + + + + + + This option will cause calibre to popup the Table of Contents Editor tool, + which will allow you to manually edit the Table of Contents, to fix any errors + caused by automatic generation. + + + &Manually fine-tune the ToC after conversion is completed + + + diff --git a/src/calibre/gui2/preferences/conversion.py b/src/calibre/gui2/preferences/conversion.py index a15ee0a750..6c9e1f8f5b 100644 --- a/src/calibre/gui2/preferences/conversion.py +++ b/src/calibre/gui2/preferences/conversion.py @@ -61,6 +61,8 @@ class Base(ConfigWidgetBase, Ui_Form): for w in widgets: w.changed_signal.connect(self.changed_signal) self.stack.addWidget(w) + if isinstance(w, TOCWidget): + w.manually_fine_tune_toc.hide() self.list.currentChanged = self.category_current_changed self.list.setCurrentIndex(self.model.index(0)) diff --git a/src/calibre/gui2/tools.py b/src/calibre/gui2/tools.py index 98a59ccdd5..eda60a4fec 100644 --- a/src/calibre/gui2/tools.py +++ b/src/calibre/gui2/tools.py @@ -82,8 +82,13 @@ def convert_single_ebook(parent, db, book_ids, auto_conversion=False, # {{{ args = [in_file.name, out_file.name, recs] temp_files.append(out_file) func = 'gui_convert_override' + parts = [] + if not auto_conversion and d.manually_fine_tune_toc: + parts.append('manually_fine_tune_toc') if same_fmt: - func += ':same_fmt' + parts.append('same_fmt') + if parts: + func += ':%s'%(';'.join(parts)) jobs.append((func, args, desc, d.output_format.upper(), book_id, temp_files)) changed = True