2014-11-16 11:57:56 +00:00
|
|
|
local CenterContainer = require("ui/widget/container/centercontainer")
|
|
|
|
local DocumentRegistry = require("document/documentregistry")
|
2017-04-29 08:38:09 +00:00
|
|
|
local Font = require("ui/font")
|
2014-11-16 11:57:56 +00:00
|
|
|
local InfoMessage = require("ui/widget/infomessage")
|
2017-04-29 08:38:09 +00:00
|
|
|
local InputContainer = require("ui/widget/container/inputcontainer")
|
2018-07-24 19:11:25 +00:00
|
|
|
local InputDialog = require("ui/widget/inputdialog")
|
2014-11-16 11:57:56 +00:00
|
|
|
local Menu = require("ui/widget/menu")
|
2017-04-29 08:38:09 +00:00
|
|
|
local UIManager = require("ui/uimanager")
|
|
|
|
local lfs = require("libs/libkoreader-lfs")
|
2020-02-05 02:14:21 +00:00
|
|
|
local BaseUtil = require("ffi/util")
|
|
|
|
local util = require("util")
|
2014-11-16 11:57:56 +00:00
|
|
|
local _ = require("gettext")
|
2017-04-29 08:38:09 +00:00
|
|
|
local Screen = require("device").screen
|
2014-11-16 11:57:56 +00:00
|
|
|
|
|
|
|
local FileSearcher = InputContainer:new{
|
|
|
|
search_dialog = nil,
|
2015-04-27 00:49:27 +00:00
|
|
|
|
2014-11-16 11:57:56 +00:00
|
|
|
--filesearcher
|
|
|
|
-- state buffer
|
|
|
|
dirs = {},
|
|
|
|
files = {},
|
|
|
|
results = {},
|
|
|
|
items = 0,
|
|
|
|
commands = nil,
|
2015-04-27 00:49:27 +00:00
|
|
|
|
2014-11-16 11:57:56 +00:00
|
|
|
--filemanagersearch
|
|
|
|
use_previous_search_results = false,
|
|
|
|
lastsearch = nil,
|
|
|
|
}
|
|
|
|
|
|
|
|
function FileSearcher:readDir()
|
|
|
|
self.dirs = {self.path}
|
|
|
|
self.files = {}
|
|
|
|
while #self.dirs ~= 0 do
|
2015-04-27 00:49:27 +00:00
|
|
|
local new_dirs = {}
|
2014-11-16 11:57:56 +00:00
|
|
|
-- handle each dir
|
|
|
|
for __, d in pairs(self.dirs) do
|
|
|
|
-- handle files in d
|
|
|
|
for f in lfs.dir(d) do
|
|
|
|
local fullpath = d.."/"..f
|
2019-09-09 16:39:36 +00:00
|
|
|
local attributes = lfs.attributes(fullpath) or {}
|
2020-02-05 02:14:21 +00:00
|
|
|
-- Don't traverse hidden folders if we're not showing them
|
|
|
|
if attributes.mode == "directory" and f ~= "." and f ~= ".." and (G_reader_settings:isTrue("show_hidden") or not util.stringStartsWith(f, ".")) then
|
2016-01-07 06:44:07 +00:00
|
|
|
table.insert(new_dirs, fullpath)
|
2017-02-25 14:26:52 +00:00
|
|
|
table.insert(self.files, {name = f, path = fullpath, attr = attributes})
|
2020-02-05 02:14:21 +00:00
|
|
|
-- Always ignore macOS resource forks, too.
|
|
|
|
elseif attributes.mode == "file" and not util.stringStartsWith(f, "._") and DocumentRegistry:hasProvider(fullpath) then
|
2014-11-16 11:57:56 +00:00
|
|
|
table.insert(self.files, {name = f, path = fullpath, attr = attributes})
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
self.dirs = new_dirs
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function FileSearcher:setSearchResults()
|
2017-02-25 14:26:52 +00:00
|
|
|
local FileManager = require("apps/filemanager/filemanager")
|
2014-11-16 11:57:56 +00:00
|
|
|
local ReaderUI = require("apps/reader/readerui")
|
|
|
|
local keywords = self.search_value
|
|
|
|
self.results = {}
|
|
|
|
if keywords == " " then -- one space to show all files
|
|
|
|
self.results = self.files
|
|
|
|
else
|
|
|
|
for __,f in pairs(self.files) do
|
2017-03-26 14:30:50 +00:00
|
|
|
if string.find(string.lower(f.name), string.lower(keywords)) and string.sub(f.name,-4) ~= ".sdr" then
|
2017-02-25 14:26:52 +00:00
|
|
|
if f.attr.mode == "directory" then
|
|
|
|
f.text = f.name.."/"
|
|
|
|
f.name = nil
|
|
|
|
f.callback = function()
|
|
|
|
FileManager:showFiles(f.path)
|
|
|
|
end
|
|
|
|
table.insert(self.results, f)
|
|
|
|
else
|
|
|
|
f.text = f.name
|
|
|
|
f.name = nil
|
|
|
|
f.callback = function()
|
|
|
|
ReaderUI:showReader(f.path)
|
|
|
|
end
|
|
|
|
table.insert(self.results, f)
|
2014-11-16 11:57:56 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
self.keywords = keywords
|
|
|
|
self.items = #self.results
|
|
|
|
end
|
|
|
|
|
|
|
|
function FileSearcher:close()
|
|
|
|
if self.search_value then
|
|
|
|
UIManager:close(self.search_dialog)
|
|
|
|
if string.len(self.search_value) > 0 then
|
2019-08-23 17:53:53 +00:00
|
|
|
self:readDir() --- @todo this probably doesn't need to be repeated once it's been done
|
|
|
|
self:setSearchResults() --- @todo doesn't have to be repeated if the search term is the same
|
2014-11-20 21:42:51 +00:00
|
|
|
if #self.results > 0 then
|
2019-08-23 17:53:53 +00:00
|
|
|
self:showSearchResults() --- @todo something about no results
|
2014-11-20 21:42:51 +00:00
|
|
|
else
|
|
|
|
UIManager:show(
|
|
|
|
InfoMessage:new{
|
2020-02-05 02:14:21 +00:00
|
|
|
text = BaseUtil.template(_("Found no files matching '%1'."),
|
2017-05-08 07:26:01 +00:00
|
|
|
self.search_value)
|
2014-11-20 21:42:51 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
end
|
2014-11-16 11:57:56 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-07-12 18:47:49 +00:00
|
|
|
function FileSearcher:onShowFileSearch()
|
2014-11-16 11:57:56 +00:00
|
|
|
local dummy = self.search_value
|
2018-07-24 19:11:25 +00:00
|
|
|
local enabled_search_home_dir = true
|
|
|
|
if not G_reader_settings:readSetting("home_dir") then
|
|
|
|
enabled_search_home_dir = false
|
|
|
|
end
|
2014-11-16 11:57:56 +00:00
|
|
|
self.search_dialog = InputDialog:new{
|
2015-04-27 00:49:27 +00:00
|
|
|
title = _("Search for books by filename"),
|
2014-11-16 11:57:56 +00:00
|
|
|
input = self.search_value,
|
2020-06-12 23:56:36 +00:00
|
|
|
width = math.floor(Screen:getWidth() * 0.9),
|
2014-11-16 11:57:56 +00:00
|
|
|
buttons = {
|
|
|
|
{
|
|
|
|
{
|
|
|
|
text = _("Cancel"),
|
|
|
|
enabled = true,
|
|
|
|
callback = function()
|
|
|
|
self.search_dialog:onClose()
|
|
|
|
UIManager:close(self.search_dialog)
|
|
|
|
end,
|
|
|
|
},
|
|
|
|
{
|
2018-07-24 19:11:25 +00:00
|
|
|
text = _("Current folder"),
|
2014-11-16 11:57:56 +00:00
|
|
|
enabled = true,
|
|
|
|
callback = function()
|
2020-07-12 18:47:49 +00:00
|
|
|
self.path = self.ui.file_chooser and self.ui.file_chooser.path or self.ui:getLastDirFile()
|
2018-07-24 19:11:25 +00:00
|
|
|
self.search_value = self.search_dialog:getInputText()
|
|
|
|
if self.search_value == dummy then -- probably DELETE this if/else block
|
|
|
|
self.use_previous_search_results = true
|
|
|
|
else
|
|
|
|
self.use_previous_search_results = false
|
|
|
|
end
|
|
|
|
self:close()
|
|
|
|
end,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text = _("Home folder"),
|
|
|
|
enabled = enabled_search_home_dir,
|
|
|
|
callback = function()
|
|
|
|
self.path = G_reader_settings:readSetting("home_dir")
|
2014-11-16 11:57:56 +00:00
|
|
|
self.search_value = self.search_dialog:getInputText()
|
|
|
|
if self.search_value == dummy then -- probably DELETE this if/else block
|
|
|
|
self.use_previous_search_results = true
|
|
|
|
else
|
|
|
|
self.use_previous_search_results = false
|
|
|
|
end
|
|
|
|
self:close()
|
|
|
|
end,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
UIManager:show(self.search_dialog)
|
2018-03-30 10:46:36 +00:00
|
|
|
self.search_dialog:onShowKeyboard()
|
2014-11-16 11:57:56 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function FileSearcher:showSearchResults()
|
|
|
|
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,
|
2017-04-29 08:38:09 +00:00
|
|
|
cface = Font:getFace("smallinfofont"),
|
2014-11-16 11:57:56 +00:00
|
|
|
_manager = self,
|
|
|
|
}
|
|
|
|
table.insert(menu_container, self.search_menu)
|
|
|
|
self.search_menu.close_callback = function()
|
|
|
|
UIManager:close(menu_container)
|
|
|
|
end
|
|
|
|
table.sort(self.results, function(v1,v2) return v1.text < v2.text end)
|
2017-02-01 14:24:21 +00:00
|
|
|
self.search_menu:switchItemTable(_("Search Results"), self.results)
|
2014-11-16 11:57:56 +00:00
|
|
|
UIManager:show(menu_container)
|
|
|
|
end
|
|
|
|
|
|
|
|
return FileSearcher
|