TOC settings: add bind chapter navigation/titles to ticks

Add 2 convenience settings, allowing ToC ignored depths
settings to apply further than just the progress bars.
pull/7322/head
poire-z 3 years ago
parent d63d282806
commit 0f7722d4a6

@ -22,6 +22,7 @@ local ReaderToc = InputContainer:new{
toc_depth = nil,
ticks = nil,
ticks_flattened = nil,
ticks_flattened_filtered = nil,
toc_indent = " ",
collapsed_toc = {},
collapse_depth = 2,
@ -60,10 +61,14 @@ end
function ReaderToc:onReadSettings(config)
self.toc_ticks_ignored_levels = config:readSetting("toc_ticks_ignored_levels") or {}
self.toc_chapter_navigation_bind_to_ticks = config:readSetting("toc_chapter_navigation_bind_to_ticks")
self.toc_chapter_title_bind_to_ticks = config:readSetting("toc_chapter_title_bind_to_ticks")
end
function ReaderToc:onSaveSettings()
self.ui.doc_settings:saveSetting("toc_ticks_ignored_levels", self.toc_ticks_ignored_levels)
self.ui.doc_settings:saveSetting("toc_chapter_navigation_bind_to_ticks", self.toc_chapter_navigation_bind_to_ticks)
self.ui.doc_settings:saveSetting("toc_chapter_title_bind_to_ticks", self.toc_chapter_title_bind_to_ticks)
end
function ReaderToc:cleanUpTocTitle(title, replace_empty)
@ -83,6 +88,7 @@ function ReaderToc:resetToc()
self.toc_depth = nil
self.ticks = nil
self.ticks_flattened = nil
self.ticks_flattened_filtered = nil
self.collapsed_toc = {}
self.collapse_depth = 2
self.expanded_nodes = {}
@ -258,54 +264,62 @@ function ReaderToc:validateAndFixToc()
logger.info(string.format("TOC had %d bogus page numbers: fixed %d items to keep them ordered.", nb_bogus, nb_fixed_pages))
end
function ReaderToc:getTocIndexByPage(pn_or_xp)
function ReaderToc:getTocIndexByPage(pn_or_xp, skip_ignored_ticks)
self:fillToc()
if #self.toc == 0 then return end
local pageno = pn_or_xp
if type(pn_or_xp) == "string" then
return self:getAccurateTocIndexByXPointer(pn_or_xp)
return self:getAccurateTocIndexByXPointer(pn_or_xp, skip_ignored_ticks)
end
local pre_index = 1
local prev_index = 1
for _k,_v in ipairs(self.toc) do
if _v.page == pageno then
-- Return the first chapter seen on the current page
pre_index = _k
break
end
if _v.page > pageno then
-- Return last chapter seen on a previous page
break
if not skip_ignored_ticks or not self.toc_ticks_ignored_levels[_v.depth] then
if _v.page == pageno then
-- Return the first chapter seen on the current page
prev_index = _k
break
end
if _v.page > pageno then
-- Return last chapter seen on a previous page
break
end
prev_index = _k
end
pre_index = _k
end
return pre_index
return prev_index
end
function ReaderToc:getAccurateTocIndexByXPointer(xptr)
function ReaderToc:getAccurateTocIndexByXPointer(xptr, skip_ignored_ticks)
local pageno = self.ui.document:getPageFromXPointer(xptr)
-- get toc entry(index) on for the current page
-- we don't get infinite loop, because the this call is not
-- with xpointer, but with page
local index = self:getTocIndexByPage(pageno)
local index = self:getTocIndexByPage(pageno, skip_ignored_ticks)
if not index or not self.toc[index] then return end
local initial_comparison = self.ui.document:compareXPointers(self.toc[index].xpointer, xptr)
if initial_comparison and initial_comparison < 0 then
local i = index - 1
while self.toc[i] do
local toc_xptr = self.toc[i].xpointer
local cmp = self.ui.document:compareXPointers(toc_xptr, xptr)
if cmp and cmp >= 0 then -- toc_xptr is before xptr(xptr >= toc_xptr)
return i
if not skip_ignored_ticks or not self.toc_ticks_ignored_levels[self.toc[i].depth] then
local toc_xptr = self.toc[i].xpointer
local cmp = self.ui.document:compareXPointers(toc_xptr, xptr)
if cmp and cmp >= 0 then -- toc_xptr is before xptr(xptr >= toc_xptr)
return i
end
end
i = i - 1
end
else
local prev_index = index
local i = index + 1
while self.toc[i] do
local toc_xptr = self.toc[i].xpointer
local cmp = self.ui.document:compareXPointers(toc_xptr, xptr)
if cmp and cmp < 0 then -- toc_xptr is after xptr(xptr < toc_xptr)
return i - 1
if not skip_ignored_ticks or not self.toc_ticks_ignored_levels[self.toc[i].depth] then
local toc_xptr = self.toc[i].xpointer
local cmp = self.ui.document:compareXPointers(toc_xptr, xptr)
if cmp and cmp < 0 then -- toc_xptr is after xptr(xptr < toc_xptr)
return prev_index
end
prev_index = i
end
i = i + 1
end
@ -314,7 +328,7 @@ function ReaderToc:getAccurateTocIndexByXPointer(xptr)
end
function ReaderToc:getTocTitleByPage(pn_or_xp)
local index = self:getTocIndexByPage(pn_or_xp)
local index = self:getTocIndexByPage(pn_or_xp, self.toc_chapter_title_bind_to_ticks)
if index then
return self:cleanUpTocTitle(self.toc[index].title)
else
@ -395,8 +409,25 @@ end
--[[
Returns a flattened list of ToC ticks, without duplicates
]]
function ReaderToc:getTocTicksFlattened()
if self.ticks_flattened then return self.ticks_flattened end
function ReaderToc:getTocTicksFlattened(for_chapter_navigation)
local wants_filtered_ticks = true
if not next(self.toc_ticks_ignored_levels) then
-- No ignored level: no need to keep an additional list of filtered ticks
wants_filtered_ticks = false
elseif for_chapter_navigation then
if not self.toc_chapter_navigation_bind_to_ticks then
wants_filtered_ticks = false
end
end
if wants_filtered_ticks then
if self.ticks_flattened_filtered then
return self.ticks_flattened_filtered
end
else
if self.ticks_flattened then
return self.ticks_flattened
end
end
-- It hasn't been cached yet, compute it.
local ticks = self:getTocTicks()
@ -405,7 +436,7 @@ function ReaderToc:getTocTicksFlattened()
-- Keep track of what we add to avoid duplicates (c.f., https://stackoverflow.com/a/20067270)
local hash = {}
for depth, v in ipairs(ticks) do
if not self.toc_ticks_ignored_levels[depth] then
if not wants_filtered_ticks or not self.toc_ticks_ignored_levels[depth] then
for _, page in ipairs(v) do
if not hash[page] then
table.insert(ticks_flattened, page)
@ -418,12 +449,17 @@ function ReaderToc:getTocTicksFlattened()
-- And finally, sort it again
table.sort(ticks_flattened)
self.ticks_flattened = ticks_flattened
return self.ticks_flattened
-- Store it in the relevant slot
if wants_filtered_ticks then
self.ticks_flattened_filtered = ticks_flattened
else
self.ticks_flattened = ticks_flattened
end
return ticks_flattened
end
function ReaderToc:getNextChapter(cur_pageno)
local ticks = self:getTocTicksFlattened()
local ticks = self:getTocTicksFlattened(true)
local next_chapter = nil
for _, page in ipairs(ticks) do
if page > cur_pageno then
@ -435,7 +471,7 @@ function ReaderToc:getNextChapter(cur_pageno)
end
function ReaderToc:getPreviousChapter(cur_pageno)
local ticks = self:getTocTicksFlattened()
local ticks = self:getTocTicksFlattened(true)
local previous_chapter = nil
for _, page in ipairs(ticks) do
if page >= cur_pageno then
@ -447,7 +483,7 @@ function ReaderToc:getPreviousChapter(cur_pageno)
end
function ReaderToc:isChapterStart(cur_pageno)
local ticks = self:getTocTicksFlattened()
local ticks = self:getTocTicksFlattened(true)
local _start = false
for _, page in ipairs(ticks) do
if page == cur_pageno then
@ -459,7 +495,7 @@ function ReaderToc:isChapterStart(cur_pageno)
end
function ReaderToc:isChapterSecondPage(cur_pageno)
local ticks = self:getTocTicksFlattened()
local ticks = self:getTocTicksFlattened(true)
local _second = false
for _, page in ipairs(ticks) do
if page + 1 == cur_pageno then
@ -471,7 +507,7 @@ function ReaderToc:isChapterSecondPage(cur_pageno)
end
function ReaderToc:isChapterEnd(cur_pageno)
local ticks = self:getTocTicksFlattened()
local ticks = self:getTocTicksFlattened(true)
local _end = false
for _, page in ipairs(ticks) do
if page - 1 == cur_pageno then
@ -880,7 +916,7 @@ See Style tweaks → Miscellaneous → Alternative ToC hints.]]),
return not self.toc_ticks_ignored_levels[level]
end,
callback = function()
self.toc_ticks_ignored_levels[level] = not self.toc_ticks_ignored_levels[level]
self.toc_ticks_ignored_levels[level] = not self.toc_ticks_ignored_levels[level] or nil
self:onUpdateToc()
self.view.footer:onUpdateFooter(self.view.footer_visible)
self.ui:handleEvent(Event:new("UpdateTopStatusBarMarkers"))
@ -915,6 +951,38 @@ See Style tweaks → Miscellaneous → Alternative ToC hints.]]),
break
end
end
toc_ticks_levels[#toc_ticks_levels].separator = true
table.insert(toc_ticks_levels, {
text = _("Bind chapter navigation to ticks"),
help_text = _([[Entries from ToC levels that are ignored in the progress bars will still be used for chapter navigation and 'page/time left until next chapter' in the footer.
Enabling this option will restrict chapter nativation to progress bar ticks.]]),
enabled_func = function()
return next(self.toc_ticks_ignored_levels) ~= nil
end,
checked_func = function()
return self.toc_chapter_navigation_bind_to_ticks
end,
callback = function()
self.toc_chapter_navigation_bind_to_ticks = not self.toc_chapter_navigation_bind_to_ticks
self:onUpdateToc()
self.view.footer:onUpdateFooter(self.view.footer_visible)
end,
})
table.insert(toc_ticks_levels, {
text = _("Chapter titles from ticks only"),
help_text = _([[Entries from ToC levels that are ignored in the progress bars will still be used for displaying the title of the current chapter in the footer and in bookmarks.
Enabling this option will restrict display to the chapter titles of progress bar ticks.]]),
enabled_func = function()
return next(self.toc_ticks_ignored_levels) ~= nil
end,
checked_func = function()
return self.toc_chapter_title_bind_to_ticks
end,
callback = function()
self.toc_chapter_title_bind_to_ticks = not self.toc_chapter_title_bind_to_ticks
self.view.footer:onUpdateFooter(self.view.footer_visible)
end,
})
return toc_ticks_levels
end,
}

Loading…
Cancel
Save