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).
pull/7393/head
NiLuJe 3 years ago committed by GitHub
parent 15ef1a3a1b
commit bf6c0cdd6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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

@ -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

@ -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)

@ -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,

@ -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()

@ -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

@ -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()

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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,

@ -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,

@ -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,
})

@ -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,
})

@ -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 = <number>: removed after <number> 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()

@ -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)

@ -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()

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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,

@ -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()

@ -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)

@ -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,

@ -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()

@ -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

@ -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")

@ -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()

@ -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])

@ -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

@ -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)

@ -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., <https://www.lua.org/manual/5.1/manual.html#2.2>.
@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)

@ -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

@ -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 })

@ -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"

@ -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,
}

@ -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."),

@ -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")

@ -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)

@ -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

@ -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"

@ -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()

@ -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

@ -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."),

@ -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

@ -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

@ -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()

@ -373,6 +373,44 @@ function util.arrayAppend(t1, t2)
end
end
--[[--
Remove elements from an array, fast.
Swap & pop, like <http://lua-users.org/lists/lua-l/2013-11/msg00027.html> / <https://stackoverflow.com/a/28942022>, but preserving order.
c.f., <https://stackoverflow.com/a/53038524>
@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)

@ -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()

@ -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()

@ -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."),
})

@ -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

@ -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

@ -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

@ -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"))

@ -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()

@ -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,
})

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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),

@ -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

@ -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

@ -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)

@ -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."),

@ -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")

@ -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"))

@ -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"))

@ -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)

Loading…
Cancel
Save