diff --git a/frontend/apps/filemanager/filemanagerbookinfo.lua b/frontend/apps/filemanager/filemanagerbookinfo.lua index 7fb6b009c..565d44f5f 100644 --- a/frontend/apps/filemanager/filemanagerbookinfo.lua +++ b/frontend/apps/filemanager/filemanagerbookinfo.lua @@ -5,6 +5,7 @@ This module provides a way to display book information (filename and book metada local BD = require("ui/bidi") local ButtonDialog = require("ui/widget/buttondialog") local DocSettings = require("docsettings") +local Document = require("document/document") local DocumentRegistry = require("document/documentregistry") local InfoMessage = require("ui/widget/infomessage") local UIManager = require("ui/uimanager") @@ -17,6 +18,15 @@ local _ = require("gettext") local Screen = require("device").screen local BookInfo = WidgetContainer:extend{ + props = { + "title", + "authors", + "series", + "series_index", + "language", + "keywords", + "description", + }, } function BookInfo:init() @@ -34,6 +44,7 @@ function BookInfo:addToMainMenu(menu_items) } end +-- Shows book information. function BookInfo:show(file, book_props, metadata_updated_caller_callback) self.updated = nil local kv_pairs = {} @@ -55,20 +66,20 @@ function BookInfo:show(file, book_props, metadata_updated_caller_callback) -- book_props may be provided if caller already has them available -- but it may lack "pages", that we may get from sidecar file if not book_props or not book_props.pages then - book_props = self:getBookProps(file, book_props) + book_props = BookInfo.getDocProps(nil, file, book_props) end local values_lang - local props = { - { _("Title:"), "title" }, - { _("Authors:"), "authors" }, - { _("Series:"), "series" }, - { _("Pages:"), "pages" }, - { _("Language:"), "language" }, - { _("Keywords:"), "keywords" }, - { _("Description:"), "description" }, + local prop_text = { + title = _("Title:"), + authors = _("Authors:"), + series = _("Series:"), + series_index = _("Series index:"), + pages = _("Pages:"), -- not in document metadata + language = _("Language:"), + keywords = _("Keywords:"), + description = _("Description:"), } - for _i, v in ipairs(props) do - local prop_text, prop_key = unpack(v) + for _i, prop_key in ipairs(self.props) do local prop = book_props[prop_key] if prop == nil or prop == "" then prop = _("N/A") @@ -84,16 +95,6 @@ function BookInfo:show(file, book_props, metadata_updated_caller_callback) else prop = BD.auto(prop) end - elseif prop_key == "series" then - -- If we were fed a BookInfo book_props (e.g., covermenu), series index is in a separate field - if book_props.series_index then - -- Here, we're assured that series_index is a Lua number, so round integers are automatically - -- displayed without decimals - prop = prop .. " #" .. book_props.series_index - else - -- But here, if we have a plain doc_props series with an index, drop empty decimals from round integers. - prop = prop:gsub("(#%d+)%.0+$", "%1") - end elseif prop_key == "language" then -- Get a chance to have title, authors... rendered with alternate -- glyphs for the book language (e.g. japanese book in chinese UI) @@ -102,7 +103,10 @@ function BookInfo:show(file, book_props, metadata_updated_caller_callback) -- Description may (often in EPUB, but not always) or may not (rarely in PDF) be HTML prop = util.htmlToPlainTextIfHtml(prop) end - table.insert(kv_pairs, { prop_text, prop }) + table.insert(kv_pairs, { prop_text[prop_key], prop }) + if prop_key == "series_index" then + table.insert(kv_pairs, { prop_text["pages"], book_props["pages"] or _("N/A") }) + end end -- cover image local is_doc = self.document and true or false @@ -150,7 +154,7 @@ function BookInfo:show(file, book_props, metadata_updated_caller_callback) local ReaderUI = require("apps/reader/readerui") ui = ReaderUI.instance end - if ui and ui.coverbrowser then + if ui and ui.coverbrowser then -- refresh cache db ui.coverbrowser:deleteBookInfo(file) end if fm_ui then @@ -169,7 +173,36 @@ function BookInfo:show(file, book_props, metadata_updated_caller_callback) UIManager:show(self.kvp_widget) end -function BookInfo:getBookProps(file, book_props, no_open_document) +-- Returns customized metadata. +function BookInfo.customizeProps(original_props, filepath) + local custom_props = {} -- stub + original_props = original_props or {} + + local props = {} + for _i, prop_key in ipairs(BookInfo.props) do + props[prop_key] = custom_props[prop_key] or original_props[prop_key] + end + props.pages = original_props.pages + -- if original title is empty, generate it as filename without extension + props.display_title = props.title or filemanagerutil.splitFileNameType(filepath) + return props +end + +-- Returns document metadata (opened document or book (file) metadata or custom metadata). +function BookInfo.getDocProps(ui, file, book_props, no_open_document, no_customize) + local original_props, filepath + if ui then -- currently opened document + original_props = ui.doc_settings:readSetting("doc_props") + filepath = ui.document.file + else -- from file + original_props = BookInfo.getBookProps(file, book_props, no_open_document) + filepath = file + end + return no_customize and original_props or BookInfo.customizeProps(original_props, filepath) +end + +-- Returns book (file) metadata, including number of pages. +function BookInfo.getBookProps(file, book_props, no_open_document) if DocSettings:hasSidecarFile(file) then local doc_settings = DocSettings:open(file) if not book_props then @@ -184,9 +217,8 @@ function BookInfo:getBookProps(file, book_props, no_open_document) -- the fact that stats.page = 0) local stats = doc_settings:readSetting("stats") if stats and stats.pages ~= 0 then - -- Let's use them as is (which was what was done before), even if - -- incomplete, to avoid expensive book opening - book_props = stats + -- title, authors, series, series_index, language + book_props = Document:getProps(stats) end end -- Files opened after 20170701 have an accurate "doc_pages" setting. @@ -229,26 +261,20 @@ function BookInfo:getBookProps(file, book_props, no_open_document) return book_props or {} end +-- Shows book information for currently opened document. function BookInfo:onShowBookInfo() - if not self.document then return end - -- Get them directly from ReaderUI's doc_settings - local doc_props = self.ui.doc_settings:readSetting("doc_props") - -- Make a copy, so we don't add "pages" to the original doc_props - -- that will be saved at some point by ReaderUI. - local book_props = { pages = self.ui.doc_settings:readSetting("doc_pages") } - for k, v in pairs(doc_props) do - book_props[k] = v + if self.document then + self.ui.doc_props.pages = self.ui.doc_settings:readSetting("doc_pages") + self:show(self.document.file, self.ui.doc_props) end - self:show(self.document.file, book_props) end function BookInfo:onShowBookDescription(description, file) if not description then if file then - description = self:getBookProps(file).description - elseif self.document then - description = self.ui.doc_settings:readSetting("doc_props").description - or self.document:getProps().description + description = BookInfo.getDocProps(nil, file).description + elseif self.document then -- currently opened document + description = self.ui.doc_props.description end end if description and description ~= "" then diff --git a/frontend/apps/filemanager/filemanagerfilesearcher.lua b/frontend/apps/filemanager/filemanagerfilesearcher.lua index f7d2153e9..5f63f8db2 100644 --- a/frontend/apps/filemanager/filemanagerfilesearcher.lua +++ b/frontend/apps/filemanager/filemanagerfilesearcher.lua @@ -1,4 +1,4 @@ -local ButtonDialogTitle = require("ui/widget/buttondialogtitle") +local ButtonDialog = require("ui/widget/buttondialog") local CheckButton = require("ui/widget/checkbutton") local CenterContainer = require("ui/widget/container/centercontainer") local DocumentRegistry = require("document/documentregistry") @@ -182,14 +182,6 @@ function FileSearcher:getList() end function FileSearcher:isFileMatch(filename, fullpath, keywords, is_file) - local metadata_keys = { - "authors", - "title", - "series", - "description", - "keywords", - "language", - } if keywords == "*" then return true end @@ -201,11 +193,14 @@ function FileSearcher:isFileMatch(filename, fullpath, keywords, is_file) end if self.include_metadata and is_file and DocumentRegistry:hasProvider(fullpath) then local book_props = self.ui.coverbrowser:getBookInfo(fullpath) or - FileManagerBookInfo:getBookProps(fullpath, nil, true) + FileManagerBookInfo.getDocProps(nil, fullpath, nil, true) if next(book_props) ~= nil then - for _, key in ipairs(metadata_keys) do + for _, key in ipairs(FileManagerBookInfo.props) do local prop = book_props[key] if prop and prop ~= "" then + if key == "series_index" then + prop = tostring(prop) + end if not self.case_sensitive then prop = Utf8Proc.lowercase(util.fixUtf8(prop, "?")) end @@ -252,8 +247,6 @@ function FileSearcher:showSearchResults(results) dimen = Screen:getSize(), } self.search_menu = Menu:new{ - width = Screen:getWidth(), - height = Screen:getHeight(), is_borderless = true, is_popout = false, show_parent = menu_container, @@ -312,7 +305,7 @@ function FileSearcher:onMenuSelect(item) end, }, }) - dialog = ButtonDialogTitle:new{ + dialog = ButtonDialog:new{ title = item.path, buttons = buttons, } diff --git a/frontend/apps/filemanager/filemanagerutil.lua b/frontend/apps/filemanager/filemanagerutil.lua index 8c12275bc..220a2e2ef 100644 --- a/frontend/apps/filemanager/filemanagerutil.lua +++ b/frontend/apps/filemanager/filemanagerutil.lua @@ -33,7 +33,8 @@ function filemanagerutil.abbreviate(path) return path end -function filemanagerutil.splitFileNameType(filename) +function filemanagerutil.splitFileNameType(filepath) + local _, filename = util.splitFilePathName(filepath) local filename_without_suffix, filetype = util.splitFileNameSuffix(filename) filetype = filetype:lower() if filetype == "zip" then diff --git a/frontend/apps/reader/modules/readerdictionary.lua b/frontend/apps/reader/modules/readerdictionary.lua index 30bbefbbc..a48f9fa3d 100644 --- a/frontend/apps/reader/modules/readerdictionary.lua +++ b/frontend/apps/reader/modules/readerdictionary.lua @@ -937,13 +937,7 @@ function ReaderDictionary:stardictLookup(word, dict_names, fuzzy_search, boxes, return end - local book_title = self.ui.doc_settings and self.ui.doc_settings:readSetting("doc_props").title or _("Dictionary lookup") - if book_title == "" then -- no or empty metadata title - if self.ui.document and self.ui.document.file then - local directory, filename = util.splitFilePathName(self.ui.document.file) -- luacheck: no unused - book_title = util.splitFileNameSuffix(filename) - end - end + local book_title = self.ui.doc_props and self.ui.doc_props.display_title or _("Dictionary lookup") -- Event for plugin to catch lookup with book title self.ui:handleEvent(Event:new("WordLookedUp", word, book_title)) diff --git a/frontend/apps/reader/modules/readerfooter.lua b/frontend/apps/reader/modules/readerfooter.lua index b59d67a7f..84b8746e2 100644 --- a/frontend/apps/reader/modules/readerfooter.lua +++ b/frontend/apps/reader/modules/readerfooter.lua @@ -384,24 +384,19 @@ local footerTextGeneratorMap = { end end, book_title = function(footer) - local doc_info = footer.ui.document:getProps() - if doc_info and doc_info.title then - local title = doc_info.title:gsub(" ", "\u{00A0}") -- replace space with no-break-space - local title_widget = TextWidget:new{ - text = title, - max_width = footer._saved_screen_width * footer.settings.book_title_max_width_pct * (1/100), - face = Font:getFace(footer.text_font_face, footer.settings.text_font_size), - bold = footer.settings.text_font_bold, - } - local fitted_title_text, add_ellipsis = title_widget:getFittedText() - title_widget:free() - if add_ellipsis then - fitted_title_text = fitted_title_text .. "…" - end - return BD.auto(fitted_title_text) - else - return "" + local title = footer.ui.doc_props.display_title:gsub(" ", "\u{00A0}") -- replace space with no-break-space + local title_widget = TextWidget:new{ + text = title, + max_width = footer._saved_screen_width * footer.settings.book_title_max_width_pct * (1/100), + face = Font:getFace(footer.text_font_face, footer.settings.text_font_size), + bold = footer.settings.text_font_bold, + } + local fitted_title_text, add_ellipsis = title_widget:getFittedText() + title_widget:free() + if add_ellipsis then + fitted_title_text = fitted_title_text .. "…" end + return BD.auto(fitted_title_text) end, book_chapter = function(footer) local chapter_title = footer.ui.toc:getTocTitleByPage(footer.pageno) diff --git a/frontend/apps/reader/modules/readerhighlight.lua b/frontend/apps/reader/modules/readerhighlight.lua index 3ba30f196..760b48f44 100644 --- a/frontend/apps/reader/modules/readerhighlight.lua +++ b/frontend/apps/reader/modules/readerhighlight.lua @@ -1436,15 +1436,6 @@ dbg:guard(ReaderHighlight, "translate", "translate must not be called with nil selected_text!") end) -function ReaderHighlight:getDocumentLanguage() - local doc_props = self.ui.doc_settings:readSetting("doc_props") - local doc_lang = doc_props and doc_props.language - if doc_lang == "" then - doc_lang = nil - end - return doc_lang -end - function ReaderHighlight:onTranslateText(text, page, index) Translator:showTranslation(text, true, nil, nil, true, page, index) end @@ -1473,7 +1464,7 @@ function ReaderHighlight:onTranslateCurrentPage() self.ui.document.configurable.text_wrap = is_reflow end if res and res.text then - Translator:showTranslation(res.text, false, self:getDocumentLanguage()) + Translator:showTranslation(res.text, false, self.ui.doc_props.language) end end diff --git a/frontend/apps/reader/modules/readerstatus.lua b/frontend/apps/reader/modules/readerstatus.lua index b8463f701..876100510 100644 --- a/frontend/apps/reader/modules/readerstatus.lua +++ b/frontend/apps/reader/modules/readerstatus.lua @@ -200,7 +200,7 @@ end function ReaderStatus:onShowBookStatus(before_show_callback) local status_page = BookStatusWidget:new { thumbnail = FileManagerBookInfo:getCoverImage(self.document), - props = self.document:getProps(), + props = self.ui.doc_props, document = self.document, settings = self.settings, ui = self.ui, diff --git a/frontend/apps/reader/modules/readertypography.lua b/frontend/apps/reader/modules/readertypography.lua index 8a4cf7fd7..9e9c15a5c 100644 --- a/frontend/apps/reader/modules/readertypography.lua +++ b/frontend/apps/reader/modules/readertypography.lua @@ -1,6 +1,7 @@ local BD = require("ui/bidi") local Device = require("device") local Event = require("ui/event") +local FileManagerBookInfo = require("apps/filemanager/filemanagerbookinfo") local InfoMessage = require("ui/widget/infomessage") local MultiConfirmBox = require("ui/widget/multiconfirmbox") local UIManager = require("ui/uimanager") @@ -776,7 +777,8 @@ end function ReaderTypography:onPreRenderDocument(config) -- This is called after the document has been loaded, -- when we know and can access the document language. - local doc_language = self.ui.document:getProps().language + local props = self.ui.document:getProps() + local doc_language = FileManagerBookInfo.customizeProps(props, self.ui.document.file).language self.book_lang_tag = self:fixLangTag(doc_language) local is_known_lang_tag = self.book_lang_tag and LANG_TAG_TO_LANG_NAME[self.book_lang_tag] ~= nil diff --git a/frontend/apps/reader/modules/readerwikipedia.lua b/frontend/apps/reader/modules/readerwikipedia.lua index 5c50ea7e5..a38c21a85 100644 --- a/frontend/apps/reader/modules/readerwikipedia.lua +++ b/frontend/apps/reader/modules/readerwikipedia.lua @@ -371,7 +371,7 @@ function ReaderWikipedia:initLanguages(word) end -- use book and UI languages if self.view then - addLanguage(self.view.document:getProps().language) + addLanguage(self.ui.doc_props.language) end addLanguage(G_reader_settings:readSetting("language")) if #self.wiki_languages == 0 and word then @@ -427,13 +427,7 @@ function ReaderWikipedia:lookupWikipedia(word, is_sane, box, get_fullpage, force local display_word = word:gsub("_", " ") if not self.disable_history then - local book_title = self.ui.doc_settings and self.ui.doc_settings:readSetting("doc_props").title or _("Wikipedia lookup") - if book_title == "" then -- no or empty metadata title - if self.ui.document and self.ui.document.file then - local directory, filename = util.splitFilePathName(self.ui.document.file) -- luacheck: no unused - book_title = util.splitFileNameSuffix(filename) - end - end + local book_title = self.ui.doc_props and self.ui.doc_props.display_title or _("Wikipedia lookup") wikipedia_history:addTableItem("wikipedia_history", { book_title = book_title, time = os.time(), diff --git a/frontend/apps/reader/readerui.lua b/frontend/apps/reader/readerui.lua index 3bec5a614..cef2d032f 100644 --- a/frontend/apps/reader/readerui.lua +++ b/frontend/apps/reader/readerui.lua @@ -457,6 +457,8 @@ function ReaderUI:init() -- (so that filemanager can use it from sideCar file to display -- Book information). self.doc_settings:saveSetting("doc_props", self.document:getProps()) + -- And have an extended and customized copy in memory for quick access. + self.doc_props = FileManagerBookInfo.getDocProps(self) -- Set "reading" status if there is no status. local summary = self.doc_settings:readSetting("summary") @@ -656,15 +658,8 @@ function ReaderUI:doShowReader(file, provider, seamless) document = document, } - local title = reader.doc_settings:readSetting("doc_props").title - - if title ~= "" then - Screen:setWindowTitle(title) - else - local _, filename = util.splitFilePathName(file) - Screen:setWindowTitle(filename) - end - Device:notifyBookState(title, document) + Screen:setWindowTitle(reader.doc_props.display_title) + Device:notifyBookState(reader.doc_props.display_title, document) -- This is mostly for the few callers that bypass the coroutine shenanigans and call doShowReader directly, -- instead of showReader... diff --git a/frontend/document/credocument.lua b/frontend/document/credocument.lua index 48ab86bff..a3bc0d1c2 100644 --- a/frontend/document/credocument.lua +++ b/frontend/document/credocument.lua @@ -213,6 +213,10 @@ function CreDocument:getDocumentFormat() return self._document:getDocumentFormat() end +function CreDocument:getDocumentProps() + return self._document:getDocumentProps() +end + function CreDocument:setupDefaultView() if self.loaded then -- Don't apply defaults if the document has already been loaded diff --git a/frontend/document/djvudocument.lua b/frontend/document/djvudocument.lua index 84bdc84a4..dad444f1d 100644 --- a/frontend/document/djvudocument.lua +++ b/frontend/document/djvudocument.lua @@ -51,23 +51,6 @@ function DjvuDocument:updateColorRendering() end end -function DjvuDocument:getProps() - local props = self._document:getMetadata() - local _, _, docname = self.file:find(".*/(.*)") - docname = docname or self.file - - -- According to djvused(1), the convention is that - -- BibTex keys are always lowercase and DocInfo capitalized - props.title = props.title or props.Title or docname:match("(.*)%.") - props.authors = props.author or props.Author - props.series = props.series or props.Series - props.language = props.language or props.Language - props.keywords = props.keywords or props.Keywords - props.description = props.description or props.Description - - return props -end - function DjvuDocument:comparePositions(pos1, pos2) return self.koptinterface:comparePositions(self, pos1, pos2) end diff --git a/frontend/document/document.lua b/frontend/document/document.lua index 785ded438..a65c9625b 100644 --- a/frontend/document/document.lua +++ b/frontend/document/document.lua @@ -207,8 +207,51 @@ function Document:getNativePageDimensions(pageno) return page_size end -function Document:getProps() - return self._document:getDocumentProps() +function Document:getDocumentProps() + -- pdfdocument, djvudocument + return self._document:getMetadata() + -- credocument, picdocument - overridden by a document implementation +end + +function Document:getProps(cached_doc_metadata) + local function makeNilIfEmpty(str) + if str == "" then + return nil + end + return str + end + local props = cached_doc_metadata or self:getDocumentProps() + local title = makeNilIfEmpty(props.title or props.Title) + local authors = makeNilIfEmpty(props.authors or props.author or props.Author) + local series = makeNilIfEmpty(props.series or props.Series) + local series_index + if series and string.find(series, "#") then + -- If there's a series index in there, split it off to series_index, and only store the name in series. + -- This property is currently only set by: + -- * DjVu, for which I couldn't find a real standard for metadata fields + -- (we currently use Series for this field, c.f., https://exiftool.org/TagNames/DjVu.html). + -- * CRe, which could offer us a split getSeriesName & getSeriesNumber... + -- except getSeriesNumber does an atoi, so it'd murder decimal values. + -- So, instead, parse how it formats the whole thing as a string ;). + local series_name + series_name, series_index = series:match("(.*) #(%d+%.?%d-)$") + if series_index then + series = series_name + series_index = tonumber(series_index) + end + end + local language = makeNilIfEmpty(props.language or props.Language) + local keywords = makeNilIfEmpty(props.keywords or props.Keywords) + local description = makeNilIfEmpty(props.description or props.Description or props.subject) + return { + title = title, + authors = authors, + series = series, + series_index = series_index, + language = language, + keywords = keywords, + description = description, + } end function Document:_readMetadata() diff --git a/frontend/document/pdfdocument.lua b/frontend/document/pdfdocument.lua index 63b7dfb35..aeed635ef 100644 --- a/frontend/document/pdfdocument.lua +++ b/frontend/document/pdfdocument.lua @@ -313,24 +313,6 @@ function PdfDocument:close() Document.close(self) end -function PdfDocument:getProps() - local props = self._document:getMetadata() - if props.title == "" then - local startPos = util.lastIndexOf(self.file, "%/") - if startPos > 0 then - props.title = string.sub(self.file, startPos + 1, -5) --remove extension .pdf - else - props.title = string.sub(self.file, 0, -5) - end - end - props.authors = props.author - props.series = "" - props.language = "" - props.keywords = props.keywords - props.description = props.subject - return props -end - function PdfDocument:getLinkFromPosition(pageno, pos) return self.koptinterface:getLinkFromPosition(self, pageno, pos) end diff --git a/frontend/document/picdocument.lua b/frontend/document/picdocument.lua index a55c25901..7c09ff7fc 100644 --- a/frontend/document/picdocument.lua +++ b/frontend/document/picdocument.lua @@ -42,12 +42,8 @@ function PicDocument:getUsedBBox(pageno) return { x0 = 0, y0 = 0, x1 = self._document.width, y1 = self._document.height } end -function PicDocument:getProps() - local _, _, docname = self.file:find(".*/(.*)") - docname = docname or self.file - return { - title = docname:match("(.*)%."), - } +function PicDocument:getDocumentProps() + return {} end function PicDocument:getCoverPageImage() diff --git a/frontend/languagesupport.lua b/frontend/languagesupport.lua index ce237905a..a4886ad64 100644 --- a/frontend/languagesupport.lua +++ b/frontend/languagesupport.lua @@ -194,7 +194,7 @@ function LanguageSupport:improveWordSelection(selection) return end - local language_code = self.document:getProps().language or "unknown" + local language_code = self.ui.doc_props.language or "unknown" logger.dbg("language support: improving", language_code, "selection", selection) -- Rather than requiring each language plugin to use document: methods @@ -250,7 +250,7 @@ end function LanguageSupport:extraDictionaryFormCandidates(text) if not self:hasActiveLanguagePlugins() then return end -- nothing to do - local language_code = self.document and self.document:getProps().language or "unknown" + local language_code = (self.ui.doc_props and self.ui.doc_props.language) or "unknown" logger.dbg("language support: convert", text, "to dictionary form (marked as", language_code..")") return self:_findAndCallPlugin( diff --git a/frontend/ui/screensaver.lua b/frontend/ui/screensaver.lua index bfa63d885..b87f888c8 100644 --- a/frontend/ui/screensaver.lua +++ b/frontend/ui/screensaver.lua @@ -154,6 +154,7 @@ function Screensaver:expandSpecial(message, fallback) local time_left_chapter = _("N/A") local time_left_document = _("N/A") local batt_lvl = _("N/A") + local props local ReaderUI = require("apps/reader/readerui") local ui = ReaderUI.instance @@ -173,12 +174,7 @@ function Screensaver:expandSpecial(message, fallback) time_left_document = self:_calcAverageTimeForPages(doc:getTotalPagesLeft(currentpage)) end percent = Math.round((currentpage * 100) / totalpages) - local props = doc:getProps() - if props then - title = props.title and props.title ~= "" and props.title or title - authors = props.authors and props.authors ~= "" and props.authors or authors - series = props.series and props.series ~= "" and props.series or series - end + props = ui.doc_props elseif DocSettings:hasSidecarFile(lastfile) then -- If there's no ReaderUI instance, but the file has sidecar data, use that local doc_settings = DocSettings:open(lastfile) @@ -186,14 +182,21 @@ function Screensaver:expandSpecial(message, fallback) percent = doc_settings:readSetting("percent_finished") or percent currentpage = Math.round(percent * totalpages) percent = Math.round(percent * 100) - local doc_props = doc_settings:readSetting("doc_props") - if doc_props then - title = doc_props.title and doc_props.title ~= "" and doc_props.title or title - authors = doc_props.authors and doc_props.authors ~= "" and doc_props.authors or authors - series = doc_props.series and doc_props.series ~= "" and doc_props.series or series - end + props = FileManagerBookInfo.customizeProps(doc_settings:readSetting("doc_props"), lastfile) -- Unable to set time_left_chapter and time_left_document without ReaderUI, so leave N/A end + if props then + title = props.display_title + if props.authors then + authors = props.authors + end + if props.series then + series = props.series + if props.series_index then + series = series .. " #" .. props.series_index + end + end + end if Device:hasBattery() then local powerd = Device:getPowerDevice() if Device:hasAuxBattery() and powerd:isAuxBatteryConnected() then @@ -644,7 +647,7 @@ function Screensaver:show() local doc_settings = ui.doc_settings widget = BookStatusWidget:new{ thumbnail = FileManagerBookInfo:getCoverImage(doc), - props = doc:getProps(), + props = ui.doc_props, document = doc, settings = doc_settings, ui = ui, diff --git a/frontend/ui/translator.lua b/frontend/ui/translator.lua index 1a951787a..527fd443e 100644 --- a/frontend/ui/translator.lua +++ b/frontend/ui/translator.lua @@ -308,14 +308,10 @@ end function Translator:getDocumentLanguage() local ui = require("apps/reader/readerui").instance - if not ui or not ui.document then - return - end - local props = ui.document:getProps() - if not props or not props.language or props.language == "" then + local lang = ui and ui.doc_props and ui.doc_props.language + if not lang then return end - local lang = props.language lang = lang:match("(.*)-") or lang lang = lang:lower() local name, supported = self:getLanguageName(lang, "") diff --git a/frontend/ui/widget/bookstatuswidget.lua b/frontend/ui/widget/bookstatuswidget.lua index c28f02724..0c4dbc90c 100644 --- a/frontend/ui/widget/bookstatuswidget.lua +++ b/frontend/ui/widget/bookstatuswidget.lua @@ -299,16 +299,13 @@ function BookStatusWidget:genBookInfoGroup() -- Get a chance to have title and authors rendered with alternate -- glyphs for the book language - local lang = nil - if self.props.language and self.props.language ~= "" then - lang = self.props.language - end + local lang = self.props.language -- title local book_meta_info_group = VerticalGroup:new{ align = "center", VerticalSpan:new{ width = height * 0.2 }, TextBoxWidget:new{ - text = self.props.title, + text = self.props.display_title, lang = lang, width = width, face = self.medium_font_face, diff --git a/plugins/coverbrowser.koplugin/bookinfomanager.lua b/plugins/coverbrowser.koplugin/bookinfomanager.lua index 6be7246cc..d8205a5ee 100644 --- a/plugins/coverbrowser.koplugin/bookinfomanager.lua +++ b/plugins/coverbrowser.koplugin/bookinfomanager.lua @@ -492,37 +492,13 @@ function BookInfoManager:extractBookInfo(filepath, cover_specs) end if loaded then dbrow.pages = pages - local props = document:getProps() + local props = FileManagerBookInfo.customizeProps(document:getProps(), filepath) if next(props) then -- there's at least one item dbrow.has_meta = 'Y' end - if props.title and props.title ~= "" then dbrow.title = props.title end - if props.authors and props.authors ~= "" then dbrow.authors = props.authors end - if props.series and props.series ~= "" then - -- NOTE: If there's a series index in there, split it off to series_index, and only store the name in series. - -- This property is currently only set by: - -- * DjVu, for which I couldn't find a real standard for metadata fields - -- (we currently use Series for this field, c.f., https://exiftool.org/TagNames/DjVu.html). - -- * CRe, which could offer us a split getSeriesName & getSeriesNumber... - -- except getSeriesNumber does an atoi, so it'd murder decimal values. - -- So, instead, parse how it formats the whole thing as a string ;). - if string.find(props.series, "#") then - dbrow.series, dbrow.series_index = props.series:match("(.*) #(%d+%.?%d-)$") - if dbrow.series_index then - -- We're inserting via a bind method, so make sure we feed it a Lua number, because it's a REAL in the db. - dbrow.series_index = tonumber(dbrow.series_index) - else - -- If the index pattern didn't match (e.g., nothing after the octothorp, or a string), - -- restore the full thing as the series name. - dbrow.series = props.series - end - else - dbrow.series = props.series - end + for k, v in pairs(props) do + dbrow[k] = v end - if props.language and props.language ~= "" then dbrow.language = props.language end - if props.keywords and props.keywords ~= "" then dbrow.keywords = props.keywords end - if props.description and props.description ~= "" then dbrow.description = props.description end if cover_specs then local spec_sizetag = cover_specs.sizetag local spec_max_cover_w = cover_specs.max_cover_w diff --git a/plugins/statistics.koplugin/main.lua b/plugins/statistics.koplugin/main.lua index bdcae3526..4b4cbb56f 100644 --- a/plugins/statistics.koplugin/main.lua +++ b/plugins/statistics.koplugin/main.lua @@ -174,23 +174,18 @@ function ReaderStatistics:initData() if not self.data then self.data = { performance_in_pages= {} } end - local book_properties = self:getBookProperties() - self.data.title = book_properties.title - if self.data.title == nil or self.data.title == "" then - self.data.title = self.document.file:match("^.+/(.+)$") - end - self.data.authors = book_properties.authors - if self.data.authors == nil or self.data.authors == "" then - self.data.authors = "N/A" - end - self.data.language = book_properties.language - if self.data.language == nil or self.data.language == "" then - self.data.language = "N/A" - end - self.data.series = book_properties.series - if self.data.series == nil or self.data.series == "" then - self.data.series = "N/A" + local book_properties = self.ui.doc_props + self.data.title = book_properties.display_title + self.data.authors = book_properties.authors or "N/A" + self.data.language = book_properties.language or "N/A" + local series + if book_properties.series then + series = book_properties.series + if book_properties.series_index then + series = series .. " #" .. book_properties.series_index + end end + self.data.series = series or "N/A" self.data.pages = self.view.document:getPageCount() if not self.data.md5 then @@ -921,15 +916,6 @@ function ReaderStatistics:getPageTimeTotalStats(id_book) return total_pages, total_time end -function ReaderStatistics:getBookProperties() - local props = self.view.document:getProps() - if props.title == "No document" or props.title == "" then - --- @fixme Sometimes crengine returns "No document", try one more time. - props = self.view.document:getProps() - end - return props -end - function ReaderStatistics:getStatisticEnabledMenuItem() return { text = _("Enabled"), @@ -2691,7 +2677,7 @@ function ReaderStatistics:onReadingResumed() end function ReaderStatistics:onReadSettings(config) - self.data = config.data.stats or {} + self.data = config:readSetting("stats", {}) end function ReaderStatistics:onReaderReady() diff --git a/plugins/vocabbuilder.koplugin/main.lua b/plugins/vocabbuilder.koplugin/main.lua index 0d181f306..b9e6be9bf 100644 --- a/plugins/vocabbuilder.koplugin/main.lua +++ b/plugins/vocabbuilder.koplugin/main.lua @@ -77,14 +77,7 @@ local function resetButtonOnLookupWindow() text = _("Add to vocabulary builder"), font_bold = false, callback = function() - local book_title = obj.ui.doc_settings and obj.ui.doc_settings:readSetting("doc_props").title or _("Dictionary lookup") - if book_title == "" then -- no or empty metadata title - if obj.ui.document and obj.ui.document.file then - local util = require("util") - local directory, filename = util.splitFilePathName(obj.ui.document.file) -- luacheck: no unused - book_title = util.splitFileNameSuffix(filename) - end - end + local book_title = obj.ui.doc_props.display_title or _("Dictionary lookup") obj.ui:handleEvent(Event:new("WordLookedUp", obj.word, book_title, true)) -- is_manual: true local button = obj.button_table.button_by_id["vocabulary"] if button then diff --git a/tools/wbuilder.lua b/tools/wbuilder.lua index a8a5b7595..7f1105b2f 100755 --- a/tools/wbuilder.lua +++ b/tools/wbuilder.lua @@ -390,7 +390,7 @@ function testBookStatus() local status_page = require("ui/widget/bookstatuswidget"):new { thumbnail = doc:getCoverPageImage(), - props = doc:getProps(), + props = reader.doc_props, document = doc, ui = reader, }