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() function CloudStorage:init()
--- @todo: Probably a good candidate for the new readSetting API
self.cs_settings = self:readSettings() self.cs_settings = self:readSettings()
self.show_parent = self self.show_parent = self
if self.item then if self.item then

@ -169,9 +169,13 @@ function FileManager:setupLayout()
} }
} }
local g_show_hidden = G_reader_settings:readSetting("show_hidden") local show_hidden
local show_hidden = g_show_hidden == nil and DSHOWHIDDENFILES or g_show_hidden if G_reader_settings:has("show_hidden") then
local show_unsupported = G_reader_settings:readSetting("show_unsupported") 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{ local file_chooser = FileChooser:new{
-- remember to adjust the height when new item is added to the group -- remember to adjust the height when new item is added to the group
path = self.root_path, path = self.root_path,
@ -760,7 +764,7 @@ end
function FileManager:goHome() function FileManager:goHome()
local home_dir = G_reader_settings:readSetting("home_dir") 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 -- Try some sane defaults, depending on platform
home_dir = Device.home_dir home_dir = Device.home_dir
end end

@ -67,7 +67,7 @@ function BookInfo:show(file, book_props)
table.insert(kv_pairs, { _("Folder:"), BD.dirpath(filemanagerutil.abbreviate(directory)), separator = true }) table.insert(kv_pairs, { _("Folder:"), BD.dirpath(filemanagerutil.abbreviate(directory)), separator = true })
-- book_props may be provided if caller already has them available -- 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 if not book_props or not book_props.pages then
-- check there is actually a sidecar file before calling DocSettings:open() -- check there is actually a sidecar file before calling DocSettings:open()
-- that would create an empty sidecar directory -- that would create an empty sidecar directory
@ -75,24 +75,24 @@ function BookInfo:show(file, book_props)
local doc_settings = DocSettings:open(file) local doc_settings = DocSettings:open(file)
if doc_settings then if doc_settings then
if not book_props then if not book_props then
-- Files opened after 20170701 have a 'doc_props' setting with -- Files opened after 20170701 have a "doc_props" setting with
-- complete metadata and 'doc_pages' with accurate nb of pages -- complete metadata and "doc_pages" with accurate nb of pages
book_props = doc_settings:readSetting('doc_props') book_props = doc_settings:readSetting("doc_props")
end end
if not book_props then 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 -- with partial metadata, or empty metadata if statistics plugin
-- was not enabled when book was read (we can guess that from -- was not enabled when book was read (we can guess that from
-- the fact that stats.page = 0) -- 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 if stats and stats.pages ~= 0 then
-- Let's use them as is (which was what was done before), even if -- Let's use them as is (which was what was done before), even if
-- incomplete, to avoid expensive book opening -- incomplete, to avoid expensive book opening
book_props = stats book_props = stats
end end
end end
-- Files opened after 20170701 have an accurate 'doc_pages' setting -- Files opened after 20170701 have an accurate "doc_pages" setting.
local doc_pages = doc_settings:readSetting('doc_pages') local doc_pages = doc_settings:readSetting("doc_pages")
if doc_pages and book_props then if doc_pages and book_props then
book_props.pages = doc_pages book_props.pages = doc_pages
end end
@ -100,7 +100,7 @@ function BookInfo:show(file, book_props)
end end
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 -- document to get them
if not book_props then if not book_props then
local document = DocumentRegistry:openDocument(file) local document = DocumentRegistry:openDocument(file)

@ -95,10 +95,7 @@ end
function FileSearcher:onShowFileSearch() function FileSearcher:onShowFileSearch()
local dummy = self.search_value local dummy = self.search_value
local enabled_search_home_dir = true local enabled_search_home_dir = G_reader_settings:has("home_dir")
if not G_reader_settings:readSetting("home_dir") then
enabled_search_home_dir = false
end
self.search_dialog = InputDialog:new{ self.search_dialog = InputDialog:new{
title = _("Search for books by filename"), title = _("Search for books by filename"),
input = self.search_value, input = self.search_value,

@ -236,18 +236,18 @@ function FileManagerMenu:setUpdateItemTable()
local current_state = _("Show new files in bold") local current_state = _("Show new files in bold")
if G_reader_settings:readSetting("show_file_in_bold") == "opened" then if G_reader_settings:readSetting("show_file_in_bold") == "opened" then
current_state = _("Show opened files in bold") 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 current_state = _("Show files in bold") -- with checkmark unchecked
end end
-- Inform that this settings applies only to classic file chooser -- Inform that this settings applies only to classic file chooser
current_state = T(_("(Classic file browser) %1"), current_state) current_state = T(_("(Classic file browser) %1"), current_state)
return current_state return current_state
end, 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 = { sub_item_table = {
{ {
text = _("Don't show files in bold"), 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() callback = function()
G_reader_settings:saveSetting("show_file_in_bold", false) G_reader_settings:saveSetting("show_file_in_bold", false)
self.ui:onRefresh() self.ui:onRefresh()
@ -264,7 +264,7 @@ function FileManagerMenu:setUpdateItemTable()
{ {
text = _("Show new (not yet opened) files in bold"), text = _("Show new (not yet opened) files in bold"),
checked_func = function() 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, end,
callback = function() callback = function()
G_reader_settings:delSetting("show_file_in_bold") G_reader_settings:delSetting("show_file_in_bold")
@ -296,12 +296,12 @@ To:
}, },
{ {
text = _("Show filename in Open last/previous menu items"), 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, callback = function() G_reader_settings:flipNilOrFalse("open_last_menu_show_filename") end,
}, },
{ {
text = _("Auto-remove deleted or purged items from history"), 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, callback = function() G_reader_settings:flipNilOrFalse("autoremove_deleted_items_from_history") end,
separator = true, separator = true,
}, },
@ -413,7 +413,7 @@ To:
else else
dbg:setVerbose(false) dbg:setVerbose(false)
dbg:turnOff() dbg:turnOff()
G_reader_settings:flipFalse("debug_verbose") G_reader_settings:makeFalse("debug_verbose")
end end
end, end,
}, },
@ -494,7 +494,7 @@ To:
G_reader_settings:saveSetting("dev_no_hw_dither", not Device.screen.hw_dithering) G_reader_settings:saveSetting("dev_no_hw_dither", not Device.screen.hw_dithering)
-- Make sure SW dithering gets disabled when we enable HW dithering -- Make sure SW dithering gets disabled when we enable HW dithering
if Device.screen.hw_dithering and Device.screen.sw_dithering then 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) Device.screen:toggleSWDithering(false)
end end
UIManager:setDirty("all", "full") UIManager:setDirty("all", "full")
@ -515,7 +515,7 @@ To:
G_reader_settings:saveSetting("dev_no_sw_dither", not Device.screen.sw_dithering) G_reader_settings:saveSetting("dev_no_sw_dither", not Device.screen.sw_dithering)
-- Make sure HW dithering gets disabled when we enable SW dithering -- Make sure HW dithering gets disabled when we enable SW dithering
if Device.screen.hw_dithering and Device.screen.sw_dithering then 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) Device.screen:toggleHWDithering(false)
end end
UIManager:setDirty("all", "full") UIManager:setDirty("all", "full")
@ -621,15 +621,15 @@ To:
-- main menu tab -- main menu tab
self.menu_items.open_last_document = { self.menu_items.open_last_document = {
text_func = function() 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") return _("Open last document")
end end
local last_file = G_reader_settings:readSetting("lastfile") 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)) return T(_("Last: %1"), BD.filename(file_name))
end, end,
enabled_func = function() enabled_func = function()
return G_reader_settings:readSetting("lastfile") ~= nil return G_reader_settings:has("lastfile")
end, end,
callback = function() callback = function()
self:onOpenLastDoc() self:onOpenLastDoc()

@ -11,12 +11,13 @@ local util = require("ffi/util")
local _ = require("gettext") local _ = require("gettext")
local T = util.template local T = util.template
local FileManagerShortcuts = InputContainer:extend{} local FileManagerShortcuts = InputContainer:extend{
folder_shortcuts = G_reader_settings:readSetting("folder_shortcuts", {}),
}
function FileManagerShortcuts:updateItemTable() function FileManagerShortcuts:updateItemTable()
local item_table = {} local item_table = {}
local folder_shortcuts = G_reader_settings:readSetting("folder_shortcuts") or {} for _, item in ipairs(self.folder_shortcuts) do
for _, item in ipairs(folder_shortcuts) do
table.insert(item_table, { table.insert(item_table, {
text = string.format("%s (%s)", item.text, item.folder), text = string.format("%s (%s)", item.text, item.folder),
folder = item.folder, folder = item.folder,
@ -107,7 +108,7 @@ function FileManagerShortcuts:addNewFolder()
end end
function FileManagerShortcuts:addFolderFromInput(friendly_name, folder) 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 if item.text == friendly_name and item.folder == folder then
UIManager:show(InfoMessage:new{ UIManager:show(InfoMessage:new{
text = _("A shortcut to this folder already exists."), text = _("A shortcut to this folder already exists."),
@ -115,12 +116,10 @@ function FileManagerShortcuts:addFolderFromInput(friendly_name, folder)
return return
end end
end end
local folder_shortcuts = G_reader_settings:readSetting("folder_shortcuts") or {} table.insert(self.folder_shortcuts, {
table.insert(folder_shortcuts, {
text = friendly_name, text = friendly_name,
folder = folder, folder = folder,
}) })
G_reader_settings:saveSetting("folder_shortcuts", folder_shortcuts)
self:updateItemTable() self:updateItemTable()
end end
@ -193,25 +192,21 @@ function FileManagerShortcuts:editFolderShortcut(item)
end end
function FileManagerShortcuts:renameFolderShortcut(item, new_name) function FileManagerShortcuts:renameFolderShortcut(item, new_name)
local folder_shortcuts = {} for _, element in ipairs(self.folder_shortcuts) do
for _, element in ipairs(G_reader_settings:readSetting("folder_shortcuts") or {}) do
if element.text == item.friendly_name and element.folder == item.folder then if element.text == item.friendly_name and element.folder == item.folder then
element.text = new_name element.text = new_name
end end
table.insert(folder_shortcuts, element)
end end
G_reader_settings:saveSetting("folder_shortcuts", folder_shortcuts)
self:updateItemTable() self:updateItemTable()
end end
function FileManagerShortcuts:deleteFolderShortcut(item) function FileManagerShortcuts:deleteFolderShortcut(item)
local folder_shortcuts = {} for i = #self.folder_shortcuts, 1, -1 do
for _, element in ipairs(G_reader_settings:readSetting("folder_shortcuts") or {}) do local element = self.folder_shortcuts[i]
if element.text ~= item.friendly_name or element.folder ~= item.folder then if element.text == item.friendly_name and element.folder == item.folder then
table.insert(folder_shortcuts, element) table.remove(self.folder_shortcuts, i)
end end
end end
G_reader_settings:saveSetting("folder_shortcuts", folder_shortcuts)
self:updateItemTable() self:updateItemTable()
end end

@ -32,12 +32,12 @@ function ReaderBookmark:init()
} }
end 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 -- The Bookmarks items per page and items' font size can now be
-- configured. Previously, the ones set for the file browser -- configured. Previously, the ones set for the file browser
-- were used. Initialize them from these ones. -- were used. Initialize them from these ones.
local items_per_page = G_reader_settings:readSetting("items_per_page") 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) G_reader_settings:saveSetting("bookmarks_items_per_page", items_per_page)
local items_font_size = G_reader_settings:readSetting("items_font_size") 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 if items_font_size and items_font_size ~= Menu.getItemFontSize(items_per_page) then
@ -186,7 +186,7 @@ end
function ReaderBookmark:fixBookmarkSort(config) function ReaderBookmark:fixBookmarkSort(config)
-- for backward compatibility, since previously bookmarks for credocuments -- for backward compatibility, since previously bookmarks for credocuments
-- are not well sorted. We need to do a whole sorting for at least once. -- 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) table.sort(self.bookmarks, function(a, b)
return self:isBookmarkInPageOrder(a, b) return self:isBookmarkInPageOrder(a, b)
end) end)
@ -197,7 +197,7 @@ function ReaderBookmark:importSavedHighlight(config)
local textmarks = config:readSetting("highlight") or {} local textmarks = config:readSetting("highlight") or {}
-- import saved highlight once, because from now on highlight are added to -- import saved highlight once, because from now on highlight are added to
-- bookmarks when they are created. -- 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 page, marks in pairs(textmarks) do
for _, mark in ipairs(marks) do for _, mark in ipairs(marks) do
page = self.ui.document.info.has_pages and page or mark.pos0 page = self.ui.document.info.has_pages and page or mark.pos0
@ -228,8 +228,8 @@ end
function ReaderBookmark:onSaveSettings() function ReaderBookmark:onSaveSettings()
self.ui.doc_settings:saveSetting("bookmarks", self.bookmarks) self.ui.doc_settings:saveSetting("bookmarks", self.bookmarks)
self.ui.doc_settings:saveSetting("bookmarks_sorted", true) self.ui.doc_settings:makeTrue("bookmarks_sorted")
self.ui.doc_settings:saveSetting("highlights_imported", true) self.ui.doc_settings:makeTrue("highlights_imported")
end end
function ReaderBookmark:isCurrentPageBookmarked() function ReaderBookmark:isCurrentPageBookmarked()

@ -29,8 +29,9 @@ function ReaderConfig:init()
if Device:isTouchDevice() then if Device:isTouchDevice() then
self:initGesListener() self:initGesListener()
end end
self.activation_menu = G_reader_settings:readSetting("activate_menu") if G_reader_settings:has("activate_menu") then
if self.activation_menu == nil then self.activation_menu = G_reader_settings:readSetting("activate_menu")
else
self.activation_menu = "swipe_tap" self.activation_menu = "swipe_tap"
end end
end end

@ -11,8 +11,9 @@ local _ = require("gettext")
local ReaderCoptListener = EventListener:new{} local ReaderCoptListener = EventListener:new{}
function ReaderCoptListener:onReadSettings(config) function ReaderCoptListener:onReadSettings(config)
local view_mode = config:readSetting("copt_view_mode") or local view_mode = config:readSetting("copt_view_mode")
G_reader_settings:readSetting("copt_view_mode") or 0 -- default to "page" 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" local view_mode_name = view_mode == 0 and "page" or "scroll"
-- Let crengine know of the view mode before rendering, as it can -- Let crengine know of the view mode before rendering, as it can
-- cause a rendering change (2-pages would become 1-page in -- cause a rendering change (2-pages would become 1-page in

@ -58,7 +58,6 @@ end
local ReaderDictionary = InputContainer:new{ local ReaderDictionary = InputContainer:new{
data_dir = nil, data_dir = nil,
dict_window_list = {}, dict_window_list = {},
disable_lookup_history = G_reader_settings:isTrue("disable_lookup_history"),
lookup_msg = _("Searching dictionary for:\n%1"), lookup_msg = _("Searching dictionary for:\n%1"),
} }
@ -96,6 +95,10 @@ local function getDictionaryFixHtmlFunc(path)
end end
function ReaderDictionary:init() 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.ui.menu:registerToMainMenu(self)
self.data_dir = STARDICT_DATA_DIR or self.data_dir = STARDICT_DATA_DIR or
os.getenv("STARDICT_DATA_DIR") or os.getenv("STARDICT_DATA_DIR") or
@ -140,19 +143,7 @@ function ReaderDictionary:init()
end end
end end
logger.dbg("found", #available_ifos, "dictionaries") logger.dbg("found", #available_ifos, "dictionaries")
if not G_reader_settings:readSetting("dicts_order") then
G_reader_settings:saveSetting("dicts_order", {})
end
self:sortAvailableIfos() 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 end
-- Prepare the -u options to give to sdcv the dictionary order and if some are disabled -- Prepare the -u options to give to sdcv the dictionary order and if some are disabled
self:updateSdcvDictNamesOptions() self:updateSdcvDictNamesOptions()
@ -163,11 +154,9 @@ function ReaderDictionary:init()
end end
function ReaderDictionary:sortAvailableIfos() function ReaderDictionary:sortAvailableIfos()
local dicts_order = G_reader_settings:readSetting("dicts_order")
table.sort(available_ifos, function(lifo, rifo) table.sort(available_ifos, function(lifo, rifo)
local lord = dicts_order[lifo.file] local lord = self.dicts_order[lifo.file]
local rord = dicts_order[rifo.file] local rord = self.dicts_order[rifo.file]
-- Both ifos without an explicit position -> lexical comparison -- Both ifos without an explicit position -> lexical comparison
if lord == rord then if lord == rord then
@ -468,9 +457,8 @@ function ReaderDictionary:getNumberOfDictionaries()
local nb_available = #available_ifos local nb_available = #available_ifos
local nb_enabled = 0 local nb_enabled = 0
local nb_disabled = 0 local nb_disabled = 0
local dicts_disabled = G_reader_settings:readSetting("dicts_disabled")
for _, ifo in pairs(available_ifos) do 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 nb_disabled = nb_disabled + 1
else else
nb_enabled = nb_enabled + 1 nb_enabled = nb_enabled + 1
@ -526,7 +514,7 @@ end
function ReaderDictionary:showDictionariesMenu(changed_callback) function ReaderDictionary:showDictionariesMenu(changed_callback)
-- Work on local copy, save to settings only when SortWidget is closed with the accept button -- 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 = {} local sort_items = {}
for _, ifo in pairs(available_ifos) do for _, ifo in pairs(available_ifos) do
@ -550,15 +538,17 @@ function ReaderDictionary:showDictionariesMenu(changed_callback)
title = _("Manage installed dictionaries"), title = _("Manage installed dictionaries"),
item_table = sort_items, item_table = sort_items,
callback = function() callback = function()
-- Save local copy of dicts_disabled -- Update both references to point to that new object
G_reader_settings:saveSetting("dicts_disabled", dicts_disabled) self.dicts_disabled = dicts_disabled
G_reader_settings:saveSetting("dicts_disabled", self.dicts_disabled)
-- Write back the sorted items to dicts_order -- Write back the sorted items to dicts_order
local dicts_order = {} local dicts_order = {}
for i, sort_item in pairs(sort_items) do for i, sort_item in pairs(sort_items) do
dicts_order[sort_item.ifo.file] = i dicts_order[sort_item.ifo.file] = i
end 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() self:sortAvailableIfos()
@ -1058,8 +1048,9 @@ function ReaderDictionary:onReadSettings(config)
if #self.preferred_dictionaries > 0 then if #self.preferred_dictionaries > 0 then
self:updateSdcvDictNamesOptions() self:updateSdcvDictNamesOptions()
end end
self.disable_fuzzy_search = config:readSetting("disable_fuzzy_search") if config:has("disable_fuzzy_search") then
if self.disable_fuzzy_search == nil then self.disable_fuzzy_search = config:isTrue("disable_fuzzy_search")
else
self.disable_fuzzy_search = G_reader_settings:isTrue("disable_fuzzy_search") self.disable_fuzzy_search = G_reader_settings:isTrue("disable_fuzzy_search")
end end
end end
@ -1118,13 +1109,13 @@ The current default (★) is enabled.]])
return disable_fuzzy_search and _("Disable (★)") or _("Disable") return disable_fuzzy_search and _("Disable (★)") or _("Disable")
end, end,
choice1_callback = function() choice1_callback = function()
G_reader_settings:saveSetting("disable_fuzzy_search", true) G_reader_settings:makeTrue("disable_fuzzy_search")
end, end,
choice2_text_func = function() choice2_text_func = function()
return disable_fuzzy_search and _("Enable") or _("Enable (★)") return disable_fuzzy_search and _("Enable") or _("Enable (★)")
end, end,
choice2_callback = function() choice2_callback = function()
G_reader_settings:saveSetting("disable_fuzzy_search", false) G_reader_settings:makeFalse("disable_fuzzy_search")
end, end,
}) })
end end

@ -56,15 +56,15 @@ end
function ReaderDogear:onReadSettings(config) function ReaderDogear:onReadSettings(config)
if not self.ui.document.info.has_pages then if not self.ui.document.info.has_pages then
-- Adjust to CreDocument margins (as done in ReaderTypeset) -- Adjust to CreDocument margins (as done in ReaderTypeset)
local h_margins = config:readSetting("copt_h_page_margins") or local h_margins = config:readSetting("copt_h_page_margins")
G_reader_settings:readSetting("copt_h_page_margins") or or G_reader_settings:readSetting("copt_h_page_margins")
DCREREADER_CONFIG_H_MARGIN_SIZES_MEDIUM or DCREREADER_CONFIG_H_MARGIN_SIZES_MEDIUM
local t_margin = config:readSetting("copt_t_page_margin") or local t_margin = config:readSetting("copt_t_page_margin")
G_reader_settings:readSetting("copt_t_page_margin") or or G_reader_settings:readSetting("copt_t_page_margin")
DCREREADER_CONFIG_T_MARGIN_SIZES_LARGE or DCREREADER_CONFIG_T_MARGIN_SIZES_LARGE
local b_margin = config:readSetting("copt_b_page_margin") or local b_margin = config:readSetting("copt_b_page_margin")
G_reader_settings:readSetting("copt_b_page_margin") or or G_reader_settings:readSetting("copt_b_page_margin")
DCREREADER_CONFIG_B_MARGIN_SIZES_LARGE or DCREREADER_CONFIG_B_MARGIN_SIZES_LARGE
local margins = { h_margins[1], t_margin, h_margins[2], b_margin } local margins = { h_margins[1], t_margin, h_margins[2], b_margin }
self:onSetPageMargins(margins) self:onSetPageMargins(margins)
end end

@ -108,48 +108,55 @@ end
function ReaderFont:onReadSettings(config) function ReaderFont:onReadSettings(config)
self.font_face = config:readSetting("font_face") self.font_face = config:readSetting("font_face")
or G_reader_settings:readSetting("cre_font") or G_reader_settings:readSetting("cre_font")
or self.ui.document.default_font or self.ui.document.default_font
self.ui.document:setFontFace(self.font_face) self.ui.document:setFontFace(self.font_face)
self.header_font_face = config:readSetting("header_font_face") self.header_font_face = config:readSetting("header_font_face")
or G_reader_settings:readSetting("header_font") or G_reader_settings:readSetting("header_font")
or self.ui.document.header_font or self.ui.document.header_font
self.ui.document:setHeaderFont(self.header_font_face) self.ui.document:setHeaderFont(self.header_font_face)
self.font_size = config:readSetting("font_size") self.font_size = config:readSetting("font_size")
or G_reader_settings:readSetting("copt_font_size") or G_reader_settings:readSetting("copt_font_size")
or DCREREADER_CONFIG_DEFAULT_FONT_SIZE or 22 or DCREREADER_CONFIG_DEFAULT_FONT_SIZE
or 22
self.ui.document:setFontSize(Screen:scaleBySize(self.font_size)) self.ui.document:setFontSize(Screen:scaleBySize(self.font_size))
self.font_embolden = config:readSetting("font_embolden") 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.ui.document:toggleFontBolder(self.font_embolden)
self.font_hinting = config:readSetting("font_hinting") 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.ui.document:setFontHinting(self.font_hinting)
self.font_kerning = config:readSetting("font_kerning") 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.ui.document:setFontKerning(self.font_kerning)
self.word_spacing = config:readSetting("word_spacing") 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.ui.document:setWordSpacing(self.word_spacing)
self.word_expansion = config:readSetting("word_expansion") 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.ui.document:setWordExpansion(self.word_expansion)
self.line_space_percent = config:readSetting("line_space_percent") self.line_space_percent = config:readSetting("line_space_percent")
or G_reader_settings:readSetting("copt_line_spacing") or G_reader_settings:readSetting("copt_line_spacing")
or DCREREADER_CONFIG_LINE_SPACE_PERCENT_MEDIUM or DCREREADER_CONFIG_LINE_SPACE_PERCENT_MEDIUM
self.ui.document:setInterlineSpacePercent(self.line_space_percent) self.ui.document:setInterlineSpacePercent(self.line_space_percent)
self.gamma_index = config:readSetting("gamma_index") self.gamma_index = config:readSetting("gamma_index")
or G_reader_settings:readSetting("copt_font_gamma") or G_reader_settings:readSetting("copt_font_gamma")
or DCREREADER_CONFIG_DEFAULT_FONT_GAMMA or 15 -- gamma = 1.0 or DCREREADER_CONFIG_DEFAULT_FONT_GAMMA
or 15 -- gamma = 1.0
self.ui.document:setGammaIndex(self.gamma_index) self.ui.document:setGammaIndex(self.gamma_index)
-- Dirty hack: we have to add following call in order to set -- Dirty hack: we have to add following call in order to set
@ -439,8 +446,8 @@ function ReaderFont:buildFontsTestDocument()
f:close() f:close()
end end
local dir = G_reader_settings:readSetting("home_dir") local dir = G_reader_settings:readSetting("home_dir")
if not dir then dir = require("apps/filemanager/filemanagerutil").getDefaultDir() end or require("apps/filemanager/filemanagerutil").getDefaultDir()
if not dir then dir = "." end or "."
local font_test_final_path = dir .. "/" .. FONT_TEST_FINAL_FILENAME local font_test_final_path = dir .. "/" .. FONT_TEST_FINAL_FILENAME
f = io.open(font_test_final_path, "w") f = io.open(font_test_final_path, "w")
if not f then return end if not f then return end

@ -387,7 +387,7 @@ local ReaderFooter = WidgetContainer:extend{
} }
function ReaderFooter:init() function ReaderFooter:init()
self.settings = G_reader_settings:readSetting("footer") or { self.settings = G_reader_settings:readSetting("footer", {
-- enable progress bar by default -- enable progress bar by default
-- disable_progress_bar = true, -- disable_progress_bar = true,
disabled = false, disabled = false,
@ -414,7 +414,7 @@ function ReaderFooter:init()
text_font_bold = false, text_font_bold = false,
container_height = DMINIBAR_CONTAINER_HEIGHT, container_height = DMINIBAR_CONTAINER_HEIGHT,
container_bottom_padding = 1, -- unscaled_size_check: ignore container_bottom_padding = 1, -- unscaled_size_check: ignore
} })
-- Remove items not supported by the current device -- Remove items not supported by the current device
if not Device:hasFastWifiStatusQuery() then if not Device:hasFastWifiStatusQuery() then
@ -889,7 +889,6 @@ function ReaderFooter:addToMainMenu(menu_items)
end, end,
callback = function() callback = function()
self.settings[option] = not self.settings[option] 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 -- We only need to send a SetPageBottomMargin event when we truly affect the margin
local should_signal = false local should_signal = false
-- only case that we don't need a UI update is enable/disable -- 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 self.mode_index[i] = sort_item.item_table[i].label
end end
self.settings.order = self.mode_index self.settings.order = self.mode_index
G_reader_settings:saveSetting("footer", self.settings)
self:updateFooterTextGenerator() self:updateFooterTextGenerator()
self:onUpdateFooter() self:onUpdateFooter()
UIManager:setDirty(nil, "ui") UIManager:setDirty(nil, "ui")
@ -994,7 +992,6 @@ function ReaderFooter:addToMainMenu(menu_items)
end, end,
callback = function() callback = function()
self.settings.auto_refresh_time = not self.settings.auto_refresh_time self.settings.auto_refresh_time = not self.settings.auto_refresh_time
G_reader_settings:saveSetting("footer", self.settings)
self:rescheduleFooterAutoRefreshIfNeeded() self:rescheduleFooterAutoRefreshIfNeeded()
end end
}, },
@ -1035,7 +1032,6 @@ function ReaderFooter:addToMainMenu(menu_items)
end, end,
callback = function() callback = function()
self.settings.skim_widget_on_hold = not self.settings.skim_widget_on_hold self.settings.skim_widget_on_hold = not self.settings.skim_widget_on_hold
G_reader_settings:saveSetting("footer", self.settings)
end, end,
}, },
{ {
@ -1857,7 +1853,7 @@ function ReaderFooter:getAvgTimePerPage()
end end
function ReaderFooter:getDataFromStatistics(title, pages) function ReaderFooter:getDataFromStatistics(title, pages)
local sec = "N/A" local sec = _("N/A")
local average_time_per_page = self:getAvgTimePerPage() local average_time_per_page = self:getAvgTimePerPage()
if average_time_per_page then if average_time_per_page then
if self.settings.duration_format == "classic" then if self.settings.duration_format == "classic" then
@ -2065,9 +2061,9 @@ end
function ReaderFooter:onReadSettings(config) function ReaderFooter:onReadSettings(config)
if not self.ui.document.info.has_pages then if not self.ui.document.info.has_pages then
local h_margins = config:readSetting("copt_h_page_margins") or local h_margins = config:readSetting("copt_h_page_margins")
G_reader_settings:readSetting("copt_h_page_margins") or or G_reader_settings:readSetting("copt_h_page_margins")
DCREREADER_CONFIG_H_MARGIN_SIZES_MEDIUM or DCREREADER_CONFIG_H_MARGIN_SIZES_MEDIUM
self.book_margins_footer_width = math.floor((h_margins[1] + h_margins[2])/2) self.book_margins_footer_width = math.floor((h_margins[1] + h_margins[2])/2)
end end
end end

@ -1175,13 +1175,13 @@ function ReaderHighlight:onCycleHighlightAction()
dictionary = "search", dictionary = "search",
search = nil, search = nil,
} }
local current_action = G_reader_settings:readSetting("default_highlight_action") if G_reader_settings:hasNot("default_highlight_action") then
if not current_action then
G_reader_settings:saveSetting("default_highlight_action", "highlight") G_reader_settings:saveSetting("default_highlight_action", "highlight")
UIManager:show(Notification:new{ UIManager:show(Notification:new{
text = _("Default highlight action changed to 'highlight'."), text = _("Default highlight action changed to 'highlight'."),
}) })
else else
local current_action = G_reader_settings:readSetting("default_highlight_action")
local next_action = next_actions[current_action] local next_action = next_actions[current_action]
G_reader_settings:saveSetting("default_highlight_action", next_action) G_reader_settings:saveSetting("default_highlight_action", next_action)
UIManager:show(Notification:new{ UIManager:show(Notification:new{
@ -1446,23 +1446,25 @@ end
function ReaderHighlight:onReadSettings(config) function ReaderHighlight:onReadSettings(config)
self.view.highlight.saved_drawer = config:readSetting("highlight_drawer") or self.view.highlight.saved_drawer self.view.highlight.saved_drawer = config:readSetting("highlight_drawer") or self.view.highlight.saved_drawer
local disable_highlight = config:readSetting("highlight_disabled") if config:has("highlight_disabled") then
if disable_highlight == nil then self.view.highlight.disabled = config:isTrue("highlight_disabled")
disable_highlight = G_reader_settings:readSetting("highlight_disabled") or false else
self.view.highlight.disabled = G_reader_settings:isTrue("highlight_disabled")
end end
self.view.highlight.disabled = disable_highlight
-- panel zoom settings isn't supported in EPUB -- panel zoom settings isn't supported in EPUB
if self.document.info.has_pages then if self.document.info.has_pages then
local ext = util.getFileNameSuffix(self.ui.document.file) 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_enabled", {cbz = true, cbt = true})
G_reader_settings:initializeExtSettings("panel_zoom_fallback_to_text_selection", {pdf = true}) G_reader_settings:initializeExtSettings("panel_zoom_fallback_to_text_selection", {pdf = true})
self.panel_zoom_enabled = config:readSetting("panel_zoom_enabled") if config:has("panel_zoom_enabled") then
if self.panel_zoom_enabled == nil 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 self.panel_zoom_enabled = G_reader_settings:getSettingForExt("panel_zoom_enabled", ext) or false
end end
self.panel_zoom_fallback_to_text_selection = config:readSetting("panel_zoom_fallback_to_text_selection") if config:has("panel_zoom_fallback_to_text_selection") then
if self.panel_zoom_fallback_to_text_selection == nil 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 self.panel_zoom_fallback_to_text_selection = G_reader_settings:getSettingForExt("panel_zoom_fallback_to_text_selection", ext) or false
end end
end end
@ -1493,13 +1495,13 @@ function ReaderHighlight:toggleDefault()
return highlight_disabled and _("Disable (★)") or _("Disable") return highlight_disabled and _("Disable (★)") or _("Disable")
end, end,
choice1_callback = function() choice1_callback = function()
G_reader_settings:saveSetting("highlight_disabled", true) G_reader_settings:makeTrue("highlight_disabled")
end, end,
choice2_text_func = function() choice2_text_func = function()
return highlight_disabled and _("Enable") or _("Enable (★)") return highlight_disabled and _("Enable") or _("Enable (★)")
end, end,
choice2_callback = function() choice2_callback = function()
G_reader_settings:saveSetting("highlight_disabled", false) G_reader_settings:makeFalse("highlight_disabled")
end, end,
}) })
end end

@ -16,15 +16,17 @@ end
function ReaderKoptListener:onReadSettings(config) function ReaderKoptListener:onReadSettings(config)
-- normal zoom mode is zoom mode used in non-reflow mode. -- normal zoom mode is zoom mode used in non-reflow mode.
local normal_zoom_mode = config:readSetting("normal_zoom_mode") or local normal_zoom_mode = config:readSetting("normal_zoom_mode")
G_reader_settings:readSetting("zoom_mode") or "page" or G_reader_settings:readSetting("zoom_mode")
or "page"
normal_zoom_mode = util.arrayContains(ReaderZooming.available_zoom_modes, normal_zoom_mode) normal_zoom_mode = util.arrayContains(ReaderZooming.available_zoom_modes, normal_zoom_mode)
and normal_zoom_mode and normal_zoom_mode
or "page" or "page"
self.normal_zoom_mode = normal_zoom_mode self.normal_zoom_mode = normal_zoom_mode
self:setZoomMode(normal_zoom_mode) self:setZoomMode(normal_zoom_mode)
self.document.configurable.contrast = config:readSetting("kopt_contrast") or self.document.configurable.contrast = config:readSetting("kopt_contrast")
G_reader_settings:readSetting("kopt_contrast") or 1.0 or G_reader_settings:readSetting("kopt_contrast")
or 1.0
self.ui:handleEvent(Event:new("GammaUpdate", 1/self.document.configurable.contrast)) 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 -- 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 -- compatability we should manually change previous -1 to a more reasonable -0.2

@ -326,7 +326,7 @@ The recommended value is -2.]]),
end end
return spin_widget return spin_widget
end 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) spin_widget = get_font_size_widget(show_absolute_font_size_widget)
UIManager:show(spin_widget) UIManager:show(spin_widget)
end, end,

