From f1726a9e5dbb9c2ceb07ece794061cfd25383239 Mon Sep 17 00:00:00 2001 From: hius07 <62179190+hius07@users.noreply.github.com> Date: Thu, 27 Feb 2025 18:45:52 +0200 Subject: [PATCH] FileSearcher: consistent results window (#13298) --- frontend/apps/filemanager/filemanager.lua | 44 ++- .../filemanager/filemanagercollection.lua | 88 +++--- .../apps/filemanager/filemanagerconverter.lua | 28 +- .../filemanager/filemanagerfilesearcher.lua | 286 ++++++++++++------ .../apps/filemanager/filemanagerhistory.lua | 145 +++++---- frontend/apps/filemanager/filemanagermenu.lua | 23 +- plugins/coverbrowser.koplugin/main.lua | 271 +++++++---------- 7 files changed, 471 insertions(+), 414 deletions(-) diff --git a/frontend/apps/filemanager/filemanager.lua b/frontend/apps/filemanager/filemanager.lua index 50946306e..97f85d7a7 100644 --- a/frontend/apps/filemanager/filemanager.lua +++ b/frontend/apps/filemanager/filemanager.lua @@ -272,6 +272,16 @@ function FileManager:setupLayout() file_manager.collections:genAddToCollectionButton(file, close_dialog_callback, refresh_callback), }) end + if Device:canExecuteScript(file) then + table.insert(buttons, { + filemanagerutil.genExecuteScriptButton(file, close_dialog_callback), + }) + end + if FileManagerConverter:isSupported(file) then + table.insert(buttons, { + FileManagerConverter:genConvertButton(file, close_dialog_callback, refresh_callback) + }) + end table.insert(buttons, { { text = _("Open with…"), @@ -288,22 +298,6 @@ function FileManager:setupLayout() filemanagerutil.genBookDescriptionButton(file, book_props, close_dialog_callback), }) end - if Device:canExecuteScript(file) then - table.insert(buttons, { - filemanagerutil.genExecuteScriptButton(file, close_dialog_callback), - }) - end - if FileManagerConverter:isSupported(file) then - table.insert(buttons, { - { - text = _("Convert"), - callback = function() - UIManager:close(self.file_dialog) - FileManagerConverter:showConvertButtons(file, self) - end, - }, - }) - end else -- folder local folder = ffiUtil.realpath(file) table.insert(buttons, { @@ -450,14 +444,13 @@ function FileChooser:onBack() elseif back_to_exit == "disable" then return true elseif back_to_exit == "prompt" then - UIManager:show(ConfirmBox:new{ - text = _("Exit KOReader?"), - ok_text = _("Exit"), - ok_callback = function() - self:onClose() - end - }) - + UIManager:show(ConfirmBox:new{ + text = _("Exit KOReader?"), + ok_text = _("Exit"), + ok_callback = function() + self:onClose() + end, + }) return true end elseif back_in_filemanager == "parent_folder" then @@ -476,7 +469,8 @@ function FileManager:onSwipeFM(ges) return true end -function FileManager:addFileDialogButtons(row_id, row_func) -- FileManager, History, Collections file_dialog +function FileManager:addFileDialogButtons(row_id, row_func) + -- long-press file_dialog in FileManager, History, Collections, FileSearcher self.file_dialog_added_buttons = self.file_dialog_added_buttons or { index = {} } if self.file_dialog_added_buttons.index[row_id] == nil then table.insert(self.file_dialog_added_buttons, row_func) diff --git a/frontend/apps/filemanager/filemanagercollection.lua b/frontend/apps/filemanager/filemanagercollection.lua index c4191530e..63e8a5365 100644 --- a/frontend/apps/filemanager/filemanagercollection.lua +++ b/frontend/apps/filemanager/filemanagercollection.lua @@ -28,6 +28,7 @@ local FileManagerCollection = WidgetContainer:extend{ } function FileManagerCollection:init() + self.show_mark = G_reader_settings:nilOrTrue("collection_show_mark") self.doc_props_cache = {} self.updated_collections = {} self.ui.menu:registerToMainMenu(self) @@ -74,14 +75,15 @@ end function FileManagerCollection:onShowColl(collection_name) collection_name = collection_name or ReadCollection.default_collection_name - self.coll_menu = BookList:new{ + -- This may be hijacked by CoverBrowser plugin and needs to be known as booklist_menu. + self.booklist_menu = BookList:new{ name = "collections", path = collection_name, title_bar_left_icon = "appbar.menu", onLeftButtonTap = function() self:showCollDialog() end, onReturn = function() self.from_collection_name = self:getCollectionTitle(collection_name) - self.coll_menu.close_callback() + self.booklist_menu.close_callback() self:onShowCollList() end, onMenuChoice = self.onMenuChoice, @@ -90,23 +92,23 @@ function FileManagerCollection:onShowColl(collection_name) _manager = self, _recreate_func = function() self:onShowColl(collection_name) end, } - table.insert(self.coll_menu.paths, true) -- enable onReturn button - self.coll_menu.close_callback = function() + table.insert(self.booklist_menu.paths, true) -- enable onReturn button + self.booklist_menu.close_callback = function() self:refreshFileManager() - UIManager:close(self.coll_menu) - self.coll_menu = nil + UIManager:close(self.booklist_menu) + self.booklist_menu = nil self.match_table = nil end self:setCollate() self:updateItemTable() - UIManager:show(self.coll_menu) + UIManager:show(self.booklist_menu) return true end function FileManagerCollection:updateItemTable(item_table, focused_file) if item_table == nil then item_table = {} - for _, item in pairs(ReadCollection.coll[self.coll_menu.path]) do + for _, item in pairs(ReadCollection.coll[self.booklist_menu.path]) do if self:isItemMatch(item) then local item_tmp = { file = item.file, @@ -126,7 +128,7 @@ function FileManagerCollection:updateItemTable(item_table, focused_file) end end local title, subtitle = self:getBookListTitle(item_table) - self.coll_menu:switchItemTable(title, item_table, -1, focused_file and { file = focused_file }, subtitle) + self.booklist_menu:switchItemTable(title, item_table, -1, focused_file and { file = focused_file }, subtitle) end function FileManagerCollection:isItemMatch(item) @@ -149,7 +151,7 @@ function FileManagerCollection:isItemMatch(item) end function FileManagerCollection:getBookListTitle(item_table) - local collection_title = self:getCollectionTitle(self.coll_menu.path) + local collection_title = self:getCollectionTitle(self.booklist_menu.path) local title = T("%1 (%2)", collection_title, #item_table) local subtitle = "" if self.match_table then @@ -197,7 +199,7 @@ function FileManagerCollection:onMenuHold(item) end local function close_dialog_menu_callback() UIManager:close(self.file_dialog) - self._manager.coll_menu.close_callback() + self.close_callback() end local function close_dialog_update_callback() UIManager:close(self.file_dialog) @@ -232,6 +234,11 @@ function FileManagerCollection:onMenuHold(item) filemanagerutil.genResetSettingsButton(doc_settings_or_file, close_dialog_update_callback, is_currently_opened), self._manager:genAddToCollectionButton(file, close_dialog_callback, close_dialog_update_callback), }) + if Device:canExecuteScript(file) then + table.insert(buttons, { + filemanagerutil.genExecuteScriptButton(file, close_dialog_menu_callback) + }) + end table.insert(buttons, { { text = _("Delete"), @@ -259,12 +266,6 @@ function FileManagerCollection:onMenuHold(item) filemanagerutil.genBookDescriptionButton(file, book_props, close_dialog_callback), }) - if Device:canExecuteScript(file) then - table.insert(buttons, { - filemanagerutil.genExecuteScriptButton(file, close_dialog_menu_callback) - }) - end - if self._manager.file_dialog_added_buttons ~= nil then for _, row_func in ipairs(self._manager.file_dialog_added_buttons) do local row = row_func(file, true, book_props) @@ -285,12 +286,12 @@ end function FileManagerCollection.getMenuInstance() local ui = require("apps/filemanager/filemanager").instance or require("apps/reader/readerui").instance - return ui.collections.coll_menu + return ui.collections.booklist_menu end function FileManagerCollection:showCollDialog() - local collection_name = self.coll_menu.path - local coll_not_empty = #self.coll_menu.item_table > 0 + local collection_name = self.booklist_menu.path + local coll_not_empty = #self.booklist_menu.item_table > 0 local coll_dialog local function genFilterByStatusButton(button_status) return { @@ -310,7 +311,7 @@ function FileManagerCollection:showCollDialog() callback = function() UIManager:close(coll_dialog) local prop_values = {} - for idx, item in ipairs(self.coll_menu.item_table) do + for idx, item in ipairs(self.booklist_menu.item_table) do local doc_prop = self:getDocProps(item.file)[button_prop] if doc_prop == nil then doc_prop = { self.empty_prop } @@ -335,7 +336,7 @@ function FileManagerCollection:showCollDialog() text = _("Collections"), callback = function() UIManager:close(coll_dialog) - self.coll_menu.close_callback() + self.booklist_menu.close_callback() self:onShowCollList() end, }}, @@ -410,7 +411,7 @@ function FileManagerCollection:showCollDialog() self.updated_collections[collection_name] = true ReadCollection:addItem(file, collection_name) self:updateItemTable(nil, file) -- show added item - self.files_updated = true + self.files_updated = self.show_mark end end, } @@ -435,7 +436,7 @@ function FileManagerCollection:showCollDialog() ReadCollection:addItem(file, collection_name) end self:updateItemTable(nil, file) - self.files_updated = true + self.files_updated = self.show_mark end, }}) end @@ -457,7 +458,7 @@ function FileManagerCollection:showPropValueList(prop, prop_values) util.tableSetValue(self, value, "match_table", "props", prop) local item_table = {} for _, idx in ipairs(item_idxs) do - table.insert(item_table, self.coll_menu.item_table[idx]) + table.insert(item_table, self.booklist_menu.item_table[idx]) end self:updateItemTable(item_table) end, @@ -478,7 +479,7 @@ function FileManagerCollection:showPropValueList(prop, prop_values) end function FileManagerCollection:setCollate(collate_id, collate_reverse) - local coll_settings = ReadCollection.coll_settings[self.coll_menu.path] + local coll_settings = ReadCollection.coll_settings[self.booklist_menu.path] if collate_id == nil then collate_id = coll_settings.collate else @@ -506,7 +507,7 @@ function FileManagerCollection:setCollate(collate_id, collate_reverse) end function FileManagerCollection:showArrangeBooksDialog() - local collection_name = self.coll_menu.path + local collection_name = self.booklist_menu.path local coll_settings = ReadCollection.coll_settings[collection_name] local curr_collate_id = coll_settings.collate local arrange_dialog @@ -558,9 +559,9 @@ function FileManagerCollection:showArrangeBooksDialog() UIManager:close(arrange_dialog) UIManager:show(SortWidget:new{ title = _("Arrange books in collection"), - item_table = self.coll_menu.item_table, + item_table = self.booklist_menu.item_table, callback = function() - ReadCollection:updateCollectionOrder(collection_name, self.coll_menu.item_table) + ReadCollection:updateCollectionOrder(collection_name, self.booklist_menu.item_table) self.updated_collections[collection_name] = true self:setCollate(false, false) self:updateItemTable() @@ -587,15 +588,15 @@ function FileManagerCollection:addBooksFromFolder(include_subfolders) util.findFiles(folder, function(file) files_found[file] = DocumentRegistry:hasProvider(file) or nil end, include_subfolders) - local count = ReadCollection:addItemsMultiple(files_found, { [self.coll_menu.path] = true }) + local count = ReadCollection:addItemsMultiple(files_found, { [self.booklist_menu.path] = true }) local text if count == 0 then text = _("No books added to collection") else - self.updated_collections[self.coll_menu.path] = true + self.updated_collections[self.booklist_menu.path] = true text = T(N_("1 book added to collection", "%1 books added to collection", count), count) self:updateItemTable() - self.files_updated = true + self.files_updated = self.show_mark end UIManager:show(InfoMessage:new{ text = text }) end, @@ -609,8 +610,8 @@ function FileManagerCollection:onBookMetadataChanged(prop_updated) file = prop_updated.filepath self.doc_props_cache[file] = prop_updated.doc_props end - if self.coll_menu then - self:updateItemTable(nil, file) -- keep showing the changed file + if self.booklist_menu then + self:updateItemTable(nil, file) -- keep showing the changed file after resorting end end @@ -910,23 +911,21 @@ function FileManagerCollection:removeCollection(item) ReadCollection:removeCollection(item.name) table.remove(self.coll_list.item_table, item.idx) self:updateCollListItemTable() - self.files_updated = true + self.files_updated = self.show_mark end, }) end function FileManagerCollection:sortCollections() - local sort_widget - sort_widget = SortWidget:new{ + UIManager:show(SortWidget:new{ title = _("Arrange collections"), - item_table = util.tableDeepCopy(self.coll_list.item_table), + item_table = self.coll_list.item_table, callback = function() self.updated_collections = { true } -- all - ReadCollection:updateCollectionListOrder(sort_widget.item_table) + ReadCollection:updateCollectionListOrder(self.coll_list.item_table) self:updateCollListItemTable(true) -- init end, - } - UIManager:show(sort_widget) + }) end function FileManagerCollection:onShowCollectionsSearchDialog(search_str, coll_name) @@ -1079,12 +1078,15 @@ function FileManagerCollection:searchCollections(coll_name) if a.coll_order ~= b.coll_order then return a.coll_order < b.coll_order end - return a.item_order < b.item_order + if a.item_order and b.item_order then + return a.item_order < b.item_order + end + return ffiUtil.strcoll(a.text, b.text) end) local new_coll_name = T(_("Search results: %1"), self.search_str) if coll_name then new_coll_name = new_coll_name .. " " .. T(_"(in %1)", coll_name) - self.coll_menu.close_callback() + self.booklist_menu.close_callback() end self.updated_collections[new_coll_name] = true ReadCollection:removeCollection(new_coll_name) diff --git a/frontend/apps/filemanager/filemanagerconverter.lua b/frontend/apps/filemanager/filemanagerconverter.lua index 68ef369b3..ba4c7be57 100644 --- a/frontend/apps/filemanager/filemanagerconverter.lua +++ b/frontend/apps/filemanager/filemanagerconverter.lua @@ -68,7 +68,14 @@ function FileConverter:isSupported(file) return self.formats_from[util.getFileNameSuffix(file)] and true or false end -function FileConverter:showConvertButtons(file, ui) +function FileConverter:showConvertButtons(file, caller_post_callback) + local function writeData(data, target_file) + UIManager:close(self.convert_dialog) + util.writeToFile(data, target_file) + if caller_post_callback then + caller_post_callback() + end + end local __, filename_pure = util.splitFilePathName(file) local filename_suffix = util.getFileNameSuffix(file) local filetype_name = self.formats_from[filename_suffix].name @@ -87,14 +94,11 @@ function FileConverter:showConvertButtons(file, ui) text = _("Overwrite existing HTML file?"), ok_text = _("Overwrite"), ok_callback = function() - util.writeToFile(html, filename_html) - UIManager:close(self.convert_dialog) + writeData(html, filename_html) end, }) else - util.writeToFile(html, filename_html) - ui:refreshPath() - UIManager:close(self.convert_dialog) + writeData(html, filename_html) end end, }, @@ -117,4 +121,16 @@ function FileConverter:cleanup() self.convert_dialog = nil end +function FileConverter:genConvertButton(file, caller_pre_callback, caller_post_callback) + return { + text = _("Convert"), + callback = function() + if caller_pre_callback then + caller_pre_callback() + end + self:showConvertButtons(file, caller_post_callback) + end, + } +end + return FileConverter diff --git a/frontend/apps/filemanager/filemanagerfilesearcher.lua b/frontend/apps/filemanager/filemanagerfilesearcher.lua index 6eae03742..13742df3f 100644 --- a/frontend/apps/filemanager/filemanagerfilesearcher.lua +++ b/frontend/apps/filemanager/filemanagerfilesearcher.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local BookList = require("ui/widget/booklist") local ButtonDialog = require("ui/widget/buttondialog") local CheckButton = require("ui/widget/checkbutton") @@ -5,6 +6,7 @@ local ConfirmBox = require("ui/widget/confirmbox") local Device = require("device") local DocumentRegistry = require("document/documentregistry") local FileChooser = require("ui/widget/filechooser") +local FileManagerConverter = require("apps/filemanager/filemanagerconverter") local InfoMessage = require("ui/widget/infomessage") local InputContainer = require("ui/widget/container/inputcontainer") local InputDialog = require("ui/widget/inputdialog") @@ -25,6 +27,9 @@ local FileSearcher = InputContainer:extend{ function FileSearcher:init() self:registerKeyEvents() + if self.ui.file_chooser then + self.ui.menu:registerToMainMenu(self) + end end function FileSearcher:registerKeyEvents() @@ -34,6 +39,30 @@ function FileSearcher:registerKeyEvents() end end +function FileSearcher:addToMainMenu(menu_items) + menu_items.file_search = { + -- @translators Search for files by name. + text = _("File search"), + help_text = _([[Search a book by filename in the current or home folder and its subfolders. + +Wildcards for one '?' or more '*' characters can be used. +A search for '*' will show all files. + +The sorting order is the same as in filemanager. + +Tap a book in the search results to open it.]]), + callback = function() + self:onShowFileSearch() + end, + } + menu_items.file_search_results = { + text = _("Last file search results"), + callback = function() + self:onShowSearchResults() + end, + } +end + function FileSearcher:onShowFileSearch(search_string) local search_dialog, check_button_case, check_button_subfolders, check_button_metadata local function _doSearch() @@ -65,7 +94,7 @@ function FileSearcher:onShowFileSearch(search_string) text = _("Home folder"), enabled = G_reader_settings:has("home_dir"), callback = function() - self.path = G_reader_settings:readSetting("home_dir") + FileSearcher.search_path = G_reader_settings:readSetting("home_dir") _doSearch() end, }, @@ -73,7 +102,7 @@ function FileSearcher:onShowFileSearch(search_string) text = self.ui.file_chooser and _("Current folder") or _("Book folder"), is_enter_default = true, callback = function() - self.path = self.ui.file_chooser and self.ui.file_chooser.path or self.ui:getLastDirFile() + FileSearcher.search_path = self.ui.file_chooser and self.ui.file_chooser.path or self.ui:getLastDirFile() _doSearch() end, }, @@ -106,7 +135,7 @@ function FileSearcher:onShowFileSearch(search_string) end function FileSearcher:doSearch() - local search_hash = self.path .. (FileSearcher.search_string or "") .. + local search_hash = FileSearcher.search_path .. (FileSearcher.search_string or "") .. tostring(self.case_sensitive) .. tostring(self.include_subfolders) .. tostring(self.include_metadata) local not_cached = FileSearcher.search_hash ~= search_hash if not_cached then @@ -163,7 +192,7 @@ function FileSearcher:getList() end local dirs, files = {}, {} - local scan_dirs = {self.path} + local scan_dirs = { FileSearcher.search_path } while #scan_dirs ~= 0 do local new_dirs = {} -- handle each dir @@ -244,47 +273,65 @@ function FileSearcher:showSearchResultsMessage(no_results) ok_text = _("Extract"), ok_callback = function() if not no_results then - self.search_menu.close_callback() + self.booklist_menu.close_callback() end - self.ui.coverbrowser:extractBooksInDirectory(self.path) + self.ui.coverbrowser:extractBooksInDirectory(FileSearcher.search_path) end, }) end end +function FileSearcher:refreshFileManager() + if self.files_updated then + if self.ui.file_chooser then + self.ui.file_chooser:refreshPath() + end + self.files_updated = nil + end +end + function FileSearcher:onShowSearchResults(not_cached) if not not_cached and FileSearcher.search_results == nil then self:onShowFileSearch() - return + return true end - - self.search_menu = BookList:new{ + -- This may be hijacked by CoverBrowser plugin and needs to be known as booklist_menu. + self.booklist_menu = BookList:new{ + name = "filesearcher", subtitle = T(_("Query: %1"), FileSearcher.search_string), title_bar_left_icon = "appbar.menu", onLeftButtonTap = function() self:setSelectMode() end, onMenuSelect = self.onMenuSelect, onMenuHold = self.onMenuHold, - handle_hold_on_hold_release = true, ui = self.ui, _manager = self, + _recreate_func = function() self:onShowSearchResults(not_cached) end, } - self.search_menu.close_callback = function() - self.selected_files = nil - UIManager:close(self.search_menu) - if self.ui.file_chooser then - self.ui.file_chooser:refreshPath() + self.booklist_menu.close_callback = function() + self:refreshFileManager() + UIManager:close(self.booklist_menu) + self.booklist_menu = nil + if self.selected_files then + self.selected_files = nil + for _, item in ipairs(FileSearcher.search_results) do + item.dim = nil + end end end - self:updateMenu(FileSearcher.search_results) - UIManager:show(self.search_menu) + self:updateItemTable(FileSearcher.search_results) + UIManager:show(self.booklist_menu) if not_cached and self.no_metadata_count ~= 0 then self:showSearchResultsMessage() end + return true end -function FileSearcher:updateMenu(item_table) - item_table = item_table or self.search_menu.item_table - self.search_menu:switchItemTable(T(_("Search results (%1)"), #item_table), item_table, -1) +function FileSearcher:updateItemTable(item_table) + if item_table == nil then + item_table = self.booklist_menu.item_table + end + local title = T(_("Search results (%1)"), #item_table) + self.booklist_menu:switchItemTable(title, item_table, -1) end function FileSearcher:onMenuSelect(item) @@ -293,41 +340,90 @@ function FileSearcher:onMenuSelect(item) if item.is_file then item.dim = not item.dim and true or nil self._manager.selected_files[item.path] = item.dim - self._manager:updateMenu() + self._manager:updateItemTable() end else - self._manager:showFileDialog(item) + if item.is_file then + if DocumentRegistry:hasProvider(item.path, nil, true) then + self.close_callback() + local FileManager = require("apps/filemanager/filemanager") + FileManager.openFile(self.ui, item.path) + end + else + self._manager.update_files = nil + self.close_callback() + if self.ui.file_chooser then + local pathname = util.splitFilePathName(item.path) + self.ui.file_chooser:changeToPath(pathname, item.path) + else -- called from Reader + self.ui:onClose() + self.ui:showFileManager(item.path) + end + end end end -function FileSearcher:showFileDialog(item) +function FileSearcher:onMenuHold(item) + if self._manager.selected_files or lfs.attributes(item.path) == nil then return true end local file = item.path - local bookinfo, dialog + local is_file = item.is_file or false + self.file_dialog = nil + local function close_dialog_callback() - UIManager:close(dialog) + UIManager:close(self.file_dialog) end local function close_dialog_menu_callback() - UIManager:close(dialog) - self.search_menu.close_callback() + UIManager:close(self.file_dialog) + self.close_callback() end - local function update_item_callback() - item.mandatory = FileChooser:getMenuItemMandatory(item, FileChooser:getCollate()) - self:updateMenu() + local function close_dialog_update_callback() + UIManager:close(self.file_dialog) + self._manager:updateItemTable() + self._manager.files_updated = true end + local function close_menu_refresh_callback() + self._manager.files_updated = true + self.close_callback() + end + local buttons = {} - if item.is_file then - local is_currently_opened = self.ui.document and self.ui.document.file == file + local book_props, is_currently_opened + if is_file then local has_provider = DocumentRegistry:hasProvider(file) local been_opened = BookList.hasBookBeenOpened(file) - local doc_settings_or_file = is_currently_opened and self.ui.doc_settings - or (been_opened and BookList.getDocSettings(file) or file) + local doc_settings_or_file = file if has_provider or been_opened then - bookinfo = self.ui.bookinfo:getDocProps(file, nil, true) - table.insert(buttons, filemanagerutil.genStatusButtonsRow(doc_settings_or_file, close_dialog_callback)) + book_props = self.ui.coverbrowser and self.ui.coverbrowser:getBookInfo(file) + is_currently_opened = file == (self.ui.document and self.ui.document.file) + if is_currently_opened then + doc_settings_or_file = self.ui.doc_settings + if not book_props then + book_props = self.ui.doc_props + book_props.has_cover = true + end + elseif been_opened then + doc_settings_or_file = BookList.getDocSettings(file) + if not book_props then + local props = doc_settings_or_file:readSetting("doc_props") + book_props = self.ui.bookinfo.extendProps(props, file) + book_props.has_cover = true + end + end + table.insert(buttons, filemanagerutil.genStatusButtonsRow(doc_settings_or_file, close_dialog_update_callback)) table.insert(buttons, {}) -- separator table.insert(buttons, { - filemanagerutil.genResetSettingsButton(doc_settings_or_file, close_dialog_callback, is_currently_opened), - self.ui.collections:genAddToCollectionButton(file, close_dialog_callback, update_item_callback), + filemanagerutil.genResetSettingsButton(doc_settings_or_file, close_dialog_update_callback, is_currently_opened), + self._manager.ui.collections:genAddToCollectionButton(file, close_dialog_callback, close_dialog_update_callback), + }) + end + if Device:canExecuteScript(file) then + table.insert(buttons, { + filemanagerutil.genExecuteScriptButton(file, close_dialog_menu_callback) + }) + end + if FileManagerConverter:isSupported(file) then + table.insert(buttons, { + FileManagerConverter:genConvertButton(file, close_dialog_callback, close_menu_refresh_callback) }) end table.insert(buttons, { @@ -336,65 +432,60 @@ function FileSearcher:showFileDialog(item) enabled = not is_currently_opened, callback = function() local function post_delete_callback() - UIManager:close(dialog) table.remove(FileSearcher.search_results, item.idx) - table.remove(self.search_menu.item_table, item.idx) - self:updateMenu() + table.remove(self.item_table, item.idx) + close_dialog_update_callback() end local FileManager = require("apps/filemanager/filemanager") FileManager:showDeleteFileDialog(file, post_delete_callback) end, }, - filemanagerutil.genBookInformationButton(doc_settings_or_file, bookinfo, close_dialog_callback), + { + text = _("Open with…"), + callback = function() + close_dialog_callback() + local FileManager = require("apps/filemanager/filemanager") + FileManager.showOpenWithDialog(self.ui, file) + end, + }, + }) + table.insert(buttons, { + filemanagerutil.genShowFolderButton(file, close_dialog_menu_callback), + filemanagerutil.genBookInformationButton(doc_settings_or_file, book_props, close_dialog_callback), + }) + if has_provider then + table.insert(buttons, { + filemanagerutil.genBookCoverButton(file, book_props, close_dialog_callback), + filemanagerutil.genBookDescriptionButton(file, book_props, close_dialog_callback), + }) + end + else -- folder + table.insert(buttons, { + filemanagerutil.genShowFolderButton(file, close_dialog_menu_callback), }) end - table.insert(buttons, { - filemanagerutil.genShowFolderButton(file, close_dialog_menu_callback), - { - text = _("Open"), - enabled = DocumentRegistry:hasProvider(file, nil, true), -- allow auxiliary providers - callback = function() - close_dialog_menu_callback() - local FileManager = require("apps/filemanager/filemanager") - FileManager.openFile(self.ui, file) - end, - }, - }) - local title = file - if bookinfo then - if bookinfo.title then - title = title .. "\n\n" .. T(_("Title: %1"), bookinfo.title) - end - if bookinfo.authors then - title = title .. "\n" .. T(_("Authors: %1"), bookinfo.authors:gsub("[\n\t]", "|")) + + if self._manager.file_dialog_added_buttons ~= nil then + for _, row_func in ipairs(self._manager.file_dialog_added_buttons) do + local row = row_func(file, true, book_props) + if row ~= nil then + table.insert(buttons, row) + end end end - dialog = ButtonDialog:new{ - title = title .. "\n", + + self.file_dialog = ButtonDialog:new{ + title = is_file and BD.filename(file) or BD.directory(file), + title_align = "center", buttons = buttons, } - UIManager:show(dialog) + UIManager:show(self.file_dialog) + return true end -function FileSearcher:onMenuHold(item) - if self._manager.selected_files or lfs.attributes(item.path) == nil then return true end - if item.is_file then - if DocumentRegistry:hasProvider(item.path, nil, true) then - self.close_callback() - local FileManager = require("apps/filemanager/filemanager") - FileManager.openFile(self.ui, item.path) - end - else - self.close_callback() - if self.ui.file_chooser then - local pathname = util.splitFilePathName(item.path) - self.ui.file_chooser:changeToPath(pathname, item.path) - else -- called from Reader - self.ui:onClose() - self.ui:showFileManager(item.path) - end - end - return true +function FileSearcher.getMenuInstance() + local ui = require("apps/filemanager/filemanager").instance or require("apps/reader/readerui").instance + return ui.filesearcher.booklist_menu end function FileSearcher:setSelectMode() @@ -402,12 +493,12 @@ function FileSearcher:setSelectMode() self:showSelectModeDialog() else self.selected_files = {} - self.search_menu:setTitleBarLeftIcon("check") + self.booklist_menu:setTitleBarLeftIcon("check") end end function FileSearcher:showSelectModeDialog() - local item_table = self.search_menu.item_table + local item_table = self.booklist_menu.item_table local select_count = util.tableSize(self.selected_files) local actions_enabled = select_count > 0 local title = actions_enabled and T(N_("1 file selected", "%1 files selected", select_count), select_count) @@ -426,7 +517,7 @@ function FileSearcher:showSelectModeDialog() for _, item in ipairs(item_table) do item.dim = nil end - self:updateMenu() + self:updateItemTable() end, }, { @@ -439,7 +530,7 @@ function FileSearcher:showSelectModeDialog() self.selected_files[item.path] = true end end - self:updateMenu() + self:updateItemTable() end, }, }, @@ -449,13 +540,13 @@ function FileSearcher:showSelectModeDialog() callback = function() UIManager:close(select_dialog) self.selected_files = nil - self.search_menu:setTitleBarLeftIcon("appbar.menu") + self.booklist_menu:setTitleBarLeftIcon("appbar.menu") if actions_enabled then for _, item in ipairs(item_table) do item.dim = nil end end - self:updateMenu() + self:updateItemTable() end, }, { @@ -464,14 +555,15 @@ function FileSearcher:showSelectModeDialog() callback = function() UIManager:close(select_dialog) local selected_files = self.selected_files - self.search_menu.close_callback() + self.files_updated = nil -- refresh fm later + self.booklist_menu.close_callback() if self.ui.file_chooser then self.ui.selected_files = selected_files self.ui.title_bar:setRightIcon("check") self.ui.file_chooser:refreshPath() else -- called from Reader self.ui:onClose() - self.ui:showFileManager(self.path .. "/", selected_files) + self.ui:showFileManager(FileSearcher.search_path .. "/", selected_files) end end, }, @@ -485,4 +577,16 @@ function FileSearcher:showSelectModeDialog() UIManager:show(select_dialog) end +function FileSearcher:onBookMetadataChanged() + if self.booklist_menu then + self.booklist_menu:updateItems() + end +end + +function FileSearcher:onCloseWidget() + if self.booklist_menu then + self.booklist_menu.close_callback() + end +end + return FileSearcher diff --git a/frontend/apps/filemanager/filemanagerhistory.lua b/frontend/apps/filemanager/filemanagerhistory.lua index c7a5e8bdb..e68a2083e 100644 --- a/frontend/apps/filemanager/filemanagerhistory.lua +++ b/frontend/apps/filemanager/filemanagerhistory.lua @@ -14,7 +14,7 @@ local _ = require("gettext") local T = require("ffi/util").template local FileManagerHistory = WidgetContainer:extend{ - hist_menu_title = _("History"), + title = _("History"), } function FileManagerHistory:init() @@ -23,7 +23,7 @@ end function FileManagerHistory:addToMainMenu(menu_items) menu_items.history = { - text = self.hist_menu_title, + text = self.title, callback = function() self:onShowHist() end, @@ -48,6 +48,52 @@ function FileManagerHistory:fetchStatuses(count) self.statuses_fetched = true end +function FileManagerHistory:refreshFileManager() + if self.files_updated then + if self.ui.file_chooser then + self.ui.file_chooser:refreshPath() + end + self.files_updated = nil + end +end + +function FileManagerHistory:onShowHist(search_info) + -- This may be hijacked by CoverBrowser plugin and needs to be known as booklist_menu. + self.booklist_menu = BookList:new{ + name = "history", + title_bar_left_icon = "appbar.menu", + onLeftButtonTap = function() self:showHistDialog() end, + onMenuChoice = self.onMenuChoice, + onMenuHold = self.onMenuHold, + ui = self.ui, + _manager = self, + _recreate_func = function() self:onShowHist(search_info) end, + } + self.booklist_menu.close_callback = function() + self:refreshFileManager() + UIManager:close(self.booklist_menu) + self.booklist_menu = nil + self.statuses_fetched = nil + G_reader_settings:saveSetting("history_filter", self.filter) + end + + if search_info then + self.search_string = search_info.search_string + self.case_sensitive = search_info.case_sensitive + else + self.search_string = nil + self.selected_collections = nil + end + self.filter = G_reader_settings:readSetting("history_filter", "all") + self.is_frozen = G_reader_settings:isTrue("history_freeze_finished_books") + if self.filter ~= "all" or self.is_frozen then + self:fetchStatuses(false) + end + self:updateItemTable() + UIManager:show(self.booklist_menu) + return true +end + function FileManagerHistory:updateItemTable() self.count = { all = #require("readhistory").hist, reading = 0, abandoned = 0, complete = 0, deleted = 0, new = 0, } @@ -67,26 +113,8 @@ function FileManagerHistory:updateItemTable() self.count[v.status] = self.count[v.status] + 1 end end - local title = T("%1 (%2)", self.hist_menu_title, #item_table) - local subtitle = "" - if self.search_string then - subtitle = T(_("Query: %1"), self.search_string) - elseif self.selected_collections then - local collections = {} - for collection in pairs(self.selected_collections) do - table.insert(collections, self.ui.collections:getCollectionTitle(collection)) - end - if #collections == 1 then - collections = collections[1] - else - table.sort(collections) - collections = table.concat(collections, ", ") - end - subtitle = T(_("Collections: %1"), collections) - elseif self.filter ~= "all" then - subtitle = BookList.getBookStatusString(self.filter, true) - end - self.hist_menu:switchItemTable(title, item_table, -1, nil, subtitle) + local title, subtitle = self:getBookListTitle(item_table) + self.booklist_menu:switchItemTable(title, item_table, -1, nil, subtitle) end function FileManagerHistory:isItemMatch(item) @@ -109,6 +137,29 @@ function FileManagerHistory:isItemMatch(item) return self.filter == "all" or item.status == self.filter end +function FileManagerHistory:getBookListTitle(item_table) + local title = T(_("History (%1)"), #item_table) + local subtitle = "" + if self.search_string then + subtitle = T(_("Query: %1"), self.search_string) + elseif self.selected_collections then + local collections = {} + for collection in pairs(self.selected_collections) do + table.insert(collections, self.ui.collections:getCollectionTitle(collection)) + end + if #collections == 1 then + collections = collections[1] + else + table.sort(collections) + collections = table.concat(collections, ", ") + end + subtitle = T(_("Collections: %1"), collections) + elseif self.filter ~= "all" then + subtitle = BookList.getBookStatusString(self.filter, true) + end + return title, subtitle +end + function FileManagerHistory:onSetDimensions(dimen) self.dimen = dimen end @@ -133,7 +184,7 @@ function FileManagerHistory:onMenuHold(item) end local function close_dialog_menu_callback() UIManager:close(self.file_dialog) - self._manager.hist_menu.close_callback() + self.close_callback() end local function close_dialog_update_callback() UIManager:close(self.file_dialog) @@ -230,47 +281,7 @@ end function FileManagerHistory.getMenuInstance() local ui = require("apps/filemanager/filemanager").instance or require("apps/reader/readerui").instance - return ui.history.hist_menu -end - -function FileManagerHistory:onShowHist(search_info) - self.hist_menu = BookList:new{ - title_bar_left_icon = "appbar.menu", - onLeftButtonTap = function() self:showHistDialog() end, - onMenuChoice = self.onMenuChoice, - onMenuHold = self.onMenuHold, - ui = self.ui, - _manager = self, - _recreate_func = function() self:onShowHist(search_info) end, - } - self.hist_menu.close_callback = function() - if self.files_updated then -- refresh Filemanager list of files - if self.ui.file_chooser then - self.ui.file_chooser:refreshPath() - end - self.files_updated = nil - end - self.statuses_fetched = nil - UIManager:close(self.hist_menu) - self.hist_menu = nil - G_reader_settings:saveSetting("history_filter", self.filter) - end - - if search_info then - self.search_string = search_info.search_string - self.case_sensitive = search_info.case_sensitive - else - self.search_string = nil - self.selected_collections = nil - end - self.filter = G_reader_settings:readSetting("history_filter", "all") - self.is_frozen = G_reader_settings:isTrue("history_freeze_finished_books") - if self.filter ~= "all" or self.is_frozen then - self:fetchStatuses(false) - end - self:updateItemTable() - UIManager:show(self.hist_menu, "flashui") - return true + return ui.history.booklist_menu end function FileManagerHistory:showHistDialog() @@ -376,7 +387,7 @@ function FileManagerHistory:onSearchHistory() if search_string ~= "" then UIManager:close(search_dialog) self.search_string = self.case_sensitive and search_string or search_string:lower() - if self.hist_menu then -- called from History + if self.booklist_menu then -- called from History self:updateItemTable() else -- called by Dispatcher local search_info = { @@ -406,8 +417,8 @@ function FileManagerHistory:onSearchHistory() end function FileManagerHistory:onBookMetadataChanged() - if self.hist_menu then - self.hist_menu:updateItems() + if self.booklist_menu then + self.booklist_menu:updateItems() end end diff --git a/frontend/apps/filemanager/filemanagermenu.lua b/frontend/apps/filemanager/filemanagermenu.lua index 8a3d15e4d..21f9c404d 100644 --- a/frontend/apps/filemanager/filemanagermenu.lua +++ b/frontend/apps/filemanager/filemanagermenu.lua @@ -388,6 +388,7 @@ To: end, callback = function() G_reader_settings:flipNilOrTrue("collection_show_mark") + self.ui.collections.show_mark = G_reader_settings:nilOrTrue("collection_show_mark") FileChooser:refreshPath() end, }, @@ -805,28 +806,6 @@ To: end, } - self.menu_items.file_search = { - -- @translators Search for files by name. - text = _("File search"), - help_text = _([[Search a book by filename in the current or home folder and its subfolders. - -Wildcards for one '?' or more '*' characters can be used. -A search for '*' will show all files. - -The sorting order is the same as in filemanager. - -Tap a book in the search results to open it.]]), - callback = function() - self.ui.filesearcher:onShowFileSearch() - end, - } - self.menu_items.file_search_results = { - text = _("Last file search results"), - callback = function() - self.ui.filesearcher:onShowSearchResults() - end, - } - -- main menu tab self.menu_items.open_last_document = { text_func = function() diff --git a/plugins/coverbrowser.koplugin/main.lua b/plugins/coverbrowser.koplugin/main.lua index 46772f587..9e6bec915 100644 --- a/plugins/coverbrowser.koplugin/main.lua +++ b/plugins/coverbrowser.koplugin/main.lua @@ -20,13 +20,22 @@ local _FileChooser__recalculateDimen_orig = FileChooser._recalculateDimen local _FileChooser_updateItems_orig = FileChooser.updateItems local _FileChooser_onCloseWidget_orig = FileChooser.onCloseWidget -local FileManagerHistory = require("apps/filemanager/filemanagerhistory") -local _FileManagerHistory_updateItemTable_orig = FileManagerHistory.updateItemTable - -local FileManagerCollection = require("apps/filemanager/filemanagercollection") -local _FileManagerCollection_updateItemTable_orig = FileManagerCollection.updateItemTable - local FileManager = require("apps/filemanager/filemanager") +local FileManagerHistory = require("apps/filemanager/filemanagerhistory") +local FileManagerCollection = require("apps/filemanager/filemanagercollection") +local FileManagerFileSearcher = require("apps/filemanager/filemanagerfilesearcher") + +local _modified_widgets = { + filemanager = FileManager, + history = FileManagerHistory, + collections = FileManagerCollection, + filesearcher = FileManagerFileSearcher, +} +local _updateItemTable_orig_funcs = { + history = FileManagerHistory.updateItemTable, + collections = FileManagerCollection.updateItemTable, + filesearcher = FileManagerFileSearcher.updateItemTable, +} -- Available display modes local DISPLAY_MODES = { @@ -37,12 +46,19 @@ local DISPLAY_MODES = { list_only_meta = true, -- metadata with no image list_image_filename = true, -- image with filename (no metadata) } +local display_mode_db_names = { + filemanager = "filemanager_display_mode", + history = "history_display_mode", + collections = "collection_display_mode", +} -- Store some states as locals, to be permanent across instantiations local init_done = false -local filemanager_display_mode = false -- not initialized yet -local history_display_mode = false -- not initialized yet -local collection_display_mode = false -- not initialized yet +local curr_display_modes = { + filemanager = false, -- not initialized yet + history = false, -- not initialized yet + collections = false, -- not initialized yet +} local series_mode = nil -- defaults to not display series local CoverBrowser = WidgetContainer:extend{ @@ -80,8 +96,8 @@ function CoverBrowser:init() end self:setupFileManagerDisplayMode(BookInfoManager:getSetting("filemanager_display_mode")) - self:setupHistoryDisplayMode(BookInfoManager:getSetting("history_display_mode")) - self:setupCollectionDisplayMode(BookInfoManager:getSetting("collection_display_mode")) + CoverBrowser.setupWidgetDisplayMode("history") + CoverBrowser.setupWidgetDisplayMode("collections") series_mode = BookInfoManager:getSetting("series_mode") init_done = true BookInfoManager:closeDbConnection() -- will be re-opened if needed @@ -94,7 +110,7 @@ function CoverBrowser:addToMainMenu(menu_items) sub_item_table[i] = { text = text, checked_func = function() - return mode == filemanager_display_mode + return mode == curr_display_modes["filemanager"] end, callback = function() self:setDisplayMode(mode) @@ -103,19 +119,19 @@ function CoverBrowser:addToMainMenu(menu_items) history_sub_item_table[i] = { text = text, checked_func = function() - return mode == history_display_mode + return mode == curr_display_modes["history"] end, callback = function() - self:setupHistoryDisplayMode(mode) + CoverBrowser.setupWidgetDisplayMode("history", mode) end, } collection_sub_item_table[i] = { text = text, checked_func = function() - return mode == collection_display_mode + return mode == curr_display_modes["collections"] end, callback = function() - self:setupCollectionDisplayMode(mode) + CoverBrowser.setupWidgetDisplayMode("collections", mode) end, } end @@ -127,8 +143,8 @@ function CoverBrowser:addToMainMenu(menu_items) end, callback = function() if BookInfoManager:toggleSetting("unified_display_mode") then - self:setupHistoryDisplayMode(filemanager_display_mode) - self:setupCollectionDisplayMode(filemanager_display_mode) + CoverBrowser.setupWidgetDisplayMode("history", curr_display_modes["filemanager"]) + CoverBrowser.setupWidgetDisplayMode("collections", curr_display_modes["filemanager"]) end end, }) @@ -487,7 +503,7 @@ function CoverBrowser:addToMainMenu(menu_items) end function CoverBrowser:genExtractBookInfoButton(close_dialog_callback) -- for FileManager Plus dialog - return filemanager_display_mode and { + return curr_display_modes["filemanager"] and { { text = _("Extract and cache book information"), callback = function() @@ -515,7 +531,8 @@ function CoverBrowser.initGrid(menu, display_mode) menu.display_mode_type = display_mode and display_mode:gsub("_.*", "") -- "mosaic" or "list" end -function CoverBrowser.addFileDialogButtons(widget) +function CoverBrowser.addFileDialogButtons(widget_id) + local widget = _modified_widgets[widget_id] FileManager.addFileDialogButtons(widget, "coverbrowser_1", function(file, is_file, bookinfo) if is_file then return bookinfo and { @@ -526,6 +543,7 @@ function CoverBrowser.addFileDialogButtons(widget) BookInfoManager:setBookInfoProperties(file, { ["ignore_cover"] = not bookinfo.ignore_cover and 'Y' or false, }) + widget.files_updated = true local menu = widget.getMenuInstance() UIManager:close(menu.file_dialog) menu:updateItems(1, true) @@ -538,6 +556,7 @@ function CoverBrowser.addFileDialogButtons(widget) BookInfoManager:setBookInfoProperties(file, { ["ignore_meta"] = not bookinfo.ignore_meta and 'Y' or false, }) + widget.files_updated = true local menu = widget.getMenuInstance() UIManager:close(menu.file_dialog) menu:updateItems(1, true) @@ -552,9 +571,10 @@ function CoverBrowser.addFileDialogButtons(widget) { -- Allow a new extraction (multiple interruptions, book replaced)... text = _("Refresh cached book information"), callback = function() + BookInfoManager:deleteBookInfo(file) + widget.files_updated = true local menu = widget.getMenuInstance() menu.resetBookInfoCache(file) - BookInfoManager:deleteBookInfo(file) UIManager:close(menu.file_dialog) menu:updateItems(1, true) end, @@ -564,7 +584,8 @@ function CoverBrowser.addFileDialogButtons(widget) end) end -function CoverBrowser.removeFileDialogButtons(widget) +function CoverBrowser.removeFileDialogButtons(widget_id) + local widget = _modified_widgets[widget_id] FileManager.removeFileDialogButtons(widget, "coverbrowser_2") FileManager.removeFileDialogButtons(widget, "coverbrowser_1") end @@ -580,8 +601,8 @@ end function CoverBrowser:setDisplayMode(display_mode) self:setupFileManagerDisplayMode(display_mode) if BookInfoManager:getSetting("unified_display_mode") then - self:setupHistoryDisplayMode(display_mode) - self:setupCollectionDisplayMode(display_mode) + CoverBrowser.setupWidgetDisplayMode("history", display_mode) + CoverBrowser.setupWidgetDisplayMode("collections", display_mode) end end @@ -589,14 +610,14 @@ function CoverBrowser:setupFileManagerDisplayMode(display_mode) if not DISPLAY_MODES[display_mode] then display_mode = nil -- unknown mode, fallback to classic end - if init_done and display_mode == filemanager_display_mode then -- no change + if init_done and display_mode == curr_display_modes["filemanager"] then -- no change return end if init_done then -- save new mode in db - BookInfoManager:saveSetting("filemanager_display_mode", display_mode) + BookInfoManager:saveSetting(display_mode_db_names["filemanager"], display_mode) end -- remember current mode in module variable - filemanager_display_mode = display_mode + curr_display_modes["filemanager"] = display_mode logger.dbg("CoverBrowser: setting FileManager display mode to:", display_mode or "classic") -- init Mosaic and List grid dimensions (in Classic mode used in the settings menu) @@ -607,11 +628,13 @@ function CoverBrowser:setupFileManagerDisplayMode(display_mode) end if not display_mode then -- classic mode + CoverBrowser.removeFileDialogButtons("filesearcher") + _modified_widgets["filesearcher"].updateItemTable = _updateItemTable_orig_funcs["filesearcher"] -- Put back original methods FileChooser.updateItems = _FileChooser_updateItems_orig FileChooser.onCloseWidget = _FileChooser_onCloseWidget_orig FileChooser._recalculateDimen = _FileChooser__recalculateDimen_orig - CoverBrowser.removeFileDialogButtons(FileManager) + CoverBrowser.removeFileDialogButtons("filemanager") -- Also clean-up what we added, even if it does not bother original code FileChooser._updateItemsBuildUI = nil FileChooser._do_cover_images = nil @@ -622,12 +645,14 @@ function CoverBrowser:setupFileManagerDisplayMode(display_mode) return end + CoverBrowser.addFileDialogButtons("filesearcher") + _modified_widgets["filesearcher"].updateItemTable = CoverBrowser.getUpdateItemTableFunc(display_mode) -- In both mosaic and list modes, replace original methods with those from -- our generic CoverMenu local CoverMenu = require("covermenu") FileChooser.updateItems = CoverMenu.updateItems FileChooser.onCloseWidget = CoverMenu.onCloseWidget - CoverBrowser.addFileDialogButtons(FileManager) + CoverBrowser.addFileDialogButtons("filemanager") if FileChooser.display_mode_type == "mosaic" then -- Replace some other original methods with those from our MosaicMenu local MosaicMenu = require("mosaicmenu") @@ -635,7 +660,6 @@ function CoverBrowser:setupFileManagerDisplayMode(display_mode) FileChooser._updateItemsBuildUI = MosaicMenu._updateItemsBuildUI -- Set MosaicMenu behaviour: FileChooser._do_cover_images = display_mode ~= "mosaic_text" - FileChooser._do_hint_opened = true -- dogear at bottom -- Don't have "../" centered in empty directories FileChooser._do_center_partial_rows = false elseif FileChooser.display_mode_type == "list" then @@ -646,8 +670,8 @@ function CoverBrowser:setupFileManagerDisplayMode(display_mode) -- Set ListMenu behaviour: FileChooser._do_cover_images = display_mode ~= "list_only_meta" FileChooser._do_filename_only = display_mode == "list_image_filename" - FileChooser._do_hint_opened = true -- dogear at bottom end + FileChooser._do_hint_opened = true -- dogear at bottom if init_done then self:refreshFileManagerInstance() @@ -661,157 +685,84 @@ function CoverBrowser:setupFileManagerDisplayMode(display_mode) end end -local function _FileManagerHistory_updateItemTable(self, ...) - -- 'self' here is the single FileManagerHistory instance - -- FileManagerHistory has just created a new instance of Menu as 'hist_menu' - -- at each display of History. Soon after instantiation, this method - -- is called. The first time it is called, we replace some methods. - local display_mode = self.display_mode - local hist_menu = self.hist_menu - - if not hist_menu._coverbrowser_overridden then - hist_menu._coverbrowser_overridden = true - - -- In both mosaic and list modes, replace original methods with those from - -- our generic CoverMenu - local CoverMenu = require("covermenu") - hist_menu.updateItems = CoverMenu.updateItems - hist_menu.onCloseWidget = CoverMenu.onCloseWidget - - CoverBrowser.initGrid(hist_menu, display_mode) - if hist_menu.display_mode_type == "mosaic" then - -- Replace some other original methods with those from our MosaicMenu - local MosaicMenu = require("mosaicmenu") - hist_menu._recalculateDimen = MosaicMenu._recalculateDimen - hist_menu._updateItemsBuildUI = MosaicMenu._updateItemsBuildUI - -- Set MosaicMenu behaviour: - hist_menu._do_cover_images = display_mode ~= "mosaic_text" - hist_menu._do_center_partial_rows = true -- nicer looking when few elements - - elseif hist_menu.display_mode_type == "list" then - -- Replace some other original methods with those from our ListMenu - local ListMenu = require("listmenu") - hist_menu._recalculateDimen = ListMenu._recalculateDimen - hist_menu._updateItemsBuildUI = ListMenu._updateItemsBuildUI - -- Set ListMenu behaviour: - hist_menu._do_cover_images = display_mode ~= "list_only_meta" - hist_menu._do_filename_only = display_mode == "list_image_filename" - - end - hist_menu._do_hint_opened = BookInfoManager:getSetting("history_hint_opened") - end - - -- And do now what the original does - _FileManagerHistory_updateItemTable_orig(self, ...) -end - -function CoverBrowser:setupHistoryDisplayMode(display_mode) +function CoverBrowser.setupWidgetDisplayMode(widget_id, display_mode) + display_mode = display_mode or BookInfoManager:getSetting(display_mode_db_names[widget_id]) if not DISPLAY_MODES[display_mode] then display_mode = nil -- unknown mode, fallback to classic end - if init_done and display_mode == history_display_mode then -- no change + if init_done and display_mode == curr_display_modes[widget_id] then -- no change return end if init_done then -- save new mode in db - BookInfoManager:saveSetting("history_display_mode", display_mode) + BookInfoManager:saveSetting(display_mode_db_names[widget_id], display_mode) end -- remember current mode in module variable - history_display_mode = display_mode - logger.dbg("CoverBrowser: setting History display mode to:", display_mode or "classic") + curr_display_modes[widget_id] = display_mode + logger.dbg("CoverBrowser: setting display mode:", widget_id, display_mode or "classic") if not init_done and not display_mode then return -- starting in classic mode, nothing to patch end - -- We only need to replace one FileManagerHistory method - if not display_mode then -- classic mode - CoverBrowser.removeFileDialogButtons(FileManagerHistory) - -- Put back original methods - FileManagerHistory.updateItemTable = _FileManagerHistory_updateItemTable_orig - FileManagerHistory.display_mode = nil - else - CoverBrowser.addFileDialogButtons(FileManagerHistory) - -- Replace original method with the one defined above - FileManagerHistory.updateItemTable = _FileManagerHistory_updateItemTable - -- And let it know which display_mode we should use - FileManagerHistory.display_mode = display_mode + -- We only need to replace one method + local widget = _modified_widgets[widget_id] + if display_mode then + CoverBrowser.addFileDialogButtons(widget_id) + widget.updateItemTable = CoverBrowser.getUpdateItemTableFunc(display_mode) + else -- classic mode + CoverBrowser.removeFileDialogButtons(widget_id) + widget.updateItemTable = _updateItemTable_orig_funcs[widget_id] end end -local function _FileManagerCollections_updateItemTable(self, ...) - -- 'self' here is the single FileManagerCollections instance - -- FileManagerCollections has just created a new instance of Menu as 'coll_menu' - -- at each display of Collection/Favorites. Soon after instantiation, this method - -- is called. The first time it is called, we replace some methods. - local display_mode = self.display_mode - local coll_menu = self.coll_menu +function CoverBrowser.getUpdateItemTableFunc(display_mode) + return function(this, ...) + -- 'this' here is the single widget instance + -- The widget has just created a new instance of BookList as 'booklist_menu' + -- at each display of the widget. Soon after instantiation, this method + -- is called. The first time it is called, we replace some methods. + local booklist_menu = this.booklist_menu + local widget_id = booklist_menu.name - if not coll_menu._coverbrowser_overridden then - coll_menu._coverbrowser_overridden = true + if not booklist_menu._coverbrowser_overridden then + booklist_menu._coverbrowser_overridden = true - -- In both mosaic and list modes, replace original methods with those from - -- our generic CoverMenu - local CoverMenu = require("covermenu") - coll_menu.updateItems = CoverMenu.updateItems - coll_menu.onCloseWidget = CoverMenu.onCloseWidget + -- In both mosaic and list modes, replace original methods with those from + -- our generic CoverMenu + local CoverMenu = require("covermenu") + booklist_menu.updateItems = CoverMenu.updateItems + booklist_menu.onCloseWidget = CoverMenu.onCloseWidget - CoverBrowser.initGrid(coll_menu, display_mode) - if coll_menu.display_mode_type == "mosaic" then - -- Replace some other original methods with those from our MosaicMenu - local MosaicMenu = require("mosaicmenu") - coll_menu._recalculateDimen = MosaicMenu._recalculateDimen - coll_menu._updateItemsBuildUI = MosaicMenu._updateItemsBuildUI - -- Set MosaicMenu behaviour: - coll_menu._do_cover_images = display_mode ~= "mosaic_text" - coll_menu._do_center_partial_rows = true -- nicer looking when few elements - - elseif coll_menu.display_mode_type == "list" then - -- Replace some other original methods with those from our ListMenu - local ListMenu = require("listmenu") - coll_menu._recalculateDimen = ListMenu._recalculateDimen - coll_menu._updateItemsBuildUI = ListMenu._updateItemsBuildUI - -- Set ListMenu behaviour: - coll_menu._do_cover_images = display_mode ~= "list_only_meta" - coll_menu._do_filename_only = display_mode == "list_image_filename" + CoverBrowser.initGrid(booklist_menu, display_mode) + if booklist_menu.display_mode_type == "mosaic" then + -- Replace some other original methods with those from our MosaicMenu + local MosaicMenu = require("mosaicmenu") + booklist_menu._recalculateDimen = MosaicMenu._recalculateDimen + booklist_menu._updateItemsBuildUI = MosaicMenu._updateItemsBuildUI + -- Set MosaicMenu behaviour: + booklist_menu._do_cover_images = display_mode ~= "mosaic_text" + booklist_menu._do_center_partial_rows = true -- nicer looking when few elements + elseif booklist_menu.display_mode_type == "list" then + -- Replace some other original methods with those from our ListMenu + local ListMenu = require("listmenu") + booklist_menu._recalculateDimen = ListMenu._recalculateDimen + booklist_menu._updateItemsBuildUI = ListMenu._updateItemsBuildUI + -- Set ListMenu behaviour: + booklist_menu._do_cover_images = display_mode ~= "list_only_meta" + booklist_menu._do_filename_only = display_mode == "list_image_filename" + end + if widget_id == "history" then + booklist_menu._do_hint_opened = BookInfoManager:getSetting("history_hint_opened") + elseif widget_id == "collections" then + booklist_menu._do_hint_opened = BookInfoManager:getSetting("collections_hint_opened") + else -- "filesearcher" + booklist_menu._do_hint_opened = true + end end - coll_menu._do_hint_opened = BookInfoManager:getSetting("collections_hint_opened") - end - -- And do now what the original does - _FileManagerCollection_updateItemTable_orig(self, ...) -end - -function CoverBrowser:setupCollectionDisplayMode(display_mode) - if not DISPLAY_MODES[display_mode] then - display_mode = nil -- unknown mode, fallback to classic - end - if init_done and display_mode == collection_display_mode then -- no change - return - end - if init_done then -- save new mode in db - BookInfoManager:saveSetting("collection_display_mode", display_mode) - end - -- remember current mode in module variable - collection_display_mode = display_mode - logger.dbg("CoverBrowser: setting Collection display mode to:", display_mode or "classic") - - if not init_done and not display_mode then - return -- starting in classic mode, nothing to patch - end - - -- We only need to replace one FileManagerCollection method - if not display_mode then -- classic mode - CoverBrowser.removeFileDialogButtons(FileManagerCollection) - -- Put back original methods - FileManagerCollection.updateItemTable = _FileManagerCollection_updateItemTable_orig - FileManagerCollection.display_mode = nil - else - CoverBrowser.addFileDialogButtons(FileManagerCollection) - -- Replace original method with the one defined above - FileManagerCollection.updateItemTable = _FileManagerCollections_updateItemTable - -- And let it know which display_mode we should use - FileManagerCollection.display_mode = display_mode + -- And do now what the original does + _updateItemTable_orig_funcs[widget_id](this, ...) end end