2014-08-14 11:49:42 +00:00
|
|
|
local CenterContainer = require("ui/widget/container/centercontainer")
|
2014-08-07 07:15:05 +00:00
|
|
|
local InputContainer = require("ui/widget/container/inputcontainer")
|
2014-08-27 03:07:25 +00:00
|
|
|
local DocumentRegistry = require("document/documentregistry")
|
2014-08-07 07:15:05 +00:00
|
|
|
local InputDialog = require("ui/widget/inputdialog")
|
2014-08-14 11:49:42 +00:00
|
|
|
local InfoMessage = require("ui/widget/infomessage")
|
|
|
|
local lfs = require("libs/libkoreader-lfs")
|
|
|
|
local UIManager = require("ui/uimanager")
|
2014-08-07 07:15:05 +00:00
|
|
|
local Menu = require("ui/widget/menu")
|
2014-10-30 18:42:18 +00:00
|
|
|
local Screen = require("device").screen
|
2014-08-26 00:59:24 +00:00
|
|
|
local util = require("ffi/util")
|
2014-08-26 10:10:26 +00:00
|
|
|
local Font = require("ui/font")
|
2014-08-27 03:07:25 +00:00
|
|
|
local DEBUG = require("dbg")
|
2014-08-26 10:10:26 +00:00
|
|
|
local _ = require("gettext")
|
2014-08-07 07:15:05 +00:00
|
|
|
|
2014-08-17 10:01:59 +00:00
|
|
|
local calibre = "metadata.calibre"
|
2014-08-19 15:50:02 +00:00
|
|
|
local koreaderfile = "temp/metadata.koreader"
|
2014-08-17 10:01:59 +00:00
|
|
|
|
2014-08-07 07:15:05 +00:00
|
|
|
local Search = InputContainer:new{
|
2014-08-07 14:27:46 +00:00
|
|
|
search_dialog = nil,
|
2014-08-19 15:50:02 +00:00
|
|
|
title = 1,
|
|
|
|
authors = 2,
|
|
|
|
authors2 = 3,
|
|
|
|
path = 4,
|
2014-08-07 07:15:05 +00:00
|
|
|
series = 5,
|
2014-08-19 15:50:02 +00:00
|
|
|
series_index = 6,
|
|
|
|
tags = 7,
|
2014-08-12 20:25:38 +00:00
|
|
|
tags2 = 8,
|
2014-08-18 07:48:46 +00:00
|
|
|
tags3 = 9,
|
2014-08-07 07:15:05 +00:00
|
|
|
count = 0,
|
|
|
|
data = {},
|
|
|
|
results = {},
|
2014-08-16 20:33:11 +00:00
|
|
|
browse_tags = {},
|
2014-08-17 10:01:59 +00:00
|
|
|
browse_series = {},
|
|
|
|
error = nil,
|
2014-08-18 07:48:46 +00:00
|
|
|
use_previous_search_results = false,
|
|
|
|
lastsearch = nil,
|
2014-08-19 15:50:02 +00:00
|
|
|
use_own_metadata_file = false,
|
|
|
|
metafile_1 = nil,
|
2014-08-23 15:19:02 +00:00
|
|
|
metafile_2 = nil,
|
2014-08-07 07:15:05 +00:00
|
|
|
}
|
|
|
|
|
2014-08-07 14:27:46 +00:00
|
|
|
local function findcalibre(root)
|
2014-08-12 20:25:38 +00:00
|
|
|
local t = nil
|
2014-08-27 03:07:25 +00:00
|
|
|
-- protect lfs.dir which will raise error on no-permission directory
|
|
|
|
local ok, iter, dir_obj = pcall(lfs.dir, root)
|
|
|
|
if ok then
|
|
|
|
for entity in iter, dir_obj do
|
|
|
|
if t then
|
|
|
|
break
|
|
|
|
else
|
|
|
|
if entity ~= "." and entity ~= ".." then
|
|
|
|
local fullPath=root .. "/" .. entity
|
|
|
|
local mode = lfs.attributes(fullPath,"mode")
|
|
|
|
if mode == "file" then
|
|
|
|
if entity == calibre or entity == "." .. calibre then
|
|
|
|
t = root .. "/" .. entity
|
|
|
|
end
|
|
|
|
elseif mode == "directory" then
|
|
|
|
t = findcalibre(fullPath)
|
2014-08-07 14:27:46 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return t
|
|
|
|
end
|
|
|
|
|
2014-08-19 15:50:02 +00:00
|
|
|
function Search:getCalibre()
|
2014-08-27 03:07:25 +00:00
|
|
|
-- check if we find the calibre file
|
|
|
|
-- check 1st file
|
2014-08-19 16:04:38 +00:00
|
|
|
if SEARCH_LIBRARY_PATH == nil then
|
2014-08-27 03:07:25 +00:00
|
|
|
DEBUG("search Calibre database")
|
|
|
|
self.metafile_1 = findcalibre("/mnt")
|
|
|
|
if not self.metafile_1 then
|
|
|
|
self.error = "SEARCH_LIBRARY_PATH in DEFAULTS.LUA is not set!"
|
|
|
|
else
|
|
|
|
settings_changed = true
|
|
|
|
end
|
2014-08-19 16:04:38 +00:00
|
|
|
else
|
|
|
|
if string.sub(SEARCH_LIBRARY_PATH,string.len(SEARCH_LIBRARY_PATH)) ~= "/" then
|
|
|
|
SEARCH_LIBRARY_PATH = SEARCH_LIBRARY_PATH .. "/"
|
|
|
|
end
|
|
|
|
if io.open(SEARCH_LIBRARY_PATH .. calibre,"r") == nil then
|
|
|
|
if io.open(SEARCH_LIBRARY_PATH .. "." .. calibre,"r") == nil then
|
|
|
|
self.error = SEARCH_LIBRARY_PATH .. calibre .. " not found!"
|
2014-08-27 03:07:25 +00:00
|
|
|
DEBUG(self.error)
|
2014-08-17 10:01:59 +00:00
|
|
|
else
|
2014-08-19 16:04:38 +00:00
|
|
|
self.metafile_1 = SEARCH_LIBRARY_PATH .. "." .. calibre
|
2014-08-17 10:01:59 +00:00
|
|
|
end
|
2014-08-19 16:04:38 +00:00
|
|
|
else
|
|
|
|
self.metafile_1 = SEARCH_LIBRARY_PATH .. calibre
|
|
|
|
end
|
2014-08-17 10:01:59 +00:00
|
|
|
|
2014-08-19 16:04:38 +00:00
|
|
|
if not (SEARCH_AUTHORS or SEARCH_TITLE or SEARCH_PATH or SEARCH_SERIES or SEARCH_TAGS) then
|
|
|
|
self.metafile_1 = nil
|
|
|
|
UIManager:show(InfoMessage:new{text = _("You must specify at least one field to search at! (SEARCH_XXX = true in defaults.lua)")})
|
|
|
|
elseif self.metafile_1 == nil then
|
|
|
|
self.metafile_1 = findcalibre("/mnt")
|
|
|
|
if self.metafile_1 then
|
|
|
|
settings_changed = true
|
2014-08-17 10:01:59 +00:00
|
|
|
end
|
|
|
|
end
|
2014-08-19 16:04:38 +00:00
|
|
|
end
|
2014-08-27 03:07:25 +00:00
|
|
|
-- check 2nd file
|
2014-08-19 16:04:38 +00:00
|
|
|
local dummy
|
2014-08-23 15:19:02 +00:00
|
|
|
|
2014-08-19 16:04:38 +00:00
|
|
|
if string.sub(SEARCH_LIBRARY_PATH2,string.len(SEARCH_LIBRARY_PATH2)) ~= "/" then
|
|
|
|
SEARCH_LIBRARY_PATH2 = SEARCH_LIBRARY_PATH2 .. "/"
|
|
|
|
end
|
|
|
|
if io.open(SEARCH_LIBRARY_PATH2 .. calibre,"r") == nil then
|
|
|
|
if io.open(SEARCH_LIBRARY_PATH2 .. "." .. calibre,"r") ~= nil then
|
|
|
|
dummy = SEARCH_LIBRARY_PATH2 .. "." .. calibre
|
2014-08-19 15:50:02 +00:00
|
|
|
end
|
2014-08-19 16:04:38 +00:00
|
|
|
else
|
|
|
|
dummy = SEARCH_LIBRARY_PATH2 .. calibre
|
|
|
|
end
|
|
|
|
if dummy and dummy ~= self.metafile_1 then
|
|
|
|
self.metafile_2 = dummy
|
|
|
|
else
|
|
|
|
self.metafile_2 = nil
|
|
|
|
end
|
2014-08-19 15:50:02 +00:00
|
|
|
|
|
|
|
-- check if they are newer than our own file
|
|
|
|
self.use_own_metadata_file = false
|
|
|
|
if self.metafile_1 then
|
|
|
|
pcall(lfs.mkdir("temp"))
|
|
|
|
if io.open(koreaderfile,"r") then
|
|
|
|
if lfs.attributes(koreaderfile).modification > lfs.attributes(self.metafile_1).modification then
|
|
|
|
if self.metafile_2 then
|
|
|
|
if lfs.attributes(koreaderfile).modification > lfs.attributes(self.metafile_2).modification then
|
|
|
|
self.use_own_metadata_file = true
|
|
|
|
end
|
|
|
|
else
|
|
|
|
self.use_own_metadata_file = true
|
|
|
|
end
|
|
|
|
end
|
2014-08-07 07:15:05 +00:00
|
|
|
end
|
|
|
|
end
|
2014-08-17 10:01:59 +00:00
|
|
|
end
|
2014-08-14 11:49:42 +00:00
|
|
|
|
2014-08-17 10:01:59 +00:00
|
|
|
function Search:ShowSearch()
|
2014-08-19 15:50:02 +00:00
|
|
|
if self.metafile_1 ~= nil then
|
2014-08-24 08:08:45 +00:00
|
|
|
local dummy = self.search_value
|
2014-08-07 07:15:05 +00:00
|
|
|
self.search_dialog = InputDialog:new{
|
2014-08-11 08:40:22 +00:00
|
|
|
title = _("Search Books"),
|
2014-08-24 08:08:45 +00:00
|
|
|
input = self.search_value,
|
2014-08-07 07:15:05 +00:00
|
|
|
buttons = {
|
|
|
|
{
|
|
|
|
{
|
2014-08-18 07:48:46 +00:00
|
|
|
text = _("Browse series"),
|
|
|
|
enabled = true,
|
|
|
|
callback = function()
|
|
|
|
self.search_value = self.search_dialog:getInputText()
|
|
|
|
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"),
|
2014-08-07 07:15:05 +00:00
|
|
|
enabled = true,
|
|
|
|
callback = function()
|
2014-08-17 10:01:59 +00:00
|
|
|
self.search_value = self.search_dialog:getInputText()
|
2014-08-18 07:48:46 +00:00
|
|
|
if not settings_changed and self.search_value == dummy and self.lastsearch == "find" then
|
2014-08-17 10:01:59 +00:00
|
|
|
self.use_previous_search_results = true
|
|
|
|
else
|
|
|
|
self.use_previous_search_results = false
|
|
|
|
end
|
2014-08-18 07:48:46 +00:00
|
|
|
self.lastsearch = "find"
|
2014-08-07 07:15:05 +00:00
|
|
|
self:close()
|
|
|
|
end,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
width = Screen:getWidth() * 0.8,
|
|
|
|
height = Screen:getHeight() * 0.2,
|
|
|
|
}
|
|
|
|
self.search_dialog:onShowKeyboard()
|
|
|
|
UIManager:show(self.search_dialog)
|
2014-08-07 14:27:46 +00:00
|
|
|
else
|
2014-08-17 10:01:59 +00:00
|
|
|
if self.error then
|
|
|
|
UIManager:show(InfoMessage:new{text = self.error .. _( " A search for a " .. calibre .. " file was not successful!"),})
|
2014-08-07 14:27:46 +00:00
|
|
|
end
|
2014-08-07 07:15:05 +00:00
|
|
|
end
|
2014-08-23 15:19:02 +00:00
|
|
|
|
2014-08-07 07:15:05 +00:00
|
|
|
end
|
|
|
|
|
2014-08-17 10:01:59 +00:00
|
|
|
function Search:init()
|
|
|
|
self.error = nil
|
|
|
|
self.data = {}
|
|
|
|
self.results = {}
|
|
|
|
end
|
|
|
|
|
2014-08-07 07:15:05 +00:00
|
|
|
function Search:close()
|
2014-08-18 20:52:29 +00:00
|
|
|
if self.search_value then
|
|
|
|
self.search_dialog:onClose()
|
|
|
|
UIManager:close(self.search_dialog)
|
|
|
|
if string.len(self.search_value) > 0 or self.lastsearch ~= "find" then
|
|
|
|
self:find(self.lastsearch)
|
|
|
|
end
|
2014-08-07 07:15:05 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-08-18 07:48:46 +00:00
|
|
|
function Search:find(option)
|
2014-08-19 15:50:02 +00:00
|
|
|
local f
|
|
|
|
local line
|
2014-08-07 07:15:05 +00:00
|
|
|
local i = 1
|
|
|
|
local upsearch
|
|
|
|
local dummy
|
2014-08-16 20:33:11 +00:00
|
|
|
local firstrun
|
2014-08-07 07:15:05 +00:00
|
|
|
|
|
|
|
-- removes leading and closing characters and converts hex-unicodes
|
2014-08-12 20:25:38 +00:00
|
|
|
local ReplaceHexChars = function(s,n,j)
|
2014-08-07 07:15:05 +00:00
|
|
|
local l=string.len(s)
|
|
|
|
|
|
|
|
if string.sub(s,l,l) == "\"" then
|
|
|
|
s=string.sub(s,n,string.len(s)-1)
|
|
|
|
else
|
2014-08-12 20:25:38 +00:00
|
|
|
s=string.sub(s,n,string.len(s)-j)
|
2014-08-07 07:15:05 +00:00
|
|
|
end
|
|
|
|
|
2014-08-26 00:59:24 +00:00
|
|
|
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)
|
2014-08-07 07:15:05 +00:00
|
|
|
|
|
|
|
return s
|
|
|
|
end
|
|
|
|
|
|
|
|
-- ready entries with multiple lines from calibre
|
|
|
|
local ReadMultipleLines = function(s)
|
2014-08-12 20:25:38 +00:00
|
|
|
self.data[i][s] = ""
|
|
|
|
if s == self.authors then
|
|
|
|
self.data[i][self.authors2] = ""
|
|
|
|
elseif s == self.tags then
|
|
|
|
self.data[i][self.tags2] = ""
|
2014-08-18 07:48:46 +00:00
|
|
|
self.data[i][self.tags3] = ""
|
2014-08-12 20:25:38 +00:00
|
|
|
end
|
2014-10-13 13:40:48 +00:00
|
|
|
while line ~= " ], " and line ~= " ]" do
|
2014-08-07 07:15:05 +00:00
|
|
|
line = f:read()
|
2014-10-13 13:40:48 +00:00
|
|
|
if line ~= " ], " and line ~= " ]" then
|
2014-08-12 20:25:38 +00:00
|
|
|
self.data[i][s] = self.data[i][s] .. "," .. ReplaceHexChars(line,8,3)
|
|
|
|
if s == self.authors then
|
|
|
|
self.data[i][self.authors2] = self.data[i][self.authors2] .. " & " .. ReplaceHexChars(line,8,3)
|
|
|
|
elseif s == self.tags then
|
2014-08-18 07:48:46 +00:00
|
|
|
local dummy = ReplaceHexChars(line,8,3)
|
|
|
|
self.data[i][self.tags2] = self.data[i][self.tags2] .. " & " .. dummy
|
2014-08-19 15:50:02 +00:00
|
|
|
self.data[i][self.tags3] = self.data[i][self.tags3] .. "\t" .. dummy
|
2014-08-18 18:37:32 +00:00
|
|
|
self.browse_tags[dummy] = (self.browse_tags[dummy] or 0) + 1
|
2014-08-12 20:25:38 +00:00
|
|
|
end
|
2014-08-07 07:15:05 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
self.data[i][s] = string.sub(self.data[i][s],2)
|
2014-08-12 20:25:38 +00:00
|
|
|
if s == self.authors then
|
|
|
|
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)
|
2014-08-19 15:50:02 +00:00
|
|
|
self.data[i][self.tags3] = self.data[i][self.tags3] .. "\t"
|
2014-08-12 20:25:38 +00:00
|
|
|
end
|
2014-08-07 07:15:05 +00:00
|
|
|
end
|
|
|
|
|
2014-08-17 10:01:59 +00:00
|
|
|
if not self.use_previous_search_results then
|
2014-08-18 07:48:46 +00:00
|
|
|
self.results = {}
|
2014-08-17 10:01:59 +00:00
|
|
|
self.data = {}
|
2014-08-18 18:37:32 +00:00
|
|
|
self.browse_series = {}
|
|
|
|
self.browse_tags = {}
|
2014-08-14 11:49:42 +00:00
|
|
|
|
2014-08-17 10:01:59 +00:00
|
|
|
if SEARCH_CASESENSITIVE then
|
2014-08-18 07:48:46 +00:00
|
|
|
upsearch = self.search_value or ""
|
2014-08-17 10:01:59 +00:00
|
|
|
else
|
2014-08-18 07:48:46 +00:00
|
|
|
upsearch = string.upper(self.search_value or "")
|
2014-08-17 10:01:59 +00:00
|
|
|
end
|
2014-08-16 20:33:11 +00:00
|
|
|
|
2014-08-17 10:01:59 +00:00
|
|
|
firstrun = true
|
2014-08-16 20:33:11 +00:00
|
|
|
|
2014-08-18 07:48:46 +00:00
|
|
|
self.data[i] = {"-","-","-","-","-","-","-","-","-"}
|
2014-08-07 07:15:05 +00:00
|
|
|
|
2014-08-19 15:50:02 +00:00
|
|
|
if self.use_own_metadata_file then
|
|
|
|
g = io.open(koreaderfile,"r")
|
|
|
|
line = g:read()
|
2014-08-25 16:01:33 +00:00
|
|
|
if line ~= "#metadata.Koreader Version 1.1" then
|
|
|
|
self.use_own_metadata_file = false
|
|
|
|
g:close()
|
|
|
|
else
|
2014-08-19 15:50:02 +00:00
|
|
|
line = g:read()
|
2014-08-25 16:01:33 +00:00
|
|
|
end
|
|
|
|
if self.use_own_metadata_file then
|
|
|
|
while line do
|
2014-08-23 15:19:02 +00:00
|
|
|
|
2014-08-25 16:01:33 +00:00
|
|
|
for j = 1,9 do
|
2014-09-30 16:28:36 +00:00
|
|
|
self.data[i][j] = line or ""
|
2014-08-25 16:01:33 +00:00
|
|
|
line = g:read()
|
|
|
|
end
|
2014-08-13 06:08:18 +00:00
|
|
|
|
2014-08-25 16:01:33 +00:00
|
|
|
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
|
2014-08-19 15:50:02 +00:00
|
|
|
end
|
2014-08-25 16:01:33 +00:00
|
|
|
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
|
2014-08-19 15:50:02 +00:00
|
|
|
|
2014-08-25 16:01:33 +00:00
|
|
|
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
|
2014-08-18 07:48:46 +00:00
|
|
|
end
|
2014-08-27 07:17:54 +00:00
|
|
|
if DocumentRegistry:getProvider(self.data[i][self.path]) then
|
|
|
|
if upsearch ~= "" then
|
|
|
|
if string.find(dummy,upsearch,nil,true) then
|
2014-08-25 16:01:33 +00:00
|
|
|
i = i + 1
|
|
|
|
end
|
2014-08-27 07:17:54 +00:00
|
|
|
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
|
2014-08-25 16:01:33 +00:00
|
|
|
end
|
2014-08-18 18:37:32 +00:00
|
|
|
end
|
2014-08-18 07:48:46 +00:00
|
|
|
end
|
|
|
|
end
|
2014-08-25 16:01:33 +00:00
|
|
|
self.data[i] = {"-","-","-","-","-","-","-","-","-"}
|
2014-08-16 20:33:11 +00:00
|
|
|
end
|
2014-08-25 16:01:33 +00:00
|
|
|
g.close()
|
2014-08-16 20:33:11 +00:00
|
|
|
end
|
2014-08-25 16:01:33 +00:00
|
|
|
end
|
|
|
|
if not self.use_own_metadata_file then
|
2014-08-19 15:50:02 +00:00
|
|
|
f = io.open(self.metafile_1)
|
|
|
|
g = io.open(koreaderfile,"w")
|
2014-08-25 16:01:33 +00:00
|
|
|
g:write("#metadata.Koreader Version 1.1\n")
|
2014-08-19 15:50:02 +00:00
|
|
|
|
2014-08-17 10:01:59 +00:00
|
|
|
line = f:read()
|
2014-08-19 15:50:02 +00:00
|
|
|
while line do
|
|
|
|
if line == " }, " or line == " }" then
|
|
|
|
-- new calibre data set
|
|
|
|
|
|
|
|
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
|
2014-08-23 15:19:02 +00:00
|
|
|
dummy = dummy .. self.data[i][self.series] .. "\n"
|
2014-08-19 15:50:02 +00:00
|
|
|
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
|
2014-08-17 10:01:59 +00:00
|
|
|
|
2014-08-19 15:50:02 +00:00
|
|
|
for j = 1,9 do
|
|
|
|
g:write(self.data[i][j] .. "\n")
|
|
|
|
end
|
|
|
|
|
|
|
|
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
|
|
|
|
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
|
|
|
|
end
|
|
|
|
|
|
|
|
self.data[i] = {"-","-","-","-","-","-","-","-","-"}
|
|
|
|
|
|
|
|
elseif line == " \"authors\": [" then -- AUTHORS
|
|
|
|
ReadMultipleLines(self.authors)
|
|
|
|
elseif line == " \"tags\": [" then -- TAGS
|
|
|
|
ReadMultipleLines(self.tags)
|
|
|
|
elseif string.sub(line,1,11) == " \"title\"" then -- TITLE
|
|
|
|
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)
|
2014-08-25 16:01:33 +00:00
|
|
|
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
|
2014-08-19 15:50:02 +00:00
|
|
|
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
|
|
|
|
self.data[i][self.series_index] = ReplaceHexChars(line,21,2)
|
|
|
|
end
|
|
|
|
line = f:read()
|
|
|
|
|
|
|
|
if not line and firstrun then
|
|
|
|
if f ~= nil then f:close() end
|
|
|
|
firstrun = false
|
2014-08-23 15:19:02 +00:00
|
|
|
|
2014-08-19 15:50:02 +00:00
|
|
|
if self.metafile_2 then
|
|
|
|
f = io.open(self.metafile_2)
|
|
|
|
line = f:read()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
g.close()
|
|
|
|
if lfs.attributes(koreaderfile).modification < lfs.attributes(self.metafile_1).modification then
|
|
|
|
lfs.touch(koreaderfile, lfs.attributes(self.metafile_1).modification + 1, lfs.attributes(self.metafile_1).modification + 1)
|
|
|
|
end
|
|
|
|
if self.metafile_2 then
|
|
|
|
if lfs.attributes(koreaderfile).modification < lfs.attributes(self.metafile_2).modification then
|
|
|
|
lfs.touch(koreaderfile, lfs.attributes(self.metafile_2).modification + 1, lfs.attributes(self.metafile_2).modification + 1)
|
2014-08-17 10:01:59 +00:00
|
|
|
end
|
2014-08-16 20:33:11 +00:00
|
|
|
end
|
|
|
|
end
|
2014-08-17 10:01:59 +00:00
|
|
|
i = i - 1
|
2014-08-07 07:15:05 +00:00
|
|
|
self.count = i
|
2014-08-17 10:01:59 +00:00
|
|
|
end
|
|
|
|
if self.count > 0 then
|
|
|
|
self.data[self.count + 1] = nil
|
2014-08-18 07:48:46 +00:00
|
|
|
if option == "find" then
|
|
|
|
self:showresults()
|
|
|
|
else
|
|
|
|
self:browse(option,1)
|
2014-08-23 15:19:02 +00:00
|
|
|
end
|
2014-08-07 07:15:05 +00:00
|
|
|
else
|
2014-08-26 02:47:15 +00:00
|
|
|
dummy = _("No match for") .. " " .. self.search_value
|
2014-08-18 18:37:32 +00:00
|
|
|
UIManager:show(InfoMessage:new{text = dummy})
|
2014-08-07 07:15:05 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-08-12 20:25:38 +00:00
|
|
|
function Search:onMenuHold(item)
|
2014-08-18 07:48:46 +00:00
|
|
|
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
|
2014-08-19 16:04:38 +00:00
|
|
|
item.info = item.info .. "\n" .. _("Size:") .. " " .. string.format("%4.1fM",lfs.attributes(item.path, "size")/1024/1024)
|
2014-08-18 07:48:46 +00:00
|
|
|
f:close()
|
|
|
|
end
|
|
|
|
item.notchecked = false
|
2014-08-16 20:33:11 +00:00
|
|
|
end
|
2014-08-27 03:07:25 +00:00
|
|
|
local thumbnail = nil
|
|
|
|
local doc = DocumentRegistry:openDocument(item.path)
|
|
|
|
if doc then
|
|
|
|
thumbnail = doc:getCoverPageImage()
|
|
|
|
doc:close()
|
|
|
|
end
|
2014-08-23 15:19:02 +00:00
|
|
|
local thumbwidth = math.min(240, Screen:getWidth()/3)
|
2014-08-27 03:07:25 +00:00
|
|
|
UIManager:show(InfoMessage:new{
|
|
|
|
text = item.info,
|
|
|
|
image = thumbnail,
|
|
|
|
image_width = thumbwidth,
|
|
|
|
image_height = thumbwidth/2*3
|
|
|
|
})
|
2014-08-21 20:34:00 +00:00
|
|
|
|
2014-08-12 20:25:38 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-08-07 07:15:05 +00:00
|
|
|
function Search:showresults()
|
2014-10-03 08:11:53 +00:00
|
|
|
local ReaderUI = require("apps/reader/readerui")
|
2014-08-07 07:15:05 +00:00
|
|
|
local menu_container = CenterContainer:new{
|
|
|
|
dimen = Screen:getSize(),
|
|
|
|
}
|
|
|
|
self.search_menu = Menu:new{
|
2014-08-16 20:33:11 +00:00
|
|
|
width = Screen:getWidth()-15,
|
|
|
|
height = Screen:getHeight()-15,
|
2014-08-07 07:15:05 +00:00
|
|
|
show_parent = menu_container,
|
2014-08-12 20:25:38 +00:00
|
|
|
onMenuHold = self.onMenuHold,
|
2014-08-16 20:33:11 +00:00
|
|
|
cface = Font:getFace("cfont", 22),
|
2014-08-07 07:15:05 +00:00
|
|
|
_manager = self,
|
|
|
|
}
|
|
|
|
table.insert(menu_container, self.search_menu)
|
|
|
|
self.search_menu.close_callback = function()
|
|
|
|
UIManager:close(menu_container)
|
|
|
|
end
|
2014-08-17 10:01:59 +00:00
|
|
|
if not self.use_previous_search_results then
|
|
|
|
self.results = {}
|
|
|
|
local i = 1
|
|
|
|
while i <= self.count do
|
|
|
|
local dummy = _("Title: ") .. (self.data[i][self.title] or "-") .. "\n \n" ..
|
2014-08-19 16:04:38 +00:00
|
|
|
_("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 "-")
|
2014-08-17 10:01:59 +00:00
|
|
|
if self.data[i][self.series] ~= "-" then
|
|
|
|
dummy = dummy .. " (" .. tostring(self.data[i][self.series_index]):gsub(".0$","") .. ")"
|
|
|
|
end
|
|
|
|
dummy = dummy .. "\n \n" .. _("Path: ")
|
2014-08-25 16:01:33 +00:00
|
|
|
local book = self.data[i][self.path]
|
2014-08-17 10:01:59 +00:00
|
|
|
table.insert(self.results, {
|
|
|
|
info = dummy,
|
|
|
|
notchecked = true,
|
2014-08-25 16:01:33 +00:00
|
|
|
path = self.data[i][self.path],
|
2014-08-17 10:01:59 +00:00
|
|
|
text = self.data[i][self.authors] .. ": " .. self.data[i][self.title],
|
|
|
|
callback = function()
|
2014-09-07 22:43:32 +00:00
|
|
|
ReaderUI:showReader(book)
|
2014-08-17 10:01:59 +00:00
|
|
|
end
|
|
|
|
})
|
|
|
|
i = i + 1
|
2014-08-16 20:33:11 +00:00
|
|
|
end
|
2014-08-07 07:15:05 +00:00
|
|
|
end
|
2014-08-18 07:48:46 +00:00
|
|
|
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)
|
2014-10-03 08:11:53 +00:00
|
|
|
local ReaderUI = require("apps/reader/readerui")
|
2014-08-18 20:52:29 +00:00
|
|
|
local restart_me = false
|
2014-08-18 07:48:46 +00:00
|
|
|
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)
|
2014-08-18 20:52:29 +00:00
|
|
|
|
2014-08-18 07:48:46 +00:00
|
|
|
self.search_menu.close_callback = function()
|
|
|
|
UIManager:close(menu_container)
|
2014-08-18 20:52:29 +00:00
|
|
|
if restart_me then
|
|
|
|
if string.len(self.search_value) > 0 or self.lastsearch ~= "find" then
|
|
|
|
self.use_previous_search_results = true
|
|
|
|
self:getCalibre(1)
|
|
|
|
self:find(self.lastsearch)
|
|
|
|
end
|
|
|
|
end
|
2014-08-23 15:19:02 +00:00
|
|
|
|
2014-08-18 07:48:46 +00:00
|
|
|
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 = {}
|
2014-08-23 15:19:02 +00:00
|
|
|
if option == "series" then
|
2014-08-26 00:59:24 +00:00
|
|
|
for v,n in util.orderedPairs(self.browse_series) do
|
2014-08-18 07:48:46 +00:00
|
|
|
dummy = v
|
|
|
|
if not SEARCH_CASESENSITIVE then dummy = string.upper(dummy) end
|
|
|
|
if string.find(dummy,upsearch,nil,true) then
|
|
|
|
table.insert(self.results, {
|
2014-08-18 18:37:32 +00:00
|
|
|
text = v .. " (" .. tostring(self.browse_series[v]) .. ")",
|
2014-08-18 07:48:46 +00:00
|
|
|
callback = function()
|
|
|
|
self:browse(option,2,v)
|
|
|
|
end
|
|
|
|
})
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
2014-08-26 00:59:24 +00:00
|
|
|
for v,n in util.orderedPairs(self.browse_tags) do
|
2014-08-18 07:48:46 +00:00
|
|
|
dummy = v
|
|
|
|
if not SEARCH_CASESENSITIVE then dummy = string.upper(dummy) end
|
|
|
|
if string.find(dummy,upsearch,nil,true) then
|
|
|
|
table.insert(self.results, {
|
2014-08-18 18:37:32 +00:00
|
|
|
text = v .. " (" .. tostring(self.browse_tags[v]) .. ")",
|
2014-08-18 07:48:46 +00:00
|
|
|
callback = function()
|
|
|
|
self:browse(option,2,v)
|
|
|
|
end
|
|
|
|
})
|
|
|
|
end
|
|
|
|
end
|
2014-08-23 15:19:02 +00:00
|
|
|
end
|
2014-08-18 07:48:46 +00:00
|
|
|
else
|
2014-08-18 20:52:29 +00:00
|
|
|
restart_me = true
|
2014-08-18 07:48:46 +00:00
|
|
|
self.results = {}
|
|
|
|
local i = 1
|
|
|
|
while i <= self.count do
|
2014-08-19 15:50:02 +00:00
|
|
|
if (option == "tags" and self.data[i][self.tags3]:find("\t" .. chosen .. "\t",nil,true)) or (option == "series" and chosen == self.data[i][self.series]) then
|
2014-08-18 07:48:46 +00:00
|
|
|
local dummy = _("Title: ") .. (self.data[i][self.title] or "-") .. "\n \n" ..
|
2014-08-19 16:04:38 +00:00
|
|
|
_("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 "-")
|
2014-08-18 07:48:46 +00:00
|
|
|
if self.data[i][self.series] ~= "-" then
|
|
|
|
dummy = dummy .. " (" .. tostring(self.data[i][self.series_index]):gsub(".0$","") .. ")"
|
|
|
|
end
|
|
|
|
dummy = dummy .. "\n \n" .. _("Path: ")
|
2014-08-25 16:01:33 +00:00
|
|
|
local book = self.data[i][self.path]
|
2014-08-18 07:48:46 +00:00
|
|
|
local text
|
|
|
|
if option == "series" then
|
2014-08-22 16:30:20 +00:00
|
|
|
if self.data[i][self.series_index] == "0.0" then
|
|
|
|
text = self.data[i][self.title] .. " (" .. self.data[i][self.authors] .. ")"
|
|
|
|
else
|
|
|
|
text = string.format("%6.1f",self.data[i][self.series_index]:gsub(".0$","")) .. ": " .. self.data[i][self.title] .. " (" .. self.data[i][self.authors] .. ")"
|
|
|
|
end
|
2014-08-18 07:48:46 +00:00
|
|
|
else
|
|
|
|
text = self.data[i][self.authors] .. ": " .. self.data[i][self.title]
|
|
|
|
end
|
|
|
|
table.insert(self.results, {
|
|
|
|
text = text,
|
|
|
|
info = dummy,
|
|
|
|
notchecked = true,
|
2014-08-25 16:01:33 +00:00
|
|
|
path = self.data[i][self.path],
|
2014-08-18 07:48:46 +00:00
|
|
|
callback = function()
|
2014-09-07 22:43:32 +00:00
|
|
|
ReaderUI:showReader(book)
|
2014-08-18 07:48:46 +00:00
|
|
|
end
|
|
|
|
})
|
|
|
|
end
|
|
|
|
i = i + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
local dummy = ""
|
2014-08-23 15:19:02 +00:00
|
|
|
|
2014-08-18 07:48:46 +00:00
|
|
|
if run == 1 then
|
2014-08-19 16:04:38 +00:00
|
|
|
dummy = _("Browse") .. " " .. option
|
2014-08-18 07:48:46 +00:00
|
|
|
else
|
|
|
|
dummy = chosen
|
|
|
|
end
|
|
|
|
|
|
|
|
table.sort(self.results, function(v1,v2) return v1.text < v2.text end)
|
|
|
|
|
|
|
|
self.search_menu:swithItemTable(dummy, self.results)
|
2014-08-07 07:15:05 +00:00
|
|
|
UIManager:show(menu_container)
|
|
|
|
end
|
|
|
|
|
|
|
|
return Search
|