From bf6c0cdd6c5b22bbb38497b5df8abe428eb80307 Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Sat, 6 Mar 2021 22:44:18 +0100 Subject: [PATCH] LuaSettings: Add a method to initialize a setting properly (#7371) * LuaSettings/DocSettings: Updated readSetting API to allow proper initialization to default. Use it to initialize tables, e.g., fixing corner-cases in readerFooter that could prevent settings from being saved. (Fixes an issue reported on Gitter). * LuaSettings/DocSettings: Add simpler API than the the flip* ones to toggle boolean settings. * Update LuaSettings/DocSettigns usage throughout the codebase to use the dedicated boolean methods wher appropriate, and clean up some of the more mind-bending uses. * FileChooser: Implement an extended default exclusion list (fix #2360) * ScreenSaver: Refactor to avoid the pile of kludges this was threatening to become. Code should be easier to follow and use, and fallbacks now behave as expected (fix #4418). --- frontend/apps/cloudstorage/cloudstorage.lua | 1 + frontend/apps/filemanager/filemanager.lua | 12 +- .../apps/filemanager/filemanagerbookinfo.lua | 18 +- .../filemanager/filemanagerfilesearcher.lua | 5 +- frontend/apps/filemanager/filemanagermenu.lua | 24 +- .../apps/filemanager/filemanagershortcuts.lua | 27 +- .../apps/reader/modules/readerbookmark.lua | 12 +- frontend/apps/reader/modules/readerconfig.lua | 5 +- .../reader/modules/readercoptlistener.lua | 5 +- .../apps/reader/modules/readerdictionary.lua | 45 +- frontend/apps/reader/modules/readerdogear.lua | 18 +- frontend/apps/reader/modules/readerfont.lua | 41 +- frontend/apps/reader/modules/readerfooter.lua | 16 +- .../apps/reader/modules/readerhighlight.lua | 26 +- .../reader/modules/readerkoptlistener.lua | 12 +- frontend/apps/reader/modules/readerlink.lua | 2 +- frontend/apps/reader/modules/readermenu.lua | 15 +- .../apps/reader/modules/readerpagemap.lua | 24 +- frontend/apps/reader/modules/readerpaging.lua | 16 +- .../apps/reader/modules/readerrolling.lua | 46 +- .../apps/reader/modules/readerstyletweak.lua | 4 +- frontend/apps/reader/modules/readertoc.lua | 8 +- .../apps/reader/modules/readertypeset.lua | 74 +- .../apps/reader/modules/readertypography.lua | 115 +-- frontend/apps/reader/modules/readerview.lua | 21 +- .../apps/reader/modules/readerwikipedia.lua | 10 +- .../apps/reader/modules/readerzooming.lua | 14 +- frontend/apps/reader/readerui.lua | 2 +- frontend/device/cervantes/device.lua | 1 + frontend/device/devicelistener.lua | 2 +- frontend/device/generic/device.lua | 22 +- frontend/device/kindle/device.lua | 12 +- frontend/device/kobo/device.lua | 6 +- frontend/device/sdl/device.lua | 8 +- frontend/device/sony-prstux/device.lua | 1 + frontend/docsettings.lua | 124 +++- frontend/document/credocument.lua | 6 +- frontend/document/documentregistry.lua | 10 +- frontend/luasettings.lua | 71 +- frontend/readhistory.lua | 4 +- frontend/ui/data/settings_migration.lua | 6 +- .../elements/common_settings_menu_table.lua | 13 +- frontend/ui/elements/flash_keyboard.lua | 4 +- .../screen_disable_double_tap_table.lua | 4 +- frontend/ui/elements/screensaver_menu.lua | 136 ++-- frontend/ui/network/manager.lua | 18 +- frontend/ui/screensaver.lua | 694 ++++++++++-------- frontend/ui/translator.lua | 4 +- frontend/ui/uimanager.lua | 12 +- frontend/ui/widget/configdialog.lua | 2 +- frontend/ui/widget/dictquicklookup.lua | 6 +- frontend/ui/widget/filechooser.lua | 90 ++- frontend/ui/widget/pathchooser.lua | 2 +- frontend/ui/widget/virtualkeyboard.lua | 2 +- frontend/util.lua | 42 +- plugins/autosuspend.koplugin/main.lua | 53 +- plugins/autoturn.koplugin/main.lua | 4 +- plugins/calibre.koplugin/main.lua | 7 +- plugins/calibre.koplugin/metadata.lua | 11 +- plugins/calibre.koplugin/search.lua | 2 +- plugins/calibre.koplugin/wireless.lua | 2 +- plugins/coverbrowser.koplugin/main.lua | 2 +- plugins/coverimage.koplugin/main.lua | 10 +- plugins/gestures.koplugin/main.lua | 10 +- plugins/gestures.koplugin/migration.lua | 2 +- plugins/kosync.koplugin/main.lua | 3 +- plugins/newsdownloader.koplugin/main.lua | 10 +- plugins/opds.koplugin/opdsbrowser.lua | 118 ++- plugins/perceptionexpander.koplugin/main.lua | 2 +- plugins/statistics.koplugin/main.lua | 147 ++-- plugins/terminal.koplugin/main.lua | 12 +- plugins/texteditor.koplugin/main.lua | 7 +- plugins/zsync.koplugin/main.lua | 2 +- reader.lua | 2 +- spec/unit/autofrontlight_spec.lua | 2 +- spec/unit/luadata_spec.lua | 4 +- spec/unit/luasettings_spec.lua | 4 +- spec/unit/readhistory_spec.lua | 4 +- 78 files changed, 1273 insertions(+), 1067 deletions(-) diff --git a/frontend/apps/cloudstorage/cloudstorage.lua b/frontend/apps/cloudstorage/cloudstorage.lua index 10b4247c4..a1ae9866b 100644 --- a/frontend/apps/cloudstorage/cloudstorage.lua +++ b/frontend/apps/cloudstorage/cloudstorage.lua @@ -32,6 +32,7 @@ local CloudStorage = Menu:extend{ } function CloudStorage:init() + --- @todo: Probably a good candidate for the new readSetting API self.cs_settings = self:readSettings() self.show_parent = self if self.item then diff --git a/frontend/apps/filemanager/filemanager.lua b/frontend/apps/filemanager/filemanager.lua index f7c0f9bcc..38ebe2bbf 100644 --- a/frontend/apps/filemanager/filemanager.lua +++ b/frontend/apps/filemanager/filemanager.lua @@ -169,9 +169,13 @@ function FileManager:setupLayout() } } - local g_show_hidden = G_reader_settings:readSetting("show_hidden") - local show_hidden = g_show_hidden == nil and DSHOWHIDDENFILES or g_show_hidden - local show_unsupported = G_reader_settings:readSetting("show_unsupported") + local show_hidden + if G_reader_settings:has("show_hidden") then + show_hidden = G_reader_settings:isTrue("show_hidden") + else + show_hidden = DSHOWHIDDENFILES + end + local show_unsupported = G_reader_settings:isTrue("show_unsupported") local file_chooser = FileChooser:new{ -- remember to adjust the height when new item is added to the group path = self.root_path, @@ -760,7 +764,7 @@ end function FileManager:goHome() local home_dir = G_reader_settings:readSetting("home_dir") - if not home_dir or lfs.attributes(home_dir, "mode") ~= "directory" then + if not home_dir or lfs.attributes(home_dir, "mode") ~= "directory" then -- Try some sane defaults, depending on platform home_dir = Device.home_dir end diff --git a/frontend/apps/filemanager/filemanagerbookinfo.lua b/frontend/apps/filemanager/filemanagerbookinfo.lua index 91c132ca0..2f8697c33 100644 --- a/frontend/apps/filemanager/filemanagerbookinfo.lua +++ b/frontend/apps/filemanager/filemanagerbookinfo.lua @@ -67,7 +67,7 @@ function BookInfo:show(file, book_props) table.insert(kv_pairs, { _("Folder:"), BD.dirpath(filemanagerutil.abbreviate(directory)), separator = true }) -- book_props may be provided if caller already has them available - -- but it may lack 'pages', that we may get from sidecar file + -- but it may lack "pages", that we may get from sidecar file if not book_props or not book_props.pages then -- check there is actually a sidecar file before calling DocSettings:open() -- that would create an empty sidecar directory @@ -75,24 +75,24 @@ function BookInfo:show(file, book_props) local doc_settings = DocSettings:open(file) if doc_settings then if not book_props then - -- Files opened after 20170701 have a 'doc_props' setting with - -- complete metadata and 'doc_pages' with accurate nb of pages - book_props = doc_settings:readSetting('doc_props') + -- Files opened after 20170701 have a "doc_props" setting with + -- complete metadata and "doc_pages" with accurate nb of pages + book_props = doc_settings:readSetting("doc_props") end if not book_props then - -- File last opened before 20170701 may have a 'stats' setting + -- File last opened before 20170701 may have a "stats" setting. -- with partial metadata, or empty metadata if statistics plugin -- was not enabled when book was read (we can guess that from -- the fact that stats.page = 0) - local stats = doc_settings:readSetting('stats') + 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 end end - -- Files opened after 20170701 have an accurate 'doc_pages' setting - local doc_pages = doc_settings:readSetting('doc_pages') + -- Files opened after 20170701 have an accurate "doc_pages" setting. + local doc_pages = doc_settings:readSetting("doc_pages") if doc_pages and book_props then book_props.pages = doc_pages end @@ -100,7 +100,7 @@ function BookInfo:show(file, book_props) end end - -- If still no book_props (book never opened or empty 'stats'), open the + -- If still no book_props (book never opened or empty "stats"), open the -- document to get them if not book_props then local document = DocumentRegistry:openDocument(file) diff --git a/frontend/apps/filemanager/filemanagerfilesearcher.lua b/frontend/apps/filemanager/filemanagerfilesearcher.lua index 117c7c133..42c33c458 100644 --- a/frontend/apps/filemanager/filemanagerfilesearcher.lua +++ b/frontend/apps/filemanager/filemanagerfilesearcher.lua @@ -95,10 +95,7 @@ end function FileSearcher:onShowFileSearch() local dummy = self.search_value - local enabled_search_home_dir = true - if not G_reader_settings:readSetting("home_dir") then - enabled_search_home_dir = false - end + local enabled_search_home_dir = G_reader_settings:has("home_dir") self.search_dialog = InputDialog:new{ title = _("Search for books by filename"), input = self.search_value, diff --git a/frontend/apps/filemanager/filemanagermenu.lua b/frontend/apps/filemanager/filemanagermenu.lua index 4871f8233..e7add1358 100644 --- a/frontend/apps/filemanager/filemanagermenu.lua +++ b/frontend/apps/filemanager/filemanagermenu.lua @@ -236,18 +236,18 @@ function FileManagerMenu:setUpdateItemTable() local current_state = _("Show new files in bold") if G_reader_settings:readSetting("show_file_in_bold") == "opened" then current_state = _("Show opened files in bold") - elseif G_reader_settings:readSetting("show_file_in_bold") == false then + elseif G_reader_settings:isFalse("show_file_in_bold") then current_state = _("Show files in bold") -- with checkmark unchecked end -- Inform that this settings applies only to classic file chooser current_state = T(_("(Classic file browser) %1"), current_state) return current_state end, - checked_func = function() return G_reader_settings:readSetting("show_file_in_bold") ~= false end, + checked_func = function() return not G_reader_settings:isFalse("show_file_in_bold") end, sub_item_table = { { text = _("Don't show files in bold"), - checked_func = function() return G_reader_settings:readSetting("show_file_in_bold") == false end, + checked_func = function() return G_reader_settings:isFalse("show_file_in_bold") end, callback = function() G_reader_settings:saveSetting("show_file_in_bold", false) self.ui:onRefresh() @@ -264,7 +264,7 @@ function FileManagerMenu:setUpdateItemTable() { text = _("Show new (not yet opened) files in bold"), checked_func = function() - return G_reader_settings:readSetting("show_file_in_bold") ~= false and G_reader_settings:readSetting("show_file_in_bold") ~= "opened" + return not G_reader_settings:isFalse("show_file_in_bold") and G_reader_settings:readSetting("show_file_in_bold") ~= "opened" end, callback = function() G_reader_settings:delSetting("show_file_in_bold") @@ -296,12 +296,12 @@ To: }, { text = _("Show filename in Open last/previous menu items"), - checked_func = function() return G_reader_settings:readSetting("open_last_menu_show_filename") end, + checked_func = function() return G_reader_settings:isTrue("open_last_menu_show_filename") end, callback = function() G_reader_settings:flipNilOrFalse("open_last_menu_show_filename") end, }, { text = _("Auto-remove deleted or purged items from history"), - checked_func = function() return G_reader_settings:readSetting("autoremove_deleted_items_from_history") end, + checked_func = function() return G_reader_settings:isTrue("autoremove_deleted_items_from_history") end, callback = function() G_reader_settings:flipNilOrFalse("autoremove_deleted_items_from_history") end, separator = true, }, @@ -413,7 +413,7 @@ To: else dbg:setVerbose(false) dbg:turnOff() - G_reader_settings:flipFalse("debug_verbose") + G_reader_settings:makeFalse("debug_verbose") end end, }, @@ -494,7 +494,7 @@ To: G_reader_settings:saveSetting("dev_no_hw_dither", not Device.screen.hw_dithering) -- Make sure SW dithering gets disabled when we enable HW dithering if Device.screen.hw_dithering and Device.screen.sw_dithering then - G_reader_settings:saveSetting("dev_no_sw_dither", true) + G_reader_settings:makeTrue("dev_no_sw_dither") Device.screen:toggleSWDithering(false) end UIManager:setDirty("all", "full") @@ -515,7 +515,7 @@ To: G_reader_settings:saveSetting("dev_no_sw_dither", not Device.screen.sw_dithering) -- Make sure HW dithering gets disabled when we enable SW dithering if Device.screen.hw_dithering and Device.screen.sw_dithering then - G_reader_settings:saveSetting("dev_no_hw_dither", true) + G_reader_settings:makeTrue("dev_no_hw_dither") Device.screen:toggleHWDithering(false) end UIManager:setDirty("all", "full") @@ -621,15 +621,15 @@ To: -- main menu tab self.menu_items.open_last_document = { text_func = function() - if not G_reader_settings:isTrue("open_last_menu_show_filename") or not G_reader_settings:readSetting("lastfile") then + if not G_reader_settings:isTrue("open_last_menu_show_filename") or G_reader_settings:hasNot("lastfile") then return _("Open last document") end local last_file = G_reader_settings:readSetting("lastfile") - local path, file_name = util.splitFilePathName(last_file); -- luacheck: no unused + local path, file_name = util.splitFilePathName(last_file) -- luacheck: no unused return T(_("Last: %1"), BD.filename(file_name)) end, enabled_func = function() - return G_reader_settings:readSetting("lastfile") ~= nil + return G_reader_settings:has("lastfile") end, callback = function() self:onOpenLastDoc() diff --git a/frontend/apps/filemanager/filemanagershortcuts.lua b/frontend/apps/filemanager/filemanagershortcuts.lua index 4f7fd2e6f..e08e3cc7d 100644 --- a/frontend/apps/filemanager/filemanagershortcuts.lua +++ b/frontend/apps/filemanager/filemanagershortcuts.lua @@ -11,12 +11,13 @@ local util = require("ffi/util") local _ = require("gettext") local T = util.template -local FileManagerShortcuts = InputContainer:extend{} +local FileManagerShortcuts = InputContainer:extend{ + folder_shortcuts = G_reader_settings:readSetting("folder_shortcuts", {}), +} function FileManagerShortcuts:updateItemTable() local item_table = {} - local folder_shortcuts = G_reader_settings:readSetting("folder_shortcuts") or {} - for _, item in ipairs(folder_shortcuts) do + for _, item in ipairs(self.folder_shortcuts) do table.insert(item_table, { text = string.format("%s (%s)", item.text, item.folder), folder = item.folder, @@ -107,7 +108,7 @@ function FileManagerShortcuts:addNewFolder() end function FileManagerShortcuts:addFolderFromInput(friendly_name, folder) - for __, item in ipairs(G_reader_settings:readSetting("folder_shortcuts") or {}) do + for __, item in ipairs(self.folder_shortcuts) do if item.text == friendly_name and item.folder == folder then UIManager:show(InfoMessage:new{ text = _("A shortcut to this folder already exists."), @@ -115,12 +116,10 @@ function FileManagerShortcuts:addFolderFromInput(friendly_name, folder) return end end - local folder_shortcuts = G_reader_settings:readSetting("folder_shortcuts") or {} - table.insert(folder_shortcuts, { + table.insert(self.folder_shortcuts, { text = friendly_name, folder = folder, }) - G_reader_settings:saveSetting("folder_shortcuts", folder_shortcuts) self:updateItemTable() end @@ -193,25 +192,21 @@ function FileManagerShortcuts:editFolderShortcut(item) end function FileManagerShortcuts:renameFolderShortcut(item, new_name) - local folder_shortcuts = {} - for _, element in ipairs(G_reader_settings:readSetting("folder_shortcuts") or {}) do + for _, element in ipairs(self.folder_shortcuts) do if element.text == item.friendly_name and element.folder == item.folder then element.text = new_name end - table.insert(folder_shortcuts, element) end - G_reader_settings:saveSetting("folder_shortcuts", folder_shortcuts) self:updateItemTable() end function FileManagerShortcuts:deleteFolderShortcut(item) - local folder_shortcuts = {} - for _, element in ipairs(G_reader_settings:readSetting("folder_shortcuts") or {}) do - if element.text ~= item.friendly_name or element.folder ~= item.folder then - table.insert(folder_shortcuts, element) + for i = #self.folder_shortcuts, 1, -1 do + local element = self.folder_shortcuts[i] + if element.text == item.friendly_name and element.folder == item.folder then + table.remove(self.folder_shortcuts, i) end end - G_reader_settings:saveSetting("folder_shortcuts", folder_shortcuts) self:updateItemTable() end diff --git a/frontend/apps/reader/modules/readerbookmark.lua b/frontend/apps/reader/modules/readerbookmark.lua index 3f35d3fb6..981e0ecc6 100644 --- a/frontend/apps/reader/modules/readerbookmark.lua +++ b/frontend/apps/reader/modules/readerbookmark.lua @@ -32,12 +32,12 @@ function ReaderBookmark:init() } end - if not G_reader_settings:readSetting("bookmarks_items_per_page") then + if G_reader_settings:hasNot("bookmarks_items_per_page") then -- The Bookmarks items per page and items' font size can now be -- configured. Previously, the ones set for the file browser -- were used. Initialize them from these ones. local items_per_page = G_reader_settings:readSetting("items_per_page") - or self.bookmarks_items_per_page_default + or self.bookmarks_items_per_page_default G_reader_settings:saveSetting("bookmarks_items_per_page", items_per_page) local items_font_size = G_reader_settings:readSetting("items_font_size") if items_font_size and items_font_size ~= Menu.getItemFontSize(items_per_page) then @@ -186,7 +186,7 @@ end function ReaderBookmark:fixBookmarkSort(config) -- for backward compatibility, since previously bookmarks for credocuments -- are not well sorted. We need to do a whole sorting for at least once. - if not config:readSetting("bookmarks_sorted") then + if config:hasNot("bookmarks_sorted") then table.sort(self.bookmarks, function(a, b) return self:isBookmarkInPageOrder(a, b) end) @@ -197,7 +197,7 @@ function ReaderBookmark:importSavedHighlight(config) local textmarks = config:readSetting("highlight") or {} -- import saved highlight once, because from now on highlight are added to -- bookmarks when they are created. - if not config:readSetting("highlights_imported") then + if config:hasNot("highlights_imported") then for page, marks in pairs(textmarks) do for _, mark in ipairs(marks) do page = self.ui.document.info.has_pages and page or mark.pos0 @@ -228,8 +228,8 @@ end function ReaderBookmark:onSaveSettings() self.ui.doc_settings:saveSetting("bookmarks", self.bookmarks) - self.ui.doc_settings:saveSetting("bookmarks_sorted", true) - self.ui.doc_settings:saveSetting("highlights_imported", true) + self.ui.doc_settings:makeTrue("bookmarks_sorted") + self.ui.doc_settings:makeTrue("highlights_imported") end function ReaderBookmark:isCurrentPageBookmarked() diff --git a/frontend/apps/reader/modules/readerconfig.lua b/frontend/apps/reader/modules/readerconfig.lua index bff7df833..17638c890 100644 --- a/frontend/apps/reader/modules/readerconfig.lua +++ b/frontend/apps/reader/modules/readerconfig.lua @@ -29,8 +29,9 @@ function ReaderConfig:init() if Device:isTouchDevice() then self:initGesListener() end - self.activation_menu = G_reader_settings:readSetting("activate_menu") - if self.activation_menu == nil then + if G_reader_settings:has("activate_menu") then + self.activation_menu = G_reader_settings:readSetting("activate_menu") + else self.activation_menu = "swipe_tap" end end diff --git a/frontend/apps/reader/modules/readercoptlistener.lua b/frontend/apps/reader/modules/readercoptlistener.lua index 76139b837..31b3d8ee5 100644 --- a/frontend/apps/reader/modules/readercoptlistener.lua +++ b/frontend/apps/reader/modules/readercoptlistener.lua @@ -11,8 +11,9 @@ local _ = require("gettext") local ReaderCoptListener = EventListener:new{} function ReaderCoptListener:onReadSettings(config) - local view_mode = config:readSetting("copt_view_mode") or - G_reader_settings:readSetting("copt_view_mode") or 0 -- default to "page" mode + local view_mode = config:readSetting("copt_view_mode") + or G_reader_settings:readSetting("copt_view_mode") + or 0 -- default to "page" mode local view_mode_name = view_mode == 0 and "page" or "scroll" -- Let crengine know of the view mode before rendering, as it can -- cause a rendering change (2-pages would become 1-page in diff --git a/frontend/apps/reader/modules/readerdictionary.lua b/frontend/apps/reader/modules/readerdictionary.lua index 22d079f83..6215031a1 100644 --- a/frontend/apps/reader/modules/readerdictionary.lua +++ b/frontend/apps/reader/modules/readerdictionary.lua @@ -58,7 +58,6 @@ end local ReaderDictionary = InputContainer:new{ data_dir = nil, dict_window_list = {}, - disable_lookup_history = G_reader_settings:isTrue("disable_lookup_history"), lookup_msg = _("Searching dictionary for:\n%1"), } @@ -96,6 +95,10 @@ local function getDictionaryFixHtmlFunc(path) end function ReaderDictionary:init() + self.disable_lookup_history = G_reader_settings:isTrue("disable_lookup_history") + self.dicts_order = G_reader_settings:readSetting("dicts_order", {}) + self.dicts_disabled = G_reader_settings:readSetting("dicts_disabled", {}) + self.ui.menu:registerToMainMenu(self) self.data_dir = STARDICT_DATA_DIR or os.getenv("STARDICT_DATA_DIR") or @@ -140,19 +143,7 @@ function ReaderDictionary:init() end end logger.dbg("found", #available_ifos, "dictionaries") - - if not G_reader_settings:readSetting("dicts_order") then - G_reader_settings:saveSetting("dicts_order", {}) - end - self:sortAvailableIfos() - - if not G_reader_settings:readSetting("dicts_disabled") then - -- Create an empty dict for this setting, so that we can - -- access and update it directly through G_reader_settings - -- and it will automatically be saved. - G_reader_settings:saveSetting("dicts_disabled", {}) - end end -- Prepare the -u options to give to sdcv the dictionary order and if some are disabled self:updateSdcvDictNamesOptions() @@ -163,11 +154,9 @@ function ReaderDictionary:init() end function ReaderDictionary:sortAvailableIfos() - local dicts_order = G_reader_settings:readSetting("dicts_order") - table.sort(available_ifos, function(lifo, rifo) - local lord = dicts_order[lifo.file] - local rord = dicts_order[rifo.file] + local lord = self.dicts_order[lifo.file] + local rord = self.dicts_order[rifo.file] -- Both ifos without an explicit position -> lexical comparison if lord == rord then @@ -468,9 +457,8 @@ function ReaderDictionary:getNumberOfDictionaries() local nb_available = #available_ifos local nb_enabled = 0 local nb_disabled = 0 - local dicts_disabled = G_reader_settings:readSetting("dicts_disabled") for _, ifo in pairs(available_ifos) do - if dicts_disabled[ifo.file] then + if self.dicts_disabled[ifo.file] then nb_disabled = nb_disabled + 1 else nb_enabled = nb_enabled + 1 @@ -526,7 +514,7 @@ end function ReaderDictionary:showDictionariesMenu(changed_callback) -- Work on local copy, save to settings only when SortWidget is closed with the accept button - local dicts_disabled = util.tableDeepCopy(G_reader_settings:readSetting("dicts_disabled")) + local dicts_disabled = util.tableDeepCopy(self.dicts_disabled) local sort_items = {} for _, ifo in pairs(available_ifos) do @@ -550,15 +538,17 @@ function ReaderDictionary:showDictionariesMenu(changed_callback) title = _("Manage installed dictionaries"), item_table = sort_items, callback = function() - -- Save local copy of dicts_disabled - G_reader_settings:saveSetting("dicts_disabled", dicts_disabled) + -- Update both references to point to that new object + self.dicts_disabled = dicts_disabled + G_reader_settings:saveSetting("dicts_disabled", self.dicts_disabled) -- Write back the sorted items to dicts_order local dicts_order = {} for i, sort_item in pairs(sort_items) do dicts_order[sort_item.ifo.file] = i end - G_reader_settings:saveSetting("dicts_order", dicts_order) + self.dicts_order = dicts_order + G_reader_settings:saveSetting("dicts_order", self.dicts_order) self:sortAvailableIfos() @@ -1058,8 +1048,9 @@ function ReaderDictionary:onReadSettings(config) if #self.preferred_dictionaries > 0 then self:updateSdcvDictNamesOptions() end - self.disable_fuzzy_search = config:readSetting("disable_fuzzy_search") - if self.disable_fuzzy_search == nil then + if config:has("disable_fuzzy_search") then + self.disable_fuzzy_search = config:isTrue("disable_fuzzy_search") + else self.disable_fuzzy_search = G_reader_settings:isTrue("disable_fuzzy_search") end end @@ -1118,13 +1109,13 @@ The current default (★) is enabled.]]) return disable_fuzzy_search and _("Disable (★)") or _("Disable") end, choice1_callback = function() - G_reader_settings:saveSetting("disable_fuzzy_search", true) + G_reader_settings:makeTrue("disable_fuzzy_search") end, choice2_text_func = function() return disable_fuzzy_search and _("Enable") or _("Enable (★)") end, choice2_callback = function() - G_reader_settings:saveSetting("disable_fuzzy_search", false) + G_reader_settings:makeFalse("disable_fuzzy_search") end, }) end diff --git a/frontend/apps/reader/modules/readerdogear.lua b/frontend/apps/reader/modules/readerdogear.lua index e44a40920..60f40c9a2 100644 --- a/frontend/apps/reader/modules/readerdogear.lua +++ b/frontend/apps/reader/modules/readerdogear.lua @@ -56,15 +56,15 @@ end function ReaderDogear:onReadSettings(config) if not self.ui.document.info.has_pages then -- Adjust to CreDocument margins (as done in ReaderTypeset) - local h_margins = config:readSetting("copt_h_page_margins") or - G_reader_settings:readSetting("copt_h_page_margins") or - DCREREADER_CONFIG_H_MARGIN_SIZES_MEDIUM - local t_margin = config:readSetting("copt_t_page_margin") or - G_reader_settings:readSetting("copt_t_page_margin") or - DCREREADER_CONFIG_T_MARGIN_SIZES_LARGE - local b_margin = config:readSetting("copt_b_page_margin") or - G_reader_settings:readSetting("copt_b_page_margin") or - DCREREADER_CONFIG_B_MARGIN_SIZES_LARGE + local h_margins = config:readSetting("copt_h_page_margins") + or G_reader_settings:readSetting("copt_h_page_margins") + or DCREREADER_CONFIG_H_MARGIN_SIZES_MEDIUM + local t_margin = config:readSetting("copt_t_page_margin") + or G_reader_settings:readSetting("copt_t_page_margin") + or DCREREADER_CONFIG_T_MARGIN_SIZES_LARGE + local b_margin = config:readSetting("copt_b_page_margin") + or G_reader_settings:readSetting("copt_b_page_margin") + or DCREREADER_CONFIG_B_MARGIN_SIZES_LARGE local margins = { h_margins[1], t_margin, h_margins[2], b_margin } self:onSetPageMargins(margins) end diff --git a/frontend/apps/reader/modules/readerfont.lua b/frontend/apps/reader/modules/readerfont.lua index 4a859f150..66cf45504 100644 --- a/frontend/apps/reader/modules/readerfont.lua +++ b/frontend/apps/reader/modules/readerfont.lua @@ -108,48 +108,55 @@ end function ReaderFont:onReadSettings(config) self.font_face = config:readSetting("font_face") - or G_reader_settings:readSetting("cre_font") - or self.ui.document.default_font + or G_reader_settings:readSetting("cre_font") + or self.ui.document.default_font self.ui.document:setFontFace(self.font_face) self.header_font_face = config:readSetting("header_font_face") - or G_reader_settings:readSetting("header_font") - or self.ui.document.header_font + or G_reader_settings:readSetting("header_font") + or self.ui.document.header_font self.ui.document:setHeaderFont(self.header_font_face) self.font_size = config:readSetting("font_size") - or G_reader_settings:readSetting("copt_font_size") - or DCREREADER_CONFIG_DEFAULT_FONT_SIZE or 22 + or G_reader_settings:readSetting("copt_font_size") + or DCREREADER_CONFIG_DEFAULT_FONT_SIZE + or 22 self.ui.document:setFontSize(Screen:scaleBySize(self.font_size)) self.font_embolden = config:readSetting("font_embolden") - or G_reader_settings:readSetting("copt_font_weight") or 0 + or G_reader_settings:readSetting("copt_font_weight") + or 0 self.ui.document:toggleFontBolder(self.font_embolden) self.font_hinting = config:readSetting("font_hinting") - or G_reader_settings:readSetting("copt_font_hinting") or 2 -- auto (default in cre.cpp) + or G_reader_settings:readSetting("copt_font_hinting") + or 2 -- auto (default in cre.cpp) self.ui.document:setFontHinting(self.font_hinting) self.font_kerning = config:readSetting("font_kerning") - or G_reader_settings:readSetting("copt_font_kerning") or 3 -- harfbuzz (slower, but needed for proper arabic) + or G_reader_settings:readSetting("copt_font_kerning") + or 3 -- harfbuzz (slower, but needed for proper arabic) self.ui.document:setFontKerning(self.font_kerning) self.word_spacing = config:readSetting("word_spacing") - or G_reader_settings:readSetting("copt_word_spacing") or {95, 75} + or G_reader_settings:readSetting("copt_word_spacing") + or {95, 75} self.ui.document:setWordSpacing(self.word_spacing) self.word_expansion = config:readSetting("word_expansion") - or G_reader_settings:readSetting("copt_word_expansion") or 0 + or G_reader_settings:readSetting("copt_word_expansion") + or 0 self.ui.document:setWordExpansion(self.word_expansion) self.line_space_percent = config:readSetting("line_space_percent") - or G_reader_settings:readSetting("copt_line_spacing") - or DCREREADER_CONFIG_LINE_SPACE_PERCENT_MEDIUM + or G_reader_settings:readSetting("copt_line_spacing") + or DCREREADER_CONFIG_LINE_SPACE_PERCENT_MEDIUM self.ui.document:setInterlineSpacePercent(self.line_space_percent) self.gamma_index = config:readSetting("gamma_index") - or G_reader_settings:readSetting("copt_font_gamma") - or DCREREADER_CONFIG_DEFAULT_FONT_GAMMA or 15 -- gamma = 1.0 + or G_reader_settings:readSetting("copt_font_gamma") + or DCREREADER_CONFIG_DEFAULT_FONT_GAMMA + or 15 -- gamma = 1.0 self.ui.document:setGammaIndex(self.gamma_index) -- Dirty hack: we have to add following call in order to set @@ -439,8 +446,8 @@ function ReaderFont:buildFontsTestDocument() f:close() end local dir = G_reader_settings:readSetting("home_dir") - if not dir then dir = require("apps/filemanager/filemanagerutil").getDefaultDir() end - if not dir then dir = "." end + or require("apps/filemanager/filemanagerutil").getDefaultDir() + or "." local font_test_final_path = dir .. "/" .. FONT_TEST_FINAL_FILENAME f = io.open(font_test_final_path, "w") if not f then return end diff --git a/frontend/apps/reader/modules/readerfooter.lua b/frontend/apps/reader/modules/readerfooter.lua index 879092307..97cc3a7fd 100644 --- a/frontend/apps/reader/modules/readerfooter.lua +++ b/frontend/apps/reader/modules/readerfooter.lua @@ -387,7 +387,7 @@ local ReaderFooter = WidgetContainer:extend{ } function ReaderFooter:init() - self.settings = G_reader_settings:readSetting("footer") or { + self.settings = G_reader_settings:readSetting("footer", { -- enable progress bar by default -- disable_progress_bar = true, disabled = false, @@ -414,7 +414,7 @@ function ReaderFooter:init() text_font_bold = false, container_height = DMINIBAR_CONTAINER_HEIGHT, container_bottom_padding = 1, -- unscaled_size_check: ignore - } + }) -- Remove items not supported by the current device if not Device:hasFastWifiStatusQuery() then @@ -889,7 +889,6 @@ function ReaderFooter:addToMainMenu(menu_items) end, callback = function() self.settings[option] = not self.settings[option] - G_reader_settings:saveSetting("footer", self.settings) -- We only need to send a SetPageBottomMargin event when we truly affect the margin local should_signal = false -- only case that we don't need a UI update is enable/disable @@ -976,7 +975,6 @@ function ReaderFooter:addToMainMenu(menu_items) self.mode_index[i] = sort_item.item_table[i].label end self.settings.order = self.mode_index - G_reader_settings:saveSetting("footer", self.settings) self:updateFooterTextGenerator() self:onUpdateFooter() UIManager:setDirty(nil, "ui") @@ -994,7 +992,6 @@ function ReaderFooter:addToMainMenu(menu_items) end, callback = function() self.settings.auto_refresh_time = not self.settings.auto_refresh_time - G_reader_settings:saveSetting("footer", self.settings) self:rescheduleFooterAutoRefreshIfNeeded() end }, @@ -1035,7 +1032,6 @@ function ReaderFooter:addToMainMenu(menu_items) end, callback = function() self.settings.skim_widget_on_hold = not self.settings.skim_widget_on_hold - G_reader_settings:saveSetting("footer", self.settings) end, }, { @@ -1857,7 +1853,7 @@ function ReaderFooter:getAvgTimePerPage() end function ReaderFooter:getDataFromStatistics(title, pages) - local sec = "N/A" + local sec = _("N/A") local average_time_per_page = self:getAvgTimePerPage() if average_time_per_page then if self.settings.duration_format == "classic" then @@ -2065,9 +2061,9 @@ end function ReaderFooter:onReadSettings(config) if not self.ui.document.info.has_pages then - local h_margins = config:readSetting("copt_h_page_margins") or - G_reader_settings:readSetting("copt_h_page_margins") or - DCREREADER_CONFIG_H_MARGIN_SIZES_MEDIUM + local h_margins = config:readSetting("copt_h_page_margins") + or G_reader_settings:readSetting("copt_h_page_margins") + or DCREREADER_CONFIG_H_MARGIN_SIZES_MEDIUM self.book_margins_footer_width = math.floor((h_margins[1] + h_margins[2])/2) end end diff --git a/frontend/apps/reader/modules/readerhighlight.lua b/frontend/apps/reader/modules/readerhighlight.lua index 8a6cacd91..c4b449974 100644 --- a/frontend/apps/reader/modules/readerhighlight.lua +++ b/frontend/apps/reader/modules/readerhighlight.lua @@ -1175,13 +1175,13 @@ function ReaderHighlight:onCycleHighlightAction() dictionary = "search", search = nil, } - local current_action = G_reader_settings:readSetting("default_highlight_action") - if not current_action then + if G_reader_settings:hasNot("default_highlight_action") then G_reader_settings:saveSetting("default_highlight_action", "highlight") UIManager:show(Notification:new{ text = _("Default highlight action changed to 'highlight'."), }) else + local current_action = G_reader_settings:readSetting("default_highlight_action") local next_action = next_actions[current_action] G_reader_settings:saveSetting("default_highlight_action", next_action) UIManager:show(Notification:new{ @@ -1446,23 +1446,25 @@ end function ReaderHighlight:onReadSettings(config) self.view.highlight.saved_drawer = config:readSetting("highlight_drawer") or self.view.highlight.saved_drawer - local disable_highlight = config:readSetting("highlight_disabled") - if disable_highlight == nil then - disable_highlight = G_reader_settings:readSetting("highlight_disabled") or false + if config:has("highlight_disabled") then + self.view.highlight.disabled = config:isTrue("highlight_disabled") + else + self.view.highlight.disabled = G_reader_settings:isTrue("highlight_disabled") end - self.view.highlight.disabled = disable_highlight -- panel zoom settings isn't supported in EPUB if self.document.info.has_pages then local ext = util.getFileNameSuffix(self.ui.document.file) G_reader_settings:initializeExtSettings("panel_zoom_enabled", {cbz = true, cbt = true}) G_reader_settings:initializeExtSettings("panel_zoom_fallback_to_text_selection", {pdf = true}) - self.panel_zoom_enabled = config:readSetting("panel_zoom_enabled") - if self.panel_zoom_enabled == nil then + if config:has("panel_zoom_enabled") then + self.panel_zoom_enabled = config:isTrue("panel_zoom_enabled") + else self.panel_zoom_enabled = G_reader_settings:getSettingForExt("panel_zoom_enabled", ext) or false end - self.panel_zoom_fallback_to_text_selection = config:readSetting("panel_zoom_fallback_to_text_selection") - if self.panel_zoom_fallback_to_text_selection == nil then + if config:has("panel_zoom_fallback_to_text_selection") then + self.panel_zoom_fallback_to_text_selection = config:isTrue("panel_zoom_fallback_to_text_selection") + else self.panel_zoom_fallback_to_text_selection = G_reader_settings:getSettingForExt("panel_zoom_fallback_to_text_selection", ext) or false end end @@ -1493,13 +1495,13 @@ function ReaderHighlight:toggleDefault() return highlight_disabled and _("Disable (★)") or _("Disable") end, choice1_callback = function() - G_reader_settings:saveSetting("highlight_disabled", true) + G_reader_settings:makeTrue("highlight_disabled") end, choice2_text_func = function() return highlight_disabled and _("Enable") or _("Enable (★)") end, choice2_callback = function() - G_reader_settings:saveSetting("highlight_disabled", false) + G_reader_settings:makeFalse("highlight_disabled") end, }) end diff --git a/frontend/apps/reader/modules/readerkoptlistener.lua b/frontend/apps/reader/modules/readerkoptlistener.lua index 777be3db8..a9ba7cf68 100644 --- a/frontend/apps/reader/modules/readerkoptlistener.lua +++ b/frontend/apps/reader/modules/readerkoptlistener.lua @@ -16,15 +16,17 @@ end function ReaderKoptListener:onReadSettings(config) -- normal zoom mode is zoom mode used in non-reflow mode. - local normal_zoom_mode = config:readSetting("normal_zoom_mode") or - G_reader_settings:readSetting("zoom_mode") or "page" + local normal_zoom_mode = config:readSetting("normal_zoom_mode") + or G_reader_settings:readSetting("zoom_mode") + or "page" normal_zoom_mode = util.arrayContains(ReaderZooming.available_zoom_modes, normal_zoom_mode) - and normal_zoom_mode + and normal_zoom_mode or "page" self.normal_zoom_mode = normal_zoom_mode self:setZoomMode(normal_zoom_mode) - self.document.configurable.contrast = config:readSetting("kopt_contrast") or - G_reader_settings:readSetting("kopt_contrast") or 1.0 + self.document.configurable.contrast = config:readSetting("kopt_contrast") + or G_reader_settings:readSetting("kopt_contrast") + or 1.0 self.ui:handleEvent(Event:new("GammaUpdate", 1/self.document.configurable.contrast)) -- since K2pdfopt v2.21 negative value of word spacing is also used, for config -- compatability we should manually change previous -1 to a more reasonable -0.2 diff --git a/frontend/apps/reader/modules/readerlink.lua b/frontend/apps/reader/modules/readerlink.lua index 93eb1ef99..059b7b7d9 100644 --- a/frontend/apps/reader/modules/readerlink.lua +++ b/frontend/apps/reader/modules/readerlink.lua @@ -326,7 +326,7 @@ The recommended value is -2.]]), end return spin_widget end - local show_absolute_font_size_widget = G_reader_settings:readSetting("footnote_popup_absolute_font_size") ~= nil + local show_absolute_font_size_widget = G_reader_settings:has("footnote_popup_absolute_font_size") spin_widget = get_font_size_widget(show_absolute_font_size_widget) UIManager:show(spin_widget) end, diff --git a/frontend/apps/reader/modules/readermenu.lua b/frontend/apps/reader/modules/readermenu.lua index bb1d643b0..f69e24c32 100644 --- a/frontend/apps/reader/modules/readermenu.lua +++ b/frontend/apps/reader/modules/readermenu.lua @@ -71,8 +71,9 @@ function ReaderMenu:init() end end end - self.activation_menu = G_reader_settings:readSetting("activate_menu") - if self.activation_menu == nil then + if G_reader_settings:has("activate_menu") then + self.activation_menu = G_reader_settings:readSetting("activate_menu") + else self.activation_menu = "swipe_tap" end end @@ -190,16 +191,16 @@ function ReaderMenu:setUpdateItemTable() text = _("Exclude this book's cover from screensaver"), enabled_func = function() return not (self.ui == nil or self.ui.document == nil) - and G_reader_settings:readSetting('screensaver_type') == "cover" + and G_reader_settings:readSetting("screensaver_type") == "cover" end, checked_func = function() - return self.ui and self.ui.doc_settings and self.ui.doc_settings:readSetting("exclude_screensaver") == true + return self.ui and self.ui.doc_settings and self.ui.doc_settings:isTrue("exclude_screensaver") end, callback = function() - if Screensaver:excluded() then - self.ui.doc_settings:saveSetting("exclude_screensaver", false) + if Screensaver:isExcluded() then + self.ui.doc_settings:makeFalse("exclude_screensaver") else - self.ui.doc_settings:saveSetting("exclude_screensaver", true) + self.ui.doc_settings:makeTrue("exclude_screensaver") end self.ui:saveSettings() end, diff --git a/frontend/apps/reader/modules/readerpagemap.lua b/frontend/apps/reader/modules/readerpagemap.lua index dd68056d5..f2daba680 100644 --- a/frontend/apps/reader/modules/readerpagemap.lua +++ b/frontend/apps/reader/modules/readerpagemap.lua @@ -88,18 +88,20 @@ function ReaderPageMap:resetLayout() end function ReaderPageMap:onReadSettings(config) - local h_margins = config:readSetting("copt_h_page_margins") or - G_reader_settings:readSetting("copt_h_page_margins") or - DCREREADER_CONFIG_H_MARGIN_SIZES_MEDIUM + local h_margins = config:readSetting("copt_h_page_margins") + or G_reader_settings:readSetting("copt_h_page_margins") + or DCREREADER_CONFIG_H_MARGIN_SIZES_MEDIUM self.max_left_label_width = Screen:scaleBySize(h_margins[1]) self.max_right_label_width = Screen:scaleBySize(h_margins[2]) - self.show_page_labels = config:readSetting("pagemap_show_page_labels") - if self.show_page_labels == nil then + if config:has("pagemap_show_page_labels") then + self.show_page_labels = config:isTrue("pagemap_show_page_labels") + else self.show_page_labels = G_reader_settings:nilOrTrue("pagemap_show_page_labels") end - self.use_page_labels = config:readSetting("pagemap_use_page_labels") - if self.use_page_labels == nil then + if config:has("pagemap_use_page_labels") then + self.use_page_labels = config:isTrue("pagemap_use_page_labels") + else self.use_page_labels = G_reader_settings:isTrue("pagemap_use_page_labels") end end @@ -352,14 +354,14 @@ function ReaderPageMap:addToMainMenu(menu_items) return use_page_labels and _("Renderer") or _("Renderer (★)") end, choice1_callback = function() - G_reader_settings:saveSetting("pagemap_use_page_labels", false) + G_reader_settings:makeFalse("pagemap_use_page_labels") if touchmenu_instance then touchmenu_instance:updateItems() end end, choice2_text_func = function() return use_page_labels and _("Reference (★)") or _("Reference") end, choice2_callback = function() - G_reader_settings:saveSetting("pagemap_use_page_labels", true) + G_reader_settings:makeTrue("pagemap_use_page_labels") if touchmenu_instance then touchmenu_instance:updateItems() end end, }) @@ -385,14 +387,14 @@ function ReaderPageMap:addToMainMenu(menu_items) return show_page_labels and _("Hide") or _("Hide (★)") end, choice1_callback = function() - G_reader_settings:saveSetting("pagemap_show_page_labels", false) + G_reader_settings:makeFalse("pagemap_show_page_labels") if touchmenu_instance then touchmenu_instance:updateItems() end end, choice2_text_func = function() return show_page_labels and _("Show (★)") or _("Show") end, choice2_callback = function() - G_reader_settings:saveSetting("pagemap_show_page_labels", true) + G_reader_settings:makeTrue("pagemap_show_page_labels") if touchmenu_instance then touchmenu_instance:updateItems() end end, }) diff --git a/frontend/apps/reader/modules/readerpaging.lua b/frontend/apps/reader/modules/readerpaging.lua index 0ebf547dc..927b4a578 100644 --- a/frontend/apps/reader/modules/readerpaging.lua +++ b/frontend/apps/reader/modules/readerpaging.lua @@ -184,14 +184,16 @@ end function ReaderPaging:onReadSettings(config) self.page_positions = config:readSetting("page_positions") or {} self:_gotoPage(config:readSetting("last_page") or 1) - self.show_overlap_enable = config:readSetting("show_overlap_enable") - if self.show_overlap_enable == nil then + if config:has("show_overlap_enable") then + self.show_overlap_enable = config:isTrue("show_overlap_enable") + else self.show_overlap_enable = DSHOWOVERLAP end self.flipping_zoom_mode = config:readSetting("flipping_zoom_mode") or "page" - self.flipping_scroll_mode = config:readSetting("flipping_scroll_mode") or false - self.inverse_reading_order = config:readSetting("inverse_reading_order") - if self.inverse_reading_order == nil then + self.flipping_scroll_mode = config:isTrue("flipping_scroll_mode") + if config:has("inverse_reading_order") then + self.inverse_reading_order = config:isTrue("inverse_reading_order") + else self.inverse_reading_order = G_reader_settings:isTrue("inverse_reading_order") end for _, v in ipairs(ReaderZooming.zoom_pan_settings) do @@ -266,14 +268,14 @@ function ReaderPaging:addToMainMenu(menu_items) return inverse_reading_order and _("LTR") or _("LTR (★)") end, choice1_callback = function() - G_reader_settings:saveSetting("inverse_reading_order", false) + G_reader_settings:makeFalse("inverse_reading_order") if touchmenu_instance then touchmenu_instance:updateItems() end end, choice2_text_func = function() return inverse_reading_order and _("RTL (★)") or _("RTL") end, choice2_callback = function() - G_reader_settings:saveSetting("inverse_reading_order", true) + G_reader_settings:makeTrue("inverse_reading_order") if touchmenu_instance then touchmenu_instance:updateItems() end end, }) diff --git a/frontend/apps/reader/modules/readerrolling.lua b/frontend/apps/reader/modules/readerrolling.lua index c52b90d09..d7a02317a 100644 --- a/frontend/apps/reader/modules/readerrolling.lua +++ b/frontend/apps/reader/modules/readerrolling.lua @@ -139,9 +139,9 @@ function ReaderRolling:onReadSettings(config) -- and highlights with old XPATHs. -- (EPUB will use the same correct DOM code no matter what DOM version -- we request here.) - if not config:readSetting("cre_dom_version") then + if config:hasNot("cre_dom_version") then -- Not previously set, guess which DOM version to use - if config:readSetting("last_xpointer") then + if config:has("last_xpointer") then -- We have a last_xpointer: this book was previously opened -- with possibly a very old version: request the oldest config:saveSetting("cre_dom_version", self.ui.document:getOldestDomVersion()) @@ -166,7 +166,7 @@ function ReaderRolling:onReadSettings(config) self.ui.typeset:ensureSanerBlockRenderingFlags() -- And check if we can migrate to a newest DOM version after -- the book is loaded (unless the user told us not to). - if not config:readSetting("cre_keep_old_dom_version") then + if config:nilOrFalse("cre_keep_old_dom_version") then self.ui:registerPostReadyCallback(function() self:checkXPointersAndProposeDOMVersionUpgrade() end) @@ -209,13 +209,15 @@ function ReaderRolling:onReadSettings(config) end end end - self.show_overlap_enable = config:readSetting("show_overlap_enable") - if self.show_overlap_enable == nil then + if config:has("show_overlap_enable") then + self.show_overlap_enable = config:isTrue("show_overlap_enable") + else self.show_overlap_enable = DSHOWOVERLAP end - self.inverse_reading_order = config:readSetting("inverse_reading_order") - if self.inverse_reading_order == nil then + if config:has("inverse_reading_order") then + self.inverse_reading_order = config:isTrue("inverse_reading_order") + else self.inverse_reading_order = G_reader_settings:isTrue("inverse_reading_order") end @@ -229,8 +231,9 @@ function ReaderRolling:onReadSettings(config) G_reader_settings:readSetting("copt_visible_pages") or 1 self.ui.document:setVisiblePageCount(self.visible_pages) - self.hide_nonlinear_flows = config:readSetting("hide_nonlinear_flows") - if self.hide_nonlinear_flows == nil then + if config:has("hide_nonlinear_flows") then + self.hide_nonlinear_flows = config:isTrue("hide_nonlinear_flows") + else self.hide_nonlinear_flows = G_reader_settings:isTrue("hide_nonlinear_flows") end self.ui.document:setHideNonlinearFlows(self.hide_nonlinear_flows) @@ -296,7 +299,7 @@ end function ReaderRolling:onSaveSettings() -- remove last_percent config since its deprecated - self.ui.doc_settings:saveSetting("last_percent", nil) + self.ui.doc_settings:delSetting("last_percent") self.ui.doc_settings:saveSetting("last_xpointer", self.xpointer) -- in scrolling mode, the document may already be closed, -- so we have to check the condition to avoid crash function self:getLastPercent() @@ -395,14 +398,14 @@ function ReaderRolling:addToMainMenu(menu_items) return inverse_reading_order and _("LTR") or _("LTR (★)") end, choice1_callback = function() - G_reader_settings:saveSetting("inverse_reading_order", false) + G_reader_settings:makeFalse("inverse_reading_order") if touchmenu_instance then touchmenu_instance:updateItems() end end, choice2_text_func = function() return inverse_reading_order and _("RTL (★)") or _("RTL") end, choice2_callback = function() - G_reader_settings:saveSetting("inverse_reading_order", true) + G_reader_settings:makeTrue("inverse_reading_order") if touchmenu_instance then touchmenu_instance:updateItems() end end, }) @@ -644,8 +647,10 @@ function ReaderRolling:onGotoXPointer(xp, marker_xp) -- followed_link_marker = true: maker shown and not auto removed -- followed_link_marker = : removed after seconds -- (no real need for a menu item, the default is the finest) - local marker_setting = G_reader_settings:readSetting("followed_link_marker") - if marker_setting == nil then + local marker_setting + if G_reader_settings:has("followed_link_marker") then + marker_setting = G_reader_settings:readSetting("followed_link_marker") + else marker_setting = 1 -- default is: shown and removed after 1 second end @@ -1279,11 +1284,14 @@ function ReaderRolling:checkXPointersAndProposeDOMVersionUpgrade() -- Switch to default block rendering mode if this book has it set to "legacy", -- unless the user had set the global mode to be "legacy". -- (see ReaderTypeset:onReadSettings() for the logic of block_rendering_mode) - local g_block_rendering_mode = G_reader_settings:readSetting("copt_block_rendering_mode") + local g_block_rendering_mode + if G_reader_settings:has("copt_block_rendering_mode") then + g_block_rendering_mode = G_reader_settings:readSetting("copt_block_rendering_mode") + else + -- nil means: use default + g_block_rendering_mode = 3 -- default in ReaderTypeset:onReadSettings() + end if g_block_rendering_mode ~= 0 then -- default is not "legacy" - if not g_block_rendering_mode then -- nil means: use default - g_block_rendering_mode = 3 -- default in ReaderTypeset:onReadSettings() - end -- This setting is actually saved by self.ui.document.configurable local block_rendering_mode = self.ui.document.configurable.block_rendering_mode if block_rendering_mode == 0 then @@ -1343,7 +1351,7 @@ Note that %1 (out of %2) xpaths from your bookmarks and highlights have been nor }}, cancel_text = _("Not for this book"), cancel_callback = function() - self.ui.doc_settings:saveSetting("cre_keep_old_dom_version", true) + self.ui.doc_settings:makeTrue("cre_keep_old_dom_version") end, ok_text = _("Upgrade now"), ok_callback = function() diff --git a/frontend/apps/reader/modules/readerstyletweak.lua b/frontend/apps/reader/modules/readerstyletweak.lua index 6bb7218ac..bb9df5e15 100644 --- a/frontend/apps/reader/modules/readerstyletweak.lua +++ b/frontend/apps/reader/modules/readerstyletweak.lua @@ -327,7 +327,7 @@ function ReaderStyleTweak:updateCssText(apply) end function ReaderStyleTweak:onReadSettings(config) - self.enabled = not (config:readSetting("style_tweaks_enabled") == false) + self.enabled = config:nilOrTrue("style_tweaks_enabled") self.doc_tweaks = config:readSetting("style_tweaks") or {} -- Default globally enabled style tweaks (for new installations) -- are defined in css_tweaks.lua @@ -342,7 +342,7 @@ function ReaderStyleTweak:onSaveSettings() if self.enabled then self.ui.doc_settings:delSetting("style_tweaks_enabled") else - self.ui.doc_settings:saveSetting("style_tweaks_enabled", false) + self.ui.doc_settings:makeFalse("style_tweaks_enabled") end self.ui.doc_settings:saveSetting("style_tweaks", util.tableSize(self.doc_tweaks) > 0 and self.doc_tweaks or nil) G_reader_settings:saveSetting("style_tweaks", self.global_tweaks) diff --git a/frontend/apps/reader/modules/readertoc.lua b/frontend/apps/reader/modules/readertoc.lua index 97a788dda..d376e6c7b 100644 --- a/frontend/apps/reader/modules/readertoc.lua +++ b/frontend/apps/reader/modules/readertoc.lua @@ -41,12 +41,12 @@ function ReaderToc:init() } end - if not G_reader_settings:readSetting("toc_items_per_page") then + if G_reader_settings:hasNot("toc_items_per_page") then -- The TOC items per page and items' font size can now be -- configured. Previously, the ones set for the file browser -- were used. Initialize them from these ones. local items_per_page = G_reader_settings:readSetting("items_per_page") - or self.toc_items_per_page_default + or self.toc_items_per_page_default G_reader_settings:saveSetting("toc_items_per_page", items_per_page) local items_font_size = G_reader_settings:readSetting("items_font_size") if items_font_size and items_font_size ~= Menu.getItemFontSize(items_per_page) then @@ -137,7 +137,7 @@ end function ReaderToc:fillToc() if self.toc then return end if self.ui.document:canHaveAlternativeToc() then - if self.ui.doc_settings:readSetting("alternative_toc") then + if self.ui.doc_settings:isTrue("alternative_toc") then -- (if the document has a cache, the previously built alternative -- TOC was saved and has been reloaded, and this will be avoided) if not self.ui.document:isTocAlternativeToc() then @@ -900,7 +900,7 @@ See Style tweaks → Miscellaneous → Alternative ToC hints.]]), self:resetToc() self.toc_ticks_ignored_levels = {} -- reset this self.ui.document:buildAlternativeToc() - self.ui.doc_settings:saveSetting("alternative_toc", true) + self.ui.doc_settings:makeTrue("alternative_toc") self:onShowToc() self.view.footer:setTocMarkers(true) self.view.footer:onUpdateFooter() diff --git a/frontend/apps/reader/modules/readertypeset.lua b/frontend/apps/reader/modules/readertypeset.lua index 2c067405a..eceea9f79 100644 --- a/frontend/apps/reader/modules/readertypeset.lua +++ b/frontend/apps/reader/modules/readertypeset.lua @@ -22,13 +22,15 @@ function ReaderTypeset:init() end function ReaderTypeset:onReadSettings(config) - self.css = config:readSetting("css") or G_reader_settings:readSetting("copt_css") - or self.ui.document.default_css + self.css = config:readSetting("css") + or G_reader_settings:readSetting("copt_css") + or self.ui.document.default_css local tweaks_css = self.ui.styletweak:getCssText() self.ui.document:setStyleSheet(self.css, tweaks_css) - self.embedded_fonts = config:readSetting("embedded_fonts") - if self.embedded_fonts == nil then + if config:has("embedded_fonts") then + self.embedded_fonts = config:isTrue("embedded_fonts") + else -- default to enable embedded fonts -- note that it's a bit confusing here: -- global settins store 0/1, while document settings store false/true @@ -42,11 +44,12 @@ function ReaderTypeset:onReadSettings(config) self.ui.document:setEmbeddedFonts(0) end - self.embedded_css = config:readSetting("embedded_css") - if self.embedded_css == nil then + if config:has("embedded_css") then + self.embedded_css = config:isTrue("embedded_css") + else -- default to enable embedded CSS -- note that it's a bit confusing here: - -- global settins store 0/1, while document settings store false/true + -- global settings store 0/1, while document settings store false/true -- we leave it that way for now to maintain backwards compatibility local global = G_reader_settings:readSetting("copt_embedded_css") self.embedded_css = (global == nil or global == 1) and true or false @@ -56,15 +59,15 @@ function ReaderTypeset:onReadSettings(config) -- Block rendering mode: stay with legacy rendering for books -- previously opened so bookmarks and highlights stay valid. -- For new books, use 'web' mode below in BLOCK_RENDERING_FLAGS - local block_rendering_default_mode = 3 - self.block_rendering_mode = config:readSetting("copt_block_rendering_mode") - if not self.block_rendering_mode then - if config:readSetting("last_xpointer") then + if config:has("copt_block_rendering_mode") then + self.block_rendering_mode = config:readSetting("copt_block_rendering_mode") + else + if config:has("last_xpointer") then -- We have a last_xpointer: this book was previously opened self.block_rendering_mode = 0 else self.block_rendering_mode = G_reader_settings:readSetting("copt_block_rendering_mode") - or block_rendering_default_mode + or 3 -- default to 'web' mode end -- Let ConfigDialog know so it can update it on screen and have it saved on quit self.ui.document.configurable.block_rendering_mode = self.block_rendering_mode @@ -72,47 +75,52 @@ function ReaderTypeset:onReadSettings(config) self:setBlockRenderingMode(self.block_rendering_mode) -- set render DPI - self.render_dpi = config:readSetting("render_dpi") or - G_reader_settings:readSetting("copt_render_dpi") or 96 + self.render_dpi = config:readSetting("render_dpi") + or G_reader_settings:readSetting("copt_render_dpi") + or 96 self:setRenderDPI(self.render_dpi) -- uncomment if we want font size to follow DPI changes -- self.ui.document:setRenderScaleFontWithDPI(1) -- set page margins - local h_margins = config:readSetting("copt_h_page_margins") or - G_reader_settings:readSetting("copt_h_page_margins") or - DCREREADER_CONFIG_H_MARGIN_SIZES_MEDIUM - local t_margin = config:readSetting("copt_t_page_margin") or - G_reader_settings:readSetting("copt_t_page_margin") or - DCREREADER_CONFIG_T_MARGIN_SIZES_LARGE - local b_margin = config:readSetting("copt_b_page_margin") or - G_reader_settings:readSetting("copt_b_page_margin") or - DCREREADER_CONFIG_B_MARGIN_SIZES_LARGE + local h_margins = config:readSetting("copt_h_page_margins") + or G_reader_settings:readSetting("copt_h_page_margins") + or DCREREADER_CONFIG_H_MARGIN_SIZES_MEDIUM + local t_margin = config:readSetting("copt_t_page_margin") + or G_reader_settings:readSetting("copt_t_page_margin") + or DCREREADER_CONFIG_T_MARGIN_SIZES_LARGE + local b_margin = config:readSetting("copt_b_page_margin") + or G_reader_settings:readSetting("copt_b_page_margin") + or DCREREADER_CONFIG_B_MARGIN_SIZES_LARGE self.unscaled_margins = { h_margins[1], t_margin, h_margins[2], b_margin } self:onSetPageMargins(self.unscaled_margins) - self.sync_t_b_page_margins = config:readSetting("copt_sync_t_b_page_margins") or - G_reader_settings:readSetting("copt_sync_t_b_page_margins") or 0 + self.sync_t_b_page_margins = config:readSetting("copt_sync_t_b_page_margins") + or G_reader_settings:readSetting("copt_sync_t_b_page_margins") + or 0 self.sync_t_b_page_margins = self.sync_t_b_page_margins == 1 and true or false -- default to disable TXT formatting as it does more harm than good - self.txt_preformatted = config:readSetting("txt_preformatted") or - G_reader_settings:readSetting("txt_preformatted") or 1 + self.txt_preformatted = config:readSetting("txt_preformatted") + or G_reader_settings:readSetting("txt_preformatted") + or 1 self:toggleTxtPreFormatted(self.txt_preformatted) -- default to disable smooth scaling for now. - self.smooth_scaling = config:readSetting("smooth_scaling") - if self.smooth_scaling == nil then + if config:has("smooth_scaling") then + self.smooth_scaling = config:isTrue("smooth_scaling") + else local global = G_reader_settings:readSetting("copt_smooth_scaling") - self.smooth_scaling = (global == nil or global == 0) and 0 or 1 + self.smooth_scaling = (global == nil or global == 0) and false or true end self:toggleImageScaling(self.smooth_scaling) -- default to automagic nightmode-friendly handling of images - self.nightmode_images = config:readSetting("nightmode_images") - if self.nightmode_images == nil then + if config:has("nightmode_images") then + self.nightmode_images = config:isTrue("nightmode_images") + else local global = G_reader_settings:readSetting("copt_nightmode_images") - self.nightmode_images = (global == nil or global == 1) and 1 or 0 + self.nightmode_images = (global == nil or global == 1) and true or false end self:toggleNightmodeImages(self.nightmode_images) end diff --git a/frontend/apps/reader/modules/readertypography.lua b/frontend/apps/reader/modules/readertypography.lua index 0af8be38b..7e263a9f6 100644 --- a/frontend/apps/reader/modules/readertypography.lua +++ b/frontend/apps/reader/modules/readertypography.lua @@ -126,7 +126,7 @@ function ReaderTypography:init() -- Migrate old readerhyphenation settings (but keep them in case one -- go back to a previous version) - if not G_reader_settings:readSetting("text_lang_default") and not G_reader_settings:readSetting("text_lang_fallback") then + if G_reader_settings:hasNot("text_lang_default") and G_reader_settings:hasNot("text_lang_fallback") then local g_text_lang_set = false local hyph_alg_default = G_reader_settings:readSetting("hyph_alg_default") if hyph_alg_default then @@ -137,11 +137,11 @@ function ReaderTypography:init() -- Tweak the other settings if the default hyph algo happens -- to be one of these: if hyph_alg_default == "@none" then - G_reader_settings:saveSetting("hyphenation", false) + G_reader_settings:makeFalse("hyphenation") elseif hyph_alg_default == "@softhyphens" then - G_reader_settings:saveSetting("hyph_soft_hyphens_only", true) + G_reader_settings:makeTrue("hyph_soft_hyphens_only") elseif hyph_alg_default == "@algorithm" then - G_reader_settings:saveSetting("hyph_force_algorithmic", true) + G_reader_settings:makeTrue("hyph_force_algorithmic") end end end @@ -328,13 +328,13 @@ When the book's language tag is not among our presets, no specific features will return text_lang_embedded_langs and _("Ignore") or _("Ignore (★)") end, choice1_callback = function() - G_reader_settings:saveSetting("text_lang_embedded_langs", false) + G_reader_settings:makeFalse("text_lang_embedded_langs") end, choice2_text_func = function() return text_lang_embedded_langs and _("Respect (★)") or _("Respect") end, choice2_callback = function() - G_reader_settings:saveSetting("text_lang_embedded_langs", true) + G_reader_settings:makeTrue("text_lang_embedded_langs") end, }) end, @@ -361,13 +361,13 @@ When the book's language tag is not among our presets, no specific features will return hyphenation and _("Disable") or _("Disable (★)") end, choice1_callback = function() - G_reader_settings:saveSetting("hyphenation", false) + G_reader_settings:makeFalse("hyphenation") end, choice2_text_func = function() return hyphenation and _("Enable (★)") or _("Enable") end, choice2_callback = function() - G_reader_settings:saveSetting("hyphenation", true) + G_reader_settings:makeTrue("hyphenation") end, }) end, @@ -379,8 +379,8 @@ When the book's language tag is not among our presets, no specific features will text_func = function() -- Note: with our callback, we either get hyph_left_hyphen_min and -- hyph_right_hyphen_min both nil, or both defined. - if G_reader_settings:readSetting("hyph_left_hyphen_min") or - G_reader_settings:readSetting("hyph_right_hyphen_min") then + if G_reader_settings:has("hyph_left_hyphen_min") or + G_reader_settings:has("hyph_right_hyphen_min") then -- @translators to RTL language translators: %1/left is the min length of the start of a hyphenated word, %2/right is the min length of the end of a hyphenated word (note that there is yet no support for hyphenation with RTL languages, so this will mostly apply to LTR documents) return T(_("Left/right minimal sizes: %1 - %2"), G_reader_settings:readSetting("hyph_left_hyphen_min"), @@ -447,13 +447,13 @@ These settings will apply to all books with any hyphenation dictionary. return hyph_trust_soft_hyphens and _("Disable") or _("Disable (★)") end, choice1_callback = function() - G_reader_settings:saveSetting("hyph_trust_soft_hyphens", false) + G_reader_settings:makeFalse("hyph_trust_soft_hyphens") end, choice2_text_func = function() return hyph_trust_soft_hyphens and _("Enable (★)") or _("Enable") end, choice2_callback = function() - G_reader_settings:saveSetting("hyph_trust_soft_hyphens", true) + G_reader_settings:makeTrue("hyph_trust_soft_hyphens") end, }) end, @@ -504,13 +504,13 @@ These settings will apply to all books with any hyphenation dictionary. return hyph_force_algorithmic and _("Disable") or _("Disable (★)") end, choice1_callback = function() - G_reader_settings:saveSetting("hyph_force_algorithmic", false) + G_reader_settings:makeFalse("hyph_force_algorithmic") end, choice2_text_func = function() return hyph_force_algorithmic and _("Enable (★)") or _("Enable") end, choice2_callback = function() - G_reader_settings:saveSetting("hyph_force_algorithmic", true) + G_reader_settings:makeTrue("hyph_force_algorithmic") end, }) end, @@ -541,13 +541,13 @@ These settings will apply to all books with any hyphenation dictionary. return hyph_soft_hyphens_only and _("Disable") or _("Disable (★)") end, choice1_callback = function() - G_reader_settings:saveSetting("hyph_soft_hyphens_only", false) + G_reader_settings:makeFalse("hyph_soft_hyphens_only") end, choice2_text_func = function() return hyph_soft_hyphens_only and _("Enable (★)") or _("Enable") end, choice2_callback = function() - G_reader_settings:saveSetting("hyph_soft_hyphens_only", true) + G_reader_settings:makeTrue("hyph_soft_hyphens_only") end, }) end, @@ -625,13 +625,13 @@ function ReaderTypography:makeDefaultFloatingPunctuation() return floating_punctuation and _("Disable") or _("Disable (★)") end, choice1_callback = function() - G_reader_settings:saveSetting("floating_punctuation", false) + G_reader_settings:makeFalse("floating_punctuation") end, choice2_text_func = function() return floating_punctuation and _("Enable (★)") or _("Enable") end, choice2_callback = function() - G_reader_settings:saveSetting("floating_punctuation", true) + G_reader_settings:makeTrue("floating_punctuation") end, }) end @@ -701,7 +701,7 @@ end -- in book settings, no default lang, and book has some language defined. function ReaderTypography:onReadSettings(config) -- Migrate old readerhyphenation setting, if one was set - if not config:readSetting("text_lang") and config:readSetting("hyph_alg") then + if config:hasNot("text_lang") and config:has("hyph_alg") then local hyph_alg = config:readSetting("hyph_alg") local dict_info = HYPH_DICT_NAME_TO_LANG_NAME_TAG[hyph_alg] if dict_info then @@ -709,46 +709,51 @@ function ReaderTypography:onReadSettings(config) -- Set the other settings if the default hyph algo happens -- to be one of these: if hyph_alg == "@none" then - config:saveSetting("hyphenation", false) + config:makeFalse("hyphenation") elseif hyph_alg == "@softhyphens" then - config:saveSetting("hyph_soft_hyphens_only", true) + config:makeTrue("hyph_soft_hyphens_only") elseif hyph_alg == "@algorithm" then - config:saveSetting("hyph_force_algorithmic", true) + config:makeTrue("hyph_force_algorithmic") end end end -- Enable text lang tags attributes by default - self.text_lang_embedded_langs = config:readSetting("text_lang_embedded_langs") - if self.text_lang_embedded_langs == nil then + if config:has("text_lang_embedded_langs") then + self.text_lang_embedded_langs = config:isTrue("text_lang_embedded_langs") + else self.text_lang_embedded_langs = G_reader_settings:nilOrTrue("text_lang_embedded_langs") end self.ui.document:setTextEmbeddedLangs(self.text_lang_embedded_langs) -- Enable hyphenation by default - self.hyphenation = config:readSetting("hyphenation") - if self.hyphenation == nil then + if config:has("hyphenation") then + self.hyphenation = config:isTrue("hyphenation") + else self.hyphenation = G_reader_settings:nilOrTrue("hyphenation") end self.ui.document:setTextHyphenation(self.hyphenation) -- Checking for soft-hyphens adds a bit of overhead, so have it disabled by default - self.hyph_trust_soft_hyphens = config:readSetting("hyph_trust_soft_hyphens") - if self.hyph_trust_soft_hyphens == nil then + if config:has("hyph_trust_soft_hyphens") then + self.hyph_trust_soft_hyphens = config:isTrue("hyph_trust_soft_hyphens") + else self.hyph_trust_soft_hyphens = G_reader_settings:isTrue("hyph_trust_soft_hyphens") end self.ui.document:setTrustSoftHyphens(self.hyph_trust_soft_hyphens) -- Alternative hyphenation method (available with all dicts) to use soft hyphens only - self.hyph_soft_hyphens_only = config:readSetting("hyph_soft_hyphens_only") - if self.hyph_soft_hyphens_only == nil then + if config:has("hyph_soft_hyphens_only") then + self.hyph_soft_hyphens_only = config:isTrue("hyph_soft_hyphens_only") + else self.hyph_soft_hyphens_only = G_reader_settings:isTrue("hyph_soft_hyphens_only") end self.ui.document:setTextHyphenationSoftHyphensOnly(self.hyph_soft_hyphens_only) -- Alternative hyphenation method (available with all dicts) to use algorithmic hyphenation - self.hyph_force_algorithmic = config:readSetting("hyph_force_algorithmic") - if self.hyph_force_algorithmic == nil then + if config:has("hyph_force_algorithmic") then + self.hyph_force_algorithmic = config:isTrue("hyph_force_algorithmic") + else self.hyph_force_algorithmic = G_reader_settings:isTrue("hyph_force_algorithmic") end self.ui.document:setTextHyphenationForceAlgorithmic(self.hyph_force_algorithmic) @@ -760,40 +765,36 @@ function ReaderTypography:onReadSettings(config) -- Default to disable hanging/floating punctuation -- (Stored as 0/1 in docsetting for historical reasons, but as true/false -- in global settings.) - self.floating_punctuation = config:readSetting("floating_punctuation") - if self.floating_punctuation == nil then + if config:has("floating_punctuation") then + self.floating_punctuation = config:readSetting("floating_punctuation") + else self.floating_punctuation = G_reader_settings:isTrue("floating_punctuation") and 1 or 0 end self:onToggleFloatingPunctuation(self.floating_punctuation) -- Decide and set the text main lang tag according to settings - self.allow_doc_lang_tag_override = false - -- Use the one manually set for this document - self.text_lang_tag = config:readSetting("text_lang") - if self.text_lang_tag then + if config:has("text_lang") then + self.allow_doc_lang_tag_override = false + -- Use the one manually set for this document + self.text_lang_tag = config:readSetting("text_lang") logger.dbg("Typography lang: using", self.text_lang_tag, "from doc settings") - self.ui.document:setTextMainLang(self.text_lang_tag) - return - end - -- Use the one manually set as default (with Hold) - self.text_lang_tag = G_reader_settings:readSetting("text_lang_default") - if self.text_lang_tag then + elseif G_reader_settings:has("text_lang_default") then + self.allow_doc_lang_tag_override = false + -- Use the one manually set as default (with Hold) + self.text_lang_tag = G_reader_settings:readSetting("text_lang_default") logger.dbg("Typography lang: using default ", self.text_lang_tag) - self.ui.document:setTextMainLang(self.text_lang_tag) - return - end - -- Document language will be allowed to override the one we set from now on - self.allow_doc_lang_tag_override = true - -- Use the one manually set as fallback (with Hold) - self.text_lang_tag = G_reader_settings:readSetting("text_lang_fallback") - if self.text_lang_tag then + elseif G_reader_settings:has("text_lang_fallback") then + -- Document language will be allowed to override the one we set from now on + self.allow_doc_lang_tag_override = true + -- Use the one manually set as fallback (with Hold) + self.text_lang_tag = G_reader_settings:readSetting("text_lang_fallback") logger.dbg("Typography lang: using fallback ", self.text_lang_tag, ", might be overriden by doc language") - self.ui.document:setTextMainLang(self.text_lang_tag) - return + else + self.allow_doc_lang_tag_override = true + -- None decided, use default (shouldn't be reached) + self.text_lang_tag = DEFAULT_LANG_TAG + logger.dbg("Typography lang: no lang set, using", self.text_lang_tag) end - -- None decided, use default (shouldn't be reached) - self.text_lang_tag = DEFAULT_LANG_TAG - logger.dbg("Typography lang: no lang set, using", self.text_lang_tag) self.ui.document:setTextMainLang(self.text_lang_tag) end diff --git a/frontend/apps/reader/modules/readerview.lua b/frontend/apps/reader/modules/readerview.lua index 44f2d9725..2d0962f64 100644 --- a/frontend/apps/reader/modules/readerview.lua +++ b/frontend/apps/reader/modules/readerview.lua @@ -33,7 +33,7 @@ local ReaderView = OverlapGroup:extend{ offset = nil, bbox = nil, }, - outer_page_color = Blitbuffer.gray(DOUTER_PAGE_COLOR/15), + outer_page_color = Blitbuffer.gray(DOUTER_PAGE_COLOR / 15), -- highlight with "lighten" or "underscore" or "invert" highlight = { lighten_factor = 0.2, @@ -45,12 +45,12 @@ local ReaderView = OverlapGroup:extend{ highlight_visible = true, -- PDF/DjVu continuous paging page_scroll = nil, - page_bgcolor = Blitbuffer.gray(DBACKGROUND_COLOR/15), + page_bgcolor = Blitbuffer.gray(DBACKGROUND_COLOR / 15), page_states = {}, -- properties of the gap drawn between each page in scroll mode: page_gap = { -- color (0 = white, 8 = gray, 15 = black) - color = Blitbuffer.gray((G_reader_settings:readSetting("page_gap_color") or 8)/15), + color = Blitbuffer.gray((G_reader_settings:readSetting("page_gap_color") or 8) / 15), }, -- DjVu page rendering mode (used in djvu.c:drawPage()) render_mode = DRENDER_MODE, -- default to COLOR @@ -758,8 +758,9 @@ function ReaderView:onReadSettings(config) -- Keep current rotation by doing nothing when sticky rota is enabled. if not locked then -- Honor docsettings's rotation - rotation_mode = config:readSetting("rotation_mode") -- Doc's - if not rotation_mode then + if config:has("rotation_mode") then + rotation_mode = config:readSetting("rotation_mode") -- Doc's + else -- No doc specific rotation, pickup global defaults for the doc type if self.ui.document.info.has_pages then rotation_mode = G_reader_settings:readSetting("kopt_rotation_mode") or Screen.ORIENTATION_PORTRAIT @@ -781,8 +782,9 @@ function ReaderView:onReadSettings(config) self.page_scroll = page_scroll == 1 and true or false self.highlight.saved = config:readSetting("highlight") or {} self.page_overlap_style = config:readSetting("page_overlap_style") or G_reader_settings:readSetting("page_overlap_style") or "dim" - self.page_gap.height = Screen:scaleBySize(config:readSetting("kopt_page_gap_height") or - G_reader_settings:readSetting("kopt_page_gap_height") or 8) + self.page_gap.height = Screen:scaleBySize(config:readSetting("kopt_page_gap_height") + or G_reader_settings:readSetting("kopt_page_gap_height") + or 8) end function ReaderView:onPageUpdate(new_page_no) @@ -965,11 +967,12 @@ function ReaderView:checkAutoSaveSettings() if not self.settings_last_save_ts then -- reader not yet ready return end - local interval = G_reader_settings:readSetting("auto_save_settings_interval_minutes") - if not interval then -- no auto save + if G_reader_settings:nilOrFalse("auto_save_settings_interval_minutes") then + -- no auto save return end + local interval = G_reader_settings:readSetting("auto_save_settings_interval_minutes") local now_ts = os.time() if now_ts - self.settings_last_save_ts >= interval*60 then self.settings_last_save_ts = now_ts diff --git a/frontend/apps/reader/modules/readerwikipedia.lua b/frontend/apps/reader/modules/readerwikipedia.lua index 919dc108c..4cf5741bc 100644 --- a/frontend/apps/reader/modules/readerwikipedia.lua +++ b/frontend/apps/reader/modules/readerwikipedia.lua @@ -175,8 +175,8 @@ function ReaderWikipedia:addToMainMenu(menu_items) local choose_directory = function() -- Default directory as chosen by DictQuickLookup local default_dir = G_reader_settings:readSetting("wikipedia_save_dir") - if not default_dir then default_dir = G_reader_settings:readSetting("home_dir") end - if not default_dir then default_dir = require("apps/filemanager/filemanagerutil").getDefaultDir() end + or G_reader_settings:readSetting("home_dir") + or require("apps/filemanager/filemanagerutil").getDefaultDir() local dialog dialog = ButtonDialogTitle:new{ title = T(_("Current Wikipedia 'Save as EPUB' folder:\n\n%1\n"), BD.dirpath(default_dir)), @@ -198,9 +198,9 @@ function ReaderWikipedia:addToMainMenu(menu_items) -- so a user reading a wikipedia article can quickly select -- it to save related new articles in the same directory local dir = G_reader_settings:readSetting("wikipedia_save_dir") - if not dir then dir = G_reader_settings:readSetting("home_dir") end - if not dir then dir = require("apps/filemanager/filemanagerutil").getDefaultDir() end - if not dir then dir = "/" end + or G_reader_settings:readSetting("home_dir") + or require("apps/filemanager/filemanagerutil").getDefaultDir() + or "/" -- If this directory has no subdirectory, we would be displaying -- a single "..", so use parent directory in that case. local has_subdirectory = false diff --git a/frontend/apps/reader/modules/readerzooming.lua b/frontend/apps/reader/modules/readerzooming.lua index 886bfd84c..0853e8eb8 100644 --- a/frontend/apps/reader/modules/readerzooming.lua +++ b/frontend/apps/reader/modules/readerzooming.lua @@ -114,13 +114,13 @@ function ReaderZooming:onReadSettings(config) or G_reader_settings:readSetting("zoom_mode") or self.DEFAULT_ZOOM_MODE zoom_mode = util.arrayContains(self.available_zoom_modes, zoom_mode) - and zoom_mode - or self.DEFAULT_ZOOM_MODE + and zoom_mode + or self.DEFAULT_ZOOM_MODE self:setZoomMode(zoom_mode, true) -- avoid informative message on load for _, setting in ipairs(self.zoom_pan_settings) do - self[setting] = config:readSetting(setting) or - G_reader_settings:readSetting(setting) or - self[setting] + self[setting] = config:readSetting(setting) + or G_reader_settings:readSetting(setting) + or self[setting] end end @@ -433,8 +433,8 @@ function ReaderZooming:getZoom(pageno) zoom = self.zoom else local zoom_factor = self.ui.doc_settings:readSetting("zoom_factor") - or G_reader_settings:readSetting("zoom_factor") - or self.zoom_factor + or G_reader_settings:readSetting("zoom_factor") + or self.zoom_factor zoom = zoom_w * zoom_factor end if zoom and zoom > 10 and not Cache:willAccept(zoom * (self.dimen.w * self.dimen.h + 64)) then diff --git a/frontend/apps/reader/readerui.lua b/frontend/apps/reader/readerui.lua index 3e6593287..36ce853e9 100644 --- a/frontend/apps/reader/readerui.lua +++ b/frontend/apps/reader/readerui.lua @@ -332,7 +332,7 @@ function ReaderUI:init() ui = self }) end - self.disable_double_tap = G_reader_settings:readSetting("disable_double_tap") ~= false + self.disable_double_tap = G_reader_settings:nilOrTrue("disable_double_tap") -- back location stack self:registerModule("back", ReaderBack:new{ ui = self, diff --git a/frontend/device/cervantes/device.lua b/frontend/device/cervantes/device.lua index 621ec1b04..63e0cc822 100644 --- a/frontend/device/cervantes/device.lua +++ b/frontend/device/cervantes/device.lua @@ -204,6 +204,7 @@ end function Cervantes:intoScreenSaver() local Screensaver = require("ui/screensaver") if self.screen_saver_mode == false then + Screensaver:setup() Screensaver:show() end self.powerd:beforeSuspend() diff --git a/frontend/device/devicelistener.lua b/frontend/device/devicelistener.lua index 34f331962..46fb4bbc7 100644 --- a/frontend/device/devicelistener.lua +++ b/frontend/device/devicelistener.lua @@ -12,7 +12,7 @@ local T = require("ffi/util").template local DeviceListener = InputContainer:new{} local function _setSetting(name) - G_reader_settings:saveSetting(name, true) + G_reader_settings:makeTrue(name) end local function _unsetSetting(name) diff --git a/frontend/device/generic/device.lua b/frontend/device/generic/device.lua index fadc9e6d8..3da2a9137 100644 --- a/frontend/device/generic/device.lua +++ b/frontend/device/generic/device.lua @@ -168,9 +168,8 @@ function Device:init() self.screen.isBGRFrameBuffer = self.hasBGRFrameBuffer - local low_pan_rate = G_reader_settings:readSetting("low_pan_rate") - if low_pan_rate ~= nil then - self.screen.low_pan_rate = low_pan_rate + if G_reader_settings:has("low_pan_rate") then + self.screen.low_pan_rate = G_reader_settings:readSetting("low_pan_rate") else self.screen.low_pan_rate = self.hasEinkScreen() end @@ -226,6 +225,7 @@ end -- Only used on platforms where we handle suspend ourselves. function Device:onPowerEvent(ev) + local Screensaver = require("ui/screensaver") if self.screen_saver_mode then if ev == "Power" or ev == "Resume" then if self.is_cover_closed then @@ -247,7 +247,7 @@ function Device:onPowerEvent(ev) if self.orig_rotation_mode then self.screen:setRotationMode(self.orig_rotation_mode) end - require("ui/screensaver"):close() + Screensaver:close() if self:needsScreenRefreshAfterResume() then UIManager:scheduleIn(1, function() self.screen:refreshFull() end) end @@ -266,14 +266,14 @@ function Device:onPowerEvent(ev) self.powerd:beforeSuspend() local UIManager = require("ui/uimanager") logger.dbg("Suspending...") + -- Let Screensaver set its widget up, so we get accurate info down the line in case fallbacks kick in... + Screensaver:setup() -- Mostly always suspend in Portrait/Inverted Portrait mode... -- ... except when we just show an InfoMessage or when the screensaver -- is disabled, as it plays badly with Landscape mode (c.f., #4098 and #5290). -- We also exclude full-screen widgets that work fine in Landscape mode, -- like ReadingProgress and BookStatus (c.f., #5724) - local screensaver_type = G_reader_settings:readSetting("screensaver_type") - if screensaver_type ~= "message" and screensaver_type ~= "disable" and - screensaver_type ~= "readingprogress" and screensaver_type ~= "bookstatus" then + if Screensaver:modeExpectsPortrait() then self.orig_rotation_mode = self.screen:getRotationMode() -- Leave Portrait & Inverted Portrait alone, that works just fine. if bit.band(self.orig_rotation_mode, 1) == 1 then @@ -285,10 +285,8 @@ function Device:onPowerEvent(ev) -- On eInk, if we're using a screensaver mode that shows an image, -- flash the screen to white first, to eliminate ghosting. - if self:hasEinkScreen() and - screensaver_type == "cover" or screensaver_type == "random_image" or - screensaver_type == "image_file" then - if not G_reader_settings:isTrue("screensaver_no_background") then + if self:hasEinkScreen() and Screensaver:modeIsImage() then + if Screensaver:withBackground() then self.screen:clear() end self.screen:refreshFull() @@ -297,7 +295,7 @@ function Device:onPowerEvent(ev) -- nil it, in case user switched ScreenSaver modes during our lifetime. self.orig_rotation_mode = nil end - require("ui/screensaver"):show() + Screensaver:show() -- NOTE: show() will return well before the refresh ioctl is even *sent*: -- the only thing it's done is *enqueued* the refresh in UIManager's stack. -- Which is why the actual suspension needs to be delayed by suspend_wait_timeout, diff --git a/frontend/device/kindle/device.lua b/frontend/device/kindle/device.lua index 48441dccf..e14c9a333 100644 --- a/frontend/device/kindle/device.lua +++ b/frontend/device/kindle/device.lua @@ -178,14 +178,14 @@ function Kindle:intoScreenSaver() -- NOTE: Meaning this is not a SO device ;) local Screensaver = require("ui/screensaver") -- NOTE: Pilefered from Device:onPowerEvent @ frontend/device/generic/device.lua + -- Let Screensaver set its widget up, so we get accurate info down the line in case fallbacks kick in... + Screensaver:setup() -- Mostly always suspend in Portrait/Inverted Portrait mode... -- ... except when we just show an InfoMessage or when the screensaver -- is disabled, as it plays badly with Landscape mode (c.f., #4098 and #5290). -- We also exclude full-screen widgets that work fine in Landscape mode, -- like ReadingProgress and BookStatus (c.f., #5724) - local screensaver_type = G_reader_settings:readSetting("screensaver_type") - if screensaver_type ~= "message" and screensaver_type ~= "disable" and - screensaver_type ~= "readingprogress" and screensaver_type ~= "bookstatus" then + if Screensaver:modeExpectsPortrait() then self.orig_rotation_mode = self.screen:getRotationMode() -- Leave Portrait & Inverted Portrait alone, that works just fine. if bit.band(self.orig_rotation_mode, 1) == 1 then @@ -197,10 +197,8 @@ function Kindle:intoScreenSaver() -- On eInk, if we're using a screensaver mode that shows an image, -- flash the screen to white first, to eliminate ghosting. - if self:hasEinkScreen() and - screensaver_type == "cover" or screensaver_type == "random_image" or - screensaver_type == "image_file" then - if not G_reader_settings:isTrue("screensaver_no_background") then + if self:hasEinkScreen() and Screensaver:modeIsImage() then + if Screensaver:withBackground() then self.screen:clear() end self.screen:refreshFull() diff --git a/frontend/device/kobo/device.lua b/frontend/device/kobo/device.lua index 377aeca30..18ff707e2 100644 --- a/frontend/device/kobo/device.lua +++ b/frontend/device/kobo/device.lua @@ -340,17 +340,15 @@ function Kobo:init() self.touchScreenProbe = function() -- if user has not set KOBO_TOUCH_MIRRORED yet if KOBO_TOUCH_MIRRORED == nil then - local switch_xy = G_reader_settings:readSetting("kobo_touch_switch_xy") -- and has no probe before - if switch_xy == nil then + if G_reader_settings:hasNot("kobo_touch_switch_xy") then local TouchProbe = require("tools/kobo_touch_probe") local UIManager = require("ui/uimanager") UIManager:show(TouchProbe:new{}) UIManager:run() -- assuming TouchProbe sets kobo_touch_switch_xy config - switch_xy = G_reader_settings:readSetting("kobo_touch_switch_xy") end - self.touch_switch_xy = switch_xy + self.touch_switch_xy = G_reader_settings:readSetting("kobo_touch_switch_xy") end self:initEventAdjustHooks() end diff --git a/frontend/device/sdl/device.lua b/frontend/device/sdl/device.lua index 762e7263c..b11b2f013 100644 --- a/frontend/device/sdl/device.lua +++ b/frontend/device/sdl/device.lua @@ -90,7 +90,7 @@ local Device = Generic:new{ external.when_back_callback = nil end end, - window = G_reader_settings:readSetting("sdl_window") or {}, + window = G_reader_settings:readSetting("sdl_window", {}), } local AppImage = Device:new{ @@ -323,12 +323,6 @@ function Device:setDateTime(year, month, day, hour, min, sec) end end -function Device:exit() - G_reader_settings:saveSetting("sdl_window", self.window) - G_reader_settings:flush() - Generic.exit(self) -end - function Emulator:simulateSuspend() local InfoMessage = require("ui/widget/infomessage") local UIManager = require("ui/uimanager") diff --git a/frontend/device/sony-prstux/device.lua b/frontend/device/sony-prstux/device.lua index bb78c62ce..b6534bda9 100644 --- a/frontend/device/sony-prstux/device.lua +++ b/frontend/device/sony-prstux/device.lua @@ -94,6 +94,7 @@ end function SonyPRSTUX:intoScreenSaver() local Screensaver = require("ui/screensaver") if self.screen_saver_mode == false then + Screensaver:setup() Screensaver:show() end self.powerd:beforeSuspend() diff --git a/frontend/docsettings.lua b/frontend/docsettings.lua index efbd618b6..21dee87f1 100644 --- a/frontend/docsettings.lua +++ b/frontend/docsettings.lua @@ -165,19 +165,136 @@ function DocSettings:open(docfile) return setmetatable(new, {__index = DocSettings}) end ---- Reads a setting. -function DocSettings:readSetting(key) +--[[-- Reads a setting, optionally initializing it to a default. + +If default is provided, and the key doesn't exist yet, it is initialized to default first. +This ensures both that the defaults are actually set if necessary, +and that the returned reference actually belongs to the DocSettings object straight away, +without requiring further interaction (e.g., saveSetting) from the caller. + +This is mainly useful if the data type you want to retrieve/store is assigned/returned/passed by reference (e.g., a table), +and you never actually break that reference by assigning another one to the same variable, (by e.g., assigning it a new object). +c.f., https://www.lua.org/manual/5.1/manual.html#2.2 + +@param key The setting's key +@param default Initialization data (Optional) +]] +function DocSettings:readSetting(key, default) + -- No initialization data: legacy behavior + if not default then + return self.data[key] + end + + if not self:has(key) then + self.data[key] = default + end return self.data[key] end --- Saves a setting. function DocSettings:saveSetting(key, value) self.data[key] = value + return self end --- Deletes a setting. function DocSettings:delSetting(key) self.data[key] = nil + return self +end + +--- Checks if setting exists. +function DocSettings:has(key) + return self.data[key] ~= nil +end + +--- Checks if setting does not exist. +function DocSettings:hasNot(key) + return self.data[key] == nil +end + +--- Checks if setting is `true` (boolean). +function DocSettings:isTrue(key) + return self.data[key] == true +end + +--- Checks if setting is `false` (boolean). +function DocSettings:isFalse(key) + return self.data[key] == false +end + +--- Checks if setting is `nil` or `true`. +function DocSettings:nilOrTrue(key) + return self:hasNot(key) or self:isTrue(key) +end + +--- Checks if setting is `nil` or `false`. +function DocSettings:nilOrFalse(key) + return self:hasNot(key) or self:isFalse(key) +end + +--- Flips `nil` or `true` to `false`, and `false` to `nil`. +--- e.g., a setting that defaults to true. +function DocSettings:flipNilOrTrue(key) + if self:nilOrTrue(key) then + self:saveSetting(key, false) + else + self:delSetting(key) + end + return self +end + +--- Flips `nil` or `false` to `true`, and `true` to `nil`. +--- e.g., a setting that defaults to false. +function DocSettings:flipNilOrFalse(key) + if self:nilOrFalse(key) then + self:saveSetting(key, true) + else + self:delSetting(key) + end + return self +end + +--- Flips a setting between `true` and `nil`. +function DocSettings:flipTrue(key) + if self:isTrue(key) then + self:delSetting(key) + else + self:saveSetting(key, true) + end + return self +end + +--- Flips a setting between `false` and `nil`. +function DocSettings:flipFalse(key) + if self:isFalse(key) then + self:delSetting(key) + else + self:saveSetting(key, false) + end + return self +end + +-- Unconditionally makes a boolean setting `true`. +function DocSettings:makeTrue(key) + self:saveSetting(key, true) + return self +end + +-- Unconditionally makes a boolean setting `false`. +function DocSettings:makeFalse(key) + self:saveSetting(key, false) + return self +end + +--- Toggles a boolean setting +function DocSettings:toggle(key) + if self:nilOrFalse(key) then + self:saveSetting(key, true) + else + self:saveSetting(key, false) + end + return self end --- Serializes settings and writes them to `metadata.lua`. @@ -220,8 +337,7 @@ function DocSettings:flush() f_out:close() if self.candidates ~= nil - and not G_reader_settings:readSetting( - "preserve_legacy_docsetting") then + and G_reader_settings:nilOrFalse("preserve_legacy_docsetting") then for _, k in pairs(self.candidates) do if k[1] ~= f and k[1] ~= f .. ".old" then logger.dbg("Remove legacy file ", k[1]) diff --git a/frontend/document/credocument.lua b/frontend/document/credocument.lua index 61e6bcdb2..cbfb67042 100644 --- a/frontend/document/credocument.lua +++ b/frontend/document/credocument.lua @@ -228,16 +228,16 @@ function CreDocument:setupDefaultView() self._document:adjustFontSizes(CanvasContext:getDPI()) -- set top status bar font size - if G_reader_settings:readSetting("cre_header_status_font_size") then + if G_reader_settings:has("cre_header_status_font_size") then self._document:setIntProperty("crengine.page.header.font.size", G_reader_settings:readSetting("cre_header_status_font_size")) end -- One can set these to change from white background - if G_reader_settings:readSetting("cre_background_color") then + if G_reader_settings:has("cre_background_color") then self:setBackgroundColor(G_reader_settings:readSetting("cre_background_color")) end - if G_reader_settings:readSetting("cre_background_image") then + if G_reader_settings:has("cre_background_image") then self:setBackgroundImage(G_reader_settings:readSetting("cre_background_image")) end end diff --git a/frontend/document/documentregistry.lua b/frontend/document/documentregistry.lua index ac54e0177..ebfb66272 100644 --- a/frontend/document/documentregistry.lua +++ b/frontend/document/documentregistry.lua @@ -72,10 +72,7 @@ function DocumentRegistry:hasProvider(file, mimetype) end local DocSettings = require("docsettings") if DocSettings:hasSidecarFile(file) then - local doc_settings_provider = DocSettings:open(file):readSetting("provider") - if doc_settings_provider then - return true - end + return DocSettings:open(file):has("provider") end return false end @@ -134,7 +131,8 @@ function DocumentRegistry:getProviders(file) local added = false local suffix = string.sub(file, -string.len(provider.extension) - 1) if string.lower(suffix) == "."..provider.extension then - for i, prov_prev in ipairs(providers) do + for i = #providers, 1, -1 do + local prov_prev = providers[i] if prov_prev.provider == provider.provider then if prov_prev.weight >= provider.weight then added = true @@ -143,7 +141,7 @@ function DocumentRegistry:getProviders(file) end end end - -- if extension == provider.extension then + -- if extension == provider.extension then -- stick highest weighted provider at the front if not added and #providers >= 1 and provider.weight > providers[1].weight then table.insert(providers, 1, provider) diff --git a/frontend/luasettings.lua b/frontend/luasettings.lua index 3fb1ca59d..6391be385 100644 --- a/frontend/luasettings.lua +++ b/frontend/luasettings.lua @@ -56,7 +56,7 @@ end Settings:saveSetting("key", { a = "b", - c = "true", + c = true, d = false, }) @@ -69,8 +69,29 @@ function LuaSettings:child(key) return LuaSettings:wrap(self:readSetting(key)) end ---- Reads a setting. -function LuaSettings:readSetting(key) +--[[-- Reads a setting, optionally initializing it to a default. + +If default is provided, and the key doesn't exist yet, it is initialized to default first. +This ensures both that the defaults are actually set if necessary, +and that the returned reference actually belongs to the LuaSettings object straight away, +without requiring further interaction (e.g., saveSetting) from the caller. + +This is mainly useful if the data type you want to retrieve/store is assigned/returned/passed by reference (e.g., a table), +and you never actually break that reference by assigning another one to the same variable, (by e.g., assigning it a new object). +c.f., . + +@param key The setting's key +@param default Initialization data (Optional) +]] +function LuaSettings:readSetting(key, default) + -- No initialization data: legacy behavior + if not default then + return self.data[key] + end + + if not self:has(key) then + self.data[key] = default + end return self.data[key] end @@ -88,22 +109,22 @@ end --- Checks if setting exists. function LuaSettings:has(key) - return self:readSetting(key) ~= nil + return self.data[key] ~= nil end --- Checks if setting does not exist. function LuaSettings:hasNot(key) - return self:readSetting(key) == nil + return self.data[key] == nil end ---- Checks if setting is `true`. +--- Checks if setting is `true` (boolean). function LuaSettings:isTrue(key) - return string.lower(tostring(self:readSetting(key))) == "true" + return self.data[key] == true end ---- Checks if setting is `false`. +--- Checks if setting is `false` (boolean). function LuaSettings:isFalse(key) - return string.lower(tostring(self:readSetting(key))) == "false" + return self.data[key] == false end --- Checks if setting is `nil` or `true`. @@ -116,7 +137,8 @@ function LuaSettings:nilOrFalse(key) return self:hasNot(key) or self:isFalse(key) end ---- Flips `nil` or `true` to `false`. +--- Flips `nil` or `true` to `false`, and `false` to `nil`. +--- e.g., a setting that defaults to true. function LuaSettings:flipNilOrTrue(key) if self:nilOrTrue(key) then self:saveSetting(key, false) @@ -126,7 +148,8 @@ function LuaSettings:flipNilOrTrue(key) return self end ---- Flips `nil` or `false` to `true`. +--- Flips `nil` or `false` to `true`, and `true` to `nil`. +--- e.g., a setting that defaults to false. function LuaSettings:flipNilOrFalse(key) if self:nilOrFalse(key) then self:saveSetting(key, true) @@ -136,7 +159,7 @@ function LuaSettings:flipNilOrFalse(key) return self end ---- Flips setting to `true`. +--- Flips a setting between `true` and `nil`. function LuaSettings:flipTrue(key) if self:isTrue(key) then self:delSetting(key) @@ -146,7 +169,7 @@ function LuaSettings:flipTrue(key) return self end ---- Flips setting to `false`. +--- Flips a setting between `false` and `nil`. function LuaSettings:flipFalse(key) if self:isFalse(key) then self:delSetting(key) @@ -156,6 +179,28 @@ function LuaSettings:flipFalse(key) return self end +-- Unconditionally makes a boolean setting `true`. +function LuaSettings:makeTrue(key) + self:saveSetting(key, true) + return self +end + +-- Unconditionally makes a boolean setting `false`. +function LuaSettings:makeFalse(key) + self:saveSetting(key, false) + return self +end + +--- Toggles a boolean setting +function LuaSettings:toggle(key) + if self:nilOrFalse(key) then + self:saveSetting(key, true) + else + self:saveSetting(key, false) + end + return self +end + -- Initializes settings per extension with default values function LuaSettings:initializeExtSettings(key, defaults, force_init) local curr = self:readSetting(key) diff --git a/frontend/readhistory.lua b/frontend/readhistory.lua index c44aa9b4c..5fe43fafe 100644 --- a/frontend/readhistory.lua +++ b/frontend/readhistory.lua @@ -195,7 +195,7 @@ function ReadHistory:getPreviousFile(current_file) end function ReadHistory:fileDeleted(path) - if G_reader_settings:readSetting("autoremove_deleted_items_from_history") then + if G_reader_settings:isTrue("autoremove_deleted_items_from_history") then self:removeItemByPath(path) else -- Make it dimed @@ -210,7 +210,7 @@ function ReadHistory:fileDeleted(path) end function ReadHistory:fileSettingsPurged(path) - if G_reader_settings:readSetting("autoremove_deleted_items_from_history") then + if G_reader_settings:isTrue("autoremove_deleted_items_from_history") then -- Also remove it from history on purge when that setting is enabled self:removeItemByPath(path) end diff --git a/frontend/ui/data/settings_migration.lua b/frontend/ui/data/settings_migration.lua index 739c645f3..b4bbf9827 100644 --- a/frontend/ui/data/settings_migration.lua +++ b/frontend/ui/data/settings_migration.lua @@ -25,8 +25,8 @@ function SettingsMigration:migrateSettings(config) end -- Fine-grained CRe margins (#4945) - local old_margins = config:readSetting("copt_page_margins") - if old_margins then + if config:has("copt_page_margins") then + local old_margins = config:readSetting("copt_page_margins") logger.info("Migrating old", cfg_class, "CRe margin settings: L", old_margins[1], "T", old_margins[2], "R", old_margins[3], "B", old_margins[4]) -- Format was: {left, top, right, bottom} config:saveSetting("copt_h_page_margins", {old_margins[1], old_margins[3]}) @@ -39,7 +39,7 @@ function SettingsMigration:migrateSettings(config) -- Space condensing to Word spacing -- From a single number (space condensing) to a table of 2 numbers ({space width scale, space condensing}). -- Be conservative and don't change space width scale: use 100% - if not config:readSetting("copt_word_spacing") and config:readSetting("copt_space_condensing") then + if config:hasNot("copt_word_spacing") and config:has("copt_space_condensing") then local space_condensing = config:readSetting("copt_space_condensing") logger.info("Migrating old", cfg_class, "CRe space condensing:", space_condensing) config:saveSetting("copt_word_spacing", { 100, space_condensing }) diff --git a/frontend/ui/elements/common_settings_menu_table.lua b/frontend/ui/elements/common_settings_menu_table.lua index e232c176c..10560fe25 100644 --- a/frontend/ui/elements/common_settings_menu_table.lua +++ b/frontend/ui/elements/common_settings_menu_table.lua @@ -157,8 +157,8 @@ if Device:isKobo() then return G_reader_settings:isTrue("ignore_power_sleepcover") end, callback = function() - G_reader_settings:flipNilOrFalse("ignore_power_sleepcover") - G_reader_settings:flipFalse("ignore_open_sleepcover") + G_reader_settings:toggle("ignore_power_sleepcover") + G_reader_settings:makeFalse("ignore_open_sleepcover") UIManager:show(InfoMessage:new{ text = _("This will take effect on next restart."), }) @@ -171,8 +171,8 @@ if Device:isKobo() then return G_reader_settings:isTrue("ignore_open_sleepcover") end, callback = function() - G_reader_settings:flipNilOrFalse("ignore_open_sleepcover") - G_reader_settings:flipFalse("ignore_power_sleepcover") + G_reader_settings:toggle("ignore_open_sleepcover") + G_reader_settings:makeFalse("ignore_power_sleepcover") UIManager:show(InfoMessage:new{ text = _("This will take effect on next restart."), }) @@ -436,7 +436,7 @@ if Device:hasKeys() then end -- Auto-save settings: default value, info text and warning, and menu items -if G_reader_settings:readSetting("auto_save_settings_interval_minutes") == nil then +if G_reader_settings:hasNot("auto_save_settings_interval_minutes") then -- Default to auto save every 15 mn G_reader_settings:saveSetting("auto_save_settings_interval_minutes", 15) end @@ -593,8 +593,7 @@ common_settings.document = { { text = _("Open next file"), enabled_func = function() - return G_reader_settings:readSetting("collate") - ~= "access" + return G_reader_settings:readSetting("collate") ~= "access" end, checked_func = function() return G_reader_settings:readSetting("end_document_action") == "next_file" diff --git a/frontend/ui/elements/flash_keyboard.lua b/frontend/ui/elements/flash_keyboard.lua index f4ce052ad..22b70af51 100644 --- a/frontend/ui/elements/flash_keyboard.lua +++ b/frontend/ui/elements/flash_keyboard.lua @@ -3,10 +3,10 @@ local _ = require("gettext") return { text = _("Flash keyboard"), checked_func = function() - return G_reader_settings:readSetting("flash_keyboard") ~= false + return G_reader_settings:nilOrTrue("flash_keyboard") end, callback = function() - local disabled = G_reader_settings:readSetting("flash_keyboard") ~= false + local disabled = G_reader_settings:nilOrTrue("flash_keyboard") G_reader_settings:saveSetting("flash_keyboard", not disabled) end, } diff --git a/frontend/ui/elements/screen_disable_double_tap_table.lua b/frontend/ui/elements/screen_disable_double_tap_table.lua index 6fe1e0acb..979b822e0 100644 --- a/frontend/ui/elements/screen_disable_double_tap_table.lua +++ b/frontend/ui/elements/screen_disable_double_tap_table.lua @@ -5,10 +5,10 @@ local _ = require("gettext") return { text = _("Disable double tap"), checked_func = function() - return G_reader_settings:readSetting("disable_double_tap") ~= false + return G_reader_settings:nilOrTrue("disable_double_tap") end, callback = function() - local disabled = G_reader_settings:readSetting("disable_double_tap") ~= false + local disabled = G_reader_settings:nilOrTrue("disable_double_tap") G_reader_settings:saveSetting("disable_double_tap", not disabled) UIManager:show(InfoMessage:new{ text = _("This will take effect on next restart."), diff --git a/frontend/ui/elements/screensaver_menu.lua b/frontend/ui/elements/screensaver_menu.lua index 4dc194152..4d9852e73 100644 --- a/frontend/ui/elements/screensaver_menu.lua +++ b/frontend/ui/elements/screensaver_menu.lua @@ -1,31 +1,22 @@ local Screensaver = require("ui/screensaver") local _ = require("gettext") -local function screensaverType() return G_reader_settings:readSetting("screensaver_type") end -local function screensaverDelay() return G_reader_settings:readSetting("screensaver_delay") end -local function lastFile() +local function hasLastFile() + if G_reader_settings:hasNot("lastfile") then + return false + end + local lfs = require("libs/libkoreader-lfs") local last_file = G_reader_settings:readSetting("lastfile") - if last_file and lfs.attributes(last_file, "mode") == "file" then - return last_file - end + return last_file and lfs.attributes(last_file, "mode") == "file" end -local function whiteBackground() return G_reader_settings:isTrue("screensaver_white_background") end -local function noBackground() return G_reader_settings:isTrue("screensaver_no_background") end -local function stretchImages() return G_reader_settings:isTrue("screensaver_stretch_images") end -local function messagePosition() return G_reader_settings:readSetting("screensaver_message_position") end -local function showMessage() return G_reader_settings:isTrue("screensaver_show_message") end return { { text = _("Use last book's cover as screensaver"), - enabled_func = function() return lastFile() ~= nil end, + enabled_func = hasLastFile, checked_func = function() - if screensaverType() == "cover" then - return true - else - return false - end + return G_reader_settings:readSetting("screensaver_type") == "cover" end, callback = function() G_reader_settings:saveSetting("screensaver_type", "cover") @@ -33,13 +24,9 @@ return { }, { text = _("Use book status as screensaver"), - enabled_func = function() return lastFile() ~= nil end, + enabled_func = hasLastFile, checked_func = function() - if screensaverType() == "bookstatus" then - return true - else - return false - end + return G_reader_settings:readSetting("screensaver_type") == "bookstatus" end, callback = function() G_reader_settings:saveSetting("screensaver_type", "bookstatus") @@ -48,11 +35,7 @@ return { { text = _("Use random image from folder as screensaver"), checked_func = function() - if screensaverType() == "random_image" then - return true - else - return false - end + return G_reader_settings:readSetting("screensaver_type") == "random_image" end, callback = function() G_reader_settings:saveSetting("screensaver_type", "random_image") @@ -61,11 +44,7 @@ return { { text = _("Use document cover as screensaver"), checked_func = function() - if screensaverType() == "document_cover" then - return true - else - return false - end + return G_reader_settings:readSetting("screensaver_type") == "document_cover" end, callback = function() G_reader_settings:saveSetting("screensaver_type", "document_cover") @@ -74,11 +53,7 @@ return { { text = _("Use image as screensaver"), checked_func = function() - if screensaverType() == "image_file" then - return true - else - return false - end + return G_reader_settings:readSetting("screensaver_type") == "image_file" end, callback = function() G_reader_settings:saveSetting("screensaver_type", "image_file") @@ -86,13 +61,9 @@ return { }, { text = _("Use reading progress as screensaver"), - enabled_func = function() return Screensaver.getReaderProgress ~= nil and lastFile() ~= nil end, + enabled_func = function() return Screensaver.getReaderProgress ~= nil and hasLastFile() end, checked_func = function() - if screensaverType() == "readingprogress" then - return true - else - return false - end + return G_reader_settings:readSetting("screensaver_type") == "readingprogress" end, callback = function() G_reader_settings:saveSetting("screensaver_type", "readingprogress") @@ -101,11 +72,7 @@ return { { text = _("Leave screen as it is"), checked_func = function() - if screensaverType() == "disable" then - return true - else - return false - end + return G_reader_settings:readSetting("screensaver_type") == "disable" or G_reader_settings:hasNot("screensaver_type") end, callback = function() G_reader_settings:saveSetting("screensaver_type", "disable") @@ -114,9 +81,11 @@ return { }, { text = _("Add message to screensaver"), - checked_func = showMessage, + checked_func = function() + return G_reader_settings:isTrue("screensaver_show_message") or G_reader_settings:hasNot("screensaver_type") + end, callback = function() - G_reader_settings:saveSetting("screensaver_show_message", not showMessage()) + G_reader_settings:toggle("screensaver_show_message") end, separator = true, }, @@ -151,27 +120,40 @@ return { Screensaver:setMessage() end, }, + { + text = _("Black background behind images"), + checked_func = function() + return G_reader_settings:readSetting("screensaver_background") == "black" or G_reader_settings:hasNot("screensaver_background") + end, + callback = function() + G_reader_settings:saveSetting("screensaver_background", "black") + end, + }, { text = _("White background behind message and images"), - checked_func = whiteBackground, + checked_func = function() + return G_reader_settings:readSetting("screensaver_background") == "white" + end, callback = function() - G_reader_settings:saveSetting("screensaver_white_background", not whiteBackground()) - G_reader_settings:flipFalse("screensaver_no_background") + G_reader_settings:saveSetting("screensaver_background", "white") end, }, { text = _("Leave background as-is behind message and images"), - checked_func = noBackground, + checked_func = function() + return G_reader_settings:readSetting("screensaver_background") == "none" + end, callback = function() - G_reader_settings:saveSetting("screensaver_no_background", not noBackground()) - G_reader_settings:flipFalse("screensaver_white_background") + G_reader_settings:saveSetting("screensaver_background", "none") end, }, { text = _("Stretch covers and images to fit screen"), - checked_func = stretchImages, + checked_func = function() + return G_reader_settings:isTrue("screensaver_stretch_images") + end, callback = function() - G_reader_settings:saveSetting("screensaver_stretch_images", not stretchImages()) + G_reader_settings:toggle("screensaver_stretch_images") end, separator = true, }, @@ -181,7 +163,7 @@ return { { text = _("Top"), checked_func = function() - return messagePosition() == "top" + return G_reader_settings:readSetting("screensaver_message_position") == "top" end, callback = function() G_reader_settings:saveSetting("screensaver_message_position", "top") @@ -190,7 +172,7 @@ return { { text = _("Middle"), checked_func = function() - return messagePosition() == "middle" or messagePosition() == nil + return G_reader_settings:readSetting("screensaver_message_position") == "middle" or G_reader_settings:hasNot("screensaver_message_position") end, callback = function() G_reader_settings:saveSetting("screensaver_message_position", "middle") @@ -199,7 +181,7 @@ return { { text = _("Bottom"), checked_func = function() - return messagePosition() == "bottom" + return G_reader_settings:readSetting("screensaver_message_position") == "bottom" end, callback = function() G_reader_settings:saveSetting("screensaver_message_position", "bottom") @@ -213,11 +195,7 @@ return { { text = _("Disable"), checked_func = function() - if screensaverDelay() == nil or screensaverDelay() == "disable" then - return true - else - return false - end + return G_reader_settings:readSetting("screensaver_delay") == "disable" or G_reader_settings:hasNot("screensaver_delay") end, callback = function() G_reader_settings:saveSetting("screensaver_delay", "disable") @@ -226,11 +204,7 @@ return { { text = _("For 1 second"), checked_func = function() - if screensaverDelay() == "1" then - return true - else - return false - end + return G_reader_settings:readSetting("screensaver_delay") == "1" end, callback = function() G_reader_settings:saveSetting("screensaver_delay", "1") @@ -239,11 +213,7 @@ return { { text = _("For 3 seconds"), checked_func = function() - if screensaverDelay() == "3" then - return true - else - return false - end + return G_reader_settings:readSetting("screensaver_delay") == "3" end, callback = function() G_reader_settings:saveSetting("screensaver_delay", "3") @@ -252,11 +222,7 @@ return { { text = _("For 5 seconds"), checked_func = function() - if screensaverDelay() == "5" then - return true - else - return false - end + return G_reader_settings:readSetting("screensaver_delay") == "5" end, callback = function() G_reader_settings:saveSetting("screensaver_delay", "5") @@ -265,11 +231,7 @@ return { { text = _("Until a tap"), checked_func = function() - if screensaverDelay() == "tap" then - return true - else - return false - end + return G_reader_settings:readSetting("screensaver_delay") == "tap" end, callback = function() G_reader_settings:saveSetting("screensaver_delay", "tap") diff --git a/frontend/ui/network/manager.lua b/frontend/ui/network/manager.lua index 1bf4c68c2..1a7670e42 100644 --- a/frontend/ui/network/manager.lua +++ b/frontend/ui/network/manager.lua @@ -25,7 +25,7 @@ function NetworkMgr:connectivityCheck(iter, callback, widget) if iter > 25 then logger.info("Failed to restore Wi-Fi (after", iter, "iterations)!") self.wifi_was_on = false - G_reader_settings:saveSetting("wifi_was_on", false) + G_reader_settings:makeFalse("wifi_was_on") -- If we abort, murder Wi-Fi and the async script first... if Device:hasWifiManager() and not Device:isEmulator() then os.execute("pkill -TERM restore-wifi-async.sh 2>/dev/null") @@ -42,7 +42,7 @@ function NetworkMgr:connectivityCheck(iter, callback, widget) if NetworkMgr:isWifiOn() and NetworkMgr:isConnected() then self.wifi_was_on = true - G_reader_settings:saveSetting("wifi_was_on", true) + G_reader_settings:makeTrue("wifi_was_on") UIManager:broadcastEvent(Event:new("NetworkConnected")) logger.info("Wi-Fi successfully restored (after", iter, "iterations)!") @@ -118,7 +118,7 @@ function NetworkMgr:promptWifiOn(complete_callback) ok_text = _("Turn on"), ok_callback = function() self.wifi_was_on = true - G_reader_settings:saveSetting("wifi_was_on", true) + G_reader_settings:makeTrue("wifi_was_on") self:turnOnWifi(complete_callback) end, }) @@ -130,7 +130,7 @@ function NetworkMgr:promptWifiOff(complete_callback) ok_text = _("Turn off"), ok_callback = function() self.wifi_was_on = false - G_reader_settings:saveSetting("wifi_was_on", false) + G_reader_settings:makeFalse("wifi_was_on") self:turnOffWifi(complete_callback) end, }) @@ -142,13 +142,13 @@ function NetworkMgr:promptWifi(complete_callback) choice1_text = _("Turn Wi-Fi off"), choice1_callback = function() self.wifi_was_on = false - G_reader_settings:saveSetting("wifi_was_on", false) + G_reader_settings:makeFalse("wifi_was_on") self:turnOffWifi(complete_callback) end, choice2_text = _("Connect"), choice2_callback = function() self.wifi_was_on = true - G_reader_settings:saveSetting("wifi_was_on", true) + G_reader_settings:makeTrue("wifi_was_on") self:turnOnWifi(complete_callback) end, }) @@ -268,9 +268,9 @@ function NetworkMgr:setHTTPProxy(proxy) http.PROXY = proxy if proxy then G_reader_settings:saveSetting("http_proxy", proxy) - G_reader_settings:saveSetting("http_proxy_enabled", true) + G_reader_settings:makeTrue("http_proxy_enabled") else - G_reader_settings:saveSetting("http_proxy_enabled", false) + G_reader_settings:makeFalse("http_proxy_enabled") end end @@ -376,7 +376,7 @@ function NetworkMgr:getWifiToggleMenuTable() -- (It's called connect_callback there). -- This makes this branch somewhat hard to reach, which is why it gets a dedicated prompt below... self.wifi_was_on = false - G_reader_settings:saveSetting("wifi_was_on", false) + G_reader_settings:makeFalse("wifi_was_on") -- NOTE: We're limiting this to only a few platforms, as it might be actually harmful on some devices. -- The intent being to unload kernel modules, and make a subsequent turnOnWifi behave sanely. -- PB: Relies on netagent, no idea what it does, but it's not using this codepath anyway (!hasWifiToggle) diff --git a/frontend/ui/screensaver.lua b/frontend/ui/screensaver.lua index 5a0d4cf59..4c49b495e 100644 --- a/frontend/ui/screensaver.lua +++ b/frontend/ui/screensaver.lua @@ -23,18 +23,41 @@ local _ = require("gettext") local Screen = Device.screen local T = require("ffi/util").template -local screensaver_provider = { - ["jpg"] = true, - ["jpeg"] = true, - ["png"] = true, - ["gif"] = true, - ["tif"] = true, - ["tiff"] = true, +-- Migrate old settings from 2021.02 or older. +if G_reader_settings:readSetting("screensaver_type", "disable") == "message" then + G_reader_settings:saveSetting("screensaver_type", "disable") + G_reader_settings:makeTrue("screensaver_show_message") +end +if G_reader_settings:has("screensaver_no_background") then + if G_reader_settings:isTrue("screensaver_no_background") then + G_reader_settings:saveSetting("screensaver_background", "none") + end + G_reader_settings:delSetting("screensaver_no_background") +end +if G_reader_settings:has("screensaver_white_background") then + if G_reader_settings:isTrue("screensaver_white_background") then + G_reader_settings:saveSetting("screensaver_background", "white") + end + G_reader_settings:delSetting("screensaver_white_background") +end + +local Screensaver = { + screensaver_provider = { + jpg = true, + jpeg = true, + png = true, + gif = true, + tif = true, + tiff = true, + }, + default_screensaver_message = _("Sleeping"), } -local default_screensaver_message = _("Sleeping") -local Screensaver = {} -local function getRandomImage(dir) +function Screensaver:_getRandomImage(dir) + if not dir then + return nil + end + if string.sub(dir, string.len(dir)) ~= "/" then dir = dir .. "/" end @@ -46,7 +69,7 @@ local function getRandomImage(dir) for entry in iter, dir_obj do if lfs.attributes(dir .. entry, "mode") == "file" then local extension = string.lower(string.match(entry, ".+%.([^.]+)") or "") - if screensaver_provider[extension] then + if self.screensaver_provider[extension] then i = i + 1 pics[i] = entry end @@ -61,6 +84,114 @@ local function getRandomImage(dir) return dir .. pics[math.random(i)] end +local function expandSpecial(message, fallback) + -- Expand special character sequences in given message. + -- %p percentage read + -- %c current page + -- %t total pages + -- %T document title + -- %A document authors + -- %S document series + + if G_reader_settings:hasNot("lastfile") then + return fallback + end + + local ret = message + local lastfile = G_reader_settings:readSetting("lastfile") + + local totalpages = 0 + local percent = 0 + local currentpage = 0 + local title = _("N/A") + local authors = _("N/A") + local series = _("N/A") + + local instance = require("apps/reader/readerui"):_getRunningInstance() + if instance == nil and DocSettings:hasSidecarFile(lastfile) then + -- If there's no ReaderUI instance, but the file has sidecar data, use that + local docinfo = DocSettings:open(lastfile) + totalpages = docinfo.data.doc_pages or totalpages + percent = docinfo.data.percent_finished or percent + currentpage = Math.round(percent * totalpages) + percent = Math.round(percent * 100) + if docinfo.data.doc_props then + title = docinfo.data.doc_props.title and docinfo.data.doc_props.title ~= "" and docinfo.data.doc_props.title or title + authors = docinfo.data.doc_props.authors and docinfo.data.doc_props.authors ~= "" and docinfo.data.doc_props.authors or authors + series = docinfo.data.doc_props.series and docinfo.data.doc_props.series ~= "" and docinfo.data.doc_props.series or series + end + docinfo:close() + elseif instance ~= nil and lfs.attributes(lastfile, "mode") == "file" then + -- But if we have a ReaderUI instance, and the file stil exists, open it + local doc = DocumentRegistry:openDocument(lastfile) + currentpage = instance.view.state.page or currentpage + totalpages = doc:getPageCount() or totalpages + 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 + doc:close() + end + + ret = string.gsub(ret, "%%c", currentpage) + ret = string.gsub(ret, "%%t", totalpages) + ret = string.gsub(ret, "%%p", percent) + ret = string.gsub(ret, "%%T", title) + ret = string.gsub(ret, "%%A", authors) + ret = string.gsub(ret, "%%S", series) + + return ret +end + +local function addOverlayMessage(widget, text) + local FrameContainer = require("ui/widget/container/framecontainer") + local RightContainer = require("ui/widget/container/rightcontainer") + local Size = require("ui/size") + local TextWidget = require("ui/widget/textwidget") + + local face = Font:getFace("infofont") + local screen_w, screen_h = Screen:getWidth(), Screen:getHeight() + + local textw = TextWidget:new{ + text = text, + face = face, + } + -- Don't make our message reach full screen width + if textw:getWidth() > screen_w * 0.9 then + -- Text too wide: use TextBoxWidget for multi lines display + textw = TextBoxWidget:new{ + text = text, + face = face, + width = math.floor(screen_w * 0.9) + } + end + textw = FrameContainer:new{ + background = Blitbuffer.COLOR_WHITE, + bordersize = Size.border.default, + margin = 0, + textw, + } + textw = RightContainer:new{ + dimen = { + w = screen_w, + h = textw:getSize().h, + }, + textw, + } + widget = OverlapGroup:new{ + dimen = { + h = screen_w, + w = screen_h, + }, + widget, + textw, + } + return widget +end + function Screensaver:chooseFolder() local buttons = {} table.insert(buttons, { @@ -90,9 +221,7 @@ function Screensaver:chooseFolder() } }) local screensaver_dir = G_reader_settings:readSetting("screensaver_dir") - if screensaver_dir == nil then - screensaver_dir = DataStorage:getDataDir() .. "/screenshots/" - end + or DataStorage:getDataDir() .. "/screenshots/" self.choose_dialog = ButtonDialogTitle:new{ title = T(_("Current screensaver image folder:\n%1"), BD.dirpath(screensaver_dir)), buttons = buttons @@ -117,7 +246,7 @@ function Screensaver:chooseFile(document_cover) local suffix = util.getFileNameSuffix(filename) if document_cover and DocumentRegistry:hasProvider(filename) then return true - elseif screensaver_provider[suffix] then + elseif self.screensaver_provider[suffix] then return true end end, @@ -152,10 +281,8 @@ function Screensaver:chooseFile(document_cover) } }) local screensaver_image = G_reader_settings:readSetting("screensaver_image") + or DataStorage:getDataDir() .. "/resources/koreader.png" local screensaver_document_cover = G_reader_settings:readSetting("screensaver_document_cover") - if screensaver_image == nil then - screensaver_image = DataStorage:getDataDir() .. "/resources/koreader.png" - end local title = document_cover and T(_("Current screensaver document cover:\n%1"), BD.filepath(screensaver_document_cover)) or T(_("Current screensaver image:\n%1"), BD.filepath(screensaver_image)) self.choose_dialog = ButtonDialogTitle:new{ @@ -165,38 +292,25 @@ function Screensaver:chooseFile(document_cover) UIManager:show(self.choose_dialog) end -function Screensaver:stretchImages() - return G_reader_settings:isTrue("screensaver_stretch_images") -end - -function Screensaver:whiteBackground() - return G_reader_settings:isTrue("screensaver_white_background") -end - -function Screensaver:noBackground() - return G_reader_settings:isTrue("screensaver_no_background") -end - -function Screensaver:showMessage() - return G_reader_settings:isTrue("screensaver_show_message") -end +function Screensaver:isExcluded() + if G_reader_settings:hasNot("lastfile") then + return false + end -function Screensaver:excluded() local lastfile = G_reader_settings:readSetting("lastfile") - local exclude_ss = false -- consider it not excluded if there's no docsetting if DocSettings:hasSidecarFile(lastfile) then local doc_settings = DocSettings:open(lastfile) - exclude_ss = doc_settings:readSetting("exclude_screensaver") + return doc_settings:isTrue("exclude_screensaver") + else + -- No DocSetting, not excluded + return false end - return exclude_ss or false end function Screensaver:setMessage() local InputDialog = require("ui/widget/inputdialog") local screensaver_message = G_reader_settings:readSetting("screensaver_message") - if screensaver_message == nil then - screensaver_message = default_screensaver_message - end + or self.default_screensaver_message self.input_dialog = InputDialog:new{ title = "Screensaver message", description = _("Enter the message to be displayed by the screensaver. The following escape sequences can be used:\n %p percentage read\n %c current page number\n %t total number of pages\n %T title\n %A authors\n %S series"), @@ -224,203 +338,245 @@ function Screensaver:setMessage() self.input_dialog:onShowKeyboard() end -function Screensaver:show(event, fallback_message) - -- These 2 (optional) parameters are to support poweroff and reboot actions - -- on Kobo (see uimanager.lua) - if self.left_msg then - UIManager:close(self.left_msg) - self.left_msg = nil - end - local covers_fullscreen = true -- hint for UIManager:_repaint() - local overlay_message - local prefix = event and event.."_" or "" -- "", "poweroff_" or "reboot_" - local screensaver_type = G_reader_settings:readSetting(prefix.."screensaver_type") - if prefix and not screensaver_type then - -- No manually added setting for poweroff/reboot, fallback to using the - -- same settings as for suspend that could be set via menus - screensaver_type = G_reader_settings:readSetting("screensaver_type") - prefix = "" - -- And display fallback_message over the common screensaver, - -- so user can distinguish between suspend (no message) and - -- poweroff (overlay message) - overlay_message = fallback_message - end +-- When called after setup(), may not match the saved settings, because it accounts for fallbacks that might have kicked in. +function Screensaver:getMode() + return self.screensaver_type +end - local show_message = self:showMessage() +function Screensaver:modeExpectsPortrait() + return self.screensaver_type ~= "message" + and self.screensaver_type ~= "disable" + and self.screensaver_type ~= "readingprogress" + and self.screensaver_type ~= "bookstatus" +end - if screensaver_type == nil then - show_message = true - end +function Screensaver:modeIsImage() + return self.screensaver_type == "cover" + or self.screensaver_type == "random_image" + or self.screensaver_type == "image_file" +end - if screensaver_type == "message" then - -- obsolete screensaver_type: migrate to new show_message = true - screensaver_type = "disable" - G_reader_settings:saveSetting("screensaver_type", "disable") - G_reader_settings:saveSetting("screensaver_show_message", true) - end +function Screensaver:withBackground() + return self.screensaver_background ~= "none" +end - -- messages can still be shown over "as-is" screensaver - if screensaver_type == "disable" and show_message == false then - return +function Screensaver:setup(event, fallback_message) + -- Handle user settings & defaults + if G_reader_settings:has("screensaver_show_message") then + self.show_message = G_reader_settings:isTrue("screensaver_show_message") + else + self.screensaver_type = "disable" + self.show_message = true end - - local widget = nil - local no_background = false - local background = Blitbuffer.COLOR_BLACK - if self:whiteBackground() then - background = Blitbuffer.COLOR_WHITE - elseif self:noBackground() then - background = nil - no_background = true + if G_reader_settings:has("screensaver_type") then + self.screensaver_type = G_reader_settings:readSetting("screensaver_type") + else + self.screensaver_type = "disable" + self.show_message = true + end + if G_reader_settings:has("screensaver_background") then + self.screensaver_background = G_reader_settings:readSetting("screensaver_background") + else + self.screensaver_background = "black" end - -- "as-is" mode obviously requires not mangling the background ;). - if screensaver_type == "disable" then - -- NOTE: Ideally, "disable" mode should *honor* all the "background" options. - -- Unfortunately, the no background option is much more recent than the "disable" mode, - -- and as such, the default assumes that in "disable" mode, the default background is nil instead of black. - -- This implies that, for the same legacy reasons, we have to honor the *white* background setting here... - -- (Which means that you can have no background, a white background, but *NOT* a black background in this mode :/). - if not self:whiteBackground() then - background = nil - no_background = true + -- These 2 (optional) parameters are to support poweroff and reboot actions on Kobo (c.f., UIManager) + self.prefix = event and event .. "_" or "" -- "", "poweroff_" or "reboot_" + self.fallback_message = fallback_message + self.overlay_message = nil + if G_reader_settings:has(self.prefix .. "screensaver_type") then + self.screensaver_type = G_reader_settings:readSetting(self.prefix .. "screensaver_type") + else + if event then + -- Display the provided fallback_message over the screensaver, + -- so the user can distinguish between suspend (no overlay), + -- and reboot/poweroff (overlaid message). + self.overlay_message = self.fallback_message end end - local lastfile = G_reader_settings:readSetting("lastfile") - if screensaver_type == "document_cover" then + -- Reset state + self.lastfile = nil + self.image = nil + self.image_file = nil + + -- Check lastfile and setup the requested mode's resources, or a fallback mode if the required resources are unavailable. + self.lastfile = G_reader_settings:readSetting("lastfile") + if self.screensaver_type == "document_cover" then -- Set lastfile to the document of which we want to show the cover. - lastfile = G_reader_settings:readSetting("screensaver_document_cover") - screensaver_type = "cover" + self.lastfile = G_reader_settings:readSetting("screensaver_document_cover") + self.screensaver_type = "cover" end - if screensaver_type == "cover" then - lastfile = lastfile ~= nil and lastfile or G_reader_settings:readSetting("lastfile") - local exclude = false -- consider it not excluded if there's no docsetting - if DocSettings:hasSidecarFile(lastfile) then - local doc_settings = DocSettings:open(lastfile) - exclude = doc_settings:readSetting("exclude_screensaver") + if self.screensaver_type == "cover" then + self.lastfile = self.lastfile ~= nil and self.lastfile or G_reader_settings:readSetting("lastfile") + local excluded + if DocSettings:hasSidecarFile(self.lastfile) then + local doc_settings = DocSettings:open(self.lastfile) + excluded = doc_settings:isTrue("exclude_screensaver") + else + -- No DocSetting, not excluded + excluded = false end - if exclude ~= true then - if lastfile and lfs.attributes(lastfile, "mode") == "file" then - local doc = DocumentRegistry:openDocument(lastfile) + if not excluded then + if self.lastfile and lfs.attributes(self.lastfile, "mode") == "file" then + local doc = DocumentRegistry:openDocument(self.lastfile) if doc.loadDocument then -- CreDocument doc:loadDocument(false) -- load only metadata end - local image = doc:getCoverPageImage() + self.image = doc:getCoverPageImage() doc:close() - if image ~= nil then - widget = ImageWidget:new{ - image = image, - image_disposable = true, - height = Screen:getHeight(), - width = Screen:getWidth(), - scale_factor = not self:stretchImages() and 0 or nil, - } - else - screensaver_type = "random_image" + if self.image == nil then + self.screensaver_type = "random_image" end else - screensaver_type = "random_image" + self.screensaver_type = "random_image" end - else --fallback to random images if this book cover is excluded - screensaver_type = "random_image" + else + -- Fallback to random images if this book cover is excluded + self.screensaver_type = "random_image" end end - if screensaver_type == "bookstatus" then - if lastfile and lfs.attributes(lastfile, "mode") == "file" then - local doc = DocumentRegistry:openDocument(lastfile) - local doc_settings = DocSettings:open(lastfile) + if self.screensaver_type == "bookstatus" then + if self.lastfile and lfs.attributes(self.lastfile, "mode") == "file" then local instance = require("apps/reader/readerui"):_getRunningInstance() - if instance ~= nil then - widget = BookStatusWidget:new { - thumbnail = doc:getCoverPageImage(), - props = doc:getProps(), - document = doc, - settings = doc_settings, - view = instance.view, - readonly = true, - } - else - show_message = true + if instance == nil then + self.screensaver_type = "disable" + self.show_message = true end - doc:close() else - show_message = true + self.screensaver_type = "disable" + self.show_message = true end end - if screensaver_type == "random_image" then - local screensaver_dir = G_reader_settings:readSetting(prefix.."screensaver_dir") - if screensaver_dir == nil and prefix ~= "" then - screensaver_dir = G_reader_settings:readSetting("screensaver_dir") - end - if screensaver_dir == nil then - screensaver_dir = DataStorage:getDataDir() .. "/screenshots/" - end - local image_file = getRandomImage(screensaver_dir) - if image_file == nil then - show_message = true - else - widget = ImageWidget:new{ - file = image_file, - file_do_cache = false, - alpha = true, - height = Screen:getHeight(), - width = Screen:getWidth(), - scale_factor = not self:stretchImages() and 0 or nil, - } + if self.screensaver_type == "random_image" then + local screensaver_dir = G_reader_settings:readSetting(self.prefix .. "screensaver_dir") + or G_reader_settings:readSetting("screensaver_dir") + self.image_file = self:_getRandomImage(screensaver_dir) + if self.image_file == nil then + self.screensaver_type = "disable" + self.show_message = true end end - if screensaver_type == "image_file" then - local screensaver_image = G_reader_settings:readSetting(prefix.."screensaver_image") - if screensaver_image == nil and prefix ~= "" then - screensaver_image = G_reader_settings:readSetting("screensaver_image") - end - if screensaver_image == nil then - screensaver_image = DataStorage:getDataDir() .. "/resources/koreader.png" - end - if lfs.attributes(screensaver_image, "mode") ~= "file" then - show_message = true - else - widget = ImageWidget:new{ - file = screensaver_image, - file_do_cache = false, - alpha = true, - height = Screen:getHeight(), - width = Screen:getWidth(), - scale_factor = not self:stretchImages() and 0 or nil, - } + if self.screensaver_type == "image_file" then + self.image_file = G_reader_settings:readSetting(self.prefix .. "screensaver_image") + or G_reader_settings:readSetting("screensaver_image") + if self.image_file == nil or lfs.attributes(self.image_file, "mode") ~= "file" then + self.screensaver_type = "disable" + self.show_message = true end end - if screensaver_type == "readingprogress" then - if Screensaver.getReaderProgress ~= nil then - widget = Screensaver.getReaderProgress() - else - show_message = true + if self.screensaver_type == "readingprogress" then + -- This is implemented by the Statistics plugin + if Screensaver.getReaderProgress == nil then + self.screensaver_type = "disable" + self.show_message = true end end - if show_message == true then - local screensaver_message = G_reader_settings:readSetting(prefix.."screensaver_message") - local message_pos = G_reader_settings:readSetting(prefix.."screensaver_message_position") - if no_background and widget == nil then - covers_fullscreen = false + -- Now that the fallbacks are in place, we know the *effective* screensaver mode. + -- For non-image modes, make black (which is also the default) synonymous with none. + -- The reasoning is that disable + show_message, which is our default and fallback, + -- looks *terrible* with a black background, which is also our default and fallback ;). + if not self:modeIsImage() and self.screensaver_background == "black" then + self.screensaver_background = "none" + end +end + +function Screensaver:show() + if self.screensaver_widget then + UIManager:close(self.screensaver_widget) + self.screensaver_widget = nil + end + + -- In as-is mode with no message and no overlay, we've got nothing to show :) + if self.screensaver_type == "disable" and not self.show_message and not self.overlay_message then + return + end + + -- Build the main widget for the effective mode, all the sanity checks were handled in setup + local widget = nil + if self.screensaver_type == "cover" then + widget = ImageWidget:new{ + image = self.image, + image_disposable = true, + height = Screen:getHeight(), + width = Screen:getWidth(), + scale_factor = G_reader_settings:isTrue("screensaver_stretch_images") and nil or 0, + } + elseif self.screensaver_type == "bookstatus" then + local doc = DocumentRegistry:openDocument(self.lastfile) + local doc_settings = DocSettings:open(self.lastfile) + local instance = require("apps/reader/readerui"):_getRunningInstance() + widget = BookStatusWidget:new{ + thumbnail = doc:getCoverPageImage(), + props = doc:getProps(), + document = doc, + settings = doc_settings, + view = instance.view, + readonly = true, + } + doc:close() + elseif self.screensaver_type == "random_image" or self.screensaver_type == "image_file" then + widget = ImageWidget:new{ + file = self.image_file, + file_do_cache = false, + alpha = true, + height = Screen:getHeight(), + width = Screen:getWidth(), + scale_factor = G_reader_settings:isTrue("screensaver_stretch_images") and nil or 0, + } + elseif self.screensaver_type == "readingprogress" then + widget = Screensaver.getReaderProgress() + end + + -- Assume that we'll be covering the full-screen by default (either because of a widget, or a background fill). + local covers_fullscreen = true + -- Speaking of, set that background fill up... + local background + if self.screensaver_background == "black" then + background = Blitbuffer.COLOR_BLACK + elseif self.screensaver_background == "white" then + background = Blitbuffer.COLOR_WHITE + elseif self.screensaver_background == "none" then + background = nil + end + + if self.show_message then + -- Handle user settings & fallbacks, with that prefix mess on top... + local screensaver_message + if G_reader_settings:has(self.prefix .. "screensaver_message") then + screensaver_message = G_reader_settings:readSetting(self.prefix .. "screensaver_message") + else + if G_reader_settings:has("screensaver_message") then + -- We prefer the global user setting to the event's fallback message. + screensaver_message = G_reader_settings:readSetting("screensaver_message") + else + screensaver_message = self.fallback_message or self.default_screensaver_message + end end - if screensaver_message == nil and prefix ~= "" then - screensaver_message = G_reader_settings:readSetting("screensaver_message") + -- NOTE: Only attempt to expand if there are special characters in the message. + if screensaver_message:find("%%") then + screensaver_message = expandSpecial(screensaver_message, self.fallback_message or self.default_screensaver_message) end - local fallback = fallback_message or default_screensaver_message - if screensaver_message == nil then - screensaver_message = fallback + local message_pos + if G_reader_settings:has(self.prefix .. "screensaver_message_position") then + message_pos = G_reader_settings:readSetting(self.prefix .. "screensaver_message_position") else - -- NOTE: Only attempt to expand if there are special characters in the message. - if screensaver_message:find("%%") then - screensaver_message = self:expandSpecial(screensaver_message, fallback) + if G_reader_settings:has("screensaver_message_position") then + message_pos = G_reader_settings:readSetting("screensaver_message_position") + else + message_pos = "middle" end end + -- The only case where we *won't* cover the full-screen is when we only display a message and no background. + if widget == nil and self.screensaver_background == "none" then + covers_fullscreen = false + end + local message_widget - if message_pos == "middle" or message_pos == nil then + if message_pos == "middle" then message_widget = InfoMessage:new{ text = screensaver_message, readonly = true, @@ -449,13 +605,13 @@ function Screensaver:show(event, fallback_message) } end - -- No overlay needed as we just displayed the message - overlay_message = nil + -- No overlay needed as we just displayed *a* message (not necessarily the event's, though). + self.overlay_message = nil - -- check if message_widget should be overlaid on another widget + -- Check if message_widget should be overlaid on another widget if message_widget then - if widget then -- we have a screensaver widget - -- show message_widget on top of previously created widget + if widget then -- We have a Screensaver widget + -- Show message_widget on top of previously created widget local screen_w, screen_h = Screen:getWidth(), Screen:getHeight() widget = OverlapGroup:new{ dimen = { @@ -466,158 +622,52 @@ function Screensaver:show(event, fallback_message) message_widget, } else - -- no prevously created widget so just show message widget + -- No prevously created widget, so just show message widget widget = message_widget end end end - if overlay_message then - widget = self:addOverlayMessage(widget, overlay_message) + if self.overlay_message then + widget = addOverlayMessage(widget, self.overlay_message) end if widget then - self.left_msg = ScreenSaverWidget:new{ + self.screensaver_widget = ScreenSaverWidget:new{ widget = widget, background = background, covers_fullscreen = covers_fullscreen, } - self.left_msg.modal = true - -- Refresh whole screen for other types - self.left_msg.dithered = true - UIManager:show(self.left_msg, "full") + self.screensaver_widget.modal = true + self.screensaver_widget.dithered = true + UIManager:show(self.screensaver_widget, "full") end end -function Screensaver:expandSpecial(message, fallback) - -- Expand special character sequences in given message. - -- %p percentage read - -- %c current page - -- %t total pages - -- %T document title - -- %A document authors - -- %S document series - - local ret = message - - local lastfile = G_reader_settings:readSetting("lastfile") - if not lastfile then - return fallback - end - - local totalpages = 0 - local percent = 0 - local currentpage = 0 - local title = "N/A" - local authors = "N/A" - local series = "N/A" - - local instance = require("apps/reader/readerui"):_getRunningInstance() - if instance == nil and DocSettings:hasSidecarFile(lastfile) then - -- If there's no ReaderUI instance, but the file has sidecar data, use that - local docinfo = DocSettings:open(lastfile) - totalpages = docinfo.data.doc_pages or totalpages - percent = docinfo.data.percent_finished or percent - currentpage = Math.round(percent * totalpages) - percent = Math.round(percent * 100) - if docinfo.data.doc_props then - title = docinfo.data.doc_props.title and docinfo.data.doc_props.title ~= "" and docinfo.data.doc_props.title or title - authors = docinfo.data.doc_props.authors and docinfo.data.doc_props.authors ~= "" and docinfo.data.doc_props.authors or authors - series = docinfo.data.doc_props.series and docinfo.data.doc_props.series ~= "" and docinfo.data.doc_props.series or series - end - docinfo:close() - elseif instance ~= nil and lfs.attributes(lastfile, "mode") == "file" then - -- But if we have a ReaderUI instance, and the file stil exists, open it - local doc = DocumentRegistry:openDocument(lastfile) - currentpage = instance.view.state.page or currentpage - totalpages = doc:getPageCount() or totalpages - 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 - doc:close() +function Screensaver:close() + if self.screensaver_widget == nil then + return end - ret = string.gsub(ret, "%%c", currentpage) - ret = string.gsub(ret, "%%t", totalpages) - ret = string.gsub(ret, "%%p", percent) - ret = string.gsub(ret, "%%T", title) - ret = string.gsub(ret, "%%A", authors) - ret = string.gsub(ret, "%%S", series) - - return ret -end - -function Screensaver:close() - if self.left_msg == nil then return end local screensaver_delay = G_reader_settings:readSetting("screensaver_delay") local screensaver_delay_number = tonumber(screensaver_delay) if screensaver_delay_number then UIManager:scheduleIn(screensaver_delay_number, function() logger.dbg("close screensaver") - if self.left_msg then - UIManager:close(self.left_msg, "full") - self.left_msg = nil + if self.screensaver_widget then + UIManager:close(self.screensaver_widget, "full") + self.screensaver_widget = nil end end) elseif screensaver_delay == "disable" or screensaver_delay == nil then logger.dbg("close screensaver") - if self.left_msg then - UIManager:close(self.left_msg, "full") - self.left_msg = nil + if self.screensaver_widget then + UIManager:close(self.screensaver_widget, "full") + self.screensaver_widget = nil end else logger.dbg("tap to exit from screensaver") end end -function Screensaver:addOverlayMessage(widget, text) - local FrameContainer = require("ui/widget/container/framecontainer") - local RightContainer = require("ui/widget/container/rightcontainer") - local Size = require("ui/size") - local TextWidget = require("ui/widget/textwidget") - - local face = Font:getFace("infofont") - local screen_w, screen_h = Screen:getWidth(), Screen:getHeight() - - local textw = TextWidget:new{ - text = text, - face = face, - } - -- Don't make our message reach full screen width - if textw:getWidth() > screen_w * 0.9 then - -- Text too wide: use TextBoxWidget for multi lines display - textw = TextBoxWidget:new{ - text = text, - face = face, - width = math.floor(screen_w * 0.9) - } - end - textw = FrameContainer:new{ - background = Blitbuffer.COLOR_WHITE, - bordersize = Size.border.default, - margin = 0, - textw, - } - textw = RightContainer:new{ - dimen = { - w = screen_w, - h = textw:getSize().h, - }, - textw, - } - widget = OverlapGroup:new{ - dimen = { - h = screen_w, - w = screen_h, - }, - widget, - textw, - } - return widget -end - return Screensaver diff --git a/frontend/ui/translator.lua b/frontend/ui/translator.lua index dba983bd0..3f3e9056f 100644 --- a/frontend/ui/translator.lua +++ b/frontend/ui/translator.lua @@ -201,7 +201,7 @@ function Translator:genSettingsMenu() return T("%1 (%2)", lang_name, lang_key) end, checked_func = function() - if G_reader_settings:readSetting(setting_name) then + if G_reader_settings:has(setting_name) then return lang_key == G_reader_settings:readSetting(setting_name) else return lang_key == default_checked_item @@ -252,7 +252,7 @@ end function Translator:getSourceLanguage() if G_reader_settings:isFalse("translator_from_auto_detect") and - G_reader_settings:readSetting("translator_from_language") then + G_reader_settings:has("translator_from_language") then return G_reader_settings:readSetting("translator_from_language") end return AUTODETECT_LANGUAGE -- "auto" diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index f71c75a4e..5ffdc1588 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -61,7 +61,9 @@ function UIManager:init() self._entered_poweroff_stage = true Device.orig_rotation_mode = Device.screen:getRotationMode() Screen:setRotationMode(Screen.ORIENTATION_PORTRAIT) - require("ui/screensaver"):show("poweroff", _("Powered off")) + local Screensaver = require("ui/screensaver") + Screensaver:setup("poweroff", _("Powered off")) + Screensaver:show() if Device:needsScreenRefreshAfterResume() then Screen:refreshFull() end @@ -78,7 +80,9 @@ function UIManager:init() self._entered_poweroff_stage = true Device.orig_rotation_mode = Device.screen:getRotationMode() Screen:setRotationMode(Screen.ORIENTATION_PORTRAIT) - require("ui/screensaver"):show("reboot", _("Rebooting…")) + local Screensaver = require("ui/screensaver") + Screensaver:setup("reboot", _("Rebooting…")) + Screensaver:show() if Device:needsScreenRefreshAfterResume() then Screen:refreshFull() end @@ -137,12 +141,12 @@ function UIManager:init() end end -- Sleep Cover handling - if G_reader_settings:readSetting("ignore_power_sleepcover") then + if G_reader_settings:isTrue("ignore_power_sleepcover") then -- NOTE: The hardware event itself will wake the kernel up if it's in suspend (:/). -- Let the unexpected wakeup guard handle that. self.event_handlers["SleepCoverClosed"] = nil self.event_handlers["SleepCoverOpened"] = nil - elseif G_reader_settings:readSetting("ignore_open_sleepcover") then + elseif G_reader_settings:isTrue("ignore_open_sleepcover") then -- Just ignore wakeup events, and do NOT set is_cover_closed, -- so device/generic/device will let us use the power button to wake ;). self.event_handlers["SleepCoverClosed"] = function() diff --git a/frontend/ui/widget/configdialog.lua b/frontend/ui/widget/configdialog.lua index a04974106..54eeac302 100644 --- a/frontend/ui/widget/configdialog.lua +++ b/frontend/ui/widget/configdialog.lua @@ -189,7 +189,7 @@ function ConfigOption:init() local padding_button = Size.padding.button -- padding for underline below letters and icons --- @todo Restore setting when there are more advanced settings. - --local show_advanced = G_reader_settings:readSetting("show_advanced") or false + --local show_advanced = G_reader_settings:isTrue("show_advanced") local show_advanced = true -- Get the width needed by the longest option name shown on the left diff --git a/frontend/ui/widget/dictquicklookup.lua b/frontend/ui/widget/dictquicklookup.lua index baeba9c77..2601ab8cb 100644 --- a/frontend/ui/widget/dictquicklookup.lua +++ b/frontend/ui/widget/dictquicklookup.lua @@ -342,9 +342,9 @@ function DictQuickLookup:init() dir = last_file:match("(.*)/") end end - if not dir then dir = G_reader_settings:readSetting("wikipedia_save_dir") end - if not dir then dir = G_reader_settings:readSetting("home_dir") end - if not dir then dir = require("apps/filemanager/filemanagerutil").getDefaultDir() end + if not dir then dir = G_reader_settings:readSetting("wikipedia_save_dir") + or G_reader_settings:readSetting("home_dir") + or require("apps/filemanager/filemanagerutil").getDefaultDir() end if not dir or not util.pathExists(dir) then UIManager:show(InfoMessage:new{ text = _("No directory to save article to could be found."), diff --git a/frontend/ui/widget/filechooser.lua b/frontend/ui/widget/filechooser.lua index a370fef0c..5dea49edb 100644 --- a/frontend/ui/widget/filechooser.lua +++ b/frontend/ui/widget/filechooser.lua @@ -25,10 +25,47 @@ local FileChooser = Menu:extend{ show_path = true, parent = nil, show_hidden = nil, - exclude_dirs = {"%.sdr$"}, + -- NOTE: Input is *always* a relative entry name + exclude_dirs = { + -- KOReader / Kindle + "%.sdr$", + -- Kobo + "^%.adobe%-digital%-editions$", + "^%.kobo$", + "^%.kobo%-images$", + -- macOS + "^%.fseventsd$", + "^%.Trashes$", + "^%.Spotlight%-V100$", + -- *nix + "^%.Trash$", + "^%.Trash%-%d+$", + -- Windows + "^RECYCLED$", + "^RECYCLER$", + "^%$Recycle%.Bin$", + "^System Volume Information$", + -- Plato + "^%.thumbnail%-previews$", + "^%.reading%-states$", + }, + exclude_files = { + -- macOS + "^%.DS_Store$", + -- *nix + "^%.directory$", + -- Windows + "^Thumbs%.db$", + -- Calibre + "^driveinfo%.calibre$", + "^metadata%.calibre$", + -- Plato + "^%.fat32%-epoch$", + "^%.metadata%.json$", + }, collate = "strcoll", -- or collate = "access", reverse_collate = false, - path_items = {}, -- store last browsed location(item index) for each path + path_items = {}, -- store last browsed location (item index) for each path goto_letter = true, } @@ -39,13 +76,20 @@ local unreadable_dir_content = {} function FileChooser:init() self.width = Screen:getWidth() - -- common dir filter - self.dir_filter = function(dirname) + -- Standard dir exclusion list + self.show_dir = function(dirname) for _, pattern in ipairs(self.exclude_dirs) do if dirname:match(pattern) then return false end end return true end + -- Standard file exclusion list + self.show_file = function(filename) + for _, pattern in ipairs(self.exclude_files) do + if filename:match(pattern) then return false end + end + return true + end self.list = function(path, dirs, files, count_only) -- lfs.dir directory without permission will give error local ok, iter, dir_obj = pcall(lfs.dir, path) @@ -53,17 +97,19 @@ function FileChooser:init() unreadable_dir_content[path] = nil for f in iter, dir_obj do if count_only then - if self.dir_filter(f) and ((not self.show_hidden and not util.stringStartsWith(f, ".")) - or (self.show_hidden and f ~= "." and f ~= ".." and not util.stringStartsWith(f, "._"))) + if ((not self.show_hidden and not util.stringStartsWith(f, ".")) + or (self.show_hidden and f ~= "." and f ~= ".." and not util.stringStartsWith(f, "._"))) + and self.show_dir(f) + and self.show_file(f) then table.insert(dirs, true) end - elseif self.show_hidden or not string.match(f, "^%.[^.]") then + elseif self.show_hidden or not util.stringStartsWith(f, ".") then local filename = path.."/"..f local attributes = lfs.attributes(filename) if attributes ~= nil then if attributes.mode == "directory" and f ~= "." and f ~= ".." then - if self.dir_filter(filename) then + if self.show_dir(f) then table.insert(dirs, {name = f, suffix = getFileNameSuffix(f), fullpath = filename, @@ -71,22 +117,24 @@ function FileChooser:init() end -- Always ignore macOS resource forks. elseif attributes.mode == "file" and not util.stringStartsWith(f, "._") then - if self.file_filter == nil or self.file_filter(filename) or self.show_unsupported then - local percent_finished = 0 - if self.collate == "percent_unopened_first" or self.collate == "percent_unopened_last" then - if DocSettings:hasSidecarFile(filename) then - local docinfo = DocSettings:open(filename) - percent_finished = docinfo.data.percent_finished - if percent_finished == nil then - percent_finished = 0 + if self.show_file(f) then + if self.file_filter == nil or self.file_filter(filename) or self.show_unsupported then + local percent_finished = 0 + if self.collate == "percent_unopened_first" or self.collate == "percent_unopened_last" then + if DocSettings:hasSidecarFile(filename) then + local docinfo = DocSettings:open(filename) + percent_finished = docinfo.data.percent_finished + if percent_finished == nil then + percent_finished = 0 + end end end + table.insert(files, {name = f, + suffix = getFileNameSuffix(f), + fullpath = filename, + attr = attributes, + percent_finished = percent_finished }) end - table.insert(files, {name = f, - suffix = getFileNameSuffix(f), - fullpath = filename, - attr = attributes, - percent_finished = percent_finished }) end end end diff --git a/frontend/ui/widget/pathchooser.lua b/frontend/ui/widget/pathchooser.lua index 53f0e9046..c3b4d23c5 100644 --- a/frontend/ui/widget/pathchooser.lua +++ b/frontend/ui/widget/pathchooser.lua @@ -37,7 +37,7 @@ function PathChooser:init() self.title = _("Long-press to select") end end - self.show_hidden = G_reader_settings:readSetting("show_hidden") + self.show_hidden = G_reader_settings:isTrue("show_hidden") if not self.show_files then self.file_filter = function() return false end -- filter out regular files end diff --git a/frontend/ui/widget/virtualkeyboard.lua b/frontend/ui/widget/virtualkeyboard.lua index 65295ce3c..8b0bc09c5 100644 --- a/frontend/ui/widget/virtualkeyboard.lua +++ b/frontend/ui/widget/virtualkeyboard.lua @@ -218,7 +218,7 @@ function VirtualKey:init() (self.keyboard.umlautmode_keys[self.label] ~= nil and self.keyboard.umlautmode) then self[1].background = Blitbuffer.COLOR_LIGHT_GRAY end - self.flash_keyboard = G_reader_settings:readSetting("flash_keyboard") ~= false + self.flash_keyboard = G_reader_settings:nilOrTrue("flash_keyboard") end function VirtualKey:genkeyboardLayoutKeyChars() diff --git a/frontend/util.lua b/frontend/util.lua index 1014fb26f..c93084425 100644 --- a/frontend/util.lua +++ b/frontend/util.lua @@ -373,6 +373,44 @@ function util.arrayAppend(t1, t2) end end +--[[-- +Remove elements from an array, fast. + +Swap & pop, like / , but preserving order. +c.f., + +@table t Lua array to filter +@func keep_cb Filtering callback. Takes three arguments: table, index, new index. Returns true to *keep* the item. See link above for potential uses of the third argument. + +@usage + +local foo = { "a", "b", "c", "b", "d", "e" } +local function drop_b(t, i, j) + -- Discard any item with value "b" + return t[i] ~= "b" +end +util.arrayRemove(foo, drop_b) +]] +function util.arrayRemove(t, keep_cb) + local j, n = 1, #t + + for i = 1, n do + if keep_cb(t, i, j) then + -- Move i's kept value to j's position, if it's not already there. + if i ~= j then + t[j] = t[i] + t[i] = nil + end + -- Increment position of where we'll place the next kept value. + j = j + 1 + else + t[i] = nil + end + end + + return t +end + --- Reverse array elements in-place in table t ---- @param t Lua table function util.arrayReverse(t) @@ -389,7 +427,7 @@ end --- and if so, return the index. ---- @param t Lua table ---- @param v ----- @function callback(v1, v2) +---- @func callback(v1, v2) function util.arrayContains(t, v, cb) cb = cb or function(v1, v2) return v1 == v2 end for _k, _v in ipairs(t) do @@ -654,7 +692,7 @@ end --- Recursively scan directory for files inside -- @string path --- @function callback(fullpath, name, attr) +-- @func callback(fullpath, name, attr) function util.findFiles(dir, cb) local function scan(current) local ok, iter, dir_obj = pcall(lfs.dir, current) diff --git a/plugins/autosuspend.koplugin/main.lua b/plugins/autosuspend.koplugin/main.lua index a8cdeee3b..9905f546c 100644 --- a/plugins/autosuspend.koplugin/main.lua +++ b/plugins/autosuspend.koplugin/main.lua @@ -9,8 +9,6 @@ if not Device:isCervantes() and return { disabled = true, } end -local DataStorage = require("datastorage") -local LuaSettings = require("luasettings") local PluginShare = require("pluginshare") local UIManager = require("ui/uimanager") local WidgetContainer = require("ui/widget/container/widgetcontainer") @@ -19,39 +17,19 @@ local _ = require("gettext") local T = require("ffi/util").template local default_autoshutdown_timeout_seconds = 3*24*60*60 +local default_auto_suspend_timeout_seconds = 60*60 local AutoSuspend = WidgetContainer:new{ name = "autosuspend", is_doc_only = false, autoshutdown_timeout_seconds = G_reader_settings:readSetting("autoshutdown_timeout_seconds") or default_autoshutdown_timeout_seconds, - settings = LuaSettings:open(DataStorage:getSettingsDir() .. "/koboautosuspend.lua"), + auto_suspend_timeout_seconds = G_reader_settings:readSetting("auto_suspend_timeout_seconds") or default_auto_suspend_timeout_seconds, last_action_sec = os.time(), standby_prevented = false, } -function AutoSuspend:_readTimeoutSecFrom(settings) - local sec = settings:readSetting("auto_suspend_timeout_seconds") - if type(sec) == "number" then - return sec - end - return -1 -end - -function AutoSuspend:_readTimeoutSec() - local candidates = { self.settings, G_reader_settings } - for _, candidate in ipairs(candidates) do - local sec = self:_readTimeoutSecFrom(candidate) - if sec ~= -1 then - return sec - end - end - - -- default setting is 60 minutes - return 60 * 60 -end - function AutoSuspend:_enabled() - return self.auto_suspend_sec > 0 + return self.auto_suspend_timeout_seconds > 0 end function AutoSuspend:_enabledShutdown() @@ -67,11 +45,11 @@ function AutoSuspend:_schedule() local delay_suspend, delay_shutdown if PluginShare.pause_auto_suspend or Device.standby_prevented or Device.powerd:isCharging() then - delay_suspend = self.auto_suspend_sec + delay_suspend = self.auto_suspend_timeout_seconds delay_shutdown = self.autoshutdown_timeout_seconds else local now_ts = os.time() - delay_suspend = self.last_action_sec + self.auto_suspend_sec - now_ts + delay_suspend = self.last_action_sec + self.auto_suspend_timeout_seconds - now_ts delay_shutdown = self.last_action_sec + self.autoshutdown_timeout_seconds - now_ts end @@ -111,7 +89,6 @@ end function AutoSuspend:init() if Device:isPocketBook() and not Device:canSuspend() then return end UIManager.event_hook:registerWidget("InputEvent", self) - self.auto_suspend_sec = self:_readTimeoutSec() self:_unschedule() self:_start() -- self.ui is nil in the testsuite @@ -158,22 +135,20 @@ function AutoSuspend:addToMainMenu(menu_items) local InfoMessage = require("ui/widget/infomessage") local Screen = Device.screen local SpinWidget = require("ui/widget/spinwidget") - local curr_items = G_reader_settings:readSetting("auto_suspend_timeout_seconds") or 60*60 local autosuspend_spin = SpinWidget:new { width = math.floor(Screen:getWidth() * 0.6), - value = curr_items / 60, + value = self.auto_suspend_timeout_seconds / 60, value_min = 5, value_max = 240, value_hold_step = 15, ok_text = _("Set timeout"), title_text = _("Timeout in minutes"), callback = function(autosuspend_spin) - local autosuspend_timeout_seconds = autosuspend_spin.value * 60 - self.auto_suspend_sec = autosuspend_timeout_seconds - G_reader_settings:saveSetting("auto_suspend_timeout_seconds", autosuspend_timeout_seconds) + self.auto_suspend_timeout_seconds = autosuspend_spin.value * 60 + G_reader_settings:saveSetting("auto_suspend_timeout_seconds", self.auto_suspend_timeout_seconds) UIManager:show(InfoMessage:new{ text = T(_("The system will automatically suspend after %1 minutes of inactivity."), - string.format("%.2f", autosuspend_timeout_seconds/60)), + string.format("%.2f", self.auto_suspend_timeout_seconds / 60)), timeout = 3, }) self:_unschedule() @@ -191,10 +166,9 @@ function AutoSuspend:addToMainMenu(menu_items) local InfoMessage = require("ui/widget/infomessage") local Screen = Device.screen local SpinWidget = require("ui/widget/spinwidget") - local curr_items = self.autoshutdown_timeout_seconds local autosuspend_spin = SpinWidget:new { width = math.floor(Screen:getWidth() * 0.6), - value = curr_items / 60 / 60, + value = self.autoshutdown_timeout_seconds / 60 / 60, -- About a minute, good for testing and battery life fanatics. -- Just high enough to avoid an instant shutdown death scenario. value_min = 0.017, @@ -206,12 +180,11 @@ function AutoSuspend:addToMainMenu(menu_items) ok_text = _("Set timeout"), title_text = _("Timeout in hours"), callback = function(autosuspend_spin) - local autoshutdown_timeout_seconds = math.floor(autosuspend_spin.value * 60*60) - self.autoshutdown_timeout_seconds = autoshutdown_timeout_seconds - G_reader_settings:saveSetting("autoshutdown_timeout_seconds", autoshutdown_timeout_seconds) + self.autoshutdown_timeout_seconds = math.floor(autosuspend_spin.value * 60 * 60) + G_reader_settings:saveSetting("autoshutdown_timeout_seconds", self.autoshutdown_timeout_seconds) UIManager:show(InfoMessage:new{ text = T(_("The system will automatically shut down after %1 hours of inactivity."), - string.format("%.2f", autoshutdown_timeout_seconds/60/60)), + string.format("%.2f", self.autoshutdown_timeout_seconds / 60 / 60)), timeout = 3, }) self:_unschedule() diff --git a/plugins/autoturn.koplugin/main.lua b/plugins/autoturn.koplugin/main.lua index 862b0ba44..bfe22362f 100644 --- a/plugins/autoturn.koplugin/main.lua +++ b/plugins/autoturn.koplugin/main.lua @@ -132,7 +132,7 @@ function AutoTurn:addToMainMenu(menu_items) title_text = _("Timeout in seconds"), cancel_callback = function() self.enabled = false - G_reader_settings:flipFalse("autoturn_enabled") + G_reader_settings:makeFalse("autoturn_enabled") self:_deprecateLastTask() menu:updateItems() end, @@ -140,7 +140,7 @@ function AutoTurn:addToMainMenu(menu_items) self.autoturn_sec = autoturn_spin.value G_reader_settings:saveSetting("autoturn_timeout_seconds", autoturn_spin.value) self.enabled = true - G_reader_settings:flipTrue("autoturn_enabled") + G_reader_settings:makeTrue("autoturn_enabled") self:_deprecateLastTask() self:_start() menu:updateItems() diff --git a/plugins/calibre.koplugin/main.lua b/plugins/calibre.koplugin/main.lua index fbde7cc7d..470ed1137 100644 --- a/plugins/calibre.koplugin/main.lua +++ b/plugins/calibre.koplugin/main.lua @@ -133,10 +133,10 @@ function Calibre:getSearchMenuTable() text = path, keep_menu_open = true, checked_func = function() - return cache:readSetting(path) + return cache:isTrue(path) end, callback = function() - cache:saveSetting(path, not cache:readSetting(path)) + cache:toggle(path) cache:flush() CalibreSearch:invalidateCache() end, @@ -165,8 +165,7 @@ function Calibre:getSearchMenuTable() return G_reader_settings:isTrue("calibre_search_from_reader") end, callback = function() - local current = G_reader_settings:isTrue("calibre_search_from_reader") - G_reader_settings:saveSetting("calibre_search_from_reader", not current) + G_reader_settings:toggle("calibre_search_from_reader") UIManager:show(InfoMessage:new{ text = _("This will take effect on next restart."), }) diff --git a/plugins/calibre.koplugin/metadata.lua b/plugins/calibre.koplugin/metadata.lua index 41eb66153..f499ca48d 100644 --- a/plugins/calibre.koplugin/metadata.lua +++ b/plugins/calibre.koplugin/metadata.lua @@ -49,7 +49,7 @@ local function findCalibreFiles(dir) local function existOrLast(file) local fullname local options = { file, "." .. file } - for _, option in pairs(options) do + for _, option in ipairs(options) do fullname = dir .. "/" .. option if util.fileExists(fullname) then return true, fullname @@ -144,11 +144,10 @@ end -- remove a book from our books table function CalibreMetadata:removeBook(lpath) - for index, book in ipairs(self.books) do - if book.lpath == lpath then - table.remove(self.books, index) - end + local function drop_lpath(t, i, j) + return t[i].lpath ~= lpath end + util.arrayRemove(self.books, drop_lpath) end -- gets the uuid and index of a book from its path @@ -165,7 +164,7 @@ end function CalibreMetadata:getBookId(index) local book = {} book.priKey = index - for _, key in pairs({ "uuid", "lpath", "last_modified"}) do + for _, key in ipairs({"uuid", "lpath", "last_modified"}) do book[key] = self.books[index][key] end return book diff --git a/plugins/calibre.koplugin/search.lua b/plugins/calibre.koplugin/search.lua index 61ea76e57..6cda85c93 100644 --- a/plugins/calibre.koplugin/search.lua +++ b/plugins/calibre.koplugin/search.lua @@ -297,7 +297,7 @@ end -- find books, series or tags function CalibreSearch:find(option) - for _, opt in pairs(self.search_options) do + for _, opt in ipairs(self.search_options) do self[opt] = G_reader_settings:nilOrTrue("calibre_search_"..opt) end diff --git a/plugins/calibre.koplugin/wireless.lua b/plugins/calibre.koplugin/wireless.lua index 2f84fdf63..671b69fed 100644 --- a/plugins/calibre.koplugin/wireless.lua +++ b/plugins/calibre.koplugin/wireless.lua @@ -26,7 +26,7 @@ require("ffi/zeromq_h") local extensions = require("extensions") local function getExtensionPathLengths() local t = {} - for _, v in pairs(extensions) do + for _, v in ipairs(extensions) do -- magic number from calibre, see -- https://github.com/koreader/koreader/pull/6177#discussion_r430753964 t[v] = 37 diff --git a/plugins/coverbrowser.koplugin/main.lua b/plugins/coverbrowser.koplugin/main.lua index e151eb33b..d5c9e2ddb 100644 --- a/plugins/coverbrowser.koplugin/main.lua +++ b/plugins/coverbrowser.koplugin/main.lua @@ -66,7 +66,7 @@ function CoverBrowser:init() BookInfoManager:saveSetting("filemanager_display_mode", "list_image_meta") BookInfoManager:saveSetting("history_display_mode", "mosaic_image") end - G_reader_settings:saveSetting("coverbrowser_initial_default_setup_done", true) + G_reader_settings:makeTrue("coverbrowser_initial_default_setup_done") end self:setupFileManagerDisplayMode(BookInfoManager:getSetting("filemanager_display_mode")) diff --git a/plugins/coverimage.koplugin/main.lua b/plugins/coverimage.koplugin/main.lua index d7cb547a4..1eccc6870 100644 --- a/plugins/coverimage.koplugin/main.lua +++ b/plugins/coverimage.koplugin/main.lua @@ -81,7 +81,7 @@ function CoverImage:cleanUpImage() end function CoverImage:createCoverImage(doc_settings) - if self.enabled and not doc_settings:readSetting("exclude_cover_image") == true then + if self.enabled and doc_settings:nilOrFalse("exclude_cover_image") then local cover_image = self.ui.document:getCoverPageImage() if cover_image then local s_w, s_h = Device.screen:getWidth(), Device.screen:getHeight() @@ -426,14 +426,14 @@ function CoverImage:addToMainMenu(menu_items) { text = _("Exclude this book cover"), checked_func = function() - return self.ui and self.ui.doc_settings and self.ui.doc_settings:readSetting("exclude_cover_image") == true + return self.ui and self.ui.doc_settings and self.ui.doc_settings:isTrue("exclude_cover_image") end, callback = function() - if self.ui.doc_settings:readSetting("exclude_cover_image") == true then - self.ui.doc_settings:saveSetting("exclude_cover_image", false) + if self.ui.doc_settings:isTrue("exclude_cover_image") then + self.ui.doc_settings:makeFalse("exclude_cover_image") self:createCoverImage(self.ui.doc_settings) else - self.ui.doc_settings:saveSetting("exclude_cover_image", true) + self.ui.doc_settings:makeTrue("exclude_cover_image") self:cleanUpImage() end self.ui:saveSettings() diff --git a/plugins/gestures.koplugin/main.lua b/plugins/gestures.koplugin/main.lua index 8cc23ca5b..fc87014b8 100644 --- a/plugins/gestures.koplugin/main.lua +++ b/plugins/gestures.koplugin/main.lua @@ -118,8 +118,8 @@ function Gestures:init() if not lfs.attributes(gestures_path, "mode") then FFIUtil.copyFile(defaults_path, gestures_path) end - self.ignore_hold_corners = G_reader_settings:readSetting("ignore_hold_corners") - self.multiswipes_enabled = G_reader_settings:readSetting("multiswipes_enabled") + self.ignore_hold_corners = G_reader_settings:isTrue("ignore_hold_corners") + self.multiswipes_enabled = G_reader_settings:isTrue("multiswipes_enabled") self.is_docless = self.ui == nil or self.ui.document == nil self.ges_mode = self.is_docless and "gesture_fm" or "gesture_reader" self.defaults = LuaSettings:open(defaults_path).data[self.ges_mode] @@ -682,7 +682,7 @@ function Gestures:addToMainMenu(menu_items) text = _("Turn on multiswipes"), checked_func = function() return self.multiswipes_enabled end, callback = function() - G_reader_settings:saveSetting("multiswipes_enabled", not self.multiswipes_enabled) + G_reader_settings:toggle("multiswipes_enabled") self.multiswipes_enabled = G_reader_settings:isTrue("multiswipes_enabled") end, help_text = multiswipes_info_text, @@ -1118,12 +1118,12 @@ function Gestures:multiswipeAction(multiswipe_directions, ges) text = _("You have just performed your first multiswipe gesture.") .."\n\n".. multiswipes_info_text, ok_text = _("Turn on"), ok_callback = function() - G_reader_settings:saveSetting("multiswipes_enabled", true) + G_reader_settings:makeTrue("multiswipes_enabled") self.multiswipes_enabled = true end, cancel_text = _("Turn off"), cancel_callback = function() - G_reader_settings:saveSetting("multiswipes_enabled", false) + G_reader_settings:makeFalse("multiswipes_enabled") self.multiswipes_enabled = false end, }) diff --git a/plugins/gestures.koplugin/migration.lua b/plugins/gestures.koplugin/migration.lua index 315d7d5f3..6d0f7c7a6 100644 --- a/plugins/gestures.koplugin/migration.lua +++ b/plugins/gestures.koplugin/migration.lua @@ -193,7 +193,7 @@ function Migration:migrateGestures(caller) end end caller.settings_data:flush() - G_reader_settings:saveSetting("gestures_migrated", true) + G_reader_settings:makeTrue("gestures_migrated") end return Migration diff --git a/plugins/kosync.koplugin/main.lua b/plugins/kosync.koplugin/main.lua index 74a90ffa7..8ad6811ae 100644 --- a/plugins/kosync.koplugin/main.lua +++ b/plugins/kosync.koplugin/main.lua @@ -15,7 +15,7 @@ local random = require("random") local T = require("ffi/util").template local _ = require("gettext") -if not G_reader_settings:readSetting("device_id") then +if G_reader_settings:hasNot("device_id") then G_reader_settings:saveSetting("device_id", random.uuid()) end @@ -104,6 +104,7 @@ function KOSync:onDispatcherRegisterActions() end function KOSync:onReaderReady() + --- @todo: Viable candidate for a port to the new readSetting API local settings = G_reader_settings:readSetting("kosync") or {} self.kosync_custom_server = settings.custom_server self.kosync_username = settings.username diff --git a/plugins/newsdownloader.koplugin/main.lua b/plugins/newsdownloader.koplugin/main.lua index 488a4e36c..95dddf7fb 100644 --- a/plugins/newsdownloader.koplugin/main.lua +++ b/plugins/newsdownloader.koplugin/main.lua @@ -97,12 +97,10 @@ function NewsDownloader:addToMainMenu(menu_items) text = _("Never download images"), keep_menu_open = true, checked_func = function() - return news_downloader_settings:readSetting("never_download_images") + return news_downloader_settings:isTrue("never_download_images") end, callback = function() - local never_download_images = news_downloader_settings:readSetting("never_download_images") or false - logger.info("NewsDownloader: previous never_download_images: ", never_download_images) - news_downloader_settings:saveSetting("never_download_images", not never_download_images) + news_downloader_settings:toggle("never_download_images") news_downloader_settings:flush() end, }, @@ -176,11 +174,11 @@ function NewsDownloader:loadConfigAndProcessFeeds() return end - local never_download_images = news_downloader_settings:readSetting("never_download_images") or false + local never_download_images = news_downloader_settings:isTrue("never_download_images") local unsupported_feeds_urls = {} - local total_feed_entries = table.getn(feed_config) + local total_feed_entries = #feed_config for idx, feed in ipairs(feed_config) do local url = feed[1] local limit = feed.limit diff --git a/plugins/opds.koplugin/opdsbrowser.lua b/plugins/opds.koplugin/opdsbrowser.lua index df51cdc38..8953cef1e 100644 --- a/plugins/opds.koplugin/opdsbrowser.lua +++ b/plugins/opds.koplugin/opdsbrowser.lua @@ -36,8 +36,34 @@ local CatalogCache = Cache:new{ } local OPDSBrowser = Menu:extend{ - opds_servers = {}, + opds_servers = G_reader_settings:readSetting("opds_servers", { + { + title = "Project Gutenberg", + url = "https://m.gutenberg.org/ebooks.opds/?format=opds", + }, + { + title = "Feedbooks", + url = "https://catalog.feedbooks.com/catalog/public_domain.atom", + }, + { + title = "ManyBooks", + url = "http://manybooks.net/opds/index.php", + }, + { + title = "Internet Archive", + url = "https://bookserver.archive.org/", + }, + { + title = "textos.info (Spanish)", + url = "https://www.textos.info/catalogo.atom", + }, + { + title = "Gallica (French)", + url = "https://gallica.bnf.fr/opds", + }, + }), calibre_name = _("Local calibre library"), + calibre_opds = G_reader_settings:readSetting("calibre_opds", {}), catalog_type = "application/atom%+xml", search_type = "application/opensearchdescription%+xml", @@ -53,38 +79,13 @@ local OPDSBrowser = Menu:extend{ } function OPDSBrowser:init() - local servers = G_reader_settings:readSetting("opds_servers") - if not servers then -- If there are no saved servers, add some defaults - servers = { - { - title = "Project Gutenberg", - url = "https://m.gutenberg.org/ebooks.opds/?format=opds", - }, - { - title = "Feedbooks", - url = "https://catalog.feedbooks.com/catalog/public_domain.atom", - }, - { - title = "ManyBooks", - url = "http://manybooks.net/opds/index.php", - }, - { - title = "Internet Archive", - url = "https://bookserver.archive.org/", - }, - { - title = "textos.info (Spanish)", - url = "https://www.textos.info/catalogo.atom", - }, - { - title = "Gallica (French)", - url = "https://gallica.bnf.fr/opds", - }, - } - G_reader_settings:saveSetting("opds_servers", servers) - elseif servers[4] and servers[4].title == "Internet Archive" and servers[4].url == "http://bookserver.archive.org/catalog/" then - servers[4].url = "https://bookserver.archive.org" + -- Update deprecated URLs + for _, server in ipairs(self.opds_servers) do + if server.url == "http://bookserver.archive.org/catalog/" then + server.url = "https://bookserver.archive.org" + end end + self.item_table = self:genItemTableFromRoot() self.catalog_title = nil Menu.init(self) -- call parent's init() @@ -92,7 +93,6 @@ end function OPDSBrowser:addServerFromInput(fields) logger.info("New OPDS catalog input:", fields) - local servers = G_reader_settings:readSetting("opds_servers") or {} local new_server = { title = fields[1], url = (fields[2]:match("^%a+://") and fields[2] or "http://" .. fields[2]), @@ -101,31 +101,28 @@ function OPDSBrowser:addServerFromInput(fields) -- Allow empty passwords password = fields[4], } - table.insert(servers, new_server) - G_reader_settings:saveSetting("opds_servers", servers) + table.insert(self.opds_servers, new_server) self:init() end function OPDSBrowser:editCalibreFromInput(fields) logger.dbg("Edit calibre server input:", fields) - local calibre = G_reader_settings:readSetting("calibre_opds") or {} if fields[1] then - calibre.host = fields[1] + self.calibre_opds.host = fields[1] end if tonumber(fields[2]) then - calibre.port = fields[2] + self.calibre_opds.port = fields[2] end if fields[3] and fields[3] ~= "" then - calibre.username = fields[3] + self.calibre_opds.username = fields[3] else - calibre.username = nil + self.calibre_opds.username = nil end if fields[4] then - calibre.password = fields[4] + self.calibre_opds.password = fields[4] else - calibre.password = nil + self.calibre_opds.password = nil end - G_reader_settings:saveSetting("calibre_opds", calibre) self:init() end @@ -178,25 +175,24 @@ function OPDSBrowser:addNewCatalog() end function OPDSBrowser:editCalibreServer() - local calibre = G_reader_settings:readSetting("calibre_opds") or {} self.add_server_dialog = MultiInputDialog:new{ title = _("Edit local calibre host and port"), fields = { { --- @todo get IP address of current device - text = calibre.host or "192.168.1.1", + text = self.calibre_opds.host or "192.168.1.1", hint = _("calibre host"), }, { - text = calibre.port and tostring(calibre.port) or "8080", + text = self.calibre_opds.port and tostring(self.calibre_opds.port) or "8080", hint = _("calibre port"), }, { - text = calibre.username or "", + text = self.calibre_opds.username or "", hint = _("Username (optional)"), }, { - text = calibre.password or "", + text = self.calibre_opds.password or "", hint = _("Password (optional)"), text_type = "password", }, @@ -229,8 +225,7 @@ end function OPDSBrowser:genItemTableFromRoot() local item_table = {} - local added_servers = G_reader_settings:readSetting("opds_servers") or {} - for _, server in ipairs(added_servers) do + for _, server in ipairs(self.opds_servers) do table.insert(item_table, { text = server.title, content = server.subtitle, @@ -242,8 +237,7 @@ function OPDSBrowser:genItemTableFromRoot() searchable = server.searchable, }) end - local calibre_opds = G_reader_settings:readSetting("calibre_opds") or {} - if not calibre_opds.host or not calibre_opds.port then + if not self.calibre_opds.host or not self.calibre_opds.port then table.insert(item_table, { text = self.calibre_name, callback = function() @@ -255,9 +249,9 @@ function OPDSBrowser:genItemTableFromRoot() table.insert(item_table, { text = self.calibre_name, url = string.format("http://%s:%d/opds", - calibre_opds.host, calibre_opds.port), - username = calibre_opds.username, - password = calibre_opds.password, + self.calibre_opds.host, self.calibre_opds.port), + username = self.calibre_opds.username, + password = self.calibre_opds.password, editable = true, deletable = false, searchable = false, @@ -772,8 +766,7 @@ end function OPDSBrowser:editServerFromInput(item, fields) logger.info("Edit OPDS catalog input:", fields) - local servers = {} - for _, server in ipairs(G_reader_settings:readSetting("opds_servers") or {}) do + for _, server in ipairs(self.opds_servers) do if server.title == item.text or server.url == item.url then server.title = fields[1] server.url = (fields[2]:match("^%a+://") and fields[2] or "http://" .. fields[2]) @@ -781,9 +774,7 @@ function OPDSBrowser:editServerFromInput(item, fields) server.username = fields[3] ~= "" and fields[3] or nil server.password = fields[4] end - table.insert(servers, server) end - G_reader_settings:saveSetting("opds_servers", servers) self:init() end @@ -838,13 +829,12 @@ end function OPDSBrowser:deleteOPDSServer(item) logger.info("Delete OPDS server:", item) - local servers = {} - for _, server in ipairs(G_reader_settings:readSetting("opds_servers") or {}) do - if server.title ~= item.text or server.url ~= item.url then - table.insert(servers, server) + for i = #self.opds_servers, 1, -1 do + local server = self.opds_servers[i] + if server.title == item.text and server.url == item.url then + table.remove(self.opds_servers, i) end end - G_reader_settings:saveSetting("opds_servers", servers) self:init() end diff --git a/plugins/perceptionexpander.koplugin/main.lua b/plugins/perceptionexpander.koplugin/main.lua index 2baf9f89c..8306004b8 100644 --- a/plugins/perceptionexpander.koplugin/main.lua +++ b/plugins/perceptionexpander.koplugin/main.lua @@ -30,7 +30,7 @@ local PerceptionExpander = Widget:extend{ function PerceptionExpander:init() if not self.settings then self:readSettingsFile() end - self.is_enabled = self.settings:readSetting("is_enabled") or false + self.is_enabled = self.settings:isTrue("is_enabled") if not self.is_enabled then return end diff --git a/plugins/statistics.koplugin/main.lua b/plugins/statistics.koplugin/main.lua index 3a0bdc0e8..486341654 100644 --- a/plugins/statistics.koplugin/main.lua +++ b/plugins/statistics.koplugin/main.lua @@ -35,7 +35,7 @@ local DEFAULT_CALENDAR_NB_BOOK_SPANS = 3 local DB_SCHEMA_VERSION = 20201022 -- This is the query used to compute the total time spent reading distinct pages of the book, --- capped at self.page_max_read_sec per distinct page. +-- capped at self.settings.max_sec per distinct page. -- c.f., comments in insertDB local STATISTICS_SQL_BOOK_CAPPED_TOTALS_QUERY = [[ SELECT count(*), @@ -137,22 +137,15 @@ function ReaderStatistics:init() end self.start_current_period = os.time() self:resetVolatileStats() - local settings = G_reader_settings:readSetting("statistics") or {} - self.page_min_read_sec = tonumber(settings.min_sec) - self.page_max_read_sec = tonumber(settings.max_sec) - self.calendar_start_day_of_week = settings.calendar_start_day_of_week - self.calendar_nb_book_spans = settings.calendar_nb_book_spans - self.calendar_show_histogram = settings.calendar_show_histogram - self.calendar_browse_future_months = settings.calendar_browse_future_months - self.is_enabled = not (settings.is_enabled == false) - self.convert_to_db = settings.convert_to_db + self.settings = G_reader_settings:readSetting("statistics", {}) + self.settings.is_enabled = not (self.settings.is_enabled == false) self.ui.menu:registerToMainMenu(self) self:checkInitDatabase() BookStatusWidget.getStats = function() - return self:getStatsBookStatus(self.id_curr_book, self.is_enabled) + return self:getStatsBookStatus(self.id_curr_book, self.settings.is_enabled) end ReaderFooter.getAvgTimePerPage = function() - if self.is_enabled then + if self.settings.is_enabled then return self.avg_time end end @@ -177,7 +170,7 @@ function ReaderStatistics:init() end function ReaderStatistics:initData() - if self:isDocless() or not self.is_enabled then + if self:isDocless() or not self.settings.is_enabled then return end -- first execution @@ -206,7 +199,7 @@ function ReaderStatistics:initData() self.avg_time = self.book_read_time / self.book_read_pages else -- NOTE: Possibly less weird-looking than initializing this to 0? - self.avg_time = math.floor(0.50 * self.page_max_read_sec) + self.avg_time = math.floor(0.50 * self.settings.max_sec) logger.dbg("ReaderStatistics: Initializing average time per page at 50% of the max value, i.e.,", self.avg_time) end end @@ -276,7 +269,7 @@ end function ReaderStatistics:checkInitDatabase() local conn = SQ3.open(db_location) - if self.convert_to_db then -- if conversion to sqlite DB has already been done + if self.settings.convert_to_db then -- if conversion to sqlite DB has already been done if not conn:exec("PRAGMA table_info('book');") then UIManager:show(ConfirmBox:new{ text = T(_([[ @@ -352,7 +345,7 @@ Do you want to create an empty database? conn = SQ3.open(db_location) end else -- Migrate stats for books in history from metadata.lua to sqlite database - self.convert_to_db = true + self.settings.convert_to_db = true if not conn:exec("PRAGMA table_info('book');") then local filename_first_history, quickstart_filename, __ if #ReadHistory.hist == 1 then @@ -379,7 +372,6 @@ Please wait… self:createDB(conn) end end - self:saveSettings() end conn:close() end @@ -593,8 +585,8 @@ function ReaderStatistics:addBookStatToDB(book_stats, conn) conn:exec('BEGIN;') stmt = conn:prepare("INSERT OR IGNORE INTO page_stat VALUES(?, ?, ?, ?);") local avg_time = math.ceil(book_stats.total_time_in_sec / read_pages) - if avg_time > self.page_max_read_sec then - avg_time = self.page_max_read_sec + if avg_time > self.settings.max_sec then + avg_time = self.settings.max_sec end local first_read_page = book_stats.performance_in_pages[sorted_performance[1]] if first_read_page > 1 then @@ -606,10 +598,10 @@ function ReaderStatistics:addBookStatToDB(book_stats, conn) for i=2, #sorted_performance do start_open_page = sorted_performance[i-1] local diff_time = sorted_performance[i] - sorted_performance[i-1] - if diff_time <= self.page_max_read_sec then + if diff_time <= self.settings.max_sec then stmt:reset():bind(id_book, book_stats.performance_in_pages[sorted_performance[i-1]], start_open_page, diff_time):step() - elseif diff_time > self.page_max_read_sec then --and diff_time <= 2 * avg_time then + elseif diff_time > self.settings.max_sec then --and diff_time <= 2 * avg_time then stmt:reset():bind(id_book, book_stats.performance_in_pages[sorted_performance[i-1]], start_open_page, avg_time):step() end @@ -640,7 +632,7 @@ function ReaderStatistics:migrateToDB(conn) local nr_of_conv_books = 0 local exclude_titles = {} for _, v in pairs(ReadHistory.hist) do - local book_stats = DocSettings:open(v.file):readSetting('stats') + local book_stats = DocSettings:open(v.file):readSetting("stats") if book_stats and book_stats.title == "" then book_stats.title = v.file:match("^.+/(.+)$") end @@ -767,9 +759,9 @@ function ReaderStatistics:insertDB(id_book, updated_pagecount) -- NOTE: See the tail end of the discussions in #6761 for more context on the choice of this heuristic. -- Basically, we're counting distinct pages, - -- while making sure the sum of durations per distinct page is clamped to self.page_max_read_sec + -- while making sure the sum of durations per distinct page is clamped to self.settings.max_sec -- This is expressly tailored to a fairer computation of self.avg_time ;). - local book_read_pages, book_read_time = conn:rowexec(string.format(STATISTICS_SQL_BOOK_CAPPED_TOTALS_QUERY, self.page_max_read_sec, id_book)) + local book_read_pages, book_read_time = conn:rowexec(string.format(STATISTICS_SQL_BOOK_CAPPED_TOTALS_QUERY, self.settings.max_sec, id_book)) -- NOTE: What we cache in the book table is the plain uncapped sum (mainly for deleteBooksByTotalDuration's benefit)... local total_read_pages, total_read_time = conn:rowexec(string.format(STATISTICS_SQL_BOOK_TOTALS_QUERY, id_book)) @@ -810,7 +802,7 @@ function ReaderStatistics:getPageTimeTotalStats(id_book) end local conn = SQ3.open(db_location) -- NOTE: Similarly, this one is used for time-based estimates and averages, so, use the capped variant - local total_pages, total_time = conn:rowexec(string.format(STATISTICS_SQL_BOOK_CAPPED_TOTALS_QUERY, self.page_max_read_sec, id_book)) + local total_pages, total_time = conn:rowexec(string.format(STATISTICS_SQL_BOOK_CAPPED_TOTALS_QUERY, self.settings.max_sec, id_book)) conn:close() if total_pages then @@ -838,23 +830,22 @@ end function ReaderStatistics:getStatisticEnabledMenuItem() return { text = _("Enabled"), - checked_func = function() return self.is_enabled end, + checked_func = function() return self.settings.is_enabled end, callback = function() -- if was enabled, have to save data to file - if self.is_enabled and not self:isDocless() then + if self.settings.is_enabled and not self:isDocless() then self:insertDB(self.id_curr_book) self.ui.doc_settings:saveSetting("stats", self.data) end - self.is_enabled = not self.is_enabled + self.settings.is_enabled = not self.settings.is_enabled -- if was disabled have to get data from db - if self.is_enabled and not self:isDocless() then + if self.settings.is_enabled and not self:isDocless() then self:initData() self.start_current_period = os.time() self.curr_page = self.ui:getCurrentPage() self:resetVolatileStats(self.start_current_period) end - self:saveSettings() if not self:isDocless() then self.view.footer:onUpdateFooter() end @@ -873,21 +864,21 @@ function ReaderStatistics:addToMainMenu(menu_items) { text_func = function() return T(_("Read page duration limits: %1 s / %2 s"), - self.page_min_read_sec, self.page_max_read_sec) + self.settings.min_sec, self.settings.max_sec) end, callback = function(touchmenu_instance) local DoubleSpinWidget = require("/ui/widget/doublespinwidget") local durations_widget durations_widget = DoubleSpinWidget:new{ left_text = _("Min"), - left_value = self.page_min_read_sec, + left_value = self.settings.min_sec, left_default = DEFAULT_MIN_READ_SEC, left_min = 3, left_max = 120, left_step = 1, left_hold_step = 10, right_text = _("Max"), - right_value = self.page_max_read_sec, + right_value = self.settings.max_sec, right_default = DEFAULT_MAX_READ_SEC, right_min = 10, right_max = 7200, @@ -906,9 +897,8 @@ The max value ensures a page you stay on for a long time (because you fell aslee if min > max then min, max = max, min end - self.page_min_read_sec = min - self.page_max_read_sec = max - self:saveSettings() + self.settings.min_sec = min + self.settings.max_sec = max UIManager:close(durations_widget) touchmenu_instance:updateItems() end, @@ -921,52 +911,52 @@ The max value ensures a page you stay on for a long time (because you fell aslee { text_func = function() return T(_("Calendar weeks start on %1"), - longDayOfWeekTranslation[weekDays[self.calendar_start_day_of_week]]) + longDayOfWeekTranslation[weekDays[self.settings.calendar_start_day_of_week]]) end, sub_item_table = { { -- Friday (Bangladesh and Maldives) text = longDayOfWeekTranslation[weekDays[6]], - checked_func = function() return self.calendar_start_day_of_week == 6 end, - callback = function() self.calendar_start_day_of_week = 6 end + checked_func = function() return self.settings.calendar_start_day_of_week == 6 end, + callback = function() self.settings.calendar_start_day_of_week = 6 end }, { -- Saturday (some Middle East countries) text = longDayOfWeekTranslation[weekDays[7]], - checked_func = function() return self.calendar_start_day_of_week == 7 end, - callback = function() self.calendar_start_day_of_week = 7 end + checked_func = function() return self.settings.calendar_start_day_of_week == 7 end, + callback = function() self.settings.calendar_start_day_of_week = 7 end }, { -- Sunday text = longDayOfWeekTranslation[weekDays[1]], - checked_func = function() return self.calendar_start_day_of_week == 1 end, - callback = function() self.calendar_start_day_of_week = 1 end + checked_func = function() return self.settings.calendar_start_day_of_week == 1 end, + callback = function() self.settings.calendar_start_day_of_week = 1 end }, { -- Monday text = longDayOfWeekTranslation[weekDays[2]], - checked_func = function() return self.calendar_start_day_of_week == 2 end, - callback = function() self.calendar_start_day_of_week = 2 end + checked_func = function() return self.settings.calendar_start_day_of_week == 2 end, + callback = function() self.settings.calendar_start_day_of_week = 2 end }, }, }, { text_func = function() - return T(_("Books per calendar day: %1"), self.calendar_nb_book_spans) + return T(_("Books per calendar day: %1"), self.settings.calendar_nb_book_spans) end, callback = function(touchmenu_instance) local SpinWidget = require("ui/widget/spinwidget") UIManager:show(SpinWidget:new{ width = math.floor(Screen:getWidth() * 0.6), - value = self.calendar_nb_book_spans, + value = self.settings.calendar_nb_book_spans, value_min = 1, value_max = 5, ok_text = _("Set"), title_text = _("Books per calendar day"), info_text = _("Set the max number of book spans to show for a day"), callback = function(spin) - self.calendar_nb_book_spans = spin.value + self.settings.calendar_nb_book_spans = spin.value touchmenu_instance:updateItems() end, extra_text = _("Use default"), extra_callback = function() - self.calendar_nb_book_spans = DEFAULT_CALENDAR_NB_BOOK_SPANS + self.settings.calendar_nb_book_spans = DEFAULT_CALENDAR_NB_BOOK_SPANS touchmenu_instance:updateItems() end }) @@ -975,16 +965,16 @@ The max value ensures a page you stay on for a long time (because you fell aslee }, { text = _("Show hourly histogram in calendar days"), - checked_func = function() return self.calendar_show_histogram end, + checked_func = function() return self.settings.calendar_show_histogram end, callback = function() - self.calendar_show_histogram = not self.calendar_show_histogram + self.settings.calendar_show_histogram = not self.settings.calendar_show_histogram end, }, { text = _("Allow browsing coming months"), - checked_func = function() return self.calendar_browse_future_months end, + checked_func = function() return self.settings.calendar_browse_future_months end, callback = function() - self.calendar_browse_future_months = not self.calendar_browse_future_months + self.settings.calendar_browse_future_months = not self.settings.calendar_browse_future_months end, }, }, @@ -1003,7 +993,7 @@ The max value ensures a page you stay on for a long time (because you fell aslee kv_pairs = self:getCurrentStat(self.id_curr_book), }) end, - enabled_func = function() return not self:isDocless() and self.is_enabled end, + enabled_func = function() return not self:isDocless() and self.settings.is_enabled end, }, { text = _("Reading progress"), @@ -1307,7 +1297,7 @@ function ReaderStatistics:getCurrentStat(id_book) -- Current book statistics -- Includes re-reads { _("Total time spent on this book"), util.secondsToClock(total_time_book, false) }, - -- Capped to self.page_max_read_sec per distinct page + -- Capped to self.settings.max_sec per distinct page { _("Time spent reading this book"), util.secondsToClock(book_read_time, false) }, -- per days { _("Reading started"), os.date("%Y-%m-%d (%H:%M)", tonumber(first_open))}, @@ -1922,7 +1912,7 @@ function ReaderStatistics:genResetBookSubItemTable() callback = function() self:resetCurrentBook() end, - enabled_func = function() return not self:isDocless() and self.is_enabled and self.id_curr_book end, + enabled_func = function() return not self:isDocless() and self.settings.is_enabled and self.id_curr_book end, separator = true, }) table.insert(sub_item_table, { @@ -2052,7 +2042,7 @@ function ReaderStatistics:resetCurrentBook() -- We also need to reset the time/page/avg tracking self.book_read_pages = 0 self.book_read_time = 0 - self.avg_time = math.floor(0.50 * self.page_max_read_sec) + self.avg_time = math.floor(0.50 * self.settings.max_sec) logger.dbg("ReaderStatistics: Initializing average time per page at 50% of the max value, i.e.,", self.avg_time) -- And the current volatile stats @@ -2143,7 +2133,7 @@ function ReaderStatistics:onPosUpdate(pos, pageno) end function ReaderStatistics:onPageUpdate(pageno) - if self:isDocless() or not self.is_enabled then + if self:isDocless() or not self.settings.is_enabled then return end @@ -2174,7 +2164,7 @@ function ReaderStatistics:onPageUpdate(pageno) -- NOTE: If all goes well, given the earlier curr_page != pageno check, curr_duration should always be 0 here. -- Compute the difference between now and the previous page's last timestamp local diff_time = now_ts - then_ts - if diff_time >= self.page_min_read_sec and diff_time <= self.page_max_read_sec then + if diff_time >= self.settings.min_sec and diff_time <= self.settings.max_sec then self.mem_read_time = self.mem_read_time + diff_time -- If it's the first time we're computing a duration for this page, count it as read if #page_data == 1 and curr_duration == 0 then @@ -2182,13 +2172,13 @@ function ReaderStatistics:onPageUpdate(pageno) end -- Update the tuple with the computed duration data_tuple[2] = curr_duration + diff_time - elseif diff_time > self.page_max_read_sec then - self.mem_read_time = self.mem_read_time + self.page_max_read_sec + elseif diff_time > self.settings.max_sec then + self.mem_read_time = self.mem_read_time + self.settings.max_sec if #page_data == 1 and curr_duration == 0 then self.mem_read_pages = self.mem_read_pages + 1 end -- Update the tuple with the computed duration - data_tuple[2] = curr_duration + self.page_max_read_sec + data_tuple[2] = curr_duration + self.settings.max_sec end -- We want a flush to db every 50 page turns @@ -2238,20 +2228,20 @@ function ReaderStatistics:importFromFile(base_path, item) end function ReaderStatistics:onCloseDocument() - if not self:isDocless() and self.is_enabled then + if not self:isDocless() and self.settings.is_enabled then self.ui.doc_settings:saveSetting("stats", self.data) self:insertDB(self.id_curr_book) end end function ReaderStatistics:onAddHighlight() - if self.is_enabled then + if self.settings.is_enabled then self.data.highlights = self.data.highlights + 1 end end function ReaderStatistics:onDelHighlight() - if self.is_enabled then + if self.settings.is_enabled then if self.data.highlights > 0 then self.data.highlights = self.data.highlights - 1 end @@ -2259,14 +2249,13 @@ function ReaderStatistics:onDelHighlight() end function ReaderStatistics:onAddNote() - if self.is_enabled then + if self.settings.is_enabled then self.data.notes = self.data.notes + 1 end end -- Triggered by auto_save_settings_interval_minutes function ReaderStatistics:onSaveSettings() - self:saveSettings() if not self:isDocless() then self.ui.doc_settings:saveSetting("stats", self.data) self:insertDB(self.id_curr_book) @@ -2287,20 +2276,6 @@ function ReaderStatistics:onResume() self:resetVolatileStats(self.start_current_period) end -function ReaderStatistics:saveSettings() - local settings = { - min_sec = self.page_min_read_sec, - max_sec = self.page_max_read_sec, - is_enabled = self.is_enabled, - convert_to_db = self.convert_to_db, - calendar_start_day_of_week = self.calendar_start_day_of_week, - calendar_nb_book_spans = self.calendar_nb_book_spans, - calendar_show_histogram = self.calendar_show_histogram, - calendar_browse_future_months = self.calendar_browse_future_months, - } - G_reader_settings:saveSetting("statistics", settings) -end - function ReaderStatistics:onReadSettings(config) self.data = config.data.stats or {} end @@ -2319,10 +2294,10 @@ function ReaderStatistics:getCalendarView() monthTranslation = monthTranslation, shortDayOfWeekTranslation = shortDayOfWeekTranslation, longDayOfWeekTranslation = longDayOfWeekTranslation, - start_day_of_week = self.calendar_start_day_of_week, - nb_book_spans = self.calendar_nb_book_spans, - show_hourly_histogram = self.calendar_show_histogram, - browse_future_months = self.calendar_browse_future_months, + start_day_of_week = self.settings.calendar_start_day_of_week, + nb_book_spans = self.settings.calendar_nb_book_spans, + show_hourly_histogram = self.settings.calendar_show_histogram, + browse_future_months = self.settings.calendar_browse_future_months, } end @@ -2433,7 +2408,7 @@ function ReaderStatistics:onShowReaderProgress() end function ReaderStatistics:onShowBookStats() - if self:isDocless() or not self.is_enabled then return end + if self:isDocless() or not self.settings.is_enabled then return end local stats = KeyValuePage:new{ title = _("Current statistics"), kv_pairs = self:getCurrentStat(self.id_curr_book), diff --git a/plugins/terminal.koplugin/main.lua b/plugins/terminal.koplugin/main.lua index fd8965775..71d947bff 100644 --- a/plugins/terminal.koplugin/main.lua +++ b/plugins/terminal.koplugin/main.lua @@ -38,11 +38,10 @@ end function Terminal:init() self:onDispatcherRegisterActions() self.ui.menu:registerToMainMenu(self) - self.shortcuts = self.settings:readSetting("shortcuts") or {} + self.shortcuts = self.settings:readSetting("shortcuts", {}) end function Terminal:saveShortcuts() - self.settings:saveSetting("shortcuts", self.shortcuts) self.settings:flush() UIManager:show(InfoMessage:new{ text = _("Shortcuts saved"), @@ -294,13 +293,12 @@ function Terminal:editName(item) end function Terminal:deleteShortcut(item) - local shortcuts = {} - for _, element in ipairs(self.shortcuts) do - if element.text ~= item.text and element.commands ~= item.commands then - table.insert(shortcuts, element) + for i = #self.shortcuts, 1, -1 do + local element = self.shortcuts[i] + if element.text == item.text and element.commands == item.commands then + table.remove(self.shortcuts, i) end end - self.shortcuts = shortcuts self:saveShortcuts() self:manageShortcuts() end diff --git a/plugins/texteditor.koplugin/main.lua b/plugins/texteditor.koplugin/main.lua index 70c0ee2bf..09e3daa6a 100644 --- a/plugins/texteditor.koplugin/main.lua +++ b/plugins/texteditor.koplugin/main.lua @@ -45,6 +45,7 @@ function TextEditor:loadSettings() return end self.settings = LuaSettings:open(self.settings_file) + -- NOTE: addToHistory assigns a new object self.history = self.settings:readSetting("history") or {} self.last_view_pos = self.settings:readSetting("last_view_pos") or {} self.last_path = self.settings:readSetting("last_path") or ffiutil.realpath(DataStorage:getDataDir()) @@ -56,10 +57,10 @@ function TextEditor:loadSettings() -- -- Allow users to set their prefered font manually in text_editor.lua -- (sadly, not via TextEditor itself, as they would be overriden on close) - if self.settings:readSetting("normal_font") then + if self.settings:has("normal_font") then self.normal_font = self.settings:readSetting("normal_font") end - if self.settings:readSetting("monospace_font") then + if self.settings:has("monospace_font") then self.monospace_font = self.settings:readSetting("monospace_font") end self.auto_para_direction = self.settings:nilOrTrue("auto_para_direction") @@ -254,7 +255,7 @@ function TextEditor:execWhenDoneFunc() end function TextEditor:removeFromHistory(file_path) - for i=#self.history, 1, -1 do + for i = #self.history, 1, -1 do if self.history[i] == file_path then table.remove(self.history, i) end diff --git a/plugins/zsync.koplugin/main.lua b/plugins/zsync.koplugin/main.lua index d077b9560..d35a465e2 100644 --- a/plugins/zsync.koplugin/main.lua +++ b/plugins/zsync.koplugin/main.lua @@ -233,7 +233,7 @@ function ZSync:subscribe() self.received = {} local zsync = self require("ui/downloadmgr"):new{ - show_hidden = G_reader_settings:readSetting("show_hidden"), + show_hidden = G_reader_settings:isTrue("show_hidden"), onConfirm = function(inbox) G_reader_settings:saveSetting("inbox_dir", inbox) zsync:onChooseInbox(inbox) diff --git a/reader.lua b/reader.lua index fb7e046c1..484d383ce 100755 --- a/reader.lua +++ b/reader.lua @@ -212,7 +212,7 @@ local UIManager = require("ui/uimanager") -- and we are not (yet?) able to guess that fact) if Device:hasColorScreen() and not G_reader_settings:has("color_rendering") then -- enable it to prevent further display of this message - G_reader_settings:saveSetting("color_rendering", true) + G_reader_settings:makeTrue("color_rendering") local InfoMessage = require("ui/widget/infomessage") UIManager:show(InfoMessage:new{ text = _("Documents will be rendered in color on this device.\nIf your device is grayscale, you can disable color rendering in the screen sub-menu for reduced memory usage."), diff --git a/spec/unit/autofrontlight_spec.lua b/spec/unit/autofrontlight_spec.lua index 0735b8499..416f641fb 100644 --- a/spec/unit/autofrontlight_spec.lua +++ b/spec/unit/autofrontlight_spec.lua @@ -41,7 +41,7 @@ describe("AutoFrontlight widget tests", function() Device.input.waitEvent = function() end require("luasettings"): open(require("datastorage"):getSettingsDir() .. "/autofrontlight.lua"): - saveSetting("enable", "true"): + saveSetting("enable", true): close() UIManager = require("ui/uimanager") diff --git a/spec/unit/luadata_spec.lua b/spec/unit/luadata_spec.lua index e368da5b4..172b5c526 100644 --- a/spec/unit/luadata_spec.lua +++ b/spec/unit/luadata_spec.lua @@ -45,7 +45,7 @@ describe("luadata module", function() Settings:saveSetting("key", { a = "b", - c = "true", + c = "True", d = false, }) @@ -55,7 +55,7 @@ describe("luadata module", function() assert.True(child:has("a")) assert.are.equal(child:readSetting("a"), "b") assert.True(child:has("c")) - assert.True(child:isTrue("c")) + assert.False(child:isTrue("c")) -- It's a string, not a bool! assert.True(child:has("d")) assert.True(child:isFalse("d")) assert.False(child:isTrue("e")) diff --git a/spec/unit/luasettings_spec.lua b/spec/unit/luasettings_spec.lua index 97aa63010..e3d527e35 100644 --- a/spec/unit/luasettings_spec.lua +++ b/spec/unit/luasettings_spec.lua @@ -45,7 +45,7 @@ describe("luasettings module", function() Settings:saveSetting("key", { a = "b", - c = "true", + c = "True", d = false, }) @@ -55,7 +55,7 @@ describe("luasettings module", function() assert.True(child:has("a")) assert.are.equal(child:readSetting("a"), "b") assert.True(child:has("c")) - assert.True(child:isTrue("c")) + assert.False(child:isTrue("c")) -- It's a string, not a bool! assert.True(child:has("d")) assert.True(child:isFalse("d")) assert.False(child:isTrue("e")) diff --git a/spec/unit/readhistory_spec.lua b/spec/unit/readhistory_spec.lua index bb5463b04..9c7f29457 100644 --- a/spec/unit/readhistory_spec.lua +++ b/spec/unit/readhistory_spec.lua @@ -367,7 +367,7 @@ describe("ReadHistory module", function() it("should automatically remove deleted items from history if setting has been set", function() - G_reader_settings:saveSetting("autoremove_deleted_items_from_history", "true") + G_reader_settings:saveSetting("autoremove_deleted_items_from_history", true) testAutoRemoveDeletedItems() G_reader_settings:delSetting("autoremove_deleted_items_from_history") end) @@ -380,7 +380,7 @@ describe("ReadHistory module", function() it("should not automatically remove deleted items from history if setting has been set to false", function() - G_reader_settings:saveSetting("autoremove_deleted_items_from_history", "false") + G_reader_settings:saveSetting("autoremove_deleted_items_from_history", false) testDoNotAutoRemoveDeletedItems() G_reader_settings:delSetting("autoremove_deleted_items_from_history") end)