diff --git a/frontend/apps/filemanager/filemanagersearch.lua b/frontend/apps/filemanager/filemanagersearch.lua index 9f4240632..b29922b58 100644 --- a/frontend/apps/filemanager/filemanagersearch.lua +++ b/frontend/apps/filemanager/filemanagersearch.lua @@ -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 diff --git a/frontend/apps/filemanager/filemanagersetdefaults.lua b/frontend/apps/filemanager/filemanagersetdefaults.lua index 0379be43a..bfae0e2d4 100644 --- a/frontend/apps/filemanager/filemanagersetdefaults.lua +++ b/frontend/apps/filemanager/filemanagersetdefaults.lua @@ -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) diff --git a/frontend/ui/widget/multiinputdialog.lua b/frontend/ui/widget/multiinputdialog.lua new file mode 100644 index 000000000..d956f4500 --- /dev/null +++ b/frontend/ui/widget/multiinputdialog.lua @@ -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 + diff --git a/koreader-base b/koreader-base index 77654ebd3..446aa9314 160000 --- a/koreader-base +++ b/koreader-base @@ -1 +1 @@ -Subproject commit 77654ebd378925518ff61186848d0d6d2ed9a501 +Subproject commit 446aa931453c0c18ecdc7e94cf827730de6bd31d