Merge pull request #842 from WS64/master

Add a new multi line input dialog and change some search behaviour
pull/852/head
Huang Xin 10 years ago
commit 451092905e

@ -9,6 +9,7 @@ local Screen = require("ui/screen")
local _ = require("gettext")
local Font = require("ui/font")
local UIToolbox = require("ui/uitoolbox")
local util = require("ffi/util")
local calibre = "metadata.calibre"
local koreaderfile = "temp/metadata.koreader"
@ -27,7 +28,6 @@ local Search = InputContainer:new{
count = 0,
data = {},
results = {},
libraries = {},
browse_tags = {},
browse_series = {},
error = nil,
@ -38,73 +38,6 @@ local Search = InputContainer:new{
metafile_2 = nil,
}
local function __genOrderedIndex( t )
-- this function is taken from http://lua-users.org/wiki/SortedIteration
local orderedIndex = {}
for key in pairs(t) do
table.insert( orderedIndex, key )
end
table.sort( orderedIndex )
return orderedIndex
end
local function orderedNext(t, state)
-- this function is taken from http://lua-users.org/wiki/SortedIteration
-- Equivalent of the next function, but returns the keys in the alphabetic
-- order. We use a temporary ordered key table that is stored in the
-- table being iterated.
if state == nil then
-- the first time, generate the index
t.__orderedIndex = __genOrderedIndex( t )
key = t.__orderedIndex[1]
return key, t[key]
end
-- fetch the next value
key = nil
for i = 1,table.getn(t.__orderedIndex) do
if t.__orderedIndex[i] == state then
key = t.__orderedIndex[i+1]
end
end
if key then
return key, t[key]
end
-- no more value to return, cleanup
t.__orderedIndex = nil
return
end
local function orderedPairs(t)
-- this function is taken from http://lua-users.org/wiki/SortedIteration
-- Equivalent of the pairs() function on tables. Allows to iterate
-- in order
return orderedNext, t, nil
end
local function unichar (value)
-- this function is taken from dkjson
-- http://dkolf.de/src/dkjson-lua.fsl/
local floor = math.floor
local strchar = string.char
if value < 0 then
return nil
elseif value <= 0x007f then
return string.char (value)
elseif value <= 0x07ff then
return string.char (0xc0 + floor(value/0x40),0x80 + (floor(value) % 0x40))
elseif value <= 0xffff then
return string.char (0xe0 + floor(value/0x1000), 0x80 + (floor(value/0x40) % 0x40), 0x80 + (floor(value) % 0x40))
elseif value <= 0x10ffff then
return string.char (0xf0 + floor(value/0x40000), 0x80 + (floor(value/0x1000) % 0x40), 0x80 + (floor(value/0x40) % 0x40), 0x80 + (floor(value) % 0x40))
else
return nil
end
end
local function findcalibre(root)
local t = nil
for entity in lfs.dir(root) do
@ -307,7 +240,7 @@ function Search:find(option)
s=string.sub(s,n,string.len(s)-j)
end
s=string.gsub(s,"\\u([a-f0-9][a-f0-9][a-f0-9][a-f0-9])",function(w) return unichar(tonumber(w, 16)) end)
s=string.gsub(s,"\\u([a-f0-9][a-f0-9][a-f0-9][a-f0-9])",function(w) return util.unichar(tonumber(w, 16)) end)
return s
end
@ -363,59 +296,67 @@ function Search:find(option)
if self.use_own_metadata_file then
g = io.open(koreaderfile,"r")
line = g:read()
while line do
for j = 1,9 do
self.data[i][j] = line
line = g:read()
end
self.libraries[i] = tonumber(line)
if line ~= "#metadata.Koreader Version 1.1" then
self.use_own_metadata_file = false
g:close()
else
line = g:read()
end
if self.use_own_metadata_file then
while line do
local dummy = ""
if option == "find" and SEARCH_AUTHORS then dummy = dummy .. self.data[i][self.authors] .. "\n" end
if option == "find" and SEARCH_TITLE then dummy = dummy .. self.data[i][self.title] .. "\n" end
if option == "find" and SEARCH_PATH then dummy = dummy .. self.data[i][self.path] .. "\n" end
if (option == "series" or SEARCH_SERIES) and self.data[i][self.series] ~= "-" then
dummy = dummy .. self.data[i][self.series] .. "\n"
self.browse_series[self.data[i][self.series]] = (self.browse_series[self.data[i][self.series]] or 0) + 1
end
if option == "tags" or SEARCH_TAGS then dummy = dummy .. self.data[i][self.tags] .. "\n" end
if not SEARCH_CASESENSITIVE then dummy = string.upper(dummy) end
for j = 1,9 do
self.data[i][j] = line
line = g:read()
end
for j in string.gmatch(self.data[i][self.tags3],"\t[^\t]+") do
if j~="\t" then
self.browse_tags[string.sub(j,2)] = (self.browse_tags[string.sub(j,2)] or 0) + 1
local dummy = ""
if option == "find" and SEARCH_AUTHORS then dummy = dummy .. self.data[i][self.authors] .. "\n" end
if option == "find" and SEARCH_TITLE then dummy = dummy .. self.data[i][self.title] .. "\n" end
if option == "find" and SEARCH_PATH then dummy = dummy .. self.data[i][self.path] .. "\n" end
if (option == "series" or SEARCH_SERIES) and self.data[i][self.series] ~= "-" then
dummy = dummy .. self.data[i][self.series] .. "\n"
self.browse_series[self.data[i][self.series]] = (self.browse_series[self.data[i][self.series]] or 0) + 1
end
end
if option == "tags" or SEARCH_TAGS then dummy = dummy .. self.data[i][self.tags] .. "\n" end
if not SEARCH_CASESENSITIVE then dummy = string.upper(dummy) end
if upsearch ~= "" then
if string.find(dummy,upsearch,nil,true) then
i = i + 1
for j in string.gmatch(self.data[i][self.tags3],"\t[^\t]+") do
if j~="\t" then
self.browse_tags[string.sub(j,2)] = (self.browse_tags[string.sub(j,2)] or 0) + 1
end
end
else
if option == "series" then
if self.browse_series[self.data[i][self.series]] then
if upsearch ~= "" then
if string.find(dummy,upsearch,nil,true) then
i = i + 1
end
elseif option == "tags" then
local found = false
for j in string.gmatch(self.data[i][self.tags3],"\t[^\t]+") do
if j~="\t" and self.browse_tags[string.sub(j,2)] then
found = true
else
if option == "series" then
if self.browse_series[self.data[i][self.series]] then
i = i + 1
end
elseif option == "tags" then
local found = false
for j in string.gmatch(self.data[i][self.tags3],"\t[^\t]+") do
if j~="\t" and self.browse_tags[string.sub(j,2)] then
found = true
end
end
if found then
i = i + 1
end
end
if found then
i = i + 1
end
end
self.data[i] = {"-","-","-","-","-","-","-","-","-"}
end
self.data[i] = {"-","-","-","-","-","-","-","-","-"}
g.close()
end
g.close()
else
end
if not self.use_own_metadata_file then
f = io.open(self.metafile_1)
g = io.open(koreaderfile,"w")
g:write("#metadata.Koreader Version 1.1\n")
line = f:read()
while line do
@ -433,16 +374,9 @@ function Search:find(option)
if option == "tags" or SEARCH_TAGS then dummy = dummy .. self.data[i][self.tags] .. "\n" end
if not SEARCH_CASESENSITIVE then dummy = string.upper(dummy) end
if firstrun then
self.libraries[i] = 1
else
self.libraries[i] = 2
end
for j = 1,9 do
g:write(self.data[i][j] .. "\n")
end
g:write(tostring(self.libraries[i]) .. "\n")
if upsearch ~= "" then
if string.find(dummy,upsearch,nil,true) then
@ -476,6 +410,11 @@ function Search:find(option)
self.data[i][self.title] = ReplaceHexChars(line,15,3)
elseif string.sub(line,1,11) == " \"lpath\"" then -- LPATH
self.data[i][self.path] = ReplaceHexChars(line,15,3)
if firstrun then
self.data[i][self.path] = SEARCH_LIBRARY_PATH .. self.data[i][self.path]
else
self.data[i][self.path] = SEARCH_LIBRARY_PATH2 .. self.data[i][self.path]
end
elseif string.sub(line,1,12) == " \"series\"" and line ~= " \"series\": null, " then -- SERIES
self.data[i][self.series] = ReplaceHexChars(line,16,3)
elseif string.sub(line,1,18) == " \"series_index\"" and line ~= " \"series_index\": null, " then -- SERIES_INDEX
@ -566,17 +505,11 @@ function Search:showresults()
dummy = dummy .. " (" .. tostring(self.data[i][self.series_index]):gsub(".0$","") .. ")"
end
dummy = dummy .. "\n \n" .. _("Path: ")
local libpath
if self.libraries[i] == 1 then
libpath = SEARCH_LIBRARY_PATH
else
libpath = SEARCH_LIBRARY_PATH2
end
local book = libpath .. self.data[i][self.path]
local book = self.data[i][self.path]
table.insert(self.results, {
info = dummy,
notchecked = true,
path = libpath .. self.data[i][self.path],
path = self.data[i][self.path],
text = self.data[i][self.authors] .. ": " .. self.data[i][self.title],
callback = function()
showReaderUI(book)
@ -627,7 +560,7 @@ function Search:browse(option,run,chosen)
if run == 1 then
self.results = {}
if option == "series" then
for v,n in orderedPairs(self.browse_series) do
for v,n in util.orderedPairs(self.browse_series) do
dummy = v
if not SEARCH_CASESENSITIVE then dummy = string.upper(dummy) end
if string.find(dummy,upsearch,nil,true) then
@ -640,7 +573,7 @@ function Search:browse(option,run,chosen)
end
end
else
for v,n in orderedPairs(self.browse_tags) do
for v,n in util.orderedPairs(self.browse_tags) do
dummy = v
if not SEARCH_CASESENSITIVE then dummy = string.upper(dummy) end
if string.find(dummy,upsearch,nil,true) then
@ -667,13 +600,7 @@ function Search:browse(option,run,chosen)
dummy = dummy .. " (" .. tostring(self.data[i][self.series_index]):gsub(".0$","") .. ")"
end
dummy = dummy .. "\n \n" .. _("Path: ")
local libpath
if self.libraries[i] == 1 then
libpath = SEARCH_LIBRARY_PATH
else
libpath = SEARCH_LIBRARY_PATH2
end
local book = libpath .. self.data[i][self.path]
local book = self.data[i][self.path]
local text
if option == "series" then
if self.data[i][self.series_index] == "0.0" then
@ -688,7 +615,7 @@ function Search:browse(option,run,chosen)
text = text,
info = dummy,
notchecked = true,
path = libpath .. self.data[i][self.path],
path = self.data[i][self.path],
callback = function()
showReaderUI(book)
end

@ -3,11 +3,13 @@ local UIManager = require("ui/uimanager")
local _ = require("gettext")
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 Screen = require("ui/screen")
local Menu = require("ui/widget/menu")
local Font = require("ui/font")
local util = require("ffi/util")
local SetDefaults = InputContainer:new{
defaults_name = {},
@ -26,54 +28,6 @@ local function settype(b,t)
end
end
local function __genOrderedIndex( t )
-- this function is taken from http://lua-users.org/wiki/SortedIteration
local orderedIndex = {}
for key in pairs(t) do
table.insert( orderedIndex, key )
end
table.sort( orderedIndex )
return orderedIndex
end
local function orderedNext(t, state)
-- this function is taken from http://lua-users.org/wiki/SortedIteration
-- Equivalent of the next function, but returns the keys in the alphabetic
-- order. We use a temporary ordered key table that is stored in the
-- table being iterated.
if state == nil then
-- the first time, generate the index
t.__orderedIndex = __genOrderedIndex( t )
key = t.__orderedIndex[1]
return key, t[key]
end
-- fetch the next value
key = nil
for i = 1,table.getn(t.__orderedIndex) do
if t.__orderedIndex[i] == state then
key = t.__orderedIndex[i+1]
end
end
if key then
return key, t[key]
end
-- no more value to return, cleanup
t.__orderedIndex = nil
return
end
local function orderedPairs(t)
-- this function is taken from http://lua-users.org/wiki/SortedIteration
-- Equivalent of the pairs() function on tables. Allows to iterate
-- in order
return orderedNext, t, nil
end
local function getTableValues(t,dtap)
local dummy = "{"
for n,v in pairs(t) do
@ -108,7 +62,7 @@ function SetDefaults:init()
if not self.already_read then
local i = 0
for n,v in orderedPairs(_G) do
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
@ -157,7 +111,7 @@ function SetDefaults:init()
callback = function()
self:close()
UIManager:show(menu_container)
end
end
},
{
text = "true",
@ -198,50 +152,107 @@ function SetDefaults:init()
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 = {
{
if type(_G[self.defaults_name[i]]) == "table" then
table.insert(self.results, {
text = self:build_setting(i),
callback = function()
self.set_dialog = MultiInputDialog:new{
title = self.defaults_name[i] .. ":",
field = _G[self.defaults_name[i]],
buttons = {
{
text = _("Cancel"),
enabled = true,
callback = function()
self:close()
UIManager:show(menu_container)
end,
{
text = _("Cancel"),
enabled = true,
callback = function()
self:close()
UIManager:show(menu_container)
end,
},
{
text = _("OK"),
enabled = true,
callback = function()
_G[self.defaults_name[i]] = MultiInputDialog:getCredential()
self.defaults_value[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 = _("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,
{
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
})
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)

@ -0,0 +1,111 @@
local FrameContainer = require("ui/widget/container/framecontainer")
local CenterContainer = require("ui/widget/container/centercontainer")
local VerticalGroup = require("ui/widget/verticalgroup")
local HorizontalGroup = require("ui/widget/horizontalgroup")
local InputDialog = require("ui/widget/inputdialog")
local InputText = require("ui/widget/inputtext")
local UIManager = require("ui/uimanager")
local Geom = require("ui/geometry")
local Screen = require("ui/screen")
local DEBUG = require("dbg")
local _ = require("gettext")
local util = require("ffi/util")
local InfoMessage = require("ui/widget/infomessage")
local input_field
local MultiInputDialog = InputDialog:extend{
field = {},
field_hint = {},
}
function MultiInputDialog:init()
-- init title and buttons in base class
InputDialog.init(self)
local VerticalGroupData = VerticalGroup:new{
align = "left",
self.title,
self.title_bar,
}
input_field = {}
local k = 0
for i,j in util.orderedPairs(self.field) do
k = k + 1
input_field[k] = InputText:new{
text = tostring(i) .. " = " .. tostring(j),
hint = tostring(self.field_hint[j]) or "",
face = self.input_face,
width = self.width * 0.9,
focused = true,
scroll = false,
parent = self,
}
table.insert(VerticalGroupData,CenterContainer:new{
dimen = Geom:new{
w = self.title_bar:getSize().w,
h = input_field[k]:getSize().h,
},
input_field[k],
})
end
-- buttons
table.insert(VerticalGroupData,CenterContainer:new{
dimen = Geom:new{
w = self.title_bar:getSize().w,
h = self.button_table:getSize().h,
},
self.button_table,
})
self.dialog_frame = FrameContainer:new{
radius = 8,
bordersize = 3,
padding = 0,
margin = 0,
background = 0,
VerticalGroupData,
}
self.input = input_field[1]
self[1] = CenterContainer:new{
dimen = Geom:new{
w = Screen:getWidth(),
h = Screen:getHeight() - self.input:getKeyboardDimen().h,
},
self.dialog_frame,
}
UIManager.repaint_all = true
UIManager.full_refresh = true
end
function MultiInputDialog:getCredential()
local field = {}
local dummy
for i=1,#input_field do
dummy = input_field[i].text
field[dummy:match("^[^= ]+")] = dummy:match("[^= ]+$")
end
return field
end
function MultiInputDialog:onSwitchFocus(inputbox)
-- unfocus current inputbox
self.input:unfocus()
self.input:onCloseKeyboard()
-- focus new inputbox
self.input = inputbox
self.input:focus()
self.input:onShowKeyboard()
UIManager:show(self)
end
return MultiInputDialog

@ -1 +1 @@
Subproject commit 77654ebd378925518ff61186848d0d6d2ed9a501
Subproject commit 446aa931453c0c18ecdc7e94cf827730de6bd31d
Loading…
Cancel
Save