Reference pages: improve Toc and status bar (#14363)

This commit is contained in:
hius07
2025-09-29 18:32:23 +03:00
committed by GitHub
parent 9decbeb701
commit 355e2ba615
3 changed files with 136 additions and 21 deletions

View File

@@ -103,6 +103,15 @@ end
function ReaderGoto:gotoPage() function ReaderGoto:gotoPage()
local page_number = self.goto_dialog:getInputText() local page_number = self.goto_dialog:getInputText()
if self.ui.pagemap and self.ui.pagemap:wantsPageLabels() then
local label = self.ui.pagemap:cleanPageLabel(page_number)
local _, pn = self.ui.pagemap:getPageLabelProps(label)
if pn then
self:close()
self.ui:handleEvent(Event:new("GotoPage", pn))
end
return
end
local relative_sign = page_number:sub(1, 1) local relative_sign = page_number:sub(1, 1)
local number = tonumber(page_number) local number = tonumber(page_number)
if number then if number then
@@ -110,16 +119,7 @@ function ReaderGoto:gotoPage()
if relative_sign == "+" or relative_sign == "-" then if relative_sign == "+" or relative_sign == "-" then
self.ui:handleEvent(Event:new("GotoRelativePage", number)) self.ui:handleEvent(Event:new("GotoRelativePage", number))
else else
if self.ui.pagemap and self.ui.pagemap:wantsPageLabels() then self.ui:handleEvent(Event:new("GotoPage", number))
number = self.ui.pagemap:getRenderedPageNumber(page_number, true)
if number then -- found
self.ui:handleEvent(Event:new("GotoPage", number))
else
return -- avoid self:close()
end
else
self.ui:handleEvent(Event:new("GotoPage", number))
end
end end
self:close() self:close()
elseif self.ui.document:hasHiddenFlows() then elseif self.ui.document:hasHiddenFlows() then

View File

@@ -24,6 +24,7 @@ local ReaderPageMap = WidgetContainer:extend{
label_color = Blitbuffer.COLOR_BLACK, label_color = Blitbuffer.COLOR_BLACK,
show_page_labels = nil, show_page_labels = nil,
use_page_labels = nil, use_page_labels = nil,
page_labels_cache = nil, -- hash table
} }
function ReaderPageMap:init() function ReaderPageMap:init()
@@ -302,17 +303,28 @@ function ReaderPageMap:getXPointerPageLabel(xp, clean_label)
return clean_label and self:cleanPageLabel(label) or label return clean_label and self:cleanPageLabel(label) or label
end end
function ReaderPageMap:getRenderedPageNumber(page_label, cleaned) function ReaderPageMap:getPageLabelProps(page_label)
-- Only used from ReaderGoTo. As page_label is a string, no if self.page_labels_cache == nil then -- fill the cache
-- way to use a binary search: do a full scan of the PageMap local page_list = self.ui.document:getPageMap()
-- here in Lua, even if it's not cheap. self.page_labels_cache = { #page_list }
local page_list = self.ui.document:getPageMap() for i, v in ipairs(page_list) do
for k, v in ipairs(page_list) do local label = self:cleanPageLabel(v.label)
local label = cleaned and self:cleanPageLabel(v.label) or v.label self.page_labels_cache[label] = { i, v.page }
if label == page_label then
return v.page
end end
end end
-- expects cleaned page_label
if page_label then
local props = self.page_labels_cache[page_label]
if props then
return props[1], props[2] -- index, rendered page
end
else
return self.page_labels_cache[1] -- total number of labels
end
end
function ReaderPageMap:onDocumentRerendered()
self.page_labels_cache = nil
end end
function ReaderPageMap:addToMainMenu(menu_items) function ReaderPageMap:addToMainMenu(menu_items)
@@ -345,6 +357,9 @@ function ReaderPageMap:addToMainMenu(menu_items)
text = _("Use reference page numbers"), text = _("Use reference page numbers"),
checked_func = function() return self.use_page_labels end, checked_func = function() return self.use_page_labels end,
callback = function() callback = function()
if self.use_page_labels then
self.page_labels_cache = nil
end
self.use_page_labels = not self.use_page_labels self.use_page_labels = not self.use_page_labels
self.ui.doc_settings:saveSetting("pagemap_use_page_labels", self.use_page_labels) self.ui.doc_settings:saveSetting("pagemap_use_page_labels", self.use_page_labels)
-- Reset a few stuff that may use page labels -- Reset a few stuff that may use page labels