@ -71,8 +71,9 @@ function ReaderMenu:init()
end end
end end
end end
self.activation_menu = G_reader_settings:readSetting("activate_menu") if G_reader_settings:has("activate_menu") then
if self.activation_menu == nil then self.activation_menu = G_reader_settings:readSetting("activate_menu")
else
self.activation_menu = "swipe_tap" self.activation_menu = "swipe_tap"
end end
end end
@ -190,16 +191,16 @@ function ReaderMenu:setUpdateItemTable()
text = _("Exclude this book's cover from screensaver"), text = _("Exclude this book's cover from screensaver"),
enabled_func = function() enabled_func = function()
return not (self.ui == nil or self.ui.document == nil) 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, end,
checked_func = function() 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, end,
callback = function() callback = function()
if Screensaver:excluded() then if Screensaver:isExcluded() then
self.ui.doc_settings:saveSetting("exclude_screensaver", false) self.ui.doc_settings:makeFalse("exclude_screensaver")
else else
self.ui.doc_settings:saveSetting("exclude_screensaver", true) self.ui.doc_settings:makeTrue("exclude_screensaver")
end end
self.ui:saveSettings() self.ui:saveSettings()
end, end,

@ -88,18 +88,20 @@ function ReaderPageMap:resetLayout()
end end
function ReaderPageMap:onReadSettings(config) function ReaderPageMap:onReadSettings(config)
local h_margins = config:readSetting("copt_h_page_margins") or local h_margins = config:readSetting("copt_h_page_margins")
G_reader_settings:readSetting("copt_h_page_margins") or or G_reader_settings:readSetting("copt_h_page_margins")
DCREREADER_CONFIG_H_MARGIN_SIZES_MEDIUM or DCREREADER_CONFIG_H_MARGIN_SIZES_MEDIUM
self.max_left_label_width = Screen:scaleBySize(h_margins[1]) self.max_left_label_width = Screen:scaleBySize(h_margins[1])
self.max_right_label_width = Screen:scaleBySize(h_margins[2]) self.max_right_label_width = Screen:scaleBySize(h_margins[2])
self.show_page_labels = config:readSetting("pagemap_show_page_labels") if config:has("pagemap_show_page_labels") then
if self.show_page_labels == nil then self.show_page_labels = config:isTrue("pagemap_show_page_labels")
else
self.show_page_labels = G_reader_settings:nilOrTrue("pagemap_show_page_labels") self.show_page_labels = G_reader_settings:nilOrTrue("pagemap_show_page_labels")
end end
self.use_page_labels = config:readSetting("pagemap_use_page_labels") if config:has("pagemap_use_page_labels") then
if self.use_page_labels == nil then self.use_page_labels = config:isTrue("pagemap_use_page_labels")
else
self.use_page_labels = G_reader_settings:isTrue("pagemap_use_page_labels") self.use_page_labels = G_reader_settings:isTrue("pagemap_use_page_labels")
end end
end end
@ -352,14 +354,14 @@ function ReaderPageMap:addToMainMenu(menu_items)
return use_page_labels and _("Renderer") or _("Renderer (★)") return use_page_labels and _("Renderer") or _("Renderer (★)")
end, end,
choice1_callback = function() 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 if touchmenu_instance then touchmenu_instance:updateItems() end
end, end,
choice2_text_func = function() choice2_text_func = function()
return use_page_labels and _("Reference (★)") or _("Reference") return use_page_labels and _("Reference (★)") or _("Reference")
end, end,
choice2_callback = function() 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 if touchmenu_instance then touchmenu_instance:updateItems() end
end, end,
}) })
@ -385,14 +387,14 @@ function ReaderPageMap:addToMainMenu(menu_items)
return show_page_labels and _("Hide") or _("Hide (★)") return show_page_labels and _("Hide") or _("Hide (★)")
end, end,
choice1_callback = function() 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 if touchmenu_instance then touchmenu_instance:updateItems() end
end, end,
choice2_text_func = function() choice2_text_func = function()
return show_page_labels and _("Show (★)") or _("Show") return show_page_labels and _("Show (★)") or _("Show")
end, end,
choice2_callback = function() 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 if touchmenu_instance then touchmenu_instance:updateItems() end
end, end,
}) })

@ -184,14 +184,16 @@ end
function ReaderPaging:onReadSettings(config) function ReaderPaging:onReadSettings(config)
self.page_positions = config:readSetting("page_positions") or {} self.page_positions = config:readSetting("page_positions") or {}
self:_gotoPage(config:readSetting("last_page") or 1) self:_gotoPage(config:readSetting("last_page") or 1)
self.show_overlap_enable = config:readSetting("show_overlap_enable") if config:has("show_overlap_enable") then
if self.show_overlap_enable == nil then self.show_overlap_enable = config:isTrue("show_overlap_enable")
else
self.show_overlap_enable = DSHOWOVERLAP self.show_overlap_enable = DSHOWOVERLAP
end end
self.flipping_zoom_mode = config:readSetting("flipping_zoom_mode") or "page" self.flipping_zoom_mode = config:readSetting("flipping_zoom_mode") or "page"
self.flipping_scroll_mode = config:readSetting("flipping_scroll_mode") or false self.flipping_scroll_mode = config:isTrue("flipping_scroll_mode")
self.inverse_reading_order = config:readSetting("inverse_reading_order") if config:has("inverse_reading_order") then
if self.inverse_reading_order == nil then self.inverse_reading_order = config:isTrue("inverse_reading_order")
else
self.inverse_reading_order = G_reader_settings:isTrue("inverse_reading_order") self.inverse_reading_order = G_reader_settings:isTrue("inverse_reading_order")
end end
for _, v in ipairs(ReaderZooming.zoom_pan_settings) do 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 (★)") return inverse_reading_order and _("LTR") or _("LTR (★)")
end, end,
choice1_callback = function() 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 if touchmenu_instance then touchmenu_instance:updateItems() end
end, end,
choice2_text_func = function() choice2_text_func = function()
return inverse_reading_order and _("RTL (★)") or _("RTL") return inverse_reading_order and _("RTL (★)") or _("RTL")
end, end,
choice2_callback = function() 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 if touchmenu_instance then touchmenu_instance:updateItems() end
end, end,
}) })

@ -139,9 +139,9 @@ function ReaderRolling:onReadSettings(config)
-- and highlights with old XPATHs. -- and highlights with old XPATHs.
-- (EPUB will use the same correct DOM code no matter what DOM version -- (EPUB will use the same correct DOM code no matter what DOM version
-- we request here.) -- 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 -- 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 -- We have a last_xpointer: this book was previously opened
-- with possibly a very old version: request the oldest -- with possibly a very old version: request the oldest
config:saveSetting("cre_dom_version", self.ui.document:getOldestDomVersion()) config:saveSetting("cre_dom_version", self.ui.document:getOldestDomVersion())
@ -166,7 +166,7 @@ function ReaderRolling:onReadSettings(config)
self.ui.typeset:ensureSanerBlockRenderingFlags() self.ui.typeset:ensureSanerBlockRenderingFlags()
-- And check if we can migrate to a newest DOM version after -- And check if we can migrate to a newest DOM version after
-- the book is loaded (unless the user told us not to). -- 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.ui:registerPostReadyCallback(function()
self:checkXPointersAndProposeDOMVersionUpgrade() self:checkXPointersAndProposeDOMVersionUpgrade()
end) end)
@ -209,13 +209,15 @@ function ReaderRolling:onReadSettings(config)
end end
end end
end end
self.show_overlap_enable = config:readSetting("show_overlap_enable") if config:has("show_overlap_enable") then
if self.show_overlap_enable == nil then self.show_overlap_enable = config:isTrue("show_overlap_enable")
else
self.show_overlap_enable = DSHOWOVERLAP self.show_overlap_enable = DSHOWOVERLAP
end end
self.inverse_reading_order = config:readSetting("inverse_reading_order") if config:has("inverse_reading_order") then
if self.inverse_reading_order == nil then self.inverse_reading_order = config:isTrue("inverse_reading_order")
else
self.inverse_reading_order = G_reader_settings:isTrue("inverse_reading_order") self.inverse_reading_order = G_reader_settings:isTrue("inverse_reading_order")
end end
@ -229,8 +231,9 @@ function ReaderRolling:onReadSettings(config)
G_reader_settings:readSetting("copt_visible_pages") or 1 G_reader_settings:readSetting("copt_visible_pages") or 1
self.ui.document:setVisiblePageCount(self.visible_pages) self.ui.document:setVisiblePageCount(self.visible_pages)
self.hide_nonlinear_flows = config:readSetting("hide_nonlinear_flows") if config:has("hide_nonlinear_flows") then
if self.hide_nonlinear_flows == nil then self.hide_nonlinear_flows = config:isTrue("hide_nonlinear_flows")
else
self.hide_nonlinear_flows = G_reader_settings:isTrue("hide_nonlinear_flows") self.hide_nonlinear_flows = G_reader_settings:isTrue("hide_nonlinear_flows")
end end
self.ui.document:setHideNonlinearFlows(self.hide_nonlinear_flows) self.ui.document:setHideNonlinearFlows(self.hide_nonlinear_flows)
@ -296,7 +299,7 @@ end
function ReaderRolling:onSaveSettings() function ReaderRolling:onSaveSettings()
-- remove last_percent config since its deprecated -- 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) self.ui.doc_settings:saveSetting("last_xpointer", self.xpointer)
-- in scrolling mode, the document may already be closed, -- in scrolling mode, the document may already be closed,
-- so we have to check the condition to avoid crash function self:getLastPercent() -- 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 (★)") return inverse_reading_order and _("LTR") or _("LTR (★)")
end, end,
choice1_callback = function() 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 if touchmenu_instance then touchmenu_instance:updateItems() end
end, end,
choice2_text_func = function() choice2_text_func = function()
return inverse_reading_order and _("RTL (★)") or _("RTL") return inverse_reading_order and _("RTL (★)") or _("RTL")
end, end,
choice2_callback = function() 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 if touchmenu_instance then touchmenu_instance:updateItems() end
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 = true: maker shown and not auto removed
-- followed_link_marker = <number>: removed after <number> seconds -- followed_link_marker = <number>: removed after <number> seconds
-- (no real need for a menu item, the default is the finest) -- (no real need for a menu item, the default is the finest)
local marker_setting = G_reader_settings:readSetting("followed_link_marker") local marker_setting
if marker_setting == nil then 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 marker_setting = 1 -- default is: shown and removed after 1 second
end end
@ -1279,11 +1284,14 @@ function ReaderRolling:checkXPointersAndProposeDOMVersionUpgrade()
-- Switch to default block rendering mode if this book has it set to "legacy", -- 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". -- unless the user had set the global mode to be "legacy".
-- (see ReaderTypeset:onReadSettings() for the logic of block_rendering_mode) -- (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 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 -- This setting is actually saved by self.ui.document.configurable
local block_rendering_mode = self.ui.document.configurable.block_rendering_mode local block_rendering_mode = self.ui.document.configurable.block_rendering_mode
if block_rendering_mode == 0 then 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_text = _("Not for this book"),
cancel_callback = function() 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, end,
ok_text = _("Upgrade now"), ok_text = _("Upgrade now"),
ok_callback = function() ok_callback = function()

@ -327,7 +327,7 @@ function ReaderStyleTweak:updateCssText(apply)
end end
function ReaderStyleTweak:onReadSettings(config) 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 {} self.doc_tweaks = config:readSetting("style_tweaks") or {}
-- Default globally enabled style tweaks (for new installations) -- Default globally enabled style tweaks (for new installations)
-- are defined in css_tweaks.lua -- are defined in css_tweaks.lua
@ -342,7 +342,7 @@ function ReaderStyleTweak:onSaveSettings()
if self.enabled then if self.enabled then
self.ui.doc_settings:delSetting("style_tweaks_enabled") self.ui.doc_settings:delSetting("style_tweaks_enabled")
else else
self.ui.doc_settings:saveSetting("style_tweaks_enabled", false) self.ui.doc_settings:makeFalse("style_tweaks_enabled")
end end
self.ui.doc_settings:saveSetting("style_tweaks", util.tableSize(self.doc_tweaks) > 0 and self.doc_tweaks or nil) 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) G_reader_settings:saveSetting("style_tweaks", self.global_tweaks)

