mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 18:54:09 -04:00
Edit book: Table of Contents tool: Allow using the title attribute on headings tags to get the text for table of contents entries
This commit is contained in:
parent
a46806c6a2
commit
db75fe003f
@ -362,8 +362,10 @@ def ensure_id(elem, all_ids):
|
|||||||
return True, elem.get('id')
|
return True, elem.get('id')
|
||||||
|
|
||||||
|
|
||||||
def elem_to_toc_text(elem):
|
def elem_to_toc_text(elem, prefer_title=False):
|
||||||
text = xml2text(elem).strip()
|
text = xml2text(elem).strip()
|
||||||
|
if prefer_title:
|
||||||
|
text = elem.get('title', '').strip() or text
|
||||||
if not text:
|
if not text:
|
||||||
text = elem.get('title', '')
|
text = elem.get('title', '')
|
||||||
if not text:
|
if not text:
|
||||||
@ -398,7 +400,7 @@ def item_at_top(elem):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def from_xpaths(container, xpaths):
|
def from_xpaths(container, xpaths, prefer_title=False):
|
||||||
'''
|
'''
|
||||||
Generate a Table of Contents from a list of XPath expressions. Each
|
Generate a Table of Contents from a list of XPath expressions. Each
|
||||||
expression in the list corresponds to a level of the generate ToC. For
|
expression in the list corresponds to a level of the generate ToC. For
|
||||||
@ -450,7 +452,7 @@ def from_xpaths(container, xpaths):
|
|||||||
lvl = item_level_map.get(item, None)
|
lvl = item_level_map.get(item, None)
|
||||||
if lvl is None:
|
if lvl is None:
|
||||||
continue
|
continue
|
||||||
text = elem_to_toc_text(item)
|
text = elem_to_toc_text(item, prefer_title)
|
||||||
parent = parent_for_level(lvl)
|
parent = parent_for_level(lvl)
|
||||||
if item_at_top(item):
|
if item_at_top(item):
|
||||||
dirtied, elem_id = False, None
|
dirtied, elem_id = False, None
|
||||||
|
@ -23,7 +23,7 @@ from calibre.ebooks.oeb.polish.toc import (
|
|||||||
TOC, add_id, commit_toc, from_files, from_links, from_xpaths, get_toc
|
TOC, add_id, commit_toc, from_files, from_links, from_xpaths, get_toc
|
||||||
)
|
)
|
||||||
from calibre.gui2 import (
|
from calibre.gui2 import (
|
||||||
Application, error_dialog, info_dialog, question_dialog, set_app_uid
|
Application, error_dialog, info_dialog, set_app_uid
|
||||||
)
|
)
|
||||||
from calibre.gui2.convert.xpath_wizard import XPathEdit
|
from calibre.gui2.convert.xpath_wizard import XPathEdit
|
||||||
from calibre.gui2.progress_indicator import ProgressIndicator
|
from calibre.gui2.progress_indicator import ProgressIndicator
|
||||||
@ -140,7 +140,7 @@ class ItemView(QStackedWidget): # {{{
|
|||||||
delete_item = pyqtSignal()
|
delete_item = pyqtSignal()
|
||||||
flatten_item = pyqtSignal()
|
flatten_item = pyqtSignal()
|
||||||
go_to_root = pyqtSignal()
|
go_to_root = pyqtSignal()
|
||||||
create_from_xpath = pyqtSignal(object, object)
|
create_from_xpath = pyqtSignal(object, object, object)
|
||||||
create_from_links = pyqtSignal()
|
create_from_links = pyqtSignal()
|
||||||
create_from_files = pyqtSignal()
|
create_from_files = pyqtSignal()
|
||||||
flatten_toc = pyqtSignal()
|
flatten_toc = pyqtSignal()
|
||||||
@ -314,23 +314,42 @@ class ItemView(QStackedWidget): # {{{
|
|||||||
self.w2.setWordWrap(True)
|
self.w2.setWordWrap(True)
|
||||||
l.addWidget(la, l.rowCount(), 0, 1, 2)
|
l.addWidget(la, l.rowCount(), 0, 1, 2)
|
||||||
|
|
||||||
def ask_if_duplicates_should_be_removed(self):
|
def headings_question(self, xpaths):
|
||||||
return not question_dialog(self, _('Remove duplicates'), _(
|
from calibre.gui2.widgets2 import Dialog
|
||||||
'Should headings with the same text at the same level be included?'),
|
|
||||||
yes_text=_('&Include duplicates'), no_text=_('&Remove duplicates'))
|
class D(Dialog):
|
||||||
|
def __init__(self, parent):
|
||||||
|
super().__init__(_('Configure ToC generation'), 'configure-toc-from-headings', parent=parent)
|
||||||
|
|
||||||
|
def setup_ui(s):
|
||||||
|
s.l = l = QVBoxLayout(s)
|
||||||
|
s.remove_duplicates_cb = rd = QCheckBox(_('Remove &duplicated headings at the same ToC level'))
|
||||||
|
l.addWidget(rd)
|
||||||
|
rd.setChecked(bool(self.prefs.get('toc_from_headings_remove_duplicates', True)))
|
||||||
|
s.prefer_title_cb = pt = QCheckBox(_('Use the &title attribute for ToC text'))
|
||||||
|
l.addWidget(pt)
|
||||||
|
pt.setToolTip(textwrap.fill(_(
|
||||||
|
'When a heading tag has the "title" attribute use its contents as the text for the ToC entry,'
|
||||||
|
' instead of the the text inside the heading tag itself.')))
|
||||||
|
pt.setChecked(bool(self.prefs.get('toc_from_headings_prefer_title')))
|
||||||
|
l.addWidget(s.bb)
|
||||||
|
|
||||||
|
d = D(self)
|
||||||
|
if d.exec_() == QDialog.DialogCode.Accepted:
|
||||||
|
self.create_from_xpath.emit(xpaths, d.remove_duplicates_cb.isChecked(), d.prefer_title_cb.isChecked())
|
||||||
|
self.prefs.set('toc_from_headings_remove_duplicates', d.remove_duplicates_cb.isChecked())
|
||||||
|
self.prefs.set('toc_from_headings_prefer_title', d.prefer_title_cb.isChecked())
|
||||||
|
|
||||||
def create_from_major_headings(self):
|
def create_from_major_headings(self):
|
||||||
self.create_from_xpath.emit(['//h:h%d'%i for i in range(1, 4)],
|
self.headings_question(['//h:h%d'%i for i in range(1, 4)])
|
||||||
self.ask_if_duplicates_should_be_removed())
|
|
||||||
|
|
||||||
def create_from_all_headings(self):
|
def create_from_all_headings(self):
|
||||||
self.create_from_xpath.emit(['//h:h%d'%i for i in range(1, 7)],
|
self.headings_question(['//h:h%d'%i for i in range(1, 7)])
|
||||||
self.ask_if_duplicates_should_be_removed())
|
|
||||||
|
|
||||||
def create_from_user_xpath(self):
|
def create_from_user_xpath(self):
|
||||||
d = XPathDialog(self, self.prefs)
|
d = XPathDialog(self, self.prefs)
|
||||||
if d.exec() == QDialog.DialogCode.Accepted and d.xpaths:
|
if d.exec() == QDialog.DialogCode.Accepted and d.xpaths:
|
||||||
self.create_from_xpath.emit(d.xpaths, d.remove_duplicates_cb.isChecked())
|
self.create_from_xpath.emit(d.xpaths, d.remove_duplicates_cb.isChecked(), False)
|
||||||
|
|
||||||
def hide_azw3_warning(self):
|
def hide_azw3_warning(self):
|
||||||
self.w1.setVisible(False), self.w2.setVisible(False)
|
self.w1.setVisible(False), self.w2.setVisible(False)
|
||||||
@ -945,8 +964,8 @@ class TOCView(QWidget): # {{{
|
|||||||
process_node(self.root, toc, nodes)
|
process_node(self.root, toc, nodes)
|
||||||
self.highlight_item(nodes[0])
|
self.highlight_item(nodes[0])
|
||||||
|
|
||||||
def create_from_xpath(self, xpaths, remove_duplicates=True):
|
def create_from_xpath(self, xpaths, remove_duplicates=True, prefer_title=False):
|
||||||
toc = from_xpaths(self.ebook, xpaths)
|
toc = from_xpaths(self.ebook, xpaths, prefer_title=prefer_title)
|
||||||
if len(toc) == 0:
|
if len(toc) == 0:
|
||||||
return error_dialog(self, _('No items found'),
|
return error_dialog(self, _('No items found'),
|
||||||
_('No items were found that could be added to the Table of Contents.'), show=True)
|
_('No items were found that could be added to the Table of Contents.'), show=True)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user