mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
File searcher: group operations (#11980)
This commit is contained in:
@@ -125,6 +125,7 @@ end
|
||||
function FileManager:setupLayout()
|
||||
self.show_parent = self.show_parent or self
|
||||
self.title_bar = TitleBar:new{
|
||||
show_parent = self.show_parent,
|
||||
fullscreen = "true",
|
||||
align = "center",
|
||||
title = self.title,
|
||||
@@ -137,7 +138,7 @@ function FileManager:setupLayout()
|
||||
left_icon_size_ratio = 1,
|
||||
left_icon_tap_callback = function() self:goHome() end,
|
||||
left_icon_hold_callback = function() self:onShowFolderMenu() end,
|
||||
right_icon = "plus",
|
||||
right_icon = self.selected_files and "check" or "plus",
|
||||
right_icon_size_ratio = 1,
|
||||
right_icon_tap_callback = function() self:onShowPlusMenu() end,
|
||||
right_icon_hold_callback = false, -- propagate long-press to dispatcher
|
||||
@@ -166,37 +167,31 @@ function FileManager:setupLayout()
|
||||
|
||||
local file_manager = self
|
||||
|
||||
function file_chooser:onPathChanged(path) -- luacheck: ignore
|
||||
function file_chooser:onPathChanged(path)
|
||||
file_manager:updateTitleBarPath(path)
|
||||
return true
|
||||
end
|
||||
|
||||
function file_chooser:onFileSelect(item) -- luacheck: ignore
|
||||
local file = item.path
|
||||
if file_manager.select_mode then
|
||||
if file_manager.selected_files[file] then
|
||||
file_manager.selected_files[file] = nil
|
||||
item.dim = nil
|
||||
else
|
||||
file_manager.selected_files[file] = true
|
||||
item.dim = true
|
||||
end
|
||||
function file_chooser:onFileSelect(item)
|
||||
if file_manager.selected_files then -- toggle selection
|
||||
item.dim = not item.dim and true or nil
|
||||
file_manager.selected_files[item.path] = item.dim
|
||||
self:updateItems()
|
||||
else
|
||||
file_manager:openFile(file)
|
||||
file_manager:openFile(item.path)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function file_chooser:onFileHold(item)
|
||||
if file_manager.select_mode then
|
||||
if file_manager.selected_files then
|
||||
file_manager:tapPlus()
|
||||
else
|
||||
self:showFileDialog(item)
|
||||
end
|
||||
end
|
||||
|
||||
function file_chooser:showFileDialog(item) -- luacheck: ignore
|
||||
function file_chooser:showFileDialog(item)
|
||||
local file = item.path
|
||||
local is_file = item.is_file
|
||||
local is_not_parent_folder = not item.is_go_up
|
||||
@@ -234,7 +229,7 @@ function FileManager:setupLayout()
|
||||
text = _("Select"),
|
||||
callback = function()
|
||||
UIManager:close(self.file_dialog)
|
||||
file_manager:onToggleSelectMode(true) -- no full screen refresh
|
||||
file_manager:onToggleSelectMode()
|
||||
if is_file then
|
||||
file_manager.selected_files[file] = true
|
||||
item.dim = true
|
||||
@@ -381,7 +376,7 @@ function FileManager:registerKeyEvents()
|
||||
-- Override the menu.lua way of handling the back key
|
||||
self.file_chooser.key_events.Back = { { Device.input.group.Back } }
|
||||
if Device:hasScreenKB() then
|
||||
self.key_events.KeyToggleWifi = { { "ScreenKB", "Home" }, event = "ToggleWifi" }
|
||||
self.key_events.ToggleWifi = { { "ScreenKB", "Home" } }
|
||||
end
|
||||
if not Device:hasFewKeys() then
|
||||
-- Also remove the handler assigned to the "Back" key by menu.lua
|
||||
@@ -495,14 +490,21 @@ function FileManager:onShowPlusMenu()
|
||||
return true
|
||||
end
|
||||
|
||||
function FileManager:onToggleSelectMode(no_refresh)
|
||||
function FileManager:onToggleSelectMode(do_refresh)
|
||||
logger.dbg("toggle select mode")
|
||||
self.select_mode = not self.select_mode
|
||||
self.selected_files = self.select_mode and {} or nil
|
||||
self.title_bar:setRightIcon(self.select_mode and "check" or "plus")
|
||||
if not no_refresh then
|
||||
self:onRefresh()
|
||||
if self.selected_files then
|
||||
self.selected_files = nil
|
||||
self.title_bar:setRightIcon("plus")
|
||||
if do_refresh then
|
||||
self.file_chooser:refreshPath()
|
||||
else
|
||||
self.file_chooser:selectAllFilesInFolder(false) -- undim
|
||||
end
|
||||
else
|
||||
self.selected_files = {}
|
||||
self.title_bar:setRightIcon("check")
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function FileManager:tapPlus()
|
||||
@@ -514,9 +516,9 @@ function FileManager:tapPlus()
|
||||
end
|
||||
|
||||
local title, buttons
|
||||
if self.select_mode then
|
||||
if self.selected_files then
|
||||
local function toggle_select_mode_callback()
|
||||
self:onToggleSelectMode()
|
||||
self:onToggleSelectMode(true)
|
||||
end
|
||||
local select_count = util.tableSize(self.selected_files)
|
||||
local actions_enabled = select_count > 0
|
||||
@@ -624,7 +626,7 @@ function FileManager:tapPlus()
|
||||
text = _("Select files"),
|
||||
callback = function()
|
||||
UIManager:close(self.file_dialog)
|
||||
self:onToggleSelectMode(true) -- no full screen refresh
|
||||
self:onToggleSelectMode()
|
||||
end,
|
||||
},
|
||||
},
|
||||
@@ -722,7 +724,7 @@ function FileManager:tapPlus()
|
||||
title = title,
|
||||
title_align = "center",
|
||||
buttons = buttons,
|
||||
select_mode = self.select_mode, -- for coverbrowser
|
||||
select_mode = self.selected_files and true or nil, -- for coverbrowser
|
||||
}
|
||||
UIManager:show(self.file_dialog)
|
||||
end
|
||||
@@ -746,9 +748,6 @@ function FileManager:reinit(path, focused_file)
|
||||
-- looks unnecessary (cheap with classic mode, less cheap with
|
||||
-- CoverBrowser plugin's cover image renderings)
|
||||
-- self:onRefresh()
|
||||
if self.select_mode then
|
||||
self.title_bar:setRightIcon("check")
|
||||
end
|
||||
end
|
||||
|
||||
function FileManager:getCurrentDir()
|
||||
@@ -989,7 +988,7 @@ function FileManager:pasteSelectedFiles(overwrite)
|
||||
icon = "notice-warning",
|
||||
})
|
||||
else
|
||||
self:onToggleSelectMode()
|
||||
self:onToggleSelectMode(true)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1117,7 +1116,7 @@ function FileManager:deleteSelectedFiles()
|
||||
icon = "notice-warning",
|
||||
})
|
||||
else
|
||||
self:onToggleSelectMode()
|
||||
self:onToggleSelectMode(true)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1208,7 +1207,7 @@ function FileManager:renameFile(file, basename, is_file)
|
||||
end
|
||||
|
||||
--- @note: This is the *only* safe way to instantiate a new FileManager instance!
|
||||
function FileManager:showFiles(path, focused_file)
|
||||
function FileManager:showFiles(path, focused_file, selected_files)
|
||||
-- Warn about and close any pre-existing FM instances first...
|
||||
if FileManager.instance then
|
||||
logger.warn("FileManager instance mismatch! Tried to spin up a new instance, while we still have an existing one:", tostring(FileManager.instance))
|
||||
@@ -1224,6 +1223,7 @@ function FileManager:showFiles(path, focused_file)
|
||||
covers_fullscreen = true, -- hint for UIManager:_repaint()
|
||||
root_path = path,
|
||||
focused_file = focused_file,
|
||||
selected_files = selected_files,
|
||||
}
|
||||
UIManager:show(file_manager)
|
||||
end
|
||||
@@ -1348,6 +1348,7 @@ function FileManager:showSelectedFilesList()
|
||||
item_table = selected_files,
|
||||
is_borderless = true,
|
||||
is_popout = false,
|
||||
title_bar_fm_style = true,
|
||||
truncate_left = true,
|
||||
onMenuSelect = function(_, item)
|
||||
UIManager:close(menu)
|
||||
|
||||
@@ -97,14 +97,9 @@ function FileSearcher:onShowFileSearch(search_string)
|
||||
end
|
||||
|
||||
function FileSearcher:doSearch()
|
||||
local results
|
||||
local dirs, files = self:getList()
|
||||
-- If we have a FileChooser instance, use it, to be able to make use of its natsort cache
|
||||
if self.ui.file_chooser then
|
||||
results = self.ui.file_chooser:genItemTable(dirs, files)
|
||||
else
|
||||
results = FileChooser:genItemTable(dirs, files)
|
||||
end
|
||||
local results = (self.ui.file_chooser or FileChooser):genItemTable(dirs, files)
|
||||
if #results > 0 then
|
||||
self:showSearchResults(results)
|
||||
else
|
||||
@@ -221,31 +216,51 @@ end
|
||||
|
||||
function FileSearcher:showSearchResults(results)
|
||||
self.search_menu = Menu:new{
|
||||
title = T(_("Search results (%1)"), #results),
|
||||
subtitle = T(_("Query: %1"), self.search_string),
|
||||
item_table = results,
|
||||
ui = self.ui,
|
||||
covers_fullscreen = true, -- hint for UIManager:_repaint()
|
||||
is_borderless = true,
|
||||
is_popout = false,
|
||||
title_bar_fm_style = true,
|
||||
title_bar_left_icon = "appbar.menu",
|
||||
onLeftButtonTap = function() self:setSelectMode() end,
|
||||
onMenuSelect = self.onMenuSelect,
|
||||
onMenuHold = self.onMenuHold,
|
||||
handle_hold_on_hold_release = true,
|
||||
ui = self.ui,
|
||||
_manager = self,
|
||||
}
|
||||
self.search_menu.close_callback = function()
|
||||
self.selected_files = nil
|
||||
UIManager:close(self.search_menu)
|
||||
if self.ui.file_chooser then
|
||||
self.ui.file_chooser:refreshPath()
|
||||
end
|
||||
end
|
||||
self:updateMenu(results)
|
||||
UIManager:show(self.search_menu)
|
||||
if self.no_metadata_count ~= 0 then
|
||||
self:showSearchResultsMessage()
|
||||
end
|
||||
end
|
||||
|
||||
function FileSearcher:updateMenu(item_table)
|
||||
item_table = item_table or self.search_menu.item_table
|
||||
self.search_menu:switchItemTable(T(_("Search results (%1)"), #item_table), item_table, -1)
|
||||
end
|
||||
|
||||
function FileSearcher:onMenuSelect(item)
|
||||
if self._manager.selected_files then
|
||||
if item.is_file then
|
||||
item.dim = not item.dim and true or nil
|
||||
self._manager.selected_files[item.path] = item.dim
|
||||
self._manager:updateMenu()
|
||||
end
|
||||
else
|
||||
self._manager:showFileDialog(item)
|
||||
end
|
||||
end
|
||||
|
||||
function FileSearcher:showFileDialog(item)
|
||||
local file = item.path
|
||||
local bookinfo, dialog
|
||||
local function close_dialog_callback()
|
||||
@@ -253,7 +268,11 @@ function FileSearcher:onMenuSelect(item)
|
||||
end
|
||||
local function close_dialog_menu_callback()
|
||||
UIManager:close(dialog)
|
||||
self.close_callback()
|
||||
self.search_menu.close_callback()
|
||||
end
|
||||
local function update_item_callback()
|
||||
item.mandatory = FileChooser:getMenuItemMandatory(item, FileChooser:getCollate())
|
||||
self:updateMenu()
|
||||
end
|
||||
local buttons = {}
|
||||
if item.is_file then
|
||||
@@ -265,7 +284,7 @@ function FileSearcher:onMenuSelect(item)
|
||||
table.insert(buttons, {}) -- separator
|
||||
table.insert(buttons, {
|
||||
filemanagerutil.genResetSettingsButton(file, close_dialog_callback, is_currently_opened),
|
||||
self.ui.collections:genAddToCollectionButton(file, close_dialog_callback),
|
||||
self.ui.collections:genAddToCollectionButton(file, close_dialog_callback, update_item_callback),
|
||||
})
|
||||
end
|
||||
table.insert(buttons, {
|
||||
@@ -275,13 +294,8 @@ function FileSearcher:onMenuSelect(item)
|
||||
callback = function()
|
||||
local function post_delete_callback()
|
||||
UIManager:close(dialog)
|
||||
for i, menu_item in ipairs(self.item_table) do
|
||||
if menu_item.path == file then
|
||||
table.remove(self.item_table, i)
|
||||
break
|
||||
end
|
||||
self:switchItemTable(T(_("Search results (%1)"), #self.item_table), self.item_table)
|
||||
end
|
||||
table.remove(self.search_menu.item_table, item.idx)
|
||||
self:updateMenu()
|
||||
end
|
||||
local FileManager = require("apps/filemanager/filemanager")
|
||||
FileManager:showDeleteFileDialog(file, post_delete_callback)
|
||||
@@ -296,9 +310,9 @@ function FileSearcher:onMenuSelect(item)
|
||||
text = _("Open"),
|
||||
enabled = DocumentRegistry:hasProvider(file, nil, true), -- allow auxiliary providers
|
||||
callback = function()
|
||||
close_dialog_callback()
|
||||
close_dialog_menu_callback()
|
||||
local FileManager = require("apps/filemanager/filemanager")
|
||||
FileManager.openFile(self.ui, file, nil, self.close_callback)
|
||||
FileManager.openFile(self.ui, file)
|
||||
end,
|
||||
},
|
||||
})
|
||||
@@ -319,10 +333,12 @@ function FileSearcher:onMenuSelect(item)
|
||||
end
|
||||
|
||||
function FileSearcher:onMenuHold(item)
|
||||
if self._manager.selected_files then return true end
|
||||
if item.is_file then
|
||||
if DocumentRegistry:hasProvider(item.path, nil, true) then
|
||||
self.close_callback()
|
||||
local FileManager = require("apps/filemanager/filemanager")
|
||||
FileManager.openFile(self.ui, item.path, nil, self.close_callback)
|
||||
FileManager.openFile(self.ui, item.path)
|
||||
end
|
||||
else
|
||||
self.close_callback()
|
||||
@@ -337,4 +353,92 @@ function FileSearcher:onMenuHold(item)
|
||||
return true
|
||||
end
|
||||
|
||||
function FileSearcher:setSelectMode()
|
||||
if self.selected_files then
|
||||
self:showSelectModeDialog()
|
||||
else
|
||||
self.selected_files = {}
|
||||
self.search_menu:setTitleBarLeftIcon("check")
|
||||
end
|
||||
end
|
||||
|
||||
function FileSearcher:showSelectModeDialog()
|
||||
local item_table = self.search_menu.item_table
|
||||
local select_count = util.tableSize(self.selected_files)
|
||||
local actions_enabled = select_count > 0
|
||||
local title = actions_enabled and T(N_("1 file selected", "%1 files selected", select_count), select_count)
|
||||
or _("No files selected")
|
||||
local select_dialog
|
||||
local buttons = {
|
||||
{
|
||||
{
|
||||
text = _("Deselect all"),
|
||||
enabled = actions_enabled,
|
||||
callback = function()
|
||||
UIManager:close(select_dialog)
|
||||
for file in pairs (self.selected_files) do
|
||||
self.selected_files[file] = nil
|
||||
end
|
||||
for _, item in ipairs(item_table) do
|
||||
item.dim = nil
|
||||
end
|
||||
self:updateMenu()
|
||||
end,
|
||||
},
|
||||
{
|
||||
text = _("Select all"),
|
||||
callback = function()
|
||||
UIManager:close(select_dialog)
|
||||
for _, item in ipairs(item_table) do
|
||||
if item.is_file then
|
||||
item.dim = true
|
||||
self.selected_files[item.path] = true
|
||||
end
|
||||
end
|
||||
self:updateMenu()
|
||||
end,
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
text = _("Exit select mode"),
|
||||
callback = function()
|
||||
UIManager:close(select_dialog)
|
||||
self.selected_files = nil
|
||||
self.search_menu:setTitleBarLeftIcon("appbar.menu")
|
||||
if actions_enabled then
|
||||
for _, item in ipairs(item_table) do
|
||||
item.dim = nil
|
||||
end
|
||||
end
|
||||
self:updateMenu()
|
||||
end,
|
||||
},
|
||||
{
|
||||
text = _("Select in file browser"),
|
||||
enabled = actions_enabled,
|
||||
callback = function()
|
||||
UIManager:close(select_dialog)
|
||||
local selected_files = self.selected_files
|
||||
self.search_menu.close_callback()
|
||||
if self.ui.file_chooser then
|
||||
self.ui.selected_files = selected_files
|
||||
self.ui.title_bar:setRightIcon("check")
|
||||
self.ui.file_chooser:refreshPath()
|
||||
else -- called from Reader
|
||||
self.ui:onClose()
|
||||
self.ui:showFileManager(self.path .. "/", selected_files)
|
||||
end
|
||||
end,
|
||||
},
|
||||
},
|
||||
}
|
||||
select_dialog = ButtonDialog:new{
|
||||
title = title,
|
||||
title_align = "center",
|
||||
buttons = buttons,
|
||||
}
|
||||
UIManager:show(select_dialog)
|
||||
end
|
||||
|
||||
return FileSearcher
|
||||
|
||||
@@ -563,7 +563,7 @@ function ReaderUI:getLastDirFile(to_file_browser)
|
||||
return last_dir, last_file
|
||||
end
|
||||
|
||||
function ReaderUI:showFileManager(file)
|
||||
function ReaderUI:showFileManager(file, selected_files)
|
||||
local FileManager = require("apps/filemanager/filemanager")
|
||||
|
||||
local last_dir, last_file
|
||||
@@ -576,7 +576,7 @@ function ReaderUI:showFileManager(file)
|
||||
if FileManager.instance then
|
||||
FileManager.instance:reinit(last_dir, last_file)
|
||||
else
|
||||
FileManager:showFiles(last_dir, last_file)
|
||||
FileManager:showFiles(last_dir, last_file, selected_files)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user