From 7fb545286b1673f12a2b9f0e9bda74d57bca7855 Mon Sep 17 00:00:00 2001 From: WS64 Date: Mon, 18 Aug 2014 09:48:46 +0200 Subject: [PATCH] New function, browse series/tags, and sorting of all search results --- .../apps/filemanager/filemanagersearch.lua | 290 +++++++++++++++--- 1 file changed, 251 insertions(+), 39 deletions(-) diff --git a/frontend/apps/filemanager/filemanagersearch.lua b/frontend/apps/filemanager/filemanagersearch.lua index bed154926..a471d8849 100644 --- a/frontend/apps/filemanager/filemanagersearch.lua +++ b/frontend/apps/filemanager/filemanagersearch.lua @@ -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