View File

@@ -341,7 +341,7 @@ function ReaderToc:completeTocWithChapterLengths()
prev_item_by_level[depth] = item prev_item_by_level[depth] = item
end end
-- Set the length of the last ones -- Set the length of the last ones
local page = self.ui.document:getPageCount() local page = self.ui.document:getPageCount() + 1
for j=#prev_item_by_level, 0, -1 do for j=#prev_item_by_level, 0, -1 do
local prev_item = prev_item_by_level[j] local prev_item = prev_item_by_level[j]
if prev_item then if prev_item then
@@ -350,6 +350,40 @@ function ReaderToc:completeTocWithChapterLengths()
end end
end end
function ReaderToc:completeTocWithChapterLengthsFromPagemap()
local toc = self.toc
local first = 1
local last = #toc
if last == 0 then
return
end
local prev_item_by_level = {}
for i = first, last do
local item = toc[i]
local page, chapter_starts_new_ref_page = self:getPagePagemapIndex(item.page)
local extra_page = chapter_starts_new_ref_page and 0 or 1
local depth = item.depth
for j=#prev_item_by_level, depth, -1 do
local prev_item = prev_item_by_level[j]
if prev_item then
local prev_page = self:getPagePagemapIndex(prev_item.page)
prev_item.chapter_length = page and prev_page and (page - prev_page + extra_page) or "\u{2013}"
end
prev_item_by_level[j] = nil
end
prev_item_by_level[depth] = item
end
-- Set the length of the last ones
local page = self.ui.pagemap:getPageLabelProps() -- last label index
for j=#prev_item_by_level, 0, -1 do
local prev_item = prev_item_by_level[j]
if prev_item then
local prev_page = self:getPagePagemapIndex(prev_item.page)
prev_item.chapter_length = page and prev_page and (page - prev_page + 1) or "\u{2013}"
end
end
end
function ReaderToc:getTocIndexByPage(pn_or_xp, skip_ignored_ticks) function ReaderToc:getTocIndexByPage(pn_or_xp, skip_ignored_ticks)
self:fillToc() self:fillToc()
if #self.toc == 0 then return end if #self.toc == 0 then return end
@@ -625,7 +659,48 @@ function ReaderToc:isChapterEnd(cur_pageno)
return _end return _end
end end
function ReaderToc:getPagePagemapIndex(pageno)
-- for chapters, pageno is a rendered page number where the chapter title is displayed
if pageno then
local xp = self.ui.document:getPageXPointer(pageno)
if xp then
-- reference page (label) of the top of the displayed page
-- (the label itself may be displayed in one of the previous pages)
local label = self.ui.pagemap:getXPointerPageLabel(xp, true)
-- label_pn - rendered page number where the label is displayed
local index, label_pn = self.ui.pagemap:getPageLabelProps(label)
if index then
return index, label_pn == pageno -- true if chapter starts at new ref page
end
end
end
end
function ReaderToc:getPreviousChapterPagemapIndex(pageno)
local chapter_pn = self:isChapterStart(pageno) and pageno or self:getPreviousChapter(pageno)
return self:getPagePagemapIndex(chapter_pn) or 1
end
function ReaderToc:getNextChapterPagemapIndex(pageno)
local chapter_pn = self:getNextChapter(pageno)
if chapter_pn then
return self:getPagePagemapIndex(chapter_pn) -- chapter_idx, chapter_starts_new_ref_page
else -- last chapter
return self.ui.pagemap:getPageLabelProps() -- last index
end
end
function ReaderToc:getChapterPageCount(pageno) function ReaderToc:getChapterPageCount(pageno)
if self.ui.pagemap and self.ui.pagemap:wantsPageLabels() then
local prev_chapter_idx = self:getPreviousChapterPagemapIndex(pageno)
if prev_chapter_idx then
local next_chapter_idx, chapter_starts_new_ref_page = self:getNextChapterPagemapIndex(pageno)
if next_chapter_idx then
return next_chapter_idx - prev_chapter_idx + (chapter_starts_new_ref_page and 0 or 1)
end
end
end
local next_chapter = self:getNextChapter(pageno) or self.ui.document:getPageCount() + 1 local next_chapter = self:getNextChapter(pageno) or self.ui.document:getPageCount() + 1
local previous_chapter = self:isChapterStart(pageno) and pageno or self:getPreviousChapter(pageno) or 1 local previous_chapter = self:isChapterStart(pageno) and pageno or self:getPreviousChapter(pageno) or 1
local page_count = next_chapter - previous_chapter local page_count = next_chapter - previous_chapter
@@ -642,6 +717,16 @@ function ReaderToc:getChapterPageCount(pageno)
end end
function ReaderToc:getChapterPagesLeft(pageno) function ReaderToc:getChapterPagesLeft(pageno)
if self.ui.pagemap and self.ui.pagemap:wantsPageLabels() then
local page_idx = self:getPagePagemapIndex(pageno)
if page_idx then
local next_chapter_idx, chapter_starts_new_ref_page = self:getNextChapterPagemapIndex(pageno)
if next_chapter_idx then
return next_chapter_idx - page_idx - (chapter_starts_new_ref_page and 1 or 0)
end
end
end
local next_chapter = self:getNextChapter(pageno) local next_chapter = self:getNextChapter(pageno)
if not next_chapter then if not next_chapter then
-- (ReaderFooter deals itself with nil and pageno in last chapter) -- (ReaderFooter deals itself with nil and pageno in last chapter)
@@ -660,6 +745,17 @@ end
function ReaderToc:getChapterPagesDone(pageno) function ReaderToc:getChapterPagesDone(pageno)
if self:isChapterStart(pageno) then return 0 end if self:isChapterStart(pageno) then return 0 end
if self.ui.pagemap and self.ui.pagemap:wantsPageLabels() then
local page_idx = self:getPagePagemapIndex(pageno)
if page_idx then
local prev_chapter_idx = self:getPreviousChapterPagemapIndex(pageno)
if prev_chapter_idx then
return page_idx - prev_chapter_idx
end
end
end
local previous_chapter = self:getPreviousChapter(pageno) local previous_chapter = self:getPreviousChapter(pageno)
if not previous_chapter then if not previous_chapter then
-- (ReaderFooter deals itself with nil and pageno not yet in first chapter) -- (ReaderFooter deals itself with nil and pageno not yet in first chapter)
@@ -727,7 +823,11 @@ function ReaderToc:onShowToc()
if #self.toc > 0 and not self.toc_menu_items_built then if #self.toc > 0 and not self.toc_menu_items_built then
self.toc_menu_items_built = true self.toc_menu_items_built = true
if items_show_chapter_length then if items_show_chapter_length then
self:completeTocWithChapterLengths() if self.ui.pagemap and self.ui.pagemap:wantsPageLabels() then
self:completeTocWithChapterLengthsFromPagemap()
else
self:completeTocWithChapterLengths()
end
end end
-- Have the width of 4 spaces be the unit of indentation -- Have the width of 4 spaces be the unit of indentation
local tmp = TextWidget:new{ local tmp = TextWidget:new{