2
0
mirror of https://github.com/koreader/koreader synced 2024-11-10 01:10:34 +00:00
koreader/frontend/apps/filemanager/filemanagersetdefaults.lua
chrox 34ea9ac574 add datastorage module to handle data directory on various platform
On kindle, kobo and pocketbook the data directory is the current
running directory but on Android the app is installed in system
defined location and users may have no access to that location.
The same circumstances should be true for the upcoming Koreader for
Ubuntu touch, so the data directory (in which tessdata, dictionaries,
global settings, persistant defaults and probably history data are
stored) could be stored in another place.
2015-06-15 16:56:27 +08:00

372 lines
15 KiB
Lua

local InfoMessage = require("ui/widget/infomessage")
local InputContainer = require("ui/widget/container/inputcontainer")
local InputDialog = require("ui/widget/inputdialog")
local MultiInputDialog = require("ui/widget/multiinputdialog")
local ConfirmBox = require("ui/widget/confirmbox")
local CenterContainer = require("ui/widget/container/centercontainer")
local DataStorage = require("datastorage")
local UIManager = require("ui/uimanager")
local Screen = require("device").screen
local Menu = require("ui/widget/menu")
local Font = require("ui/font")
local util = require("ffi/util")
local DEBUG = require("dbg")
local _ = require("gettext")
local SetDefaults = InputContainer:new{
defaults_name = {},
defaults_value = {},
results = {},
defaults_menu = {},
already_read = false,
changed = {}
}
local function settype(b,t)
if t == "boolean" then
if b == "false" then return false else return true end
else
return b
end
end
local function getTableValues(t,dtap)
local dummy = "{"
for n,v in pairs(t) do
if dtap:sub(1,4) == "DTAP" or dtap:sub(1,11) == "DDOUBLE_TAP" then
dummy = dummy .. tostring(n) .. " = " .. tostring(v) .. ", "
elseif tonumber(v) then
dummy = dummy .. tostring(v) .. ", "
else
dummy = dummy .. "\"" .. tostring(v) .. "\", "
end
end
dummy = dummy:sub(1,string.len(dummy) - 2) .. "}"
return dummy
end
function SetDefaults:ConfirmEdit()
if not SetDefaults.EditConfirmed then
UIManager:show(ConfirmBox:new{
text = _("Some changes will not work until the next restart. Be careful; the wrong settings might crash KOReader!\nAre you sure you want to continue?"),
ok_callback = function()
self.EditConfirmed = true
self:init()
end,
})
else
self:init()
end
end
function SetDefaults:init()
self.results = {}
if not self.already_read then
local i = 0
for n,v in util.orderedPairs(_G) do
if (not string.find(tostring(v), "<")) and (not string.find(tostring(v), ": ")) and string.sub(n,1,1) ~= "_" and string.upper(n) == n and n ~= "LIBRARY_PATH" then
i = i + 1
self.defaults_name[i] = n
self.defaults_value[i] = v
end
if string.find(tostring(v), "table: ") and string.upper(n) == n and n ~= "ARGV" and n ~= "_G" then
i = i + 1
self.defaults_name[i] = n
self.defaults_value[i] = getTableValues(v,n)
end
end
self.already_read = true
end
local menu_container = CenterContainer:new{
dimen = Screen:getSize(),
}
-- FIXME:
-- in this use case (an input dialog is closed and the menu container is opened
-- immediately) we need to set the full screen dirty because otherwise only
-- the input dialog part of the screen is refreshed.
menu_container.onShow = function()
UIManager:setDirty(nil, "partial")
end
self.defaults_menu = Menu:new{
width = Screen:getWidth()-15,
height = Screen:getHeight()-15,
cface = Font:getFace("cfont", 22),
show_parent = menu_container,
_manager = self,
}
table.insert(menu_container, self.defaults_menu)
self.defaults_menu.close_callback = function()
UIManager:close(menu_container)
end
for i=1,#self.defaults_name do
self.changed[i] = false
local settings_type = type(_G[self.defaults_name[i]])
if settings_type == "boolean" then
table.insert(self.results, {
text = self:build_setting(i),
callback = function()
self.set_dialog = InputDialog:new{
title = self.defaults_name[i] .. ":",
input = tostring(self.defaults_value[i]),
buttons = {
{
{
text = _("Cancel"),
enabled = true,
callback = function()
self:close()
UIManager:show(menu_container)
end
},
{
text = "true",
enabled = true,
callback = function()
self.defaults_value[i] = true
_G[self.defaults_name[i]] = true
settings_changed = true
self.changed[i] = true
self.results[i].text = self:build_setting(i)
self:close()
self.defaults_menu:swithItemTable("Defaults", self.results, i)
UIManager:show(menu_container)
end
},
{
text = "false",
enabled = true,
callback = function()
self.defaults_value[i] = false
_G[self.defaults_name[i]] = false
settings_changed = true
self.changed[i] = true
self.results[i].text = self:build_setting(i)
self.defaults_menu:swithItemTable("Defaults", self.results, i)
self:close()
UIManager:show(menu_container)
end
},
},
},
input_type = settings_type,
width = Screen:getWidth() * 0.95,
height = Screen:getHeight() * 0.2,
}
self.set_dialog:onShowKeyboard()
UIManager:show(self.set_dialog)
end
})
else
if type(_G[self.defaults_name[i]]) == "table" then
table.insert(self.results, {
text = self:build_setting(i),
callback = function()
local fields = {}
for m, n in util.orderedPairs(_G[self.defaults_name[i]]) do
table.insert(fields, {
text = tostring(m) .. " = " .. tostring(n),
hint = "",
})
end
self.set_dialog = MultiInputDialog:new{
title = self.defaults_name[i] .. ":",
fields = fields,
buttons = {
{
{
text = _("Cancel"),
enabled = true,
callback = function()
self:close()
UIManager:show(menu_container)
end,
},
{
text = _("OK"),
enabled = true,
callback = function()
local fields = {}
for _, field in ipairs(MultiInputDialog:getFields()) do
fields[field:match("^[^= ]+")] = field:match("[^= ]+$")
end
_G[self.defaults_name[i]] = fields
self.defaults_value[i] = "{"
DEBUG(_G[self.defaults_name[i]])
for k,v in util.orderedPairs(_G[self.defaults_name[i]]) do
if tonumber(k) then
self.defaults_value[i] = self.defaults_value[i] .. v .. ", "
else
self.defaults_value[i] = self.defaults_value[i] .. k .. " = " .. v .. ", "
end
end
self.defaults_value[i] = self.defaults_value[i]:sub(1,self.defaults_value[i]:len()-2) .. "}"
settings_changed = true
self.changed[i] = true
self.results[i].text = self:build_setting(i)
self:close()
self.defaults_menu:swithItemTable("Defaults", self.results, i)
UIManager:show(menu_container)
end,
},
},
},
input_type = "number",
width = Screen:getWidth() * 0.95,
height = Screen:getHeight() * 0.2,
}
self.set_dialog:onShowKeyboard()
UIManager:show(self.set_dialog)
end
})
else
table.insert(self.results, {
text = self:build_setting(i),
callback = function()
self.set_dialog = InputDialog:new{
title = self.defaults_name[i] .. ":",
input = tostring(self.defaults_value[i]),
buttons = {
{
{
text = _("Cancel"),
enabled = true,
callback = function()
self:close()
UIManager:show(menu_container)
end,
},
{
text = _("OK"),
enabled = true,
callback = function()
if type(_G[self.defaults_name[i]]) == "table" then
self.defaults_value[i] = self.set_dialog:getInputText()
elseif _G[self.defaults_name[i]] ~= settype(self.set_dialog:getInputText(),settings_type) then
_G[self.defaults_name[i]] = settype(self.set_dialog:getInputText(),settings_type)
self.defaults_value[i] = _G[self.defaults_name[i]]
end
settings_changed = true
self.changed[i] = true
self.results[i].text = self:build_setting(i)
self:close()
self.defaults_menu:swithItemTable("Defaults", self.results, i)
UIManager:show(menu_container)
end,
},
},
},
input_type = settings_type,
width = Screen:getWidth() * 0.95,
height = Screen:getHeight() * 0.2,
}
self.set_dialog:onShowKeyboard()
UIManager:show(self.set_dialog)
end
})
end
end
end
self.defaults_menu:swithItemTable("Defaults", self.results)
UIManager:show(menu_container)
end
function SetDefaults:close()
self.set_dialog:onClose()
UIManager:close(self.set_dialog)
end
function SetDefaults:ConfirmSave()
UIManager:show(ConfirmBox:new{
text = _("Are you sure you want to save the settings to \"defaults.persistent.lua\"?"),
ok_callback = function()
self:SaveSettings()
end,
})
end
function SetDefaults:build_setting(j)
local ret = self.defaults_name[j] .. " = "
if type(_G[self.defaults_name[j]]) == "boolean" or type(_G[self.defaults_name[j]]) == "table" then
ret = ret .. tostring(self.defaults_value[j])
elseif tonumber(self.defaults_value[j]) then
ret = ret .. tostring(tonumber(self.defaults_value[j]))
else
ret = ret .. "\"" .. tostring(self.defaults_value[j]) .. "\""
end
return ret
end
function SetDefaults:SaveSettings()
local function fileread(filename,array)
local file = io.open(filename)
local line = file:read()
local counter = 0
while line do
counter = counter + 1
local i = string.find(line,"[-][-]") -- remove comments from file
if (i or 0)>1 then line = string.sub(line,1,i-1) end
array[counter] = line:gsub("^%s*(.-)%s*$", "%1") -- trim
line = file:read()
end
file:close()
end
local persistent_filename = DataStorage:getDataDir() .. "/defaults.persistent.lua"
local file
if io.open(persistent_filename,"r") == nil then
file = io.open(persistent_filename, "w")
file:write("-- For configuration changes that persists between (nightly) releases\n")
file:close()
end
local dpl = {}
fileread(persistent_filename, dpl)
local dl = {}
fileread("defaults.lua",dl)
self.results = {}
local done = {}
for j=1,#SetDefaults.defaults_name do
if not self.changed[j] then done[j] = true end
end
-- handle case "found in persistent", replace it
for i = 1,#dpl do
for j=1,#SetDefaults.defaults_name do
if not done[j] and string.find(dpl[i],SetDefaults.defaults_name[j] .. " ") == 1 then
dpl[i] = self:build_setting(j)
done[j] = true
end
end
end
-- handle case "not in persistent and different in non-persistent", add to persistent
for j=1,#SetDefaults.defaults_name do
if not done[j] then
dpl[#dpl+1] = self:build_setting(j)
end
end
file = io.open(persistent_filename, "w")
if file then
for i = 1,#dpl do
file:write(dpl[i] .. "\n")
end
file:close()
UIManager:show(InfoMessage:new{
text = _("Default settings were saved successfully!"),
})
end
settings_changed = false
end
return SetDefaults