@ -41,12 +41,12 @@ function ReaderToc:init()
} }
end 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 -- The TOC items per page and items' font size can now be
-- configured. Previously, the ones set for the file browser -- configured. Previously, the ones set for the file browser
-- were used. Initialize them from these ones. -- were used. Initialize them from these ones.
local items_per_page = G_reader_settings:readSetting("items_per_page") 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) G_reader_settings:saveSetting("toc_items_per_page", items_per_page)
local items_font_size = G_reader_settings:readSetting("items_font_size") 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 if items_font_size and items_font_size ~= Menu.getItemFontSize(items_per_page) then
@ -137,7 +137,7 @@ end
function ReaderToc:fillToc() function ReaderToc:fillToc()
if self.toc then return end if self.toc then return end
if self.ui.document:canHaveAlternativeToc() then 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 -- (if the document has a cache, the previously built alternative
-- TOC was saved and has been reloaded, and this will be avoided) -- TOC was saved and has been reloaded, and this will be avoided)
if not self.ui.document:isTocAlternativeToc() then if not self.ui.document:isTocAlternativeToc() then
@ -900,7 +900,7 @@ See Style tweaks → Miscellaneous → Alternative ToC hints.]]),
self:resetToc() self:resetToc()
self.toc_ticks_ignored_levels = {} -- reset this self.toc_ticks_ignored_levels = {} -- reset this
self.ui.document:buildAlternativeToc() self.ui.document:buildAlternativeToc()
self.ui.doc_settings:saveSetting("alternative_toc", true) self.ui.doc_settings:makeTrue("alternative_toc")
self:onShowToc() self:onShowToc()
self.view.footer:setTocMarkers(true) self.view.footer:setTocMarkers(true)
self.view.footer:onUpdateFooter() self.view.footer:onUpdateFooter()

@ -22,13 +22,15 @@ function ReaderTypeset:init()
end end
function ReaderTypeset:onReadSettings(config) function ReaderTypeset:onReadSettings(config)
self.css = config:readSetting("css") or G_reader_settings:readSetting("copt_css") self.css = config:readSetting("css")
or self.ui.document.default_css or G_reader_settings:readSetting("copt_css")
or self.ui.document.default_css
local tweaks_css = self.ui.styletweak:getCssText() local tweaks_css = self.ui.styletweak:getCssText()
self.ui.document:setStyleSheet(self.css, tweaks_css) self.ui.document:setStyleSheet(self.css, tweaks_css)
self.embedded_fonts = config:readSetting("embedded_fonts") if config:has("embedded_fonts") then
if self.embedded_fonts == nil then self.embedded_fonts = config:isTrue("embedded_fonts")
else
-- default to enable embedded fonts -- default to enable embedded fonts
-- note that it's a bit confusing here: -- note that it's a bit confusing here:
-- global settins store 0/1, while document settings store false/true -- global settins store 0/1, while document settings store false/true
@ -42,11 +44,12 @@ function ReaderTypeset:onReadSettings(config)
self.ui.document:setEmbeddedFonts(0) self.ui.document:setEmbeddedFonts(0)
end end
self.embedded_css = config:readSetting("embedded_css") if config:has("embedded_css") then
if self.embedded_css == nil then self.embedded_css = config:isTrue("embedded_css")
else
-- default to enable embedded CSS -- default to enable embedded CSS
-- note that it's a bit confusing here: -- 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 -- we leave it that way for now to maintain backwards compatibility
local global = G_reader_settings:readSetting("copt_embedded_css") local global = G_reader_settings:readSetting("copt_embedded_css")
self.embedded_css = (global == nil or global == 1) and true or false 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 -- Block rendering mode: stay with legacy rendering for books
-- previously opened so bookmarks and highlights stay valid. -- previously opened so bookmarks and highlights stay valid.
-- For new books, use 'web' mode below in BLOCK_RENDERING_FLAGS -- For new books, use 'web' mode below in BLOCK_RENDERING_FLAGS
local block_rendering_default_mode = 3 if config:has("copt_block_rendering_mode") then
self.block_rendering_mode = config:readSetting("copt_block_rendering_mode") self.block_rendering_mode = config:readSetting("copt_block_rendering_mode")
if not self.block_rendering_mode then else
if config:readSetting("last_xpointer") then if config:has("last_xpointer") then
-- We have a last_xpointer: this book was previously opened -- We have a last_xpointer: this book was previously opened
self.block_rendering_mode = 0 self.block_rendering_mode = 0
else else
self.block_rendering_mode = G_reader_settings:readSetting("copt_block_rendering_mode") self.block_rendering_mode = G_reader_settings:readSetting("copt_block_rendering_mode")
or block_rendering_default_mode or 3 -- default to 'web' mode
end end
-- Let ConfigDialog know so it can update it on screen and have it saved on quit -- 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 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) self:setBlockRenderingMode(self.block_rendering_mode)
-- set render DPI -- set render DPI
self.render_dpi = config:readSetting("render_dpi") or self.render_dpi = config:readSetting("render_dpi")
G_reader_settings:readSetting("copt_render_dpi") or 96 or G_reader_settings:readSetting("copt_render_dpi")
or 96
self:setRenderDPI(self.render_dpi) self:setRenderDPI(self.render_dpi)
-- uncomment if we want font size to follow DPI changes -- uncomment if we want font size to follow DPI changes
-- self.ui.document:setRenderScaleFontWithDPI(1) -- self.ui.document:setRenderScaleFontWithDPI(1)
-- set page margins -- set page margins
local h_margins = config:readSetting("copt_h_page_margins") or local h_margins = config:readSetting("copt_h_page_margins")
G_reader_settings:readSetting("copt_h_page_margins") or or G_reader_settings:readSetting("copt_h_page_margins")
DCREREADER_CONFIG_H_MARGIN_SIZES_MEDIUM or DCREREADER_CONFIG_H_MARGIN_SIZES_MEDIUM
local t_margin = config:readSetting("copt_t_page_margin") or local t_margin = config:readSetting("copt_t_page_margin")
G_reader_settings:readSetting("copt_t_page_margin") or or G_reader_settings:readSetting("copt_t_page_margin")
DCREREADER_CONFIG_T_MARGIN_SIZES_LARGE or DCREREADER_CONFIG_T_MARGIN_SIZES_LARGE
local b_margin = config:readSetting("copt_b_page_margin") or local b_margin = config:readSetting("copt_b_page_margin")
G_reader_settings:readSetting("copt_b_page_margin") or or G_reader_settings:readSetting("copt_b_page_margin")
DCREREADER_CONFIG_B_MARGIN_SIZES_LARGE or DCREREADER_CONFIG_B_MARGIN_SIZES_LARGE
self.unscaled_margins = { h_margins[1], t_margin, h_margins[2], b_margin } self.unscaled_margins = { h_margins[1], t_margin, h_margins[2], b_margin }
self:onSetPageMargins(self.unscaled_margins) self:onSetPageMargins(self.unscaled_margins)
self.sync_t_b_page_margins = config:readSetting("copt_sync_t_b_page_margins") or self.sync_t_b_page_margins = config:readSetting("copt_sync_t_b_page_margins")
G_reader_settings:readSetting("copt_sync_t_b_page_margins") or 0 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 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 -- default to disable TXT formatting as it does more harm than good
self.txt_preformatted = config:readSetting("txt_preformatted") or self.txt_preformatted = config:readSetting("txt_preformatted")
G_reader_settings:readSetting("txt_preformatted") or 1 or G_reader_settings:readSetting("txt_preformatted")
or 1
self:toggleTxtPreFormatted(self.txt_preformatted) self:toggleTxtPreFormatted(self.txt_preformatted)
-- default to disable smooth scaling for now. -- default to disable smooth scaling for now.
self.smooth_scaling = config:readSetting("smooth_scaling") if config:has("smooth_scaling") then
if self.smooth_scaling == nil then self.smooth_scaling = config:isTrue("smooth_scaling")
else
local global = G_reader_settings:readSetting("copt_smooth_scaling") 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 end
self:toggleImageScaling(self.smooth_scaling) self:toggleImageScaling(self.smooth_scaling)
-- default to automagic nightmode-friendly handling of images -- default to automagic nightmode-friendly handling of images
self.nightmode_images = config:readSetting("nightmode_images") if config:has("nightmode_images") then
if self.nightmode_images == nil then self.nightmode_images = config:isTrue("nightmode_images")
else
local global = G_reader_settings:readSetting("copt_nightmode_images") 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 end
self:toggleNightmodeImages(self.nightmode_images) self:toggleNightmodeImages(self.nightmode_images)
end end

@ -126,7 +126,7 @@ function ReaderTypography:init()
-- Migrate old readerhyphenation settings (but keep them in case one -- Migrate old readerhyphenation settings (but keep them in case one
-- go back to a previous version) -- 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 g_text_lang_set = false
local hyph_alg_default = G_reader_settings:readSetting("hyph_alg_default") local hyph_alg_default = G_reader_settings:readSetting("hyph_alg_default")
if hyph_alg_default then if hyph_alg_default then
@ -137,11 +137,11 @@ function ReaderTypography:init()
-- Tweak the other settings if the default hyph algo happens -- Tweak the other settings if the default hyph algo happens
-- to be one of these: -- to be one of these:
if hyph_alg_default == "@none" then if hyph_alg_default == "@none" then
G_reader_settings:saveSetting("hyphenation", false) G_reader_settings:makeFalse("hyphenation")
elseif hyph_alg_default == "@softhyphens" then 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 elseif hyph_alg_default == "@algorithm" then
G_reader_settings:saveSetting("hyph_force_algorithmic", true) G_reader_settings:makeTrue("hyph_force_algorithmic")
end end
end 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 (★)") return text_lang_embedded_langs and _("Ignore") or _("Ignore (★)")
end, end,
choice1_callback = function() choice1_callback = function()
G_reader_settings:saveSetting("text_lang_embedded_langs", false) G_reader_settings:makeFalse("text_lang_embedded_langs")
end, end,
choice2_text_func = function() choice2_text_func = function()
return text_lang_embedded_langs and _("Respect (★)") or _("Respect") return text_lang_embedded_langs and _("Respect (★)") or _("Respect")
end, end,
choice2_callback = function() choice2_callback = function()
G_reader_settings:saveSetting("text_lang_embedded_langs", true) G_reader_settings:makeTrue("text_lang_embedded_langs")
end, end,
}) })
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 (★)") return hyphenation and _("Disable") or _("Disable (★)")
end, end,
choice1_callback = function() choice1_callback = function()
G_reader_settings:saveSetting("hyphenation", false) G_reader_settings:makeFalse("hyphenation")
end, end,
choice2_text_func = function() choice2_text_func = function()
return hyphenation and _("Enable (★)") or _("Enable") return hyphenation and _("Enable (★)") or _("Enable")
end, end,
choice2_callback = function() choice2_callback = function()
G_reader_settings:saveSetting("hyphenation", true) G_reader_settings:makeTrue("hyphenation")
end, end,
}) })
end, end,
@ -379,8 +379,8 @@ When the book's language tag is not among our presets, no specific features will
text_func = function() text_func = function()
-- Note: with our callback, we either get hyph_left_hyphen_min and -- Note: with our callback, we either get hyph_left_hyphen_min and
-- hyph_right_hyphen_min both nil, or both defined. -- hyph_right_hyphen_min both nil, or both defined.
if G_reader_settings:readSetting("hyph_left_hyphen_min") or if G_reader_settings:has("hyph_left_hyphen_min") or
G_reader_settings:readSetting("hyph_right_hyphen_min") then 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) -- @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"), return T(_("Left/right minimal sizes: %1 - %2"),
G_reader_settings:readSetting("hyph_left_hyphen_min"), 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 (★)") return hyph_trust_soft_hyphens and _("Disable") or _("Disable (★)")
end, end,
choice1_callback = function() choice1_callback = function()
G_reader_settings:saveSetting("hyph_trust_soft_hyphens", false) G_reader_settings:makeFalse("hyph_trust_soft_hyphens")
end, end,
choice2_text_func = function() choice2_text_func = function()
return hyph_trust_soft_hyphens and _("Enable (★)") or _("Enable") return hyph_trust_soft_hyphens and _("Enable (★)") or _("Enable")
end, end,
choice2_callback = function() choice2_callback = function()
G_reader_settings:saveSetting("hyph_trust_soft_hyphens", true) G_reader_settings:makeTrue("hyph_trust_soft_hyphens")
end, end,
}) })
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 (★)") return hyph_force_algorithmic and _("Disable") or _("Disable (★)")
end, end,
choice1_callback = function() choice1_callback = function()
G_reader_settings:saveSetting("hyph_force_algorithmic", false) G_reader_settings:makeFalse("hyph_force_algorithmic")
end, end,
choice2_text_func = function() choice2_text_func = function()
return hyph_force_algorithmic and _("Enable (★)") or _("Enable") return hyph_force_algorithmic and _("Enable (★)") or _("Enable")
end, end,
choice2_callback = function() choice2_callback = function()
G_reader_settings:saveSetting("hyph_force_algorithmic", true) G_reader_settings:makeTrue("hyph_force_algorithmic")
end, end,
}) })
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 (★)") return hyph_soft_hyphens_only and _("Disable") or _("Disable (★)")
end, end,
choice1_callback = function() choice1_callback = function()
G_reader_settings:saveSetting("hyph_soft_hyphens_only", false) G_reader_settings:makeFalse("hyph_soft_hyphens_only")
end, end,
choice2_text_func = function() choice2_text_func = function()
return hyph_soft_hyphens_only and _("Enable (★)") or _("Enable") return hyph_soft_hyphens_only and _("Enable (★)") or _("Enable")
end, end,
choice2_callback = function() choice2_callback = function()
G_reader_settings:saveSetting("hyph_soft_hyphens_only", true) G_reader_settings:makeTrue("hyph_soft_hyphens_only")
end, end,
}) })
end, end,
@ -625,13 +625,13 @@ function ReaderTypography:makeDefaultFloatingPunctuation()
return floating_punctuation and _("Disable") or _("Disable (★)") return floating_punctuation and _("Disable") or _("Disable (★)")
end, end,
choice1_callback = function() choice1_callback = function()
G_reader_settings:saveSetting("floating_punctuation", false) G_reader_settings:makeFalse("floating_punctuation")
end, end,
choice2_text_func = function() choice2_text_func = function()
return floating_punctuation and _("Enable (★)") or _("Enable") return floating_punctuation and _("Enable (★)") or _("Enable")
end, end,
choice2_callback = function() choice2_callback = function()
G_reader_settings:saveSetting("floating_punctuation", true) G_reader_settings:makeTrue("floating_punctuation")
end, end,
}) })
end end
@ -701,7 +701,7 @@ end
-- in book settings, no default lang, and book has some language defined. -- in book settings, no default lang, and book has some language defined.
function ReaderTypography:onReadSettings(config) function ReaderTypography:onReadSettings(config)
-- Migrate old readerhyphenation setting, if one was set -- 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 hyph_alg = config:readSetting("hyph_alg")
local dict_info = HYPH_DICT_NAME_TO_LANG_NAME_TAG[hyph_alg] local dict_info = HYPH_DICT_NAME_TO_LANG_NAME_TAG[hyph_alg]
if dict_info then if dict_info then
@ -709,46 +709,51 @@ function ReaderTypography:onReadSettings(config)
-- Set the other settings if the default hyph algo happens -- Set the other settings if the default hyph algo happens
-- to be one of these: -- to be one of these:
if hyph_alg == "@none" then if hyph_alg == "@none" then
config:saveSetting("hyphenation", false) config:makeFalse("hyphenation")
elseif hyph_alg == "@softhyphens" then elseif hyph_alg == "@softhyphens" then
config:saveSetting("hyph_soft_hyphens_only", true) config:makeTrue("hyph_soft_hyphens_only")
elseif hyph_alg == "@algorithm" then elseif hyph_alg == "@algorithm" then
config:saveSetting("hyph_force_algorithmic", true) config:makeTrue("hyph_force_algorithmic")
end end
end end
end end
-- Enable text lang tags attributes by default -- Enable text lang tags attributes by default
self.text_lang_embedded_langs = config:readSetting("text_lang_embedded_langs") if config:has("text_lang_embedded_langs") then
if self.text_lang_embedded_langs == nil 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") self.text_lang_embedded_langs = G_reader_settings:nilOrTrue("text_lang_embedded_langs")
end end
self.ui.document:setTextEmbeddedLangs(self.text_lang_embedded_langs) self.ui.document:setTextEmbeddedLangs(self.text_lang_embedded_langs)
-- Enable hyphenation by default -- Enable hyphenation by default
self.hyphenation = config:readSetting("hyphenation") if config:has("hyphenation") then
if self.hyphenation == nil then self.hyphenation = config:isTrue("hyphenation")
else
self.hyphenation = G_reader_settings:nilOrTrue("hyphenation") self.hyphenation = G_reader_settings:nilOrTrue("hyphenation")
end end
self.ui.document:setTextHyphenation(self.hyphenation) self.ui.document:setTextHyphenation(self.hyphenation)
-- Checking for soft-hyphens adds a bit of overhead, so have it disabled by default -- 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 config:has("hyph_trust_soft_hyphens") then
if self.hyph_trust_soft_hyphens == nil 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") self.hyph_trust_soft_hyphens = G_reader_settings:isTrue("hyph_trust_soft_hyphens")
end end
self.ui.document:setTrustSoftHyphens(self.hyph_trust_soft_hyphens) self.ui.document:setTrustSoftHyphens(self.hyph_trust_soft_hyphens)
-- Alternative hyphenation method (available with all dicts) to use soft hyphens only -- Alternative hyphenation method (available with all dicts) to use soft hyphens only
self.hyph_soft_hyphens_only = config:readSetting("hyph_soft_hyphens_only") if config:has("hyph_soft_hyphens_only") then
if self.hyph_soft_hyphens_only == nil 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") self.hyph_soft_hyphens_only = G_reader_settings:isTrue("hyph_soft_hyphens_only")
end end
self.ui.document:setTextHyphenationSoftHyphensOnly(self.hyph_soft_hyphens_only) self.ui.document:setTextHyphenationSoftHyphensOnly(self.hyph_soft_hyphens_only)
-- Alternative hyphenation method (available with all dicts) to use algorithmic hyphenation -- Alternative hyphenation method (available with all dicts) to use algorithmic hyphenation
self.hyph_force_algorithmic = config:readSetting("hyph_force_algorithmic") if config:has("hyph_force_algorithmic") then
if self.hyph_force_algorithmic == nil then self.hyph_force_algorithmic = config:isTrue("hyph_force_algorithmic")
else
self.hyph_force_algorithmic = G_reader_settings:isTrue("hyph_force_algorithmic") self.hyph_force_algorithmic = G_reader_settings:isTrue("hyph_force_algorithmic")
end end
self.ui.document:setTextHyphenationForceAlgorithmic(self.hyph_force_algorithmic) self.ui.document:setTextHyphenationForceAlgorithmic(self.hyph_force_algorithmic)
@ -760,40 +765,36 @@ function ReaderTypography:onReadSettings(config)
-- Default to disable hanging/floating punctuation -- Default to disable hanging/floating punctuation
-- (Stored as 0/1 in docsetting for historical reasons, but as true/false -- (Stored as 0/1 in docsetting for historical reasons, but as true/false
-- in global settings.) -- in global settings.)
self.floating_punctuation = config:readSetting("floating_punctuation") if config:has("floating_punctuation") then
if self.floating_punctuation == nil then self.floating_punctuation = config:readSetting("floating_punctuation")
else
self.floating_punctuation = G_reader_settings:isTrue("floating_punctuation") and 1 or 0 self.floating_punctuation = G_reader_settings:isTrue("floating_punctuation") and 1 or 0
end end
self:onToggleFloatingPunctuation(self.floating_punctuation) self:onToggleFloatingPunctuation(self.floating_punctuation)
-- Decide and set the text main lang tag according to settings -- Decide and set the text main lang tag according to settings
self.allow_doc_lang_tag_override = false if config:has("text_lang") then
-- Use the one manually set for this document self.allow_doc_lang_tag_override = false
self.text_lang_tag = config:readSetting("text_lang") -- Use the one manually set for this document
if self.text_lang_tag then self.text_lang_tag = config:readSetting("text_lang")
logger.dbg("Typography lang: using", self.text_lang_tag, "from doc settings") logger.dbg("Typography lang: using", self.text_lang_tag, "from doc settings")
self.ui.document:setTextMainLang(self.text_lang_tag) elseif G_reader_settings:has("text_lang_default") then
return self.allow_doc_lang_tag_override = false
end -- Use the one manually set as default (with Hold)
-- Use the one manually set as default (with Hold) self.text_lang_tag = G_reader_settings:readSetting("text_lang_default")
self.text_lang_tag = G_reader_settings:readSetting("text_lang_default")
if self.text_lang_tag then
logger.dbg("Typography lang: using default ", self.text_lang_tag) logger.dbg("Typography lang: using default ", self.text_lang_tag)
self.ui.document:setTextMainLang(self.text_lang_tag) elseif G_reader_settings:has("text_lang_fallback") then
return -- Document language will be allowed to override the one we set from now on
end self.allow_doc_lang_tag_override = true
-- Document language will be allowed to override the one we set from now on -- Use the one manually set as fallback (with Hold)
self.allow_doc_lang_tag_override = true self.text_lang_tag = G_reader_settings:readSetting("text_lang_fallback")
-- 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
logger.dbg("Typography lang: using fallback ", self.text_lang_tag, ", might be overriden by doc language") logger.dbg("Typography lang: using fallback ", self.text_lang_tag, ", might be overriden by doc language")
self.ui.document:setTextMainLang(self.text_lang_tag) else
return 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 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) self.ui.document:setTextMainLang(self.text_lang_tag)
end end

