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.

This commit is contained in:
Kovid Goyal 2013-03-24 13:43:16 +05:30
parent 4bc20eb4f4
commit 8535e21694
7 changed files with 106 additions and 48 deletions

View File

@ -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 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. 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 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 you can have |app| override any Table of Contents found in the metadata of the input document with the
auto generated one. auto generated one.
@ -456,7 +468,7 @@ For example, to remove all entries titles "Next" or "Previous" use::
Next|Previous 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 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 :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 how to construct XPath expressions. Next to each option is a button that launches a wizard to help with the creation

View File

@ -167,8 +167,8 @@ class ConvertAction(InterfaceAction):
def queue_convert_jobs(self, jobs, changed, bad, rows, previous, def queue_convert_jobs(self, jobs, changed, bad, rows, previous,
converted_func, extra_job_args=[], rows_are_ids=False): converted_func, extra_job_args=[], rows_are_ids=False):
for func, args, desc, fmt, id, temp_files in jobs: for func, args, desc, fmt, id, temp_files in jobs:
func, _, same_fmt = func.partition(':') func, _, parts = func.partition(':')
same_fmt = same_fmt == 'same_fmt' parts = {x for x in parts.split(';')}
input_file = args[0] input_file = args[0]
input_fmt = os.path.splitext(input_file)[1] input_fmt = os.path.splitext(input_file)[1]
core_usage = 1 core_usage = 1
@ -182,7 +182,8 @@ class ConvertAction(InterfaceAction):
job = self.gui.job_manager.run_job(Dispatcher(converted_func), job = self.gui.job_manager.run_job(Dispatcher(converted_func),
func, args=args, description=desc, func, args=args, description=desc,
core_usage=core_usage) 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 args = [temp_files, fmt, id]+extra_job_args
self.conversion_jobs[job] = tuple(args) self.conversion_jobs[job] = tuple(args)
@ -223,6 +224,7 @@ class ConvertAction(InterfaceAction):
self.gui.job_exception(job) self.gui.job_exception(job)
return return
same_fmt = getattr(job, 'conversion_of_same_fmt', False) 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 fmtf = temp_files[-1].name
if os.stat(fmtf).st_size < 1: if os.stat(fmtf).st_size < 1:
raise Exception(_('Empty output file, ' raise Exception(_('Empty output file, '
@ -248,4 +250,7 @@ class ConvertAction(InterfaceAction):
current = self.gui.library_view.currentIndex() current = self.gui.library_view.currentIndex()
if current.isValid(): if current.isValid():
self.gui.library_view.model().current_changed(current, QModelIndex()) 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())

View File

@ -88,6 +88,7 @@ class BulkConfig(Config):
ps = widget_factory(PageSetupWidget) ps = widget_factory(PageSetupWidget)
sd = widget_factory(StructureDetectionWidget) sd = widget_factory(StructureDetectionWidget)
toc = widget_factory(TOCWidget) toc = widget_factory(TOCWidget)
toc.manually_fine_tune_toc.hide()
output_widget = self.plumber.output_plugin.gui_configuration_widget( output_widget = self.plumber.output_plugin.gui_configuration_widget(
self.stack, self.plumber.get_option_by_name, self.stack, self.plumber.get_option_by_name,

View File

@ -165,6 +165,12 @@ class Config(ResizableDialog, Ui_Dialog):
def output_format(self): def output_format(self):
return unicode(self.output_formats.currentText()).lower() 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): def setup_pipeline(self, *args):
oidx = self.groups.currentIndex().row() oidx = self.groups.currentIndex().row()
@ -191,6 +197,8 @@ class Config(ResizableDialog, Ui_Dialog):
ps = widget_factory(PageSetupWidget) ps = widget_factory(PageSetupWidget)
sd = widget_factory(StructureDetectionWidget) sd = widget_factory(StructureDetectionWidget)
toc = widget_factory(TOCWidget) 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) debug = widget_factory(DebugWidget)
output_widget = self.plumber.output_plugin.gui_configuration_widget( output_widget = self.plumber.output_plugin.gui_configuration_widget(

View File

@ -6,22 +6,32 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>436</width> <width>596</width>
<height>382</height> <height>493</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="7" column="1">
<widget class="QSpinBox" name="opt_toc_threshold"/>
</item>
<item row="1" column="0" colspan="2"> <item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="opt_use_auto_toc">
<property name="text">
<string>&amp;Force use of auto-generated Table of Contents</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="opt_no_chapters_in_toc"> <widget class="QCheckBox" name="opt_no_chapters_in_toc">
<property name="text"> <property name="text">
<string>Do not add &amp;detected chapters to the Table of Contents</string> <string>Do not add &amp;detected chapters to the Table of Contents</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="6" column="0">
<widget class="QLabel" name="label_10"> <widget class="QLabel" name="label_10">
<property name="text"> <property name="text">
<string>Number of &amp;links to add to Table of Contents</string> <string>Number of &amp;links to add to Table of Contents</string>
@ -31,34 +41,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="8" column="0">
<widget class="QSpinBox" name="opt_max_toc_links">
<property name="maximum">
<number>10000</number>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Chapter &amp;threshold</string>
</property>
<property name="buddy">
<cstring>opt_toc_threshold</cstring>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="opt_toc_threshold"/>
</item>
<item row="0" column="0" colspan="2">
<widget class="QCheckBox" name="opt_use_auto_toc">
<property name="text">
<string>&amp;Force use of auto-generated Table of Contents</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>TOC &amp;Filter:</string> <string>TOC &amp;Filter:</string>
@ -68,19 +51,27 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="1"> <item row="11" column="0" colspan="2">
<widget class="QLineEdit" name="opt_toc_filter"/>
</item>
<item row="6" column="0" colspan="2">
<widget class="XPathEdit" name="opt_level1_toc" native="true"/>
</item>
<item row="7" column="0" colspan="2">
<widget class="XPathEdit" name="opt_level2_toc" native="true"/>
</item>
<item row="8" column="0" colspan="2">
<widget class="XPathEdit" name="opt_level3_toc" native="true"/> <widget class="XPathEdit" name="opt_level3_toc" native="true"/>
</item> </item>
<item row="9" column="0"> <item row="6" column="1">
<widget class="QSpinBox" name="opt_max_toc_links">
<property name="maximum">
<number>10000</number>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Chapter &amp;threshold</string>
</property>
<property name="buddy">
<cstring>opt_toc_threshold</cstring>
</property>
</widget>
</item>
<item row="13" column="0">
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
@ -93,13 +84,47 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="2" column="0" colspan="2"> <item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="opt_duplicate_links_in_toc"> <widget class="QCheckBox" name="opt_duplicate_links_in_toc">
<property name="text"> <property name="text">
<string>Allow &amp;duplicate links when creating the Table of Contents</string> <string>Allow &amp;duplicate links when creating the Table of Contents</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="10" column="0" colspan="2">
<widget class="XPathEdit" name="opt_level2_toc" native="true"/>
</item>
<item row="8" column="1">
<widget class="QLineEdit" name="opt_toc_filter"/>
</item>
<item row="9" column="0" colspan="2">
<widget class="XPathEdit" name="opt_level1_toc" native="true"/>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>&lt;a href=&quot;http://manual.calibre-ebook.com/conversion.html#table-of-contents&quot;&gt;Help with using these options to generate a Table of Contents&lt;/a&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="12" column="0" colspan="2">
<widget class="QCheckBox" name="manually_fine_tune_toc">
<property name="toolTip">
<string>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.</string>
</property>
<property name="text">
<string>&amp;Manually fine-tune the ToC after conversion is completed</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<customwidgets> <customwidgets>

View File

@ -61,6 +61,8 @@ class Base(ConfigWidgetBase, Ui_Form):
for w in widgets: for w in widgets:
w.changed_signal.connect(self.changed_signal) w.changed_signal.connect(self.changed_signal)
self.stack.addWidget(w) self.stack.addWidget(w)
if isinstance(w, TOCWidget):
w.manually_fine_tune_toc.hide()
self.list.currentChanged = self.category_current_changed self.list.currentChanged = self.category_current_changed
self.list.setCurrentIndex(self.model.index(0)) self.list.setCurrentIndex(self.model.index(0))

View File

@ -82,8 +82,13 @@ def convert_single_ebook(parent, db, book_ids, auto_conversion=False, # {{{
args = [in_file.name, out_file.name, recs] args = [in_file.name, out_file.name, recs]
temp_files.append(out_file) temp_files.append(out_file)
func = 'gui_convert_override' func = 'gui_convert_override'
parts = []
if not auto_conversion and d.manually_fine_tune_toc:
parts.append('manually_fine_tune_toc')
if same_fmt: 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)) jobs.append((func, args, desc, d.output_format.upper(), book_id, temp_files))
changed = True changed = True