mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
New function, browse series/tags, and sorting of all search results
This commit is contained in:
@@ -22,6 +22,7 @@ local Search = InputContainer:new{
|
||||
authors2 = 6,
|
||||
series_index = 7,
|
||||
tags2 = 8,
|
||||
tags3 = 9,
|
||||
count = 0,
|
||||
data = {},
|
||||
results = {},
|
||||
@@ -29,9 +30,57 @@ local Search = InputContainer:new{
|
||||
browse_tags = {},
|
||||
browse_series = {},
|
||||
error = nil,
|
||||
use_previous_search_results = false
|
||||
use_previous_search_results = false,
|
||||
lastsearch = 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/
|
||||
@@ -52,11 +101,6 @@ local function unichar (value)
|
||||
end
|
||||
end
|
||||
|
||||
local function fillbrowse()
|
||||
if _browse_tags + _browse_series == 0 then
|
||||
end
|
||||
end
|
||||
|
||||
local function findcalibre(root)
|
||||
local t = nil
|
||||
for entity in lfs.dir(root) do
|
||||
@@ -148,15 +192,54 @@ function Search:ShowSearch()
|
||||
buttons = {
|
||||
{
|
||||
{
|
||||
text = _("Find"),
|
||||
text = _("Browse series"),
|
||||
enabled = true,
|
||||
callback = function()
|
||||
self.search_value = self.search_dialog:getInputText()
|
||||
if not settings_changed and self.search_value == dummy then
|
||||
if not settings_changed and self.search_value == dummy and self.lastsearch == "series" then
|
||||
self.use_previous_search_results = true
|
||||
else
|
||||
self.use_previous_search_results = false
|
||||
end
|
||||
self.lastsearch = "series"
|
||||
self:close()
|
||||
end,
|
||||
},
|
||||
{
|
||||
text = _("Browse tags"),
|
||||
enabled = true,
|
||||
callback = function()
|
||||
self.search_value = self.search_dialog:getInputText()
|
||||
if not settings_changed and self.search_value == dummy and self.lastsearch == "tags" then
|
||||
self.use_previous_search_results = true
|
||||
else
|
||||
self.use_previous_search_results = false
|
||||
end
|
||||
self.lastsearch = "tags"
|
||||
self:close()
|
||||
end,
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
text = _("Cancel"),
|
||||
enabled = true,
|
||||
callback = function()
|
||||
self.search_dialog:onClose()
|
||||
UIManager:close(self.search_dialog)
|
||||
end,
|
||||
},
|
||||
{
|
||||
text = _("Find books"),
|
||||
enabled = true,
|
||||
callback = function()
|
||||
self.search_value = self.search_dialog:getInputText()
|
||||
if not settings_changed and self.search_value == dummy and self.lastsearch == "find" then
|
||||
self.use_previous_search_results = true
|
||||
else
|
||||
self.use_previous_search_results = false
|
||||
end
|
||||
self.lastsearch = "find"
|
||||
self:close()
|
||||
end,
|
||||
},
|
||||
@@ -185,12 +268,12 @@ end
|
||||
function Search:close()
|
||||
self.search_dialog:onClose()
|
||||
UIManager:close(self.search_dialog)
|
||||
if string.len(self.search_value) > 0 then
|
||||
self:find()
|
||||
if string.len(self.search_value) > 0 or self.lastsearch ~= "find" then
|
||||
self:find(self.lastsearch)
|
||||
end
|
||||
end
|
||||
|
||||
function Search:find()
|
||||
function Search:find(option)
|
||||
local f = io.open(self.calibrefile)
|
||||
local line = f:read()
|
||||
local i = 1
|
||||
@@ -220,6 +303,7 @@ function Search:find()
|
||||
self.data[i][self.authors2] = ""
|
||||
elseif s == self.tags then
|
||||
self.data[i][self.tags2] = ""
|
||||
self.data[i][self.tags3] = ""
|
||||
end
|
||||
while line ~= " ], " do
|
||||
line = f:read()
|
||||
@@ -228,7 +312,10 @@ function Search:find()
|
||||
if s == self.authors then
|
||||
self.data[i][self.authors2] = self.data[i][self.authors2] .. " & " .. ReplaceHexChars(line,8,3)
|
||||
elseif s == self.tags then
|
||||
self.data[i][self.tags2] = self.data[i][self.tags2] .. " & " .. ReplaceHexChars(line,8,3)
|
||||
local dummy = ReplaceHexChars(line,8,3)
|
||||
self.data[i][self.tags2] = self.data[i][self.tags2] .. " & " .. dummy
|
||||
self.data[i][self.tags3] = self.data[i][self.tags3] .. "\n" .. dummy
|
||||
self.browse_tags[dummy] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -237,22 +324,23 @@ function Search:find()
|
||||
self.data[i][self.authors2] = string.sub(self.data[i][self.authors2],4)
|
||||
elseif s == self.tags then
|
||||
self.data[i][self.tags2] = string.sub(self.data[i][self.tags2],4)
|
||||
self.data[i][self.tags3] = self.data[i][self.tags3] .. "\n"
|
||||
end
|
||||
end
|
||||
|
||||
if not self.use_previous_search_results then
|
||||
self.reults = {}
|
||||
self.results = {}
|
||||
self.data = {}
|
||||
|
||||
if SEARCH_CASESENSITIVE then
|
||||
upsearch = self.search_value
|
||||
upsearch = self.search_value or ""
|
||||
else
|
||||
upsearch = string.upper(self.search_value)
|
||||
upsearch = string.upper(self.search_value or "")
|
||||
end
|
||||
|
||||
firstrun = true
|
||||
|
||||
self.data[i] = {"-","-","-","-","-","-","-","-"}
|
||||
self.data[i] = {"-","-","-","-","-","-","-","-","-"}
|
||||
self.libraries[i] = 1
|
||||
|
||||
while line do
|
||||
@@ -260,23 +348,32 @@ function Search:find()
|
||||
-- new calibre data set
|
||||
|
||||
dummy = ""
|
||||
if SEARCH_AUTHORS then dummy = dummy .. self.data[i][self.authors] .. "\n" end
|
||||
if SEARCH_TITLE then dummy = dummy .. self.data[i][self.title] .. "\n" end
|
||||
if SEARCH_PATH then dummy = dummy .. self.data[i][self.path] .. "\n" end
|
||||
if SEARCH_SERIES then
|
||||
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 then
|
||||
dummy = dummy .. self.data[i][self.series] .. "\n"
|
||||
self.browse_series[self.data[i][self.series]] = true
|
||||
end
|
||||
if SEARCH_TAGS then
|
||||
dummy = dummy .. self.data[i][self.tags] .. "\n"
|
||||
self.browse_tags[self.data[i][self.tags]] = true
|
||||
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 string.find(dummy,upsearch,nil,true) then
|
||||
i = i + 1
|
||||
if upsearch ~= "" then
|
||||
if string.find(dummy,upsearch,nil,true) then
|
||||
i = i + 1
|
||||
end
|
||||
else
|
||||
if option == "series" then
|
||||
if self.browse_series[self.data[i][self.series]] then
|
||||
i = i + 1
|
||||
end
|
||||
elseif option == "tags" then
|
||||
if self.browse_tags[self.data[i][self.tags]] then
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
self.data[i] = {"-","-","-","-","-","-","-","-"}
|
||||
self.data[i] = {"-","-","-","-","-","-","-","-","-"}
|
||||
if firstrun then
|
||||
self.libraries[i] = 1
|
||||
else
|
||||
@@ -312,25 +409,31 @@ function Search:find()
|
||||
end
|
||||
if self.count > 0 then
|
||||
self.data[self.count + 1] = nil
|
||||
self:showresults()
|
||||
if option == "find" then
|
||||
self:showresults()
|
||||
else
|
||||
self:browse(option,1)
|
||||
end
|
||||
else
|
||||
UIManager:show(InfoMessage:new{text = _("No match for " .. self.search_value)})
|
||||
end
|
||||
end
|
||||
|
||||
function Search:onMenuHold(item)
|
||||
if item.notchecked then
|
||||
item.info = item.info .. item.path
|
||||
local f = io.open(item.path)
|
||||
if f == nil then
|
||||
item.info = item.info .. "\nFile not found!"
|
||||
else
|
||||
item.info = item.info .. "\n" .. string.format("%4.1fM",lfs.attributes(item.path, "size")/1024/1024)
|
||||
f:close()
|
||||
if string.len(item.info or "") > 0 then
|
||||
if item.notchecked then
|
||||
item.info = item.info .. item.path
|
||||
local f = io.open(item.path)
|
||||
if f == nil then
|
||||
item.info = item.info .. "\n" .. _("File not found!")
|
||||
else
|
||||
item.info = item.info .. "\n" .. _("Size: ") .. string.format("%4.1fM",lfs.attributes(item.path, "size")/1024/1024)
|
||||
f:close()
|
||||
end
|
||||
item.notchecked = false
|
||||
end
|
||||
item.notchecked = false
|
||||
UIManager:show(InfoMessage:new{text = item.info})
|
||||
end
|
||||
UIManager:show(InfoMessage:new{text = item.info})
|
||||
end
|
||||
|
||||
function Search:showresults()
|
||||
@@ -382,7 +485,116 @@ function Search:showresults()
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
self.search_menu:swithItemTable("Search Results", self.results)
|
||||
table.sort(self.results, function(v1,v2) return v1.text < v2.text end)
|
||||
self.search_menu:swithItemTable(_("Search Results"), self.results)
|
||||
UIManager:show(menu_container)
|
||||
end
|
||||
|
||||
function Search:browse(option,run,chosen)
|
||||
local menu_container = CenterContainer:new{
|
||||
dimen = Screen:getSize(),
|
||||
}
|
||||
self.search_menu = Menu:new{
|
||||
width = Screen:getWidth()-15,
|
||||
height = Screen:getHeight()-15,
|
||||
show_parent = menu_container,
|
||||
onMenuHold = self.onMenuHold,
|
||||
cface = Font:getFace("cfont", 22),
|
||||
_manager = self,
|
||||
}
|
||||
table.insert(menu_container, self.search_menu)
|
||||
self.search_menu.close_callback = function()
|
||||
UIManager:close(menu_container)
|
||||
end
|
||||
local upsearch
|
||||
local dummy
|
||||
if SEARCH_CASESENSITIVE then
|
||||
upsearch = self.search_value or ""
|
||||
else
|
||||
upsearch = string.upper(self.search_value or "")
|
||||
end
|
||||
|
||||
if run == 1 then
|
||||
self.results = {}
|
||||
if option == "series" then
|
||||
for v,n in 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
|
||||
table.insert(self.results, {
|
||||
text = v,
|
||||
callback = function()
|
||||
self:browse(option,2,v)
|
||||
end
|
||||
})
|
||||
end
|
||||
end
|
||||
else
|
||||
for v,n in 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
|
||||
table.insert(self.results, {
|
||||
text = v,
|
||||
callback = function()
|
||||
self:browse(option,2,v)
|
||||
end
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
self.results = {}
|
||||
local i = 1
|
||||
while i <= self.count do
|
||||
if (option == "series" and chosen == self.data[i][self.series]) or (option == "tags" and string.find("\n" .. chosen .. "\n",self.data[i][self.tags3],nil,true)) then
|
||||
local dummy = _("Title: ") .. (self.data[i][self.title] or "-") .. "\n \n" ..
|
||||
_("Author(s): ") .. (self.data[i][self.authors2] or "-") .. "\n \n" ..
|
||||
_("Tags: ") .. (self.data[i][self.tags2] or "-") .. "\n \n" ..
|
||||
_("Series: ") .. (self.data[i][self.series] or "-")
|
||||
if self.data[i][self.series] ~= "-" then
|
||||
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 text
|
||||
if option == "series" then
|
||||
text = string.format("%6.1f",self.data[i][self.series_index]):gsub(".0$","") .. ": " .. self.data[i][self.title] .. " (" .. self.data[i][self.authors] .. ")"
|
||||
else
|
||||
text = self.data[i][self.authors] .. ": " .. self.data[i][self.title]
|
||||
end
|
||||
table.insert(self.results, {
|
||||
text = text,
|
||||
info = dummy,
|
||||
notchecked = true,
|
||||
path = libpath .. self.data[i][self.path],
|
||||
callback = function()
|
||||
if book then
|
||||
showReaderUI(book)
|
||||
end
|
||||
end
|
||||
})
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
local dummy = ""
|
||||
|
||||
if run == 1 then
|
||||
dummy = _("Browse ") .. option
|
||||
else
|
||||
dummy = chosen
|
||||
end
|
||||
|
||||
table.sort(self.results, function(v1,v2) return v1.text < v2.text end)
|
||||
|
||||
self.search_menu:swithItemTable(dummy, self.results)
|
||||
UIManager:show(menu_container)
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user