@ -33,7 +33,7 @@ local ReaderView = OverlapGroup:extend{
offset = nil, offset = nil,
bbox = 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 with "lighten" or "underscore" or "invert"
highlight = { highlight = {
lighten_factor = 0.2, lighten_factor = 0.2,
@ -45,12 +45,12 @@ local ReaderView = OverlapGroup:extend{
highlight_visible = true, highlight_visible = true,
-- PDF/DjVu continuous paging -- PDF/DjVu continuous paging
page_scroll = nil, page_scroll = nil,
page_bgcolor = Blitbuffer.gray(DBACKGROUND_COLOR/15), page_bgcolor = Blitbuffer.gray(DBACKGROUND_COLOR / 15),
page_states = {}, page_states = {},
-- properties of the gap drawn between each page in scroll mode: -- properties of the gap drawn between each page in scroll mode:
page_gap = { page_gap = {
-- color (0 = white, 8 = gray, 15 = black) -- 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()) -- DjVu page rendering mode (used in djvu.c:drawPage())
render_mode = DRENDER_MODE, -- default to COLOR 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. -- Keep current rotation by doing nothing when sticky rota is enabled.
if not locked then if not locked then
-- Honor docsettings's rotation -- Honor docsettings's rotation
rotation_mode = config:readSetting("rotation_mode") -- Doc's if config:has("rotation_mode") then
if not rotation_mode then rotation_mode = config:readSetting("rotation_mode") -- Doc's
else
-- No doc specific rotation, pickup global defaults for the doc type -- No doc specific rotation, pickup global defaults for the doc type
if self.ui.document.info.has_pages then if self.ui.document.info.has_pages then
rotation_mode = G_reader_settings:readSetting("kopt_rotation_mode") or Screen.ORIENTATION_PORTRAIT 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.page_scroll = page_scroll == 1 and true or false
self.highlight.saved = config:readSetting("highlight") or {} 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_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 self.page_gap.height = Screen:scaleBySize(config:readSetting("kopt_page_gap_height")
G_reader_settings:readSetting("kopt_page_gap_height") or 8) or G_reader_settings:readSetting("kopt_page_gap_height")
or 8)
end end
function ReaderView:onPageUpdate(new_page_no) 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 if not self.settings_last_save_ts then -- reader not yet ready
return return
end end
local interval = G_reader_settings:readSetting("auto_save_settings_interval_minutes") if G_reader_settings:nilOrFalse("auto_save_settings_interval_minutes") then
if not interval then -- no auto save -- no auto save
return return
end end
local interval = G_reader_settings:readSetting("auto_save_settings_interval_minutes")
local now_ts = os.time() local now_ts = os.time()
if now_ts - self.settings_last_save_ts >= interval*60 then if now_ts - self.settings_last_save_ts >= interval*60 then
self.settings_last_save_ts = now_ts self.settings_last_save_ts = now_ts

@ -175,8 +175,8 @@ function ReaderWikipedia:addToMainMenu(menu_items)
local choose_directory = function() local choose_directory = function()
-- Default directory as chosen by DictQuickLookup -- Default directory as chosen by DictQuickLookup
local default_dir = G_reader_settings:readSetting("wikipedia_save_dir") local default_dir = G_reader_settings:readSetting("wikipedia_save_dir")
if not default_dir then default_dir = G_reader_settings:readSetting("home_dir") end or G_reader_settings:readSetting("home_dir")
if not default_dir then default_dir = require("apps/filemanager/filemanagerutil").getDefaultDir() end or require("apps/filemanager/filemanagerutil").getDefaultDir()
local dialog local dialog
dialog = ButtonDialogTitle:new{ dialog = ButtonDialogTitle:new{
title = T(_("Current Wikipedia 'Save as EPUB' folder:\n\n%1\n"), BD.dirpath(default_dir)), 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 -- so a user reading a wikipedia article can quickly select
-- it to save related new articles in the same directory -- it to save related new articles in the same directory
local dir = G_reader_settings:readSetting("wikipedia_save_dir") local dir = G_reader_settings:readSetting("wikipedia_save_dir")
if not dir then dir = G_reader_settings:readSetting("home_dir") end or G_reader_settings:readSetting("home_dir")
if not dir then dir = require("apps/filemanager/filemanagerutil").getDefaultDir() end or require("apps/filemanager/filemanagerutil").getDefaultDir()
if not dir then dir = "/" end or "/"
-- If this directory has no subdirectory, we would be displaying -- If this directory has no subdirectory, we would be displaying
-- a single "..", so use parent directory in that case. -- a single "..", so use parent directory in that case.
local has_subdirectory = false local has_subdirectory = false

@ -114,13 +114,13 @@ function ReaderZooming:onReadSettings(config)
or G_reader_settings:readSetting("zoom_mode") or G_reader_settings:readSetting("zoom_mode")
or self.DEFAULT_ZOOM_MODE or self.DEFAULT_ZOOM_MODE
zoom_mode = util.arrayContains(self.available_zoom_modes, zoom_mode) zoom_mode = util.arrayContains(self.available_zoom_modes, zoom_mode)
and zoom_mode and zoom_mode
or self.DEFAULT_ZOOM_MODE or self.DEFAULT_ZOOM_MODE
self:setZoomMode(zoom_mode, true) -- avoid informative message on load self:setZoomMode(zoom_mode, true) -- avoid informative message on load
for _, setting in ipairs(self.zoom_pan_settings) do for _, setting in ipairs(self.zoom_pan_settings) do
self[setting] = config:readSetting(setting) or self[setting] = config:readSetting(setting)
G_reader_settings:readSetting(setting) or or G_reader_settings:readSetting(setting)
self[setting] or self[setting]
end end
end end
@ -433,8 +433,8 @@ function ReaderZooming:getZoom(pageno)
zoom = self.zoom zoom = self.zoom
else else
local zoom_factor = self.ui.doc_settings:readSetting("zoom_factor") local zoom_factor = self.ui.doc_settings:readSetting("zoom_factor")
or G_reader_settings:readSetting("zoom_factor") or G_reader_settings:readSetting("zoom_factor")
or self.zoom_factor or self.zoom_factor
zoom = zoom_w * zoom_factor zoom = zoom_w * zoom_factor
end end
if zoom and zoom > 10 and not Cache:willAccept(zoom * (self.dimen.w * self.dimen.h + 64)) then 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 ui = self
}) })
end 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 -- back location stack
self:registerModule("back", ReaderBack:new{ self:registerModule("back", ReaderBack:new{
ui = self, ui = self,

@ -204,6 +204,7 @@ end
function Cervantes:intoScreenSaver() function Cervantes:intoScreenSaver()
local Screensaver = require("ui/screensaver") local Screensaver = require("ui/screensaver")
if self.screen_saver_mode == false then if self.screen_saver_mode == false then
Screensaver:setup()
Screensaver:show() Screensaver:show()
end end
self.powerd:beforeSuspend() self.powerd:beforeSuspend()

@ -12,7 +12,7 @@ local T = require("ffi/util").template
local DeviceListener = InputContainer:new{} local DeviceListener = InputContainer:new{}
local function _setSetting(name) local function _setSetting(name)
G_reader_settings:saveSetting(name, true) G_reader_settings:makeTrue(name)
end end
local function _unsetSetting(name) local function _unsetSetting(name)

@ -168,9 +168,8 @@ function Device:init()
self.screen.isBGRFrameBuffer = self.hasBGRFrameBuffer self.screen.isBGRFrameBuffer = self.hasBGRFrameBuffer
local low_pan_rate = G_reader_settings:readSetting("low_pan_rate") if G_reader_settings:has("low_pan_rate") then
if low_pan_rate ~= nil then self.screen.low_pan_rate = G_reader_settings:readSetting("low_pan_rate")
self.screen.low_pan_rate = low_pan_rate
else else
self.screen.low_pan_rate = self.hasEinkScreen() self.screen.low_pan_rate = self.hasEinkScreen()
end end
@ -226,6 +225,7 @@ end
-- Only used on platforms where we handle suspend ourselves. -- Only used on platforms where we handle suspend ourselves.
function Device:onPowerEvent(ev) function Device:onPowerEvent(ev)
local Screensaver = require("ui/screensaver")
if self.screen_saver_mode then if self.screen_saver_mode then
if ev == "Power" or ev == "Resume" then if ev == "Power" or ev == "Resume" then
if self.is_cover_closed then if self.is_cover_closed then
@ -247,7 +247,7 @@ function Device:onPowerEvent(ev)
if self.orig_rotation_mode then if self.orig_rotation_mode then
self.screen:setRotationMode(self.orig_rotation_mode) self.screen:setRotationMode(self.orig_rotation_mode)
end end
require("ui/screensaver"):close() Screensaver:close()
if self:needsScreenRefreshAfterResume() then if self:needsScreenRefreshAfterResume() then
UIManager:scheduleIn(1, function() self.screen:refreshFull() end) UIManager:scheduleIn(1, function() self.screen:refreshFull() end)
end end
@ -266,14 +266,14 @@ function Device:onPowerEvent(ev)
self.powerd:beforeSuspend() self.powerd:beforeSuspend()
local UIManager = require("ui/uimanager") local UIManager = require("ui/uimanager")
logger.dbg("Suspending...") 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... -- Mostly always suspend in Portrait/Inverted Portrait mode...
-- ... except when we just show an InfoMessage or when the screensaver -- ... 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). -- 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, -- We also exclude full-screen widgets that work fine in Landscape mode,
-- like ReadingProgress and BookStatus (c.f., #5724) -- like ReadingProgress and BookStatus (c.f., #5724)
local screensaver_type = G_reader_settings:readSetting("screensaver_type") if Screensaver:modeExpectsPortrait() then
if screensaver_type ~= "message" and screensaver_type ~= "disable" and
screensaver_type ~= "readingprogress" and screensaver_type ~= "bookstatus" then
self.orig_rotation_mode = self.screen:getRotationMode() self.orig_rotation_mode = self.screen:getRotationMode()
-- Leave Portrait & Inverted Portrait alone, that works just fine. -- Leave Portrait & Inverted Portrait alone, that works just fine.
if bit.band(self.orig_rotation_mode, 1) == 1 then 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, -- On eInk, if we're using a screensaver mode that shows an image,
-- flash the screen to white first, to eliminate ghosting. -- flash the screen to white first, to eliminate ghosting.
if self:hasEinkScreen() and if self:hasEinkScreen() and Screensaver:modeIsImage() then
screensaver_type == "cover" or screensaver_type == "random_image" or if Screensaver:withBackground() then
screensaver_type == "image_file" then
if not G_reader_settings:isTrue("screensaver_no_background") then
self.screen:clear() self.screen:clear()
end end
self.screen:refreshFull() self.screen:refreshFull()
@ -297,7 +295,7 @@ function Device:onPowerEvent(ev)
-- nil it, in case user switched ScreenSaver modes during our lifetime. -- nil it, in case user switched ScreenSaver modes during our lifetime.
self.orig_rotation_mode = nil self.orig_rotation_mode = nil
end end
require("ui/screensaver"):show() Screensaver:show()
-- NOTE: show() will return well before the refresh ioctl is even *sent*: -- 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. -- 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, -- 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 ;) -- NOTE: Meaning this is not a SO device ;)
local Screensaver = require("ui/screensaver") local Screensaver = require("ui/screensaver")
-- NOTE: Pilefered from Device:onPowerEvent @ frontend/device/generic/device.lua -- 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... -- Mostly always suspend in Portrait/Inverted Portrait mode...
-- ... except when we just show an InfoMessage or when the screensaver -- ... 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). -- 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, -- We also exclude full-screen widgets that work fine in Landscape mode,
-- like ReadingProgress and BookStatus (c.f., #5724) -- like ReadingProgress and BookStatus (c.f., #5724)
local screensaver_type = G_reader_settings:readSetting("screensaver_type") if Screensaver:modeExpectsPortrait() then
if screensaver_type ~= "message" and screensaver_type ~= "disable" and
screensaver_type ~= "readingprogress" and screensaver_type ~= "bookstatus" then
self.orig_rotation_mode = self.screen:getRotationMode() self.orig_rotation_mode = self.screen:getRotationMode()
-- Leave Portrait & Inverted Portrait alone, that works just fine. -- Leave Portrait & Inverted Portrait alone, that works just fine.
if bit.band(self.orig_rotation_mode, 1) == 1 then 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, -- On eInk, if we're using a screensaver mode that shows an image,
-- flash the screen to white first, to eliminate ghosting. -- flash the screen to white first, to eliminate ghosting.
if self:hasEinkScreen() and if self:hasEinkScreen() and Screensaver:modeIsImage() then
screensaver_type == "cover" or screensaver_type == "random_image" or if Screensaver:withBackground() then
screensaver_type == "image_file" then
if not G_reader_settings:isTrue("screensaver_no_background") then
self.screen:clear() self.screen:clear()
end end
self.screen:refreshFull() self.screen:refreshFull()

@ -340,17 +340,15 @@ function Kobo:init()
self.touchScreenProbe = function() self.touchScreenProbe = function()
-- if user has not set KOBO_TOUCH_MIRRORED yet -- if user has not set KOBO_TOUCH_MIRRORED yet
if KOBO_TOUCH_MIRRORED == nil then if KOBO_TOUCH_MIRRORED == nil then
local switch_xy = G_reader_settings:readSetting("kobo_touch_switch_xy")
-- and has no probe before -- 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 TouchProbe = require("tools/kobo_touch_probe")
local UIManager = require("ui/uimanager") local UIManager = require("ui/uimanager")
UIManager:show(TouchProbe:new{}) UIManager:show(TouchProbe:new{})
UIManager:run() UIManager:run()
-- assuming TouchProbe sets kobo_touch_switch_xy config -- assuming TouchProbe sets kobo_touch_switch_xy config
switch_xy = G_reader_settings:readSetting("kobo_touch_switch_xy")
end end
self.touch_switch_xy = switch_xy self.touch_switch_xy = G_reader_settings:readSetting("kobo_touch_switch_xy")
end end
self:initEventAdjustHooks() self:initEventAdjustHooks()
end end

@ -90,7 +90,7 @@ local Device = Generic:new{
external.when_back_callback = nil external.when_back_callback = nil
end end
end, end,
window = G_reader_settings:readSetting("sdl_window") or {}, window = G_reader_settings:readSetting("sdl_window", {}),
} }
local AppImage = Device:new{ local AppImage = Device:new{
@ -323,12 +323,6 @@ function Device:setDateTime(year, month, day, hour, min, sec)
end end
end end
function Device:exit()
G_reader_settings:saveSetting("sdl_window", self.window)
G_reader_settings:flush()
Generic.exit(self)
end
function Emulator:simulateSuspend() function Emulator:simulateSuspend()
local InfoMessage = require("ui/widget/infomessage") local InfoMessage = require("ui/widget/infomessage")
local UIManager = require("ui/uimanager") local UIManager = require("ui/uimanager")

@ -94,6 +94,7 @@ end
function SonyPRSTUX:intoScreenSaver() function SonyPRSTUX:intoScreenSaver()
local Screensaver = require("ui/screensaver") local Screensaver = require("ui/screensaver")
if self.screen_saver_mode == false then if self.screen_saver_mode == false then
Screensaver:setup()
Screensaver:show() Screensaver:show()
end end
self.powerd:beforeSuspend() self.powerd:beforeSuspend()

@ -165,19 +165,136 @@ function DocSettings:open(docfile)
return setmetatable(new, {__index = DocSettings}) return setmetatable(new, {__index = DocSettings})
end end
--- Reads a setting. --[[-- Reads a setting, optionally initializing it to a default.
function DocSettings:readSetting(key)
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] return self.data[key]
end end
--- Saves a setting. --- Saves a setting.
function DocSettings:saveSetting(key, value) function DocSettings:saveSetting(key, value)
self.data[key] = value self.data[key] = value
return self
end end
--- Deletes a setting. --- Deletes a setting.
function DocSettings:delSetting(key) function DocSettings:delSetting(key)
self.data[key] = nil 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 end
--- Serializes settings and writes them to `metadata.lua`. --- Serializes settings and writes them to `metadata.lua`.
@ -220,8 +337,7 @@ function DocSettings:flush()
f_out:close() f_out:close()
if self.candidates ~= nil if self.candidates ~= nil
and not G_reader_settings:readSetting( and G_reader_settings:nilOrFalse("preserve_legacy_docsetting") then
"preserve_legacy_docsetting") then
for _, k in pairs(self.candidates) do for _, k in pairs(self.candidates) do
if k[1] ~= f and k[1] ~= f .. ".old" then if k[1] ~= f and k[1] ~= f .. ".old" then
logger.dbg("Remove legacy file ", k[1]) logger.dbg("Remove legacy file ", k[1])

@ -228,16 +228,16 @@ function CreDocument:setupDefaultView()
self._document:adjustFontSizes(CanvasContext:getDPI()) self._document:adjustFontSizes(CanvasContext:getDPI())
-- set top status bar font size -- 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", self._document:setIntProperty("crengine.page.header.font.size",
G_reader_settings:readSetting("cre_header_status_font_size")) G_reader_settings:readSetting("cre_header_status_font_size"))
end end
-- One can set these to change from white background -- 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")) self:setBackgroundColor(G_reader_settings:readSetting("cre_background_color"))
end 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")) self:setBackgroundImage(G_reader_settings:readSetting("cre_background_image"))
end end
end end

@ -72,10 +72,7 @@ function DocumentRegistry:hasProvider(file, mimetype)
end end
local DocSettings = require("docsettings") local DocSettings = require("docsettings")
if DocSettings:hasSidecarFile(file) then if DocSettings:hasSidecarFile(file) then
local doc_settings_provider = DocSettings:open(file):readSetting("provider") return DocSettings:open(file):has("provider")
if doc_settings_provider then
return true
end
end end
return false return false
end end
@ -134,7 +131,8 @@ function DocumentRegistry:getProviders(file)
local added = false local added = false
local suffix = string.sub(file, -string.len(provider.extension) - 1) local suffix = string.sub(file, -string.len(provider.extension) - 1)
if string.lower(suffix) == "."..provider.extension then 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.provider == provider.provider then
if prov_prev.weight >= provider.weight then if prov_prev.weight >= provider.weight then
added = true added = true
@ -143,7 +141,7 @@ function DocumentRegistry:getProviders(file)
end end
end end
end end
-- if extension == provider.extension then -- if extension == provider.extension then
-- stick highest weighted provider at the front -- stick highest weighted provider at the front
if not added and #providers >= 1 and provider.weight > providers[1].weight then if not added and #providers >= 1 and provider.weight > providers[1].weight then
table.insert(providers, 1, provider) table.insert(providers, 1, provider)

@ -56,7 +56,7 @@ end
Settings:saveSetting("key", { Settings:saveSetting("key", {
a = "b", a = "b",
c = "true", c = true,
d = false, d = false,
}) })
@ -69,8 +69,29 @@ function LuaSettings:child(key)
return LuaSettings:wrap(self:readSetting(key)) return LuaSettings:wrap(self:readSetting(key))
end end
--- Reads a setting. --[[-- Reads a setting, optionally initializing it to a default.
function LuaSettings:readSetting(key)
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] return self.data[key]
end end
@ -88,22 +109,22 @@ end
--- Checks if setting exists. --- Checks if setting exists.
function LuaSettings:has(key) function LuaSettings:has(key)
return self:readSetting(key) ~= nil return self.data[key] ~= nil
end end
--- Checks if setting does not exist. --- Checks if setting does not exist.
function LuaSettings:hasNot(key) function LuaSettings:hasNot(key)
return self:readSetting(key) == nil return self.data[key] == nil
end end
--- Checks if setting is `true`. --- Checks if setting is `true` (boolean).
function LuaSettings:isTrue(key) function LuaSettings:isTrue(key)
return string.lower(tostring(self:readSetting(key))) == "true" return self.data[key] == true
end end
--- Checks if setting is `false`. --- Checks if setting is `false` (boolean).
function LuaSettings:isFalse(key) function LuaSettings:isFalse(key)
return string.lower(tostring(self:readSetting(key))) == "false" return self.data[key] == false
end end
--- Checks if setting is `nil` or `true`. --- Checks if setting is `nil` or `true`.
@ -116,7 +137,8 @@ function LuaSettings:nilOrFalse(key)
return self:hasNot(key) or self:isFalse(key) return self:hasNot(key) or self:isFalse(key)
end 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) function LuaSettings:flipNilOrTrue(key)
if self:nilOrTrue(key) then if self:nilOrTrue(key) then
self:saveSetting(key, false) self:saveSetting(key, false)
@ -126,7 +148,8 @@ function LuaSettings:flipNilOrTrue(key)
return self return self
end 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) function LuaSettings:flipNilOrFalse(key)
if self:nilOrFalse(key) then if self:nilOrFalse(key) then
self:saveSetting(key, true) self:saveSetting(key, true)
@ -136,7 +159,7 @@ function LuaSettings:flipNilOrFalse(key)
return self return self
end end
--- Flips setting to `true`. --- Flips a setting between `true` and `nil`.
function LuaSettings:flipTrue(key) function LuaSettings:flipTrue(key)
if self:isTrue(key) then if self:isTrue(key) then
self:delSetting(key) self:delSetting(key)
@ -146,7 +169,7 @@ function LuaSettings:flipTrue(key)
return self return self
end end
--- Flips setting to `false`. --- Flips a setting between `false` and `nil`.
function LuaSettings:flipFalse(key) function LuaSettings:flipFalse(key)
if self:isFalse(key) then if self:isFalse(key) then
self:delSetting(key) self:delSetting(key)
@ -156,6 +179,28 @@ function LuaSettings:flipFalse(key)
return self return self
end 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 -- Initializes settings per extension with default values
function LuaSettings:initializeExtSettings(key, defaults, force_init) function LuaSettings:initializeExtSettings(key, defaults, force_init)
local curr = self:readSetting(key) local curr = self:readSetting(key)

@ -195,7 +195,7 @@ function ReadHistory:getPreviousFile(current_file)
end end
function ReadHistory:fileDeleted(path) 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) self:removeItemByPath(path)
else else
-- Make it dimed -- Make it dimed
@ -210,7 +210,7 @@ function ReadHistory:fileDeleted(path)
end end
function ReadHistory:fileSettingsPurged(path) 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 -- Also remove it from history on purge when that setting is enabled
self:removeItemByPath(path) self:removeItemByPath(path)
end end

@ -25,8 +25,8 @@ function SettingsMigration:migrateSettings(config)
end end
-- Fine-grained CRe margins (#4945) -- Fine-grained CRe margins (#4945)
local old_margins = config:readSetting("copt_page_margins") if config:has("copt_page_margins") then
if old_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]) 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} -- Format was: {left, top, right, bottom}
config:saveSetting("copt_h_page_margins", {old_margins[1], old_margins[3]}) 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 -- Space condensing to Word spacing
-- From a single number (space condensing) to a table of 2 numbers ({space width scale, space condensing}). -- 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% -- 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") local space_condensing = config:readSetting("copt_space_condensing")
logger.info("Migrating old", cfg_class, "CRe space condensing:", space_condensing) logger.info("Migrating old", cfg_class, "CRe space condensing:", space_condensing)
config:saveSetting("copt_word_spacing", { 100, 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") return G_reader_settings:isTrue("ignore_power_sleepcover")
end, end,
callback = function() callback = function()
G_reader_settings:flipNilOrFalse("ignore_power_sleepcover") G_reader_settings:toggle("ignore_power_sleepcover")
G_reader_settings:flipFalse("ignore_open_sleepcover") G_reader_settings:makeFalse("ignore_open_sleepcover")
UIManager:show(InfoMessage:new{ UIManager:show(InfoMessage:new{
text = _("This will take effect on next restart."), text = _("This will take effect on next restart."),
}) })
@ -171,8 +171,8 @@ if Device:isKobo() then
return G_reader_settings:isTrue("ignore_open_sleepcover") return G_reader_settings:isTrue("ignore_open_sleepcover")
end, end,
callback = function() callback = function()
G_reader_settings:flipNilOrFalse("ignore_open_sleepcover") G_reader_settings:toggle("ignore_open_sleepcover")
G_reader_settings:flipFalse("ignore_power_sleepcover") G_reader_settings:makeFalse("ignore_power_sleepcover")
UIManager:show(InfoMessage:new{ UIManager:show(InfoMessage:new{
text = _("This will take effect on next restart."), text = _("This will take effect on next restart."),
}) })
@ -436,7 +436,7 @@ if Device:hasKeys() then
end end
-- Auto-save settings: default value, info text and warning, and menu items -- 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 -- Default to auto save every 15 mn
G_reader_settings:saveSetting("auto_save_settings_interval_minutes", 15) G_reader_settings:saveSetting("auto_save_settings_interval_minutes", 15)
end end
@ -593,8 +593,7 @@ common_settings.document = {
{ {
text = _("Open next file"), text = _("Open next file"),
enabled_func = function() enabled_func = function()
return G_reader_settings:readSetting("collate") return G_reader_settings:readSetting("collate") ~= "access"
~= "access"
end, end,
checked_func = function() checked_func = function()
return G_reader_settings:readSetting("end_document_action") == "next_file" return G_reader_settings:readSetting("end_document_action") == "next_file"

@ -3,10 +3,10 @@ local _ = require("gettext")
return { return {
text = _("Flash keyboard"), text = _("Flash keyboard"),
checked_func = function() checked_func = function()
return G_reader_settings:readSetting("flash_keyboard") ~= false return G_reader_settings:nilOrTrue("flash_keyboard")
end, end,
callback = function() 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) G_reader_settings:saveSetting("flash_keyboard", not disabled)
end, end,
} }

@ -5,10 +5,10 @@ local _ = require("gettext")
return { return {
text = _("Disable double tap"), text = _("Disable double tap"),
checked_func = function() checked_func = function()
return G_reader_settings:readSetting("disable_double_tap") ~= false return G_reader_settings:nilOrTrue("disable_double_tap")
end, end,
callback = function() 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) G_reader_settings:saveSetting("disable_double_tap", not disabled)
UIManager:show(InfoMessage:new{ UIManager:show(InfoMessage:new{
text = _("This will take effect on next restart."), text = _("This will take effect on next restart."),

@ -1,31 +1,22 @@
local Screensaver = require("ui/screensaver") local Screensaver = require("ui/screensaver")
local _ = require("gettext") local _ = require("gettext")
local function screensaverType() return G_reader_settings:readSetting("screensaver_type") end local function hasLastFile()
local function screensaverDelay() return G_reader_settings:readSetting("screensaver_delay") end if G_reader_settings:hasNot("lastfile") then
local function lastFile() return false
end
local lfs = require("libs/libkoreader-lfs") local lfs = require("libs/libkoreader-lfs")
local last_file = G_reader_settings:readSetting("lastfile") local last_file = G_reader_settings:readSetting("lastfile")
if last_file and lfs.attributes(last_file, "mode") == "file" then return last_file and lfs.attributes(last_file, "mode") == "file"
return last_file
end
end 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 { return {
{ {
text = _("Use last book's cover as screensaver"), text = _("Use last book's cover as screensaver"),
enabled_func = function() return lastFile() ~= nil end, enabled_func = hasLastFile,
checked_func = function() checked_func = function()
if screensaverType() == "cover" then return G_reader_settings:readSetting("screensaver_type") == "cover"
return true
else
return false
end
end, end,
callback = function() callback = function()
G_reader_settings:saveSetting("screensaver_type", "cover") G_reader_settings:saveSetting("screensaver_type", "cover")
@ -33,13 +24,9 @@ return {
}, },
{ {
text = _("Use book status as screensaver"), text = _("Use book status as screensaver"),
enabled_func = function() return lastFile() ~= nil end, enabled_func = hasLastFile,
checked_func = function() checked_func = function()
if screensaverType() == "bookstatus" then return G_reader_settings:readSetting("screensaver_type") == "bookstatus"
return true
else
return false
end
end, end,
callback = function() callback = function()
G_reader_settings:saveSetting("screensaver_type", "bookstatus") G_reader_settings:saveSetting("screensaver_type", "bookstatus")
@ -48,11 +35,7 @@ return {
{ {
text = _("Use random image from folder as screensaver"), text = _("Use random image from folder as screensaver"),
checked_func = function() checked_func = function()
if screensaverType() == "random_image" then return G_reader_settings:readSetting("screensaver_type") == "random_image"
return true
else
return false
end
end, end,
callback = function() callback = function()
G_reader_settings:saveSetting("screensaver_type", "random_image") G_reader_settings:saveSetting("screensaver_type", "random_image")
@ -61,11 +44,7 @@ return {
{ {
text = _("Use document cover as screensaver"), text = _("Use document cover as screensaver"),
checked_func = function() checked_func = function()
if screensaverType() == "document_cover" then return G_reader_settings:readSetting("screensaver_type") == "document_cover"
return true
else
return false
end
end, end,
callback = function() callback = function()
G_reader_settings:saveSetting("screensaver_type", "document_cover") G_reader_settings:saveSetting("screensaver_type", "document_cover")
@ -74,11 +53,7 @@ return {
{ {
text = _("Use image as screensaver"), text = _("Use image as screensaver"),
checked_func = function() checked_func = function()
if screensaverType() == "image_file" then return G_reader_settings:readSetting("screensaver_type") == "image_file"
return true
else
return false
end
end, end,
callback = function() callback = function()
G_reader_settings:saveSetting("screensaver_type", "image_file") G_reader_settings:saveSetting("screensaver_type", "image_file")
@ -86,13 +61,9 @@ return {
}, },
{ {
text = _("Use reading progress as screensaver"), 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() checked_func = function()
if screensaverType() == "readingprogress" then return G_reader_settings:readSetting("screensaver_type") == "readingprogress"
return true
else
return false
end
end, end,
callback = function() callback = function()
G_reader_settings:saveSetting("screensaver_type", "readingprogress") G_reader_settings:saveSetting("screensaver_type", "readingprogress")
@ -101,11 +72,7 @@ return {
{ {
text = _("Leave screen as it is"), text = _("Leave screen as it is"),
checked_func = function() checked_func = function()
if screensaverType() == "disable" then return G_reader_settings:readSetting("screensaver_type") == "disable" or G_reader_settings:hasNot("screensaver_type")
return true
else
return false
end
end, end,
callback = function() callback = function()
G_reader_settings:saveSetting("screensaver_type", "disable") G_reader_settings:saveSetting("screensaver_type", "disable")
@ -114,9 +81,11 @@ return {
}, },
{ {
text = _("Add message to screensaver"), 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() callback = function()
G_reader_settings:saveSetting("screensaver_show_message", not showMessage()) G_reader_settings:toggle("screensaver_show_message")
end, end,
separator = true, separator = true,
}, },
@ -151,27 +120,40 @@ return {
Screensaver:setMessage() Screensaver:setMessage()
end, 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"), text = _("White background behind message and images"),
checked_func = whiteBackground, checked_func = function()
return G_reader_settings:readSetting("screensaver_background") == "white"
end,
callback = function() callback = function()
G_reader_settings:saveSetting("screensaver_white_background", not whiteBackground()) G_reader_settings:saveSetting("screensaver_background", "white")
G_reader_settings:flipFalse("screensaver_no_background")
end, end,
}, },
{ {
text = _("Leave background as-is behind message and images"), 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() callback = function()
G_reader_settings:saveSetting("screensaver_no_background", not noBackground()) G_reader_settings:saveSetting("screensaver_background", "none")
G_reader_settings:flipFalse("screensaver_white_background")
end, end,
}, },
{ {
text = _("Stretch covers and images to fit screen"), 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() callback = function()
G_reader_settings:saveSetting("screensaver_stretch_images", not stretchImages()) G_reader_settings:toggle("screensaver_stretch_images")
end, end,
separator = true, separator = true,
}, },
@ -181,7 +163,7 @@ return {
{ {
text = _("Top"), text = _("Top"),
checked_func = function() checked_func = function()
return messagePosition() == "top" return G_reader_settings:readSetting("screensaver_message_position") == "top"
end, end,
callback = function() callback = function()
G_reader_settings:saveSetting("screensaver_message_position", "top") G_reader_settings:saveSetting("screensaver_message_position", "top")
@ -190,7 +172,7 @@ return {
{ {
text = _("Middle"), text = _("Middle"),
checked_func = function() 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, end,
callback = function() callback = function()
G_reader_settings:saveSetting("screensaver_message_position", "middle") G_reader_settings:saveSetting("screensaver_message_position", "middle")
@ -199,7 +181,7 @@ return {
{ {
text = _("Bottom"), text = _("Bottom"),
checked_func = function() checked_func = function()
return messagePosition() == "bottom" return G_reader_settings:readSetting("screensaver_message_position") == "bottom"
end, end,
callback = function() callback = function()
G_reader_settings:saveSetting("screensaver_message_position", "bottom") G_reader_settings:saveSetting("screensaver_message_position", "bottom")
@ -213,11 +195,7 @@ return {
{ {
text = _("Disable"), text = _("Disable"),
checked_func = function() checked_func = function()
if screensaverDelay() == nil or screensaverDelay() == "disable" then return G_reader_settings:readSetting("screensaver_delay") == "disable" or G_reader_settings:hasNot("screensaver_delay")
return true
else
return false
end
end, end,
callback = function() callback = function()
G_reader_settings:saveSetting("screensaver_delay", "disable") G_reader_settings:saveSetting("screensaver_delay", "disable")
@ -226,11 +204,7 @@ return {
{ {
text = _("For 1 second"), text = _("For 1 second"),
checked_func = function() checked_func = function()
if screensaverDelay() == "1" then return G_reader_settings:readSetting("screensaver_delay") == "1"
return true
else
return false
end
end, end,
callback = function() callback = function()
G_reader_settings:saveSetting("screensaver_delay", "1") G_reader_settings:saveSetting("screensaver_delay", "1")
@ -239,11 +213,7 @@ return {
{ {
text = _("For 3 seconds"), text = _("For 3 seconds"),
checked_func = function() checked_func = function()
if screensaverDelay() == "3" then return G_reader_settings:readSetting("screensaver_delay") == "3"
return true
else
return false
end
end, end,
callback = function() callback = function()
G_reader_settings:saveSetting("screensaver_delay", "3") G_reader_settings:saveSetting("screensaver_delay", "3")
@ -252,11 +222,7 @@ return {
{ {
text = _("For 5 seconds"), text = _("For 5 seconds"),
checked_func = function() checked_func = function()
if screensaverDelay() == "5" then return G_reader_settings:readSetting("screensaver_delay") == "5"
return true
else
return false
end
end, end,
callback = function() callback = function()
G_reader_settings:saveSetting("screensaver_delay", "5") G_reader_settings:saveSetting("screensaver_delay", "5")
@ -265,11 +231,7 @@ return {
{ {
text = _("Until a tap"), text = _("Until a tap"),
checked_func = function() checked_func = function()
if screensaverDelay() == "tap" then return G_reader_settings:readSetting("screensaver_delay") == "tap"
return true
else
return false
end
end, end,
callback = function() callback = function()
G_reader_settings:saveSetting("screensaver_delay", "tap") G_reader_settings:saveSetting("screensaver_delay", "tap")

@ -25,7 +25,7 @@ function NetworkMgr:connectivityCheck(iter, callback, widget)
if iter > 25 then if iter > 25 then
logger.info("Failed to restore Wi-Fi (after", iter, "iterations)!") logger.info("Failed to restore Wi-Fi (after", iter, "iterations)!")
self.wifi_was_on = false 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 we abort, murder Wi-Fi and the async script first...
if Device:hasWifiManager() and not Device:isEmulator() then if Device:hasWifiManager() and not Device:isEmulator() then
os.execute("pkill -TERM restore-wifi-async.sh 2>/dev/null") 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 if NetworkMgr:isWifiOn() and NetworkMgr:isConnected() then
self.wifi_was_on = true 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")) UIManager:broadcastEvent(Event:new("NetworkConnected"))
logger.info("Wi-Fi successfully restored (after", iter, "iterations)!") logger.info("Wi-Fi successfully restored (after", iter, "iterations)!")
@ -118,7 +118,7 @@ function NetworkMgr:promptWifiOn(complete_callback)
ok_text = _("Turn on"), ok_text = _("Turn on"),
ok_callback = function() ok_callback = function()
self.wifi_was_on = true self.wifi_was_on = true
G_reader_settings:saveSetting("wifi_was_on", true) G_reader_settings:makeTrue("wifi_was_on")
self:turnOnWifi(complete_callback) self:turnOnWifi(complete_callback)
end, end,
}) })
@ -130,7 +130,7 @@ function NetworkMgr:promptWifiOff(complete_callback)
ok_text = _("Turn off"), ok_text = _("Turn off"),
ok_callback = function() ok_callback = function()
self.wifi_was_on = false self.wifi_was_on = false
G_reader_settings:saveSetting("wifi_was_on", false) G_reader_settings:makeFalse("wifi_was_on")
self:turnOffWifi(complete_callback) self:turnOffWifi(complete_callback)
end, end,
}) })
@ -142,13 +142,13 @@ function NetworkMgr:promptWifi(complete_callback)
choice1_text = _("Turn Wi-Fi off"), choice1_text = _("Turn Wi-Fi off"),
choice1_callback = function() choice1_callback = function()
self.wifi_was_on = false self.wifi_was_on = false
G_reader_settings:saveSetting("wifi_was_on", false) G_reader_settings:makeFalse("wifi_was_on")
self:turnOffWifi(complete_callback) self:turnOffWifi(complete_callback)
end, end,
choice2_text = _("Connect"), choice2_text = _("Connect"),
choice2_callback = function() choice2_callback = function()
self.wifi_was_on = true self.wifi_was_on = true
G_reader_settings:saveSetting("wifi_was_on", true) G_reader_settings:makeTrue("wifi_was_on")
self:turnOnWifi(complete_callback) self:turnOnWifi(complete_callback)
end, end,
}) })
@ -268,9 +268,9 @@ function NetworkMgr:setHTTPProxy(proxy)
http.PROXY = proxy http.PROXY = proxy
if proxy then if proxy then
G_reader_settings:saveSetting("http_proxy", proxy) G_reader_settings:saveSetting("http_proxy", proxy)
G_reader_settings:saveSetting("http_proxy_enabled", true) G_reader_settings:makeTrue("http_proxy_enabled")
else else
G_reader_settings:saveSetting("http_proxy_enabled", false) G_reader_settings:makeFalse("http_proxy_enabled")
end end
end end
@ -376,7 +376,7 @@ function NetworkMgr:getWifiToggleMenuTable()
-- (It's called connect_callback there). -- (It's called connect_callback there).
-- This makes this branch somewhat hard to reach, which is why it gets a dedicated prompt below... -- This makes this branch somewhat hard to reach, which is why it gets a dedicated prompt below...
self.wifi_was_on = false 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. -- 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. -- 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) -- 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 Screen = Device.screen
local T = require("ffi/util").template local T = require("ffi/util").template
local screensaver_provider = { -- Migrate old settings from 2021.02 or older.
["jpg"] = true, if G_reader_settings:readSetting("screensaver_type", "disable") == "message" then
["jpeg"] = true, G_reader_settings:saveSetting("screensaver_type", "disable")
["png"] = true, G_reader_settings:makeTrue("screensaver_show_message")
["gif"] = true, end
["tif"] = true, if G_reader_settings:has("screensaver_no_background") then
["tiff"] = true, 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 if string.sub(dir, string.len(dir)) ~= "/" then
dir = dir .. "/" dir = dir .. "/"
end end
@ -46,7 +69,7 @@ local function getRandomImage(dir)
for entry in iter, dir_obj do for entry in iter, dir_obj do
if lfs.attributes(dir .. entry, "mode") == "file" then if lfs.attributes(dir .. entry, "mode") == "file" then
local extension = string.lower(string.match(entry, ".+%.([^.]+)") or "") local extension = string.lower(string.match(entry, ".+%.([^.]+)") or "")
if screensaver_provider[extension] then if self.screensaver_provider[extension] then
i = i + 1 i = i + 1
pics[i] = entry pics[i] = entry
end end
@ -61,6 +84,114 @@ local function getRandomImage(dir)
return dir .. pics[math.random(i)] return dir .. pics[math.random(i)]
end 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() function Screensaver:chooseFolder()
local buttons = {} local buttons = {}
table.insert(buttons, { table.insert(buttons, {
@ -90,9 +221,7 @@ function Screensaver:chooseFolder()
} }
}) })
local screensaver_dir = G_reader_settings:readSetting("screensaver_dir") local screensaver_dir = G_reader_settings:readSetting("screensaver_dir")
if screensaver_dir == nil then or DataStorage:getDataDir() .. "/screenshots/"
screensaver_dir = DataStorage:getDataDir() .. "/screenshots/"
end
self.choose_dialog = ButtonDialogTitle:new{ self.choose_dialog = ButtonDialogTitle:new{
title = T(_("Current screensaver image folder:\n%1"), BD.dirpath(screensaver_dir)), title = T(_("Current screensaver image folder:\n%1"), BD.dirpath(screensaver_dir)),
buttons = buttons buttons = buttons
@ -117,7 +246,7 @@ function Screensaver:chooseFile(document_cover)
local suffix = util.getFileNameSuffix(filename) local suffix = util.getFileNameSuffix(filename)
if document_cover and DocumentRegistry:hasProvider(filename) then if document_cover and DocumentRegistry:hasProvider(filename) then
return true return true
elseif screensaver_provider[suffix] then elseif self.screensaver_provider[suffix] then
return true return true
end end
end, end,
@ -152,10 +281,8 @@ function Screensaver:chooseFile(document_cover)
} }
}) })
local screensaver_image = G_reader_settings:readSetting("screensaver_image") 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") 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)) 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)) or T(_("Current screensaver image:\n%1"), BD.filepath(screensaver_image))
self.choose_dialog = ButtonDialogTitle:new{ self.choose_dialog = ButtonDialogTitle:new{
@ -165,38 +292,25 @@ function Screensaver:chooseFile(document_cover)
UIManager:show(self.choose_dialog) UIManager:show(self.choose_dialog)
end end
function Screensaver:stretchImages() function Screensaver:isExcluded()
return G_reader_settings:isTrue("screensaver_stretch_images") if G_reader_settings:hasNot("lastfile") then
end return false
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:excluded()
local lastfile = G_reader_settings:readSetting("lastfile") 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 if DocSettings:hasSidecarFile(lastfile) then
local doc_settings = DocSettings:open(lastfile) 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 end
return exclude_ss or false
end end
function Screensaver:setMessage() function Screensaver:setMessage()
local InputDialog = require("ui/widget/inputdialog") local InputDialog = require("ui/widget/inputdialog")
local screensaver_message = G_reader_settings:readSetting("screensaver_message") local screensaver_message = G_reader_settings:readSetting("screensaver_message")
if screensaver_message == nil then or self.default_screensaver_message
screensaver_message = default_screensaver_message
end
self.input_dialog = InputDialog:new{ self.input_dialog = InputDialog:new{
title = "Screensaver message", 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"), 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() self.input_dialog:onShowKeyboard()
end end
function Screensaver:show(event, fallback_message) -- When called after setup(), may not match the saved settings, because it accounts for fallbacks that might have kicked in.
-- These 2 (optional) parameters are to support poweroff and reboot actions function Screensaver:getMode()
-- on Kobo (see uimanager.lua) return self.screensaver_type
if self.left_msg then end
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
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 function Screensaver:modeIsImage()
show_message = true return self.screensaver_type == "cover"
end or self.screensaver_type == "random_image"
or self.screensaver_type == "image_file"
end
if screensaver_type == "message" then function Screensaver:withBackground()
-- obsolete screensaver_type: migrate to new show_message = true return self.screensaver_background ~= "none"
screensaver_type = "disable" end
G_reader_settings:saveSetting("screensaver_type", "disable")
G_reader_settings:saveSetting("screensaver_show_message", true)
end
-- messages can still be shown over "as-is" screensaver function Screensaver:setup(event, fallback_message)
if screensaver_type == "disable" and show_message == false then -- Handle user settings & defaults
return 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 end
if G_reader_settings:has("screensaver_type") then
local widget = nil self.screensaver_type = G_reader_settings:readSetting("screensaver_type")
local no_background = false else
local background = Blitbuffer.COLOR_BLACK self.screensaver_type = "disable"
if self:whiteBackground() then self.show_message = true
background = Blitbuffer.COLOR_WHITE end
elseif self:noBackground() then if G_reader_settings:has("screensaver_background") then
background = nil self.screensaver_background = G_reader_settings:readSetting("screensaver_background")
no_background = true else
self.screensaver_background = "black"
end end
-- "as-is" mode obviously requires not mangling the background ;). -- These 2 (optional) parameters are to support poweroff and reboot actions on Kobo (c.f., UIManager)
if screensaver_type == "disable" then self.prefix = event and event .. "_" or "" -- "", "poweroff_" or "reboot_"
-- NOTE: Ideally, "disable" mode should *honor* all the "background" options. self.fallback_message = fallback_message
-- Unfortunately, the no background option is much more recent than the "disable" mode, self.overlay_message = nil
-- and as such, the default assumes that in "disable" mode, the default background is nil instead of black. if G_reader_settings:has(self.prefix .. "screensaver_type") then
-- This implies that, for the same legacy reasons, we have to honor the *white* background setting here... self.screensaver_type = G_reader_settings:readSetting(self.prefix .. "screensaver_type")
-- (Which means that you can have no background, a white background, but *NOT* a black background in this mode :/). else
if not self:whiteBackground() then if event then
background = nil -- Display the provided fallback_message over the screensaver,
no_background = true -- so the user can distinguish between suspend (no overlay),
-- and reboot/poweroff (overlaid message).
self.overlay_message = self.fallback_message
end end
end end
local lastfile = G_reader_settings:readSetting("lastfile") -- Reset state
if screensaver_type == "document_cover" then 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. -- Set lastfile to the document of which we want to show the cover.
lastfile = G_reader_settings:readSetting("screensaver_document_cover") self.lastfile = G_reader_settings:readSetting("screensaver_document_cover")
screensaver_type = "cover" self.screensaver_type = "cover"
end end
if screensaver_type == "cover" then if self.screensaver_type == "cover" then
lastfile = lastfile ~= nil and lastfile or G_reader_settings:readSetting("lastfile") self.lastfile = self.lastfile ~= nil and self.lastfile or G_reader_settings:readSetting("lastfile")
local exclude = false -- consider it not excluded if there's no docsetting local excluded
if DocSettings:hasSidecarFile(lastfile) then if DocSettings:hasSidecarFile(self.lastfile) then
local doc_settings = DocSettings:open(lastfile) local doc_settings = DocSettings:open(self.lastfile)
exclude = doc_settings:readSetting("exclude_screensaver") excluded = doc_settings:isTrue("exclude_screensaver")
else
-- No DocSetting, not excluded
excluded = false
end end
if exclude ~= true then if not excluded then
if lastfile and lfs.attributes(lastfile, "mode") == "file" then if self.lastfile and lfs.attributes(self.lastfile, "mode") == "file" then
local doc = DocumentRegistry:openDocument(lastfile) local doc = DocumentRegistry:openDocument(self.lastfile)
if doc.loadDocument then -- CreDocument if doc.loadDocument then -- CreDocument
doc:loadDocument(false) -- load only metadata doc:loadDocument(false) -- load only metadata
end end
local image = doc:getCoverPageImage() self.image = doc:getCoverPageImage()
doc:close() doc:close()
if image ~= nil then if self.image == nil then
widget = ImageWidget:new{ self.screensaver_type = "random_image"
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"
end end
else else
screensaver_type = "random_image" self.screensaver_type = "random_image"
end end
else --fallback to random images if this book cover is excluded else
screensaver_type = "random_image" -- Fallback to random images if this book cover is excluded
self.screensaver_type = "random_image"
end end
end end
if screensaver_type == "bookstatus" then if self.screensaver_type == "bookstatus" then
if lastfile and lfs.attributes(lastfile, "mode") == "file" then if self.lastfile and lfs.attributes(self.lastfile, "mode") == "file" then
local doc = DocumentRegistry:openDocument(lastfile)
local doc_settings = DocSettings:open(lastfile)
local instance = require("apps/reader/readerui"):_getRunningInstance() local instance = require("apps/reader/readerui"):_getRunningInstance()
if instance ~= nil then if instance == nil then
widget = BookStatusWidget:new { self.screensaver_type = "disable"
thumbnail = doc:getCoverPageImage(), self.show_message = true
props = doc:getProps(),
document = doc,
settings = doc_settings,
view = instance.view,
readonly = true,
}
else
show_message = true
end end
doc:close()
else else
show_message = true self.screensaver_type = "disable"
self.show_message = true
end end
end end
if screensaver_type == "random_image" then if self.screensaver_type == "random_image" then
local screensaver_dir = G_reader_settings:readSetting(prefix.."screensaver_dir") local screensaver_dir = G_reader_settings:readSetting(self.prefix .. "screensaver_dir")
if screensaver_dir == nil and prefix ~= "" then or G_reader_settings:readSetting("screensaver_dir")
screensaver_dir = G_reader_settings:readSetting("screensaver_dir") self.image_file = self:_getRandomImage(screensaver_dir)
end if self.image_file == nil then
if screensaver_dir == nil then self.screensaver_type = "disable"
screensaver_dir = DataStorage:getDataDir() .. "/screenshots/" self.show_message = true
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,
}
end end
end end
if screensaver_type == "image_file" then if self.screensaver_type == "image_file" then
local screensaver_image = G_reader_settings:readSetting(prefix.."screensaver_image") self.image_file = G_reader_settings:readSetting(self.prefix .. "screensaver_image")
if screensaver_image == nil and prefix ~= "" then or G_reader_settings:readSetting("screensaver_image")
screensaver_image = G_reader_settings:readSetting("screensaver_image") if self.image_file == nil or lfs.attributes(self.image_file, "mode") ~= "file" then
end self.screensaver_type = "disable"
if screensaver_image == nil then self.show_message = true
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,
}
end end
end end
if screensaver_type == "readingprogress" then if self.screensaver_type == "readingprogress" then
if Screensaver.getReaderProgress ~= nil then -- This is implemented by the Statistics plugin
widget = Screensaver.getReaderProgress() if Screensaver.getReaderProgress == nil then
else self.screensaver_type = "disable"
show_message = true self.show_message = true
end end
end end
if show_message == true then -- Now that the fallbacks are in place, we know the *effective* screensaver mode.
local screensaver_message = G_reader_settings:readSetting(prefix.."screensaver_message") -- For non-image modes, make black (which is also the default) synonymous with none.
local message_pos = G_reader_settings:readSetting(prefix.."screensaver_message_position") -- The reasoning is that disable + show_message, which is our default and fallback,
if no_background and widget == nil then -- looks *terrible* with a black background, which is also our default and fallback ;).
covers_fullscreen = false 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 end
if screensaver_message == nil and prefix ~= "" then -- NOTE: Only attempt to expand if there are special characters in the message.
screensaver_message = G_reader_settings:readSetting("screensaver_message") if screensaver_message:find("%%") then
screensaver_message = expandSpecial(screensaver_message, self.fallback_message or self.default_screensaver_message)
end end
local fallback = fallback_message or default_screensaver_message local message_pos
if screensaver_message == nil then if G_reader_settings:has(self.prefix .. "screensaver_message_position") then
screensaver_message = fallback message_pos = G_reader_settings:readSetting(self.prefix .. "screensaver_message_position")
else else
-- NOTE: Only attempt to expand if there are special characters in the message. if G_reader_settings:has("screensaver_message_position") then
if screensaver_message:find("%%") then message_pos = G_reader_settings:readSetting("screensaver_message_position")
screensaver_message = self:expandSpecial(screensaver_message, fallback) else
message_pos = "middle"
end end
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 local message_widget
if message_pos == "middle" or message_pos == nil then if message_pos == "middle" then
message_widget = InfoMessage:new{ message_widget = InfoMessage:new{
text = screensaver_message, text = screensaver_message,
readonly = true, readonly = true,
@ -449,13 +605,13 @@ function Screensaver:show(event, fallback_message)
} }
end end
-- No overlay needed as we just displayed the message -- No overlay needed as we just displayed *a* message (not necessarily the event's, though).
overlay_message = nil 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 message_widget then
if widget then -- we have a screensaver widget if widget then -- We have a Screensaver widget
-- show message_widget on top of previously created widget -- Show message_widget on top of previously created widget
local screen_w, screen_h = Screen:getWidth(), Screen:getHeight() local screen_w, screen_h = Screen:getWidth(), Screen:getHeight()
widget = OverlapGroup:new{ widget = OverlapGroup:new{
dimen = { dimen = {
@ -466,158 +622,52 @@ function Screensaver:show(event, fallback_message)
message_widget, message_widget,
} }
else else
-- no prevously created widget so just show message widget -- No prevously created widget, so just show message widget
widget = message_widget widget = message_widget
end end
end end
end end
if overlay_message then if self.overlay_message then
widget = self:addOverlayMessage(widget, overlay_message) widget = addOverlayMessage(widget, self.overlay_message)
end end
if widget then if widget then
self.left_msg = ScreenSaverWidget:new{ self.screensaver_widget = ScreenSaverWidget:new{
widget = widget, widget = widget,
background = background, background = background,
covers_fullscreen = covers_fullscreen, covers_fullscreen = covers_fullscreen,
} }
self.left_msg.modal = true self.screensaver_widget.modal = true
-- Refresh whole screen for other types self.screensaver_widget.dithered = true
self.left_msg.dithered = true UIManager:show(self.screensaver_widget, "full")
UIManager:show(self.left_msg, "full")
end end
end end
function Screensaver:expandSpecial(message, fallback) function Screensaver:close()
-- Expand special character sequences in given message. if self.screensaver_widget == nil then
-- %p percentage read return
-- %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()
end 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 = G_reader_settings:readSetting("screensaver_delay")
local screensaver_delay_number = tonumber(screensaver_delay) local screensaver_delay_number = tonumber(screensaver_delay)
if screensaver_delay_number then if screensaver_delay_number then
UIManager:scheduleIn(screensaver_delay_number, function() UIManager:scheduleIn(screensaver_delay_number, function()
logger.dbg("close screensaver") logger.dbg("close screensaver")
if self.left_msg then if self.screensaver_widget then
UIManager:close(self.left_msg, "full") UIManager:close(self.screensaver_widget, "full")
self.left_msg = nil self.screensaver_widget = nil
end end
end) end)
elseif screensaver_delay == "disable" or screensaver_delay == nil then elseif screensaver_delay == "disable" or screensaver_delay == nil then
logger.dbg("close screensaver") logger.dbg("close screensaver")
if self.left_msg then if self.screensaver_widget then
UIManager:close(self.left_msg, "full") UIManager:close(self.screensaver_widget, "full")
self.left_msg = nil self.screensaver_widget = nil
end end
else else
logger.dbg("tap to exit from screensaver") logger.dbg("tap to exit from screensaver")
end end
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 return Screensaver

@ -201,7 +201,7 @@ function Translator:genSettingsMenu()
return T("%1 (%2)", lang_name, lang_key) return T("%1 (%2)", lang_name, lang_key)
end, end,
checked_func = function() 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) return lang_key == G_reader_settings:readSetting(setting_name)
else else
return lang_key == default_checked_item return lang_key == default_checked_item
@ -252,7 +252,7 @@ end
function Translator:getSourceLanguage() function Translator:getSourceLanguage()
if G_reader_settings:isFalse("translator_from_auto_detect") and 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") return G_reader_settings:readSetting("translator_from_language")
end end
return AUTODETECT_LANGUAGE -- "auto" return AUTODETECT_LANGUAGE -- "auto"

@ -61,7 +61,9 @@ function UIManager:init()
self._entered_poweroff_stage = true self._entered_poweroff_stage = true
Device.orig_rotation_mode = Device.screen:getRotationMode() Device.orig_rotation_mode = Device.screen:getRotationMode()
Screen:setRotationMode(Screen.ORIENTATION_PORTRAIT) 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 if Device:needsScreenRefreshAfterResume() then
Screen:refreshFull() Screen:refreshFull()
end end
@ -78,7 +80,9 @@ function UIManager:init()
self._entered_poweroff_stage = true self._entered_poweroff_stage = true
Device.orig_rotation_mode = Device.screen:getRotationMode() Device.orig_rotation_mode = Device.screen:getRotationMode()
Screen:setRotationMode(Screen.ORIENTATION_PORTRAIT) 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 if Device:needsScreenRefreshAfterResume() then
Screen:refreshFull() Screen:refreshFull()
end end
@ -137,12 +141,12 @@ function UIManager:init()
end end
end end
-- Sleep Cover handling -- 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 (:/). -- NOTE: The hardware event itself will wake the kernel up if it's in suspend (:/).
-- Let the unexpected wakeup guard handle that. -- Let the unexpected wakeup guard handle that.
self.event_handlers["SleepCoverClosed"] = nil self.event_handlers["SleepCoverClosed"] = nil
self.event_handlers["SleepCoverOpened"] = 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, -- Just ignore wakeup events, and do NOT set is_cover_closed,
-- so device/generic/device will let us use the power button to wake ;). -- so device/generic/device will let us use the power button to wake ;).
self.event_handlers["SleepCoverClosed"] = function() 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 local padding_button = Size.padding.button -- padding for underline below letters and icons
--- @todo Restore setting when there are more advanced settings. --- @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 local show_advanced = true
-- Get the width needed by the longest option name shown on the left -- Get the width needed by the longest option name shown on the left

@ -342,9 +342,9 @@ function DictQuickLookup:init()
dir = last_file:match("(.*)/") dir = last_file:match("(.*)/")
end end
end end
if not dir then dir = G_reader_settings:readSetting("wikipedia_save_dir") end if not dir then dir = G_reader_settings:readSetting("wikipedia_save_dir")
if not dir then dir = G_reader_settings:readSetting("home_dir") end or G_reader_settings:readSetting("home_dir")
if not dir then dir = require("apps/filemanager/filemanagerutil").getDefaultDir() end or require("apps/filemanager/filemanagerutil").getDefaultDir() end
if not dir or not util.pathExists(dir) then if not dir or not util.pathExists(dir) then
UIManager:show(InfoMessage:new{ UIManager:show(InfoMessage:new{
text = _("No directory to save article to could be found."), text = _("No directory to save article to could be found."),

@ -25,10 +25,47 @@ local FileChooser = Menu:extend{
show_path = true, show_path = true,
parent = nil, parent = nil,
show_hidden = 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", collate = "strcoll", -- or collate = "access",
reverse_collate = false, 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, goto_letter = true,
} }
@ -39,13 +76,20 @@ local unreadable_dir_content = {}
function FileChooser:init() function FileChooser:init()
self.width = Screen:getWidth() self.width = Screen:getWidth()
-- common dir filter -- Standard dir exclusion list
self.dir_filter = function(dirname) self.show_dir = function(dirname)
for _, pattern in ipairs(self.exclude_dirs) do for _, pattern in ipairs(self.exclude_dirs) do
if dirname:match(pattern) then return false end if dirname:match(pattern) then return false end
end end
return true return true
end 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) self.list = function(path, dirs, files, count_only)
-- lfs.dir directory without permission will give error -- lfs.dir directory without permission will give error
local ok, iter, dir_obj = pcall(lfs.dir, path) local ok, iter, dir_obj = pcall(lfs.dir, path)
@ -53,17 +97,19 @@ function FileChooser:init()
unreadable_dir_content[path] = nil unreadable_dir_content[path] = nil
for f in iter, dir_obj do for f in iter, dir_obj do
if count_only then if count_only then
if self.dir_filter(f) and ((not self.show_hidden 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, "._"))) or (self.show_hidden and f ~= "." and f ~= ".." and not util.stringStartsWith(f, "._")))
and self.show_dir(f)
and self.show_file(f)
then then
table.insert(dirs, true) table.insert(dirs, true)
end 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 filename = path.."/"..f
local attributes = lfs.attributes(filename) local attributes = lfs.attributes(filename)
if attributes ~= nil then if attributes ~= nil then
if attributes.mode == "directory" and f ~= "." and f ~= ".." 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, table.insert(dirs, {name = f,
suffix = getFileNameSuffix(f), suffix = getFileNameSuffix(f),
fullpath = filename, fullpath = filename,
@ -71,22 +117,24 @@ function FileChooser:init()
end end
-- Always ignore macOS resource forks. -- Always ignore macOS resource forks.
elseif attributes.mode == "file" and not util.stringStartsWith(f, "._") then 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 if self.show_file(f) then
local percent_finished = 0 if self.file_filter == nil or self.file_filter(filename) or self.show_unsupported then
if self.collate == "percent_unopened_first" or self.collate == "percent_unopened_last" then local percent_finished = 0
if DocSettings:hasSidecarFile(filename) then if self.collate == "percent_unopened_first" or self.collate == "percent_unopened_last" then
local docinfo = DocSettings:open(filename) if DocSettings:hasSidecarFile(filename) then
percent_finished = docinfo.data.percent_finished local docinfo = DocSettings:open(filename)
if percent_finished == nil then percent_finished = docinfo.data.percent_finished
percent_finished = 0 if percent_finished == nil then
percent_finished = 0
end
end end
end end
table.insert(files, {name = f,
suffix = getFileNameSuffix(f),
fullpath = filename,
attr = attributes,
percent_finished = percent_finished })
end end
table.insert(files, {name = f,
suffix = getFileNameSuffix(f),
fullpath = filename,
attr = attributes,
percent_finished = percent_finished })
end end
end end
end end

@ -37,7 +37,7 @@ function PathChooser:init()
self.title = _("Long-press to select") self.title = _("Long-press to select")
end end
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 if not self.show_files then
self.file_filter = function() return false end -- filter out regular files self.file_filter = function() return false end -- filter out regular files
end end

@ -218,7 +218,7 @@ function VirtualKey:init()
(self.keyboard.umlautmode_keys[self.label] ~= nil and self.keyboard.umlautmode) then (self.keyboard.umlautmode_keys[self.label] ~= nil and self.keyboard.umlautmode) then
self[1].background = Blitbuffer.COLOR_LIGHT_GRAY self[1].background = Blitbuffer.COLOR_LIGHT_GRAY
end end
self.flash_keyboard = G_reader_settings:readSetting("flash_keyboard") ~= false self.flash_keyboard = G_reader_settings:nilOrTrue("flash_keyboard")
end end
function VirtualKey:genkeyboardLayoutKeyChars() function VirtualKey:genkeyboardLayoutKeyChars()

@ -373,6 +373,44 @@ function util.arrayAppend(t1, t2)
end end
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 --- Reverse array elements in-place in table t
---- @param t Lua table ---- @param t Lua table
function util.arrayReverse(t) function util.arrayReverse(t)
@ -389,7 +427,7 @@ end
--- and if so, return the index. --- and if so, return the index.
---- @param t Lua table ---- @param t Lua table
---- @param v ---- @param v
---- @function callback(v1, v2) ---- @func callback(v1, v2)
function util.arrayContains(t, v, cb) function util.arrayContains(t, v, cb)
cb = cb or function(v1, v2) return v1 == v2 end cb = cb or function(v1, v2) return v1 == v2 end
for _k, _v in ipairs(t) do for _k, _v in ipairs(t) do
@ -654,7 +692,7 @@ end
--- Recursively scan directory for files inside --- Recursively scan directory for files inside
-- @string path -- @string path
-- @function callback(fullpath, name, attr) -- @func callback(fullpath, name, attr)
function util.findFiles(dir, cb) function util.findFiles(dir, cb)
local function scan(current) local function scan(current)
local ok, iter, dir_obj = pcall(lfs.dir, current) local ok, iter, dir_obj = pcall(lfs.dir, current)

@ -9,8 +9,6 @@ if not Device:isCervantes() and
return { disabled = true, } return { disabled = true, }
end end
local DataStorage = require("datastorage")
local LuaSettings = require("luasettings")
local PluginShare = require("pluginshare") local PluginShare = require("pluginshare")
local UIManager = require("ui/uimanager") local UIManager = require("ui/uimanager")
local WidgetContainer = require("ui/widget/container/widgetcontainer") local WidgetContainer = require("ui/widget/container/widgetcontainer")
@ -19,39 +17,19 @@ local _ = require("gettext")
local T = require("ffi/util").template local T = require("ffi/util").template
local default_autoshutdown_timeout_seconds = 3*24*60*60 local default_autoshutdown_timeout_seconds = 3*24*60*60
local default_auto_suspend_timeout_seconds = 60*60
local AutoSuspend = WidgetContainer:new{ local AutoSuspend = WidgetContainer:new{
name = "autosuspend", name = "autosuspend",
is_doc_only = false, is_doc_only = false,
autoshutdown_timeout_seconds = G_reader_settings:readSetting("autoshutdown_timeout_seconds") or default_autoshutdown_timeout_seconds, 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(), last_action_sec = os.time(),
standby_prevented = false, 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() function AutoSuspend:_enabled()
return self.auto_suspend_sec > 0 return self.auto_suspend_timeout_seconds > 0
end end
function AutoSuspend:_enabledShutdown() function AutoSuspend:_enabledShutdown()
@ -67,11 +45,11 @@ function AutoSuspend:_schedule()
local delay_suspend, delay_shutdown local delay_suspend, delay_shutdown
if PluginShare.pause_auto_suspend or Device.standby_prevented or Device.powerd:isCharging() then 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 delay_shutdown = self.autoshutdown_timeout_seconds
else else
local now_ts = os.time() 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 delay_shutdown = self.last_action_sec + self.autoshutdown_timeout_seconds - now_ts
end end
@ -111,7 +89,6 @@ end
function AutoSuspend:init() function AutoSuspend:init()
if Device:isPocketBook() and not Device:canSuspend() then return end if Device:isPocketBook() and not Device:canSuspend() then return end
UIManager.event_hook:registerWidget("InputEvent", self) UIManager.event_hook:registerWidget("InputEvent", self)
self.auto_suspend_sec = self:_readTimeoutSec()
self:_unschedule() self:_unschedule()
self:_start() self:_start()
-- self.ui is nil in the testsuite -- self.ui is nil in the testsuite
@ -158,22 +135,20 @@ function AutoSuspend:addToMainMenu(menu_items)
local InfoMessage = require("ui/widget/infomessage") local InfoMessage = require("ui/widget/infomessage")
local Screen = Device.screen local Screen = Device.screen
local SpinWidget = require("ui/widget/spinwidget") 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 { local autosuspend_spin = SpinWidget:new {
width = math.floor(Screen:getWidth() * 0.6), width = math.floor(Screen:getWidth() * 0.6),
value = curr_items / 60, value = self.auto_suspend_timeout_seconds / 60,
value_min = 5, value_min = 5,
value_max = 240, value_max = 240,
value_hold_step = 15, value_hold_step = 15,
ok_text = _("Set timeout"), ok_text = _("Set timeout"),
title_text = _("Timeout in minutes"), title_text = _("Timeout in minutes"),
callback = function(autosuspend_spin) callback = function(autosuspend_spin)
local autosuspend_timeout_seconds = autosuspend_spin.value * 60 self.auto_suspend_timeout_seconds = autosuspend_spin.value * 60
self.auto_suspend_sec = autosuspend_timeout_seconds G_reader_settings:saveSetting("auto_suspend_timeout_seconds", self.auto_suspend_timeout_seconds)
G_reader_settings:saveSetting("auto_suspend_timeout_seconds", autosuspend_timeout_seconds)
UIManager:show(InfoMessage:new{ UIManager:show(InfoMessage:new{
text = T(_("The system will automatically suspend after %1 minutes of inactivity."), 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, timeout = 3,
}) })
self:_unschedule() self:_unschedule()
@ -191,10 +166,9 @@ function AutoSuspend:addToMainMenu(menu_items)
local InfoMessage = require("ui/widget/infomessage") local InfoMessage = require("ui/widget/infomessage")
local Screen = Device.screen local Screen = Device.screen
local SpinWidget = require("ui/widget/spinwidget") local SpinWidget = require("ui/widget/spinwidget")
local curr_items = self.autoshutdown_timeout_seconds
local autosuspend_spin = SpinWidget:new { local autosuspend_spin = SpinWidget:new {
width = math.floor(Screen:getWidth() * 0.6), 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. -- About a minute, good for testing and battery life fanatics.
-- Just high enough to avoid an instant shutdown death scenario. -- Just high enough to avoid an instant shutdown death scenario.
value_min = 0.017, value_min = 0.017,
@ -206,12 +180,11 @@ function AutoSuspend:addToMainMenu(menu_items)
ok_text = _("Set timeout"), ok_text = _("Set timeout"),
title_text = _("Timeout in hours"), title_text = _("Timeout in hours"),
callback = function(autosuspend_spin) callback = function(autosuspend_spin)
local autoshutdown_timeout_seconds = math.floor(autosuspend_spin.value * 60*60) self.autoshutdown_timeout_seconds = math.floor(autosuspend_spin.value * 60 * 60)
self.autoshutdown_timeout_seconds = autoshutdown_timeout_seconds G_reader_settings:saveSetting("autoshutdown_timeout_seconds", self.autoshutdown_timeout_seconds)
G_reader_settings:saveSetting("autoshutdown_timeout_seconds", autoshutdown_timeout_seconds)
UIManager:show(InfoMessage:new{ UIManager:show(InfoMessage:new{
text = T(_("The system will automatically shut down after %1 hours of inactivity."), 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, timeout = 3,
}) })
self:_unschedule() self:_unschedule()

@ -132,7 +132,7 @@ function AutoTurn:addToMainMenu(menu_items)
title_text = _("Timeout in seconds"), title_text = _("Timeout in seconds"),
cancel_callback = function() cancel_callback = function()
self.enabled = false self.enabled = false
G_reader_settings:flipFalse("autoturn_enabled") G_reader_settings:makeFalse("autoturn_enabled")
self:_deprecateLastTask() self:_deprecateLastTask()
menu:updateItems() menu:updateItems()
end, end,
@ -140,7 +140,7 @@ function AutoTurn:addToMainMenu(menu_items)
self.autoturn_sec = autoturn_spin.value self.autoturn_sec = autoturn_spin.value
G_reader_settings:saveSetting("autoturn_timeout_seconds", autoturn_spin.value) G_reader_settings:saveSetting("autoturn_timeout_seconds", autoturn_spin.value)
self.enabled = true self.enabled = true
G_reader_settings:flipTrue("autoturn_enabled") G_reader_settings:makeTrue("autoturn_enabled")
self:_deprecateLastTask() self:_deprecateLastTask()
self:_start() self:_start()
menu:updateItems() menu:updateItems()

@ -133,10 +133,10 @@ function Calibre:getSearchMenuTable()
text = path, text = path,
keep_menu_open = true, keep_menu_open = true,
checked_func = function() checked_func = function()
return cache:readSetting(path) return cache:isTrue(path)
end, end,
callback = function() callback = function()
cache:saveSetting(path, not cache:readSetting(path)) cache:toggle(path)
cache:flush() cache:flush()
CalibreSearch:invalidateCache() CalibreSearch:invalidateCache()
end, end,
@ -165,8 +165,7 @@ function Calibre:getSearchMenuTable()
return G_reader_settings:isTrue("calibre_search_from_reader") return G_reader_settings:isTrue("calibre_search_from_reader")
end, end,
callback = function() callback = function()
local current = G_reader_settings:isTrue("calibre_search_from_reader") G_reader_settings:toggle("calibre_search_from_reader")
G_reader_settings:saveSetting("calibre_search_from_reader", not current)
UIManager:show(InfoMessage:new{ UIManager:show(InfoMessage:new{
text = _("This will take effect on next restart."), text = _("This will take effect on next restart."),
}) })

@ -49,7 +49,7 @@ local function findCalibreFiles(dir)
local function existOrLast(file) local function existOrLast(file)
local fullname local fullname
local options = { file, "." .. file } local options = { file, "." .. file }
for _, option in pairs(options) do for _, option in ipairs(options) do
fullname = dir .. "/" .. option fullname = dir .. "/" .. option
if util.fileExists(fullname) then if util.fileExists(fullname) then
return true, fullname return true, fullname
@ -144,11 +144,10 @@ end
-- remove a book from our books table -- remove a book from our books table
function CalibreMetadata:removeBook(lpath) function CalibreMetadata:removeBook(lpath)
for index, book in ipairs(self.books) do local function drop_lpath(t, i, j)
if book.lpath == lpath then return t[i].lpath ~= lpath
table.remove(self.books, index)
end
end end
util.arrayRemove(self.books, drop_lpath)
end end
-- gets the uuid and index of a book from its path -- gets the uuid and index of a book from its path
@ -165,7 +164,7 @@ end
function CalibreMetadata:getBookId(index) function CalibreMetadata:getBookId(index)
local book = {} local book = {}
book.priKey = index 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] book[key] = self.books[index][key]
end end
return book return book

@ -297,7 +297,7 @@ end
-- find books, series or tags -- find books, series or tags
function CalibreSearch:find(option) 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) self[opt] = G_reader_settings:nilOrTrue("calibre_search_"..opt)
end end

@ -26,7 +26,7 @@ require("ffi/zeromq_h")
local extensions = require("extensions") local extensions = require("extensions")
local function getExtensionPathLengths() local function getExtensionPathLengths()
local t = {} local t = {}
for _, v in pairs(extensions) do for _, v in ipairs(extensions) do
-- magic number from calibre, see -- magic number from calibre, see
-- https://github.com/koreader/koreader/pull/6177#discussion_r430753964 -- https://github.com/koreader/koreader/pull/6177#discussion_r430753964
t[v] = 37 t[v] = 37

@ -66,7 +66,7 @@ function CoverBrowser:init()
BookInfoManager:saveSetting("filemanager_display_mode", "list_image_meta") BookInfoManager:saveSetting("filemanager_display_mode", "list_image_meta")
BookInfoManager:saveSetting("history_display_mode", "mosaic_image") BookInfoManager:saveSetting("history_display_mode", "mosaic_image")
end end
G_reader_settings:saveSetting("coverbrowser_initial_default_setup_done", true) G_reader_settings:makeTrue("coverbrowser_initial_default_setup_done")
end end
self:setupFileManagerDisplayMode(BookInfoManager:getSetting("filemanager_display_mode")) self:setupFileManagerDisplayMode(BookInfoManager:getSetting("filemanager_display_mode"))

@ -81,7 +81,7 @@ function CoverImage:cleanUpImage()
end end
function CoverImage:createCoverImage(doc_settings) 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() local cover_image = self.ui.document:getCoverPageImage()
if cover_image then if cover_image then
local s_w, s_h = Device.screen:getWidth(), Device.screen:getHeight() 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"), text = _("Exclude this book cover"),
checked_func = function() 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, end,
callback = function() callback = function()
if self.ui.doc_settings:readSetting("exclude_cover_image") == true then if self.ui.doc_settings:isTrue("exclude_cover_image") then
self.ui.doc_settings:saveSetting("exclude_cover_image", false) self.ui.doc_settings:makeFalse("exclude_cover_image")
self:createCoverImage(self.ui.doc_settings) self:createCoverImage(self.ui.doc_settings)
else else
self.ui.doc_settings:saveSetting("exclude_cover_image", true) self.ui.doc_settings:makeTrue("exclude_cover_image")
self:cleanUpImage() self:cleanUpImage()
end end
self.ui:saveSettings() self.ui:saveSettings()

@ -118,8 +118,8 @@ function Gestures:init()
if not lfs.attributes(gestures_path, "mode") then if not lfs.attributes(gestures_path, "mode") then
FFIUtil.copyFile(defaults_path, gestures_path) FFIUtil.copyFile(defaults_path, gestures_path)
end end
self.ignore_hold_corners = G_reader_settings:readSetting("ignore_hold_corners") self.ignore_hold_corners = G_reader_settings:isTrue("ignore_hold_corners")
self.multiswipes_enabled = G_reader_settings:readSetting("multiswipes_enabled") self.multiswipes_enabled = G_reader_settings:isTrue("multiswipes_enabled")
self.is_docless = self.ui == nil or self.ui.document == nil self.is_docless = self.ui == nil or self.ui.document == nil
self.ges_mode = self.is_docless and "gesture_fm" or "gesture_reader" self.ges_mode = self.is_docless and "gesture_fm" or "gesture_reader"
self.defaults = LuaSettings:open(defaults_path).data[self.ges_mode] self.defaults = LuaSettings:open(defaults_path).data[self.ges_mode]
@ -682,7 +682,7 @@ function Gestures:addToMainMenu(menu_items)
text = _("Turn on multiswipes"), text = _("Turn on multiswipes"),
checked_func = function() return self.multiswipes_enabled end, checked_func = function() return self.multiswipes_enabled end,
callback = function() 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") self.multiswipes_enabled = G_reader_settings:isTrue("multiswipes_enabled")
end, end,
help_text = multiswipes_info_text, 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, text = _("You have just performed your first multiswipe gesture.") .."\n\n".. multiswipes_info_text,
ok_text = _("Turn on"), ok_text = _("Turn on"),
ok_callback = function() ok_callback = function()
G_reader_settings:saveSetting("multiswipes_enabled", true) G_reader_settings:makeTrue("multiswipes_enabled")
self.multiswipes_enabled = true self.multiswipes_enabled = true
end, end,
cancel_text = _("Turn off"), cancel_text = _("Turn off"),
cancel_callback = function() cancel_callback = function()
G_reader_settings:saveSetting("multiswipes_enabled", false) G_reader_settings:makeFalse("multiswipes_enabled")
self.multiswipes_enabled = false self.multiswipes_enabled = false
end, end,
}) })

@ -193,7 +193,7 @@ function Migration:migrateGestures(caller)
end end
end end
caller.settings_data:flush() caller.settings_data:flush()
G_reader_settings:saveSetting("gestures_migrated", true) G_reader_settings:makeTrue("gestures_migrated")
end end
return Migration return Migration

@ -15,7 +15,7 @@ local random = require("random")
local T = require("ffi/util").template local T = require("ffi/util").template
local _ = require("gettext") 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()) G_reader_settings:saveSetting("device_id", random.uuid())
end end
@ -104,6 +104,7 @@ function KOSync:onDispatcherRegisterActions()
end end
function KOSync:onReaderReady() function KOSync:onReaderReady()
--- @todo: Viable candidate for a port to the new readSetting API
local settings = G_reader_settings:readSetting("kosync") or {} local settings = G_reader_settings:readSetting("kosync") or {}
self.kosync_custom_server = settings.custom_server self.kosync_custom_server = settings.custom_server
self.kosync_username = settings.username self.kosync_username = settings.username

@ -97,12 +97,10 @@ function NewsDownloader:addToMainMenu(menu_items)
text = _("Never download images"), text = _("Never download images"),
keep_menu_open = true, keep_menu_open = true,
checked_func = function() checked_func = function()
return news_downloader_settings:readSetting("never_download_images") return news_downloader_settings:isTrue("never_download_images")
end, end,
callback = function() callback = function()
local never_download_images = news_downloader_settings:readSetting("never_download_images") or false news_downloader_settings:toggle("never_download_images")
logger.info("NewsDownloader: previous never_download_images: ", never_download_images)
news_downloader_settings:saveSetting("never_download_images", not never_download_images)
news_downloader_settings:flush() news_downloader_settings:flush()
end, end,
}, },
@ -176,11 +174,11 @@ function NewsDownloader:loadConfigAndProcessFeeds()
return return
end 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 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 for idx, feed in ipairs(feed_config) do
local url = feed[1] local url = feed[1]
local limit = feed.limit local limit = feed.limit

@ -36,8 +36,34 @@ local CatalogCache = Cache:new{
} }
local OPDSBrowser = Menu:extend{ 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_name = _("Local calibre library"),
calibre_opds = G_reader_settings:readSetting("calibre_opds", {}),
catalog_type = "application/atom%+xml", catalog_type = "application/atom%+xml",
search_type = "application/opensearchdescription%+xml", search_type = "application/opensearchdescription%+xml",
@ -53,38 +79,13 @@ local OPDSBrowser = Menu:extend{
} }
function OPDSBrowser:init() function OPDSBrowser:init()
local servers = G_reader_settings:readSetting("opds_servers") -- Update deprecated URLs
if not servers then -- If there are no saved servers, add some defaults for _, server in ipairs(self.opds_servers) do
servers = { if server.url == "http://bookserver.archive.org/catalog/" then
{ server.url = "https://bookserver.archive.org"
title = "Project Gutenberg", end
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"
end end
self.item_table = self:genItemTableFromRoot() self.item_table = self:genItemTableFromRoot()
self.catalog_title = nil self.catalog_title = nil
Menu.init(self) -- call parent's init() Menu.init(self) -- call parent's init()
@ -92,7 +93,6 @@ end
function OPDSBrowser:addServerFromInput(fields) function OPDSBrowser:addServerFromInput(fields)
logger.info("New OPDS catalog input:", fields) logger.info("New OPDS catalog input:", fields)
local servers = G_reader_settings:readSetting("opds_servers") or {}
local new_server = { local new_server = {
title = fields[1], title = fields[1],
url = (fields[2]:match("^%a+://") and fields[2] or "http://" .. fields[2]), url = (fields[2]:match("^%a+://") and fields[2] or "http://" .. fields[2]),
@ -101,31 +101,28 @@ function OPDSBrowser:addServerFromInput(fields)
-- Allow empty passwords -- Allow empty passwords
password = fields[4], password = fields[4],
} }
table.insert(servers, new_server) table.insert(self.opds_servers, new_server)
G_reader_settings:saveSetting("opds_servers", servers)
self:init() self:init()
end end
function OPDSBrowser:editCalibreFromInput(fields) function OPDSBrowser:editCalibreFromInput(fields)
logger.dbg("Edit calibre server input:", fields) logger.dbg("Edit calibre server input:", fields)
local calibre = G_reader_settings:readSetting("calibre_opds") or {}
if fields[1] then if fields[1] then
calibre.host = fields[1] self.calibre_opds.host = fields[1]
end end
if tonumber(fields[2]) then if tonumber(fields[2]) then
calibre.port = fields[2] self.calibre_opds.port = fields[2]
end end
if fields[3] and fields[3] ~= "" then if fields[3] and fields[3] ~= "" then
calibre.username = fields[3] self.calibre_opds.username = fields[3]
else else
calibre.username = nil self.calibre_opds.username = nil
end end
if fields[4] then if fields[4] then
calibre.password = fields[4] self.calibre_opds.password = fields[4]
else else
calibre.password = nil self.calibre_opds.password = nil
end end
G_reader_settings:saveSetting("calibre_opds", calibre)
self:init() self:init()
end end
@ -178,25 +175,24 @@ function OPDSBrowser:addNewCatalog()
end end
function OPDSBrowser:editCalibreServer() function OPDSBrowser:editCalibreServer()
local calibre = G_reader_settings:readSetting("calibre_opds") or {}
self.add_server_dialog = MultiInputDialog:new{ self.add_server_dialog = MultiInputDialog:new{
title = _("Edit local calibre host and port"), title = _("Edit local calibre host and port"),
fields = { fields = {
{ {
--- @todo get IP address of current device --- @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"), 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"), hint = _("calibre port"),
}, },
{ {
text = calibre.username or "", text = self.calibre_opds.username or "",
hint = _("Username (optional)"), hint = _("Username (optional)"),
}, },
{ {
text = calibre.password or "", text = self.calibre_opds.password or "",
hint = _("Password (optional)"), hint = _("Password (optional)"),
text_type = "password", text_type = "password",
}, },
@ -229,8 +225,7 @@ end
function OPDSBrowser:genItemTableFromRoot() function OPDSBrowser:genItemTableFromRoot()
local item_table = {} local item_table = {}
local added_servers = G_reader_settings:readSetting("opds_servers") or {} for _, server in ipairs(self.opds_servers) do
for _, server in ipairs(added_servers) do
table.insert(item_table, { table.insert(item_table, {
text = server.title, text = server.title,
content = server.subtitle, content = server.subtitle,
@ -242,8 +237,7 @@ function OPDSBrowser:genItemTableFromRoot()
searchable = server.searchable, searchable = server.searchable,
}) })
end end
local calibre_opds = G_reader_settings:readSetting("calibre_opds") or {} if not self.calibre_opds.host or not self.calibre_opds.port then
if not calibre_opds.host or not calibre_opds.port then
table.insert(item_table, { table.insert(item_table, {
text = self.calibre_name, text = self.calibre_name,
callback = function() callback = function()
@ -255,9 +249,9 @@ function OPDSBrowser:genItemTableFromRoot()
table.insert(item_table, { table.insert(item_table, {
text = self.calibre_name, text = self.calibre_name,
url = string.format("http://%s:%d/opds", url = string.format("http://%s:%d/opds",
calibre_opds.host, calibre_opds.port), self.calibre_opds.host, self.calibre_opds.port),
username = calibre_opds.username, username = self.calibre_opds.username,
password = calibre_opds.password, password = self.calibre_opds.password,
editable = true, editable = true,
deletable = false, deletable = false,
searchable = false, searchable = false,
@ -772,8 +766,7 @@ end
function OPDSBrowser:editServerFromInput(item, fields) function OPDSBrowser:editServerFromInput(item, fields)
logger.info("Edit OPDS catalog input:", fields) logger.info("Edit OPDS catalog input:", fields)
local servers = {} for _, server in ipairs(self.opds_servers) do
for _, server in ipairs(G_reader_settings:readSetting("opds_servers") or {}) do
if server.title == item.text or server.url == item.url then if server.title == item.text or server.url == item.url then
server.title = fields[1] server.title = fields[1]
server.url = (fields[2]:match("^%a+://") and fields[2] or "http://" .. fields[2]) 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.username = fields[3] ~= "" and fields[3] or nil
server.password = fields[4] server.password = fields[4]
end end
table.insert(servers, server)
end end
G_reader_settings:saveSetting("opds_servers", servers)
self:init() self:init()
end end
@ -838,13 +829,12 @@ end
function OPDSBrowser:deleteOPDSServer(item) function OPDSBrowser:deleteOPDSServer(item)
logger.info("Delete OPDS server:", item) logger.info("Delete OPDS server:", item)
local servers = {} for i = #self.opds_servers, 1, -1 do
for _, server in ipairs(G_reader_settings:readSetting("opds_servers") or {}) do local server = self.opds_servers[i]
if server.title ~= item.text or server.url ~= item.url then if server.title == item.text and server.url == item.url then
table.insert(servers, server) table.remove(self.opds_servers, i)
end end
end end
G_reader_settings:saveSetting("opds_servers", servers)
self:init() self:init()
end end

@ -30,7 +30,7 @@ local PerceptionExpander = Widget:extend{
function PerceptionExpander:init() function PerceptionExpander:init()
if not self.settings then self:readSettingsFile() end 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 if not self.is_enabled then
return return
end end

@ -35,7 +35,7 @@ local DEFAULT_CALENDAR_NB_BOOK_SPANS = 3
local DB_SCHEMA_VERSION = 20201022 local DB_SCHEMA_VERSION = 20201022
-- This is the query used to compute the total time spent reading distinct pages of the book, -- 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 -- c.f., comments in insertDB
local STATISTICS_SQL_BOOK_CAPPED_TOTALS_QUERY = [[ local STATISTICS_SQL_BOOK_CAPPED_TOTALS_QUERY = [[
SELECT count(*), SELECT count(*),
@ -137,22 +137,15 @@ function ReaderStatistics:init()
end end
self.start_current_period = os.time() self.start_current_period = os.time()
self:resetVolatileStats() self:resetVolatileStats()
local settings = G_reader_settings:readSetting("statistics") or {} self.settings = G_reader_settings:readSetting("statistics", {})
self.page_min_read_sec = tonumber(settings.min_sec) self.settings.is_enabled = not (self.settings.is_enabled == false)
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.ui.menu:registerToMainMenu(self) self.ui.menu:registerToMainMenu(self)
self:checkInitDatabase() self:checkInitDatabase()
BookStatusWidget.getStats = function() 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 end
ReaderFooter.getAvgTimePerPage = function() ReaderFooter.getAvgTimePerPage = function()
if self.is_enabled then if self.settings.is_enabled then
return self.avg_time return self.avg_time
end end
end end
@ -177,7 +170,7 @@ function ReaderStatistics:init()
end end
function ReaderStatistics:initData() function ReaderStatistics:initData()
if self:isDocless() or not self.is_enabled then if self:isDocless() or not self.settings.is_enabled then
return return
end end
-- first execution -- first execution
@ -206,7 +199,7 @@ function ReaderStatistics:initData()
self.avg_time = self.book_read_time / self.book_read_pages self.avg_time = self.book_read_time / self.book_read_pages
else else
-- NOTE: Possibly less weird-looking than initializing this to 0? -- 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) logger.dbg("ReaderStatistics: Initializing average time per page at 50% of the max value, i.e.,", self.avg_time)
end end
end end
@ -276,7 +269,7 @@ end
function ReaderStatistics:checkInitDatabase() function ReaderStatistics:checkInitDatabase()
local conn = SQ3.open(db_location) 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 if not conn:exec("PRAGMA table_info('book');") then
UIManager:show(ConfirmBox:new{ UIManager:show(ConfirmBox:new{
text = T(_([[ text = T(_([[
@ -352,7 +345,7 @@ Do you want to create an empty database?
conn = SQ3.open(db_location) conn = SQ3.open(db_location)
end end
else -- Migrate stats for books in history from metadata.lua to sqlite database 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 if not conn:exec("PRAGMA table_info('book');") then
local filename_first_history, quickstart_filename, __ local filename_first_history, quickstart_filename, __
if #ReadHistory.hist == 1 then if #ReadHistory.hist == 1 then
@ -379,7 +372,6 @@ Please wait…
self:createDB(conn) self:createDB(conn)
end end
end end
self:saveSettings()
end end
conn:close() conn:close()
end end
@ -593,8 +585,8 @@ function ReaderStatistics:addBookStatToDB(book_stats, conn)
conn:exec('BEGIN;') conn:exec('BEGIN;')
stmt = conn:prepare("INSERT OR IGNORE INTO page_stat VALUES(?, ?, ?, ?);") stmt = conn:prepare("INSERT OR IGNORE INTO page_stat VALUES(?, ?, ?, ?);")
local avg_time = math.ceil(book_stats.total_time_in_sec / read_pages) local avg_time = math.ceil(book_stats.total_time_in_sec / read_pages)
if avg_time > self.page_max_read_sec then if avg_time > self.settings.max_sec then
avg_time = self.page_max_read_sec avg_time = self.settings.max_sec
end end
local first_read_page = book_stats.performance_in_pages[sorted_performance[1]] local first_read_page = book_stats.performance_in_pages[sorted_performance[1]]
if first_read_page > 1 then if first_read_page > 1 then
@ -606,10 +598,10 @@ function ReaderStatistics:addBookStatToDB(book_stats, conn)
for i=2, #sorted_performance do for i=2, #sorted_performance do
start_open_page = sorted_performance[i-1] start_open_page = sorted_performance[i-1]
local diff_time = sorted_performance[i] - 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]], stmt:reset():bind(id_book, book_stats.performance_in_pages[sorted_performance[i-1]],
start_open_page, diff_time):step() 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]], stmt:reset():bind(id_book, book_stats.performance_in_pages[sorted_performance[i-1]],
start_open_page, avg_time):step() start_open_page, avg_time):step()
end end
@ -640,7 +632,7 @@ function ReaderStatistics:migrateToDB(conn)
local nr_of_conv_books = 0 local nr_of_conv_books = 0
local exclude_titles = {} local exclude_titles = {}
for _, v in pairs(ReadHistory.hist) do 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 if book_stats and book_stats.title == "" then
book_stats.title = v.file:match("^.+/(.+)$") book_stats.title = v.file:match("^.+/(.+)$")
end 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. -- 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, -- 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 ;). -- 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)... -- 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)) 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 end
local conn = SQ3.open(db_location) local conn = SQ3.open(db_location)
-- NOTE: Similarly, this one is used for time-based estimates and averages, so, use the capped variant -- 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() conn:close()
if total_pages then if total_pages then
@ -838,23 +830,22 @@ end
function ReaderStatistics:getStatisticEnabledMenuItem() function ReaderStatistics:getStatisticEnabledMenuItem()
return { return {
text = _("Enabled"), text = _("Enabled"),
checked_func = function() return self.is_enabled end, checked_func = function() return self.settings.is_enabled end,
callback = function() callback = function()
-- if was enabled, have to save data to file -- 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:insertDB(self.id_curr_book)
self.ui.doc_settings:saveSetting("stats", self.data) self.ui.doc_settings:saveSetting("stats", self.data)
end 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 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:initData()
self.start_current_period = os.time() self.start_current_period = os.time()
self.curr_page = self.ui:getCurrentPage() self.curr_page = self.ui:getCurrentPage()
self:resetVolatileStats(self.start_current_period) self:resetVolatileStats(self.start_current_period)
end end
self:saveSettings()
if not self:isDocless() then if not self:isDocless() then
self.view.footer:onUpdateFooter() self.view.footer:onUpdateFooter()
end end
@ -873,21 +864,21 @@ function ReaderStatistics:addToMainMenu(menu_items)
{ {
text_func = function() text_func = function()
return T(_("Read page duration limits: %1 s / %2 s"), 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, end,
callback = function(touchmenu_instance) callback = function(touchmenu_instance)
local DoubleSpinWidget = require("/ui/widget/doublespinwidget") local DoubleSpinWidget = require("/ui/widget/doublespinwidget")
local durations_widget local durations_widget
durations_widget = DoubleSpinWidget:new{ durations_widget = DoubleSpinWidget:new{
left_text = _("Min"), left_text = _("Min"),
left_value = self.page_min_read_sec, left_value = self.settings.min_sec,
left_default = DEFAULT_MIN_READ_SEC, left_default = DEFAULT_MIN_READ_SEC,
left_min = 3, left_min = 3,
left_max = 120, left_max = 120,
left_step = 1, left_step = 1,
left_hold_step = 10, left_hold_step = 10,
right_text = _("Max"), right_text = _("Max"),
right_value = self.page_max_read_sec, right_value = self.settings.max_sec,
right_default = DEFAULT_MAX_READ_SEC, right_default = DEFAULT_MAX_READ_SEC,
right_min = 10, right_min = 10,
right_max = 7200, 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 if min > max then
min, max = max, min min, max = max, min
end end
self.page_min_read_sec = min self.settings.min_sec = min
self.page_max_read_sec = max self.settings.max_sec = max
self:saveSettings()
UIManager:close(durations_widget) UIManager:close(durations_widget)
touchmenu_instance:updateItems() touchmenu_instance:updateItems()
end, 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() text_func = function()
return T(_("Calendar weeks start on %1"), 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, end,
sub_item_table = { sub_item_table = {
{ -- Friday (Bangladesh and Maldives) { -- Friday (Bangladesh and Maldives)
text = longDayOfWeekTranslation[weekDays[6]], text = longDayOfWeekTranslation[weekDays[6]],
checked_func = function() return self.calendar_start_day_of_week == 6 end, checked_func = function() return self.settings.calendar_start_day_of_week == 6 end,
callback = function() self.calendar_start_day_of_week = 6 end callback = function() self.settings.calendar_start_day_of_week = 6 end
}, },
{ -- Saturday (some Middle East countries) { -- Saturday (some Middle East countries)
text = longDayOfWeekTranslation[weekDays[7]], text = longDayOfWeekTranslation[weekDays[7]],
checked_func = function() return self.calendar_start_day_of_week == 7 end, checked_func = function() return self.settings.calendar_start_day_of_week == 7 end,
callback = function() self.calendar_start_day_of_week = 7 end callback = function() self.settings.calendar_start_day_of_week = 7 end
}, },
{ -- Sunday { -- Sunday
text = longDayOfWeekTranslation[weekDays[1]], text = longDayOfWeekTranslation[weekDays[1]],
checked_func = function() return self.calendar_start_day_of_week == 1 end, checked_func = function() return self.settings.calendar_start_day_of_week == 1 end,
callback = function() self.calendar_start_day_of_week = 1 end callback = function() self.settings.calendar_start_day_of_week = 1 end
}, },
{ -- Monday { -- Monday
text = longDayOfWeekTranslation[weekDays[2]], text = longDayOfWeekTranslation[weekDays[2]],
checked_func = function() return self.calendar_start_day_of_week == 2 end, checked_func = function() return self.settings.calendar_start_day_of_week == 2 end,
callback = function() self.calendar_start_day_of_week = 2 end callback = function() self.settings.calendar_start_day_of_week = 2 end
}, },
}, },
}, },
{ {
text_func = function() 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, end,
callback = function(touchmenu_instance) callback = function(touchmenu_instance)
local SpinWidget = require("ui/widget/spinwidget") local SpinWidget = require("ui/widget/spinwidget")
UIManager:show(SpinWidget:new{ UIManager:show(SpinWidget:new{
width = math.floor(Screen:getWidth() * 0.6), width = math.floor(Screen:getWidth() * 0.6),
value = self.calendar_nb_book_spans, value = self.settings.calendar_nb_book_spans,
value_min = 1, value_min = 1,
value_max = 5, value_max = 5,
ok_text = _("Set"), ok_text = _("Set"),
title_text = _("Books per calendar day"), title_text = _("Books per calendar day"),
info_text = _("Set the max number of book spans to show for a day"), info_text = _("Set the max number of book spans to show for a day"),
callback = function(spin) callback = function(spin)
self.calendar_nb_book_spans = spin.value self.settings.calendar_nb_book_spans = spin.value
touchmenu_instance:updateItems() touchmenu_instance:updateItems()
end, end,
extra_text = _("Use default"), extra_text = _("Use default"),
extra_callback = function() 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() touchmenu_instance:updateItems()
end 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"), 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() callback = function()
self.calendar_show_histogram = not self.calendar_show_histogram self.settings.calendar_show_histogram = not self.settings.calendar_show_histogram
end, end,
}, },
{ {
text = _("Allow browsing coming months"), 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() 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, 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), kv_pairs = self:getCurrentStat(self.id_curr_book),
}) })
end, 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"), text = _("Reading progress"),
@ -1307,7 +1297,7 @@ function ReaderStatistics:getCurrentStat(id_book)
-- Current book statistics -- Current book statistics
-- Includes re-reads -- Includes re-reads
{ _("Total time spent on this book"), util.secondsToClock(total_time_book, false) }, { _("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) }, { _("Time spent reading this book"), util.secondsToClock(book_read_time, false) },
-- per days -- per days
{ _("Reading started"), os.date("%Y-%m-%d (%H:%M)", tonumber(first_open))}, { _("Reading started"), os.date("%Y-%m-%d (%H:%M)", tonumber(first_open))},
@ -1922,7 +1912,7 @@ function ReaderStatistics:genResetBookSubItemTable()
callback = function() callback = function()
self:resetCurrentBook() self:resetCurrentBook()
end, 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, separator = true,
}) })
table.insert(sub_item_table, { table.insert(sub_item_table, {
@ -2052,7 +2042,7 @@ function ReaderStatistics:resetCurrentBook()
-- We also need to reset the time/page/avg tracking -- We also need to reset the time/page/avg tracking
self.book_read_pages = 0 self.book_read_pages = 0
self.book_read_time = 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) logger.dbg("ReaderStatistics: Initializing average time per page at 50% of the max value, i.e.,", self.avg_time)
-- And the current volatile stats -- And the current volatile stats
@ -2143,7 +2133,7 @@ function ReaderStatistics:onPosUpdate(pos, pageno)
end end
function ReaderStatistics:onPageUpdate(pageno) function ReaderStatistics:onPageUpdate(pageno)
if self:isDocless() or not self.is_enabled then if self:isDocless() or not self.settings.is_enabled then
return return
end 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. -- 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 -- Compute the difference between now and the previous page's last timestamp
local diff_time = now_ts - then_ts 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 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 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 if #page_data == 1 and curr_duration == 0 then
@ -2182,13 +2172,13 @@ function ReaderStatistics:onPageUpdate(pageno)
end end
-- Update the tuple with the computed duration -- Update the tuple with the computed duration
data_tuple[2] = curr_duration + diff_time data_tuple[2] = curr_duration + diff_time
elseif diff_time > self.page_max_read_sec then elseif diff_time > self.settings.max_sec then
self.mem_read_time = self.mem_read_time + self.page_max_read_sec self.mem_read_time = self.mem_read_time + self.settings.max_sec
if #page_data == 1 and curr_duration == 0 then if #page_data == 1 and curr_duration == 0 then
self.mem_read_pages = self.mem_read_pages + 1 self.mem_read_pages = self.mem_read_pages + 1
end end
-- Update the tuple with the computed duration -- 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 end
-- We want a flush to db every 50 page turns -- We want a flush to db every 50 page turns
@ -2238,20 +2228,20 @@ function ReaderStatistics:importFromFile(base_path, item)
end end
function ReaderStatistics:onCloseDocument() 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.ui.doc_settings:saveSetting("stats", self.data)
self:insertDB(self.id_curr_book) self:insertDB(self.id_curr_book)
end end
end end
function ReaderStatistics:onAddHighlight() function ReaderStatistics:onAddHighlight()
if self.is_enabled then if self.settings.is_enabled then
self.data.highlights = self.data.highlights + 1 self.data.highlights = self.data.highlights + 1
end end
end end
function ReaderStatistics:onDelHighlight() function ReaderStatistics:onDelHighlight()
if self.is_enabled then if self.settings.is_enabled then
if self.data.highlights > 0 then if self.data.highlights > 0 then
self.data.highlights = self.data.highlights - 1 self.data.highlights = self.data.highlights - 1
end end
@ -2259,14 +2249,13 @@ function ReaderStatistics:onDelHighlight()
end end
function ReaderStatistics:onAddNote() function ReaderStatistics:onAddNote()
if self.is_enabled then if self.settings.is_enabled then
self.data.notes = self.data.notes + 1 self.data.notes = self.data.notes + 1
end end
end end
-- Triggered by auto_save_settings_interval_minutes -- Triggered by auto_save_settings_interval_minutes
function ReaderStatistics:onSaveSettings() function ReaderStatistics:onSaveSettings()
self:saveSettings()
if not self:isDocless() then if not self:isDocless() then
self.ui.doc_settings:saveSetting("stats", self.data) self.ui.doc_settings:saveSetting("stats", self.data)
self:insertDB(self.id_curr_book) self:insertDB(self.id_curr_book)
@ -2287,20 +2276,6 @@ function ReaderStatistics:onResume()
self:resetVolatileStats(self.start_current_period) self:resetVolatileStats(self.start_current_period)
end 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) function ReaderStatistics:onReadSettings(config)
self.data = config.data.stats or {} self.data = config.data.stats or {}
end end
@ -2319,10 +2294,10 @@ function ReaderStatistics:getCalendarView()
monthTranslation = monthTranslation, monthTranslation = monthTranslation,
shortDayOfWeekTranslation = shortDayOfWeekTranslation, shortDayOfWeekTranslation = shortDayOfWeekTranslation,
longDayOfWeekTranslation = longDayOfWeekTranslation, longDayOfWeekTranslation = longDayOfWeekTranslation,
start_day_of_week = self.calendar_start_day_of_week, start_day_of_week = self.settings.calendar_start_day_of_week,
nb_book_spans = self.calendar_nb_book_spans, nb_book_spans = self.settings.calendar_nb_book_spans,
show_hourly_histogram = self.calendar_show_histogram, show_hourly_histogram = self.settings.calendar_show_histogram,
browse_future_months = self.calendar_browse_future_months, browse_future_months = self.settings.calendar_browse_future_months,
} }
end end
@ -2433,7 +2408,7 @@ function ReaderStatistics:onShowReaderProgress()
end end
function ReaderStatistics:onShowBookStats() 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{ local stats = KeyValuePage:new{
title = _("Current statistics"), title = _("Current statistics"),
kv_pairs = self:getCurrentStat(self.id_curr_book), kv_pairs = self:getCurrentStat(self.id_curr_book),

@ -38,11 +38,10 @@ end
function Terminal:init() function Terminal:init()
self:onDispatcherRegisterActions() self:onDispatcherRegisterActions()
self.ui.menu:registerToMainMenu(self) self.ui.menu:registerToMainMenu(self)
self.shortcuts = self.settings:readSetting("shortcuts") or {} self.shortcuts = self.settings:readSetting("shortcuts", {})
end end
function Terminal:saveShortcuts() function Terminal:saveShortcuts()
self.settings:saveSetting("shortcuts", self.shortcuts)
self.settings:flush() self.settings:flush()
UIManager:show(InfoMessage:new{ UIManager:show(InfoMessage:new{
text = _("Shortcuts saved"), text = _("Shortcuts saved"),
@ -294,13 +293,12 @@ function Terminal:editName(item)
end end
function Terminal:deleteShortcut(item) function Terminal:deleteShortcut(item)
local shortcuts = {} for i = #self.shortcuts, 1, -1 do
for _, element in ipairs(self.shortcuts) do local element = self.shortcuts[i]
if element.text ~= item.text and element.commands ~= item.commands then if element.text == item.text and element.commands == item.commands then
table.insert(shortcuts, element) table.remove(self.shortcuts, i)
end end
end end
self.shortcuts = shortcuts
self:saveShortcuts() self:saveShortcuts()
self:manageShortcuts() self:manageShortcuts()
end end

@ -45,6 +45,7 @@ function TextEditor:loadSettings()
return return
end end
self.settings = LuaSettings:open(self.settings_file) self.settings = LuaSettings:open(self.settings_file)
-- NOTE: addToHistory assigns a new object
self.history = self.settings:readSetting("history") or {} self.history = self.settings:readSetting("history") or {}
self.last_view_pos = self.settings:readSetting("last_view_pos") 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()) 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 -- Allow users to set their prefered font manually in text_editor.lua
-- (sadly, not via TextEditor itself, as they would be overriden on close) -- (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") self.normal_font = self.settings:readSetting("normal_font")
end end
if self.settings:readSetting("monospace_font") then if self.settings:has("monospace_font") then
self.monospace_font = self.settings:readSetting("monospace_font") self.monospace_font = self.settings:readSetting("monospace_font")
end end
self.auto_para_direction = self.settings:nilOrTrue("auto_para_direction") self.auto_para_direction = self.settings:nilOrTrue("auto_para_direction")
@ -254,7 +255,7 @@ function TextEditor:execWhenDoneFunc()
end end
function TextEditor:removeFromHistory(file_path) 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 if self.history[i] == file_path then
table.remove(self.history, i) table.remove(self.history, i)
end end

@ -233,7 +233,7 @@ function ZSync:subscribe()
self.received = {} self.received = {}
local zsync = self local zsync = self
require("ui/downloadmgr"):new{ require("ui/downloadmgr"):new{
show_hidden = G_reader_settings:readSetting("show_hidden"), show_hidden = G_reader_settings:isTrue("show_hidden"),
onConfirm = function(inbox) onConfirm = function(inbox)
G_reader_settings:saveSetting("inbox_dir", inbox) G_reader_settings:saveSetting("inbox_dir", inbox)
zsync:onChooseInbox(inbox) zsync:onChooseInbox(inbox)

@ -212,7 +212,7 @@ local UIManager = require("ui/uimanager")
-- and we are not (yet?) able to guess that fact) -- and we are not (yet?) able to guess that fact)
if Device:hasColorScreen() and not G_reader_settings:has("color_rendering") then if Device:hasColorScreen() and not G_reader_settings:has("color_rendering") then
-- enable it to prevent further display of this message -- 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") local InfoMessage = require("ui/widget/infomessage")
UIManager:show(InfoMessage:new{ 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."), 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 Device.input.waitEvent = function() end
require("luasettings"): require("luasettings"):
open(require("datastorage"):getSettingsDir() .. "/autofrontlight.lua"): open(require("datastorage"):getSettingsDir() .. "/autofrontlight.lua"):
saveSetting("enable", "true"): saveSetting("enable", true):
close() close()
UIManager = require("ui/uimanager") UIManager = require("ui/uimanager")

@ -45,7 +45,7 @@ describe("luadata module", function()
Settings:saveSetting("key", { Settings:saveSetting("key", {
a = "b", a = "b",
c = "true", c = "True",
d = false, d = false,
}) })
@ -55,7 +55,7 @@ describe("luadata module", function()
assert.True(child:has("a")) assert.True(child:has("a"))
assert.are.equal(child:readSetting("a"), "b") assert.are.equal(child:readSetting("a"), "b")
assert.True(child:has("c")) 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:has("d"))
assert.True(child:isFalse("d")) assert.True(child:isFalse("d"))
assert.False(child:isTrue("e")) assert.False(child:isTrue("e"))

@ -45,7 +45,7 @@ describe("luasettings module", function()
Settings:saveSetting("key", { Settings:saveSetting("key", {
a = "b", a = "b",
c = "true", c = "True",
d = false, d = false,
}) })
@ -55,7 +55,7 @@ describe("luasettings module", function()
assert.True(child:has("a")) assert.True(child:has("a"))
assert.are.equal(child:readSetting("a"), "b") assert.are.equal(child:readSetting("a"), "b")
assert.True(child:has("c")) 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:has("d"))
assert.True(child:isFalse("d")) assert.True(child:isFalse("d"))
assert.False(child:isTrue("e")) 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", it("should automatically remove deleted items from history if setting has been set",
function() function()
G_reader_settings:saveSetting("autoremove_deleted_items_from_history", "true") G_reader_settings:saveSetting("autoremove_deleted_items_from_history", true)
testAutoRemoveDeletedItems() testAutoRemoveDeletedItems()
G_reader_settings:delSetting("autoremove_deleted_items_from_history") G_reader_settings:delSetting("autoremove_deleted_items_from_history")
end) 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", it("should not automatically remove deleted items from history if setting has been set to false",
function() function()
G_reader_settings:saveSetting("autoremove_deleted_items_from_history", "false") G_reader_settings:saveSetting("autoremove_deleted_items_from_history", false)
testDoNotAutoRemoveDeletedItems() testDoNotAutoRemoveDeletedItems()
G_reader_settings:delSetting("autoremove_deleted_items_from_history") G_reader_settings:delSetting("autoremove_deleted_items_from_history")
end) end)

Loading…
Cancel
Save