@ -57,6 +57,10 @@ local FileManager = InputContainer:extend{
cp_bin = Device : isAndroid ( ) and " /system/bin/cp " or " /bin/cp " ,
cp_bin = Device : isAndroid ( ) and " /system/bin/cp " or " /bin/cp " ,
}
}
local function isFile ( file )
return lfs.attributes ( file , " mode " ) == " file "
end
function FileManager : onSetRotationMode ( rotation )
function FileManager : onSetRotationMode ( rotation )
if rotation ~= nil and rotation ~= Screen : getRotationMode ( ) then
if rotation ~= nil and rotation ~= Screen : getRotationMode ( ) then
Screen : setRotationMode ( rotation )
Screen : setRotationMode ( rotation )
@ -190,7 +194,7 @@ function FileManager:setupLayout()
end
end
function file_chooser : showFileDialog ( file ) -- luacheck: ignore
function file_chooser : showFileDialog ( file ) -- luacheck: ignore
local is_file = lfs.attributes( file , " mode " ) == " file "
local is_file = isFile( file )
local is_folder = lfs.attributes ( file , " mode " ) == " directory "
local is_folder = lfs.attributes ( file , " mode " ) == " directory "
local is_not_parent_folder = BaseUtil.basename ( file ) ~= " .. "
local is_not_parent_folder = BaseUtil.basename ( file ) ~= " .. "
@ -220,7 +224,7 @@ function FileManager:setupLayout()
enabled = file_manager.clipboard and true or false ,
enabled = file_manager.clipboard and true or false ,
callback = function ( )
callback = function ( )
UIManager : close ( self.file_dialog )
UIManager : close ( self.file_dialog )
file_manager : paste Here ( file )
file_manager : paste FileFromClipboard ( file )
end ,
end ,
} ,
} ,
{
{
@ -514,20 +518,9 @@ function FileManager:tapPlus()
text = _ ( " Copy " ) ,
text = _ ( " Copy " ) ,
enabled = actions_enabled ,
enabled = actions_enabled ,
callback = function ( )
callback = function ( )
UIManager : show ( ConfirmBox : new {
self.cutfile = false
text = _ ( " Copy selected files to the current folder? " ) ,
self : showCopyMoveSelectedFilesDialog ( close_dialog_callback )
ok_text = _ ( " Copy " ) ,
end ,
ok_callback = function ( )
UIManager : close ( self.file_dialog )
self.cutfile = false
for file in pairs ( self.selected_files ) do
self.clipboard = file
self : pasteHere ( )
end
self : onToggleSelectMode ( )
end ,
} )
end
} ,
} ,
} ,
} ,
{
{
@ -543,20 +536,9 @@ function FileManager:tapPlus()
text = _ ( " Move " ) ,
text = _ ( " Move " ) ,
enabled = actions_enabled ,
enabled = actions_enabled ,
callback = function ( )
callback = function ( )
UIManager : show ( ConfirmBox : new {
self.cutfile = true
text = _ ( " Move selected files to the current folder? " ) ,
self : showCopyMoveSelectedFilesDialog ( close_dialog_callback )
ok_text = _ ( " Move " ) ,
end ,
ok_callback = function ( )
UIManager : close ( self.file_dialog )
self.cutfile = true
for file in pairs ( self.selected_files ) do
self.clipboard = file
self : pasteHere ( )
end
self : onToggleSelectMode ( )
end ,
} )
end
} ,
} ,
} ,
} ,
{
{
@ -565,7 +547,9 @@ function FileManager:tapPlus()
enabled = actions_enabled ,
enabled = actions_enabled ,
callback = function ( )
callback = function ( )
UIManager : close ( self.file_dialog )
UIManager : close ( self.file_dialog )
self.selected_files = { }
for file in pairs ( self.selected_files ) do
self.selected_files [ file ] = nil
end
self : onRefresh ( )
self : onRefresh ( )
end ,
end ,
} ,
} ,
@ -578,10 +562,7 @@ function FileManager:tapPlus()
ok_text = _ ( " Delete " ) ,
ok_text = _ ( " Delete " ) ,
ok_callback = function ( )
ok_callback = function ( )
UIManager : close ( self.file_dialog )
UIManager : close ( self.file_dialog )
for file in pairs ( self.selected_files ) do
self : deleteSelectedFiles ( )
self : deleteFile ( file , true ) -- only files can be selected
end
self : onToggleSelectMode ( )
end ,
end ,
} )
} )
end ,
end ,
@ -642,7 +623,7 @@ function FileManager:tapPlus()
enabled = self.clipboard and true or false ,
enabled = self.clipboard and true or false ,
callback = function ( )
callback = function ( )
UIManager : close ( self.file_dialog )
UIManager : close ( self.file_dialog )
self : paste Here ( )
self : paste FileFromClipboard ( )
end ,
end ,
} ,
} ,
} ,
} ,
@ -651,7 +632,7 @@ function FileManager:tapPlus()
text = _ ( " Set as HOME folder " ) ,
text = _ ( " Set as HOME folder " ) ,
callback = function ( )
callback = function ( )
UIManager : close ( self.file_dialog )
UIManager : close ( self.file_dialog )
self : setHome ( self.file_chooser . path )
self : setHome ( )
end
end
} ,
} ,
} ,
} ,
@ -850,66 +831,137 @@ function FileManager:cutFile(file)
self.clipboard = file
self.clipboard = file
end
end
function FileManager : paste Here ( file )
function FileManager : paste FileFromClipboard ( file )
local orig_file = BaseUtil.realpath ( self.clipboard )
local orig_file = BaseUtil.realpath ( self.clipboard )
local orig_name = BaseUtil.basename ( self.clipboard )
local orig_name = BaseUtil.basename ( orig_file )
local dest_path = BaseUtil.realpath ( file or self.file_chooser . path )
local dest_path = BaseUtil.realpath ( file or self.file_chooser . path )
dest_path = lfs.attributes( dest_path , " mode " ) == " directory " and dest_path or dest_path : match ( " (.*/) " )
dest_path = isFile( dest_path ) and dest_path : match ( " (.*/) " ) or dest_path
local dest_file = BaseUtil.joinPath ( dest_path , orig_name )
local dest_file = BaseUtil.joinPath ( dest_path , orig_name )
local is_file = lfs.attributes( orig_file , " mode " ) == " file "
local is_file = isFile( orig_file )
local function infoCopyFile ( )
local function doPaste ( )
if self : copyRecursive ( orig_file , dest_path ) then
local ok
if is_file then
if self.cutfile then
DocSettings.updateLocation ( orig_file , dest_file , true )
ok = self : moveFile ( orig_file , dest_path )
else
ok = self : copyRecursive ( orig_file , dest_path )
end
if ok then
if is_file then -- move or copy sdr
DocSettings.updateLocation ( orig_file , dest_file , not self.cutfile )
end
end
return true
if self.cutfile then -- for move only
if is_file then
ReadHistory : updateItem ( orig_file , dest_file )
ReadCollection : updateItem ( orig_file , dest_file )
else
ReadHistory : updateItemsByPath ( orig_file , dest_file )
ReadCollection : updateItemsByPath ( orig_file , dest_file )
end
end
self.clipboard = nil
self : onRefresh ( )
else
else
local text = self.cutfile and " Failed to move: \n %1 \n to: \n %2 "
or " Failed to copy: \n %1 \n to: \n %2 "
UIManager : show ( InfoMessage : new {
UIManager : show ( InfoMessage : new {
text = T ( _ ( " Failed to copy: \n %1 \n to: \n %2 " ) , BD.filepath ( orig_name ) , BD.dirpath ( dest_path ) ) ,
text = T ( _ ( text ) , BD.filepath ( orig_name ) , BD.dirpath ( dest_path ) ) ,
icon = " notice-warning " ,
icon = " notice-warning " ,
} )
} )
end
end
end
end
local function infoMoveFile ( )
local mode_dest = lfs.attributes ( dest_file , " mode " )
if self : moveFile ( orig_file , dest_path ) then
if mode_dest then -- file or folder with target name already exists
if is_file then
local can_overwrite = ( mode_dest == " file " ) == is_file
DocSettings.updateLocation ( orig_file , dest_file )
local text = can_overwrite == is_file and T ( _ ( " File already exists: \n %1 " ) , BD.filename ( orig_name ) )
ReadHistory : updateItemByPath ( orig_file , dest_file ) -- (will update "lastfile" if needed)
or T ( _ ( " Folder already exists: \n %1 " ) , BD.directory ( orig_name ) )
else
if can_overwrite then
ReadHistory : updateItemsByPath ( orig_file , dest_file )
UIManager : show ( ConfirmBox : new {
end
text = text ,
ReadCollection : updateItemByPath ( orig_file , dest_file )
ok_text = _ ( " Overwrite " ) ,
return true
ok_callback = function ( )
doPaste ( )
end ,
} )
else
else
UIManager : show ( InfoMessage : new {
UIManager : show ( InfoMessage : new {
text = T ( _ ( " Failed to move: \n %1 \n to: \n %2 " ) , BD.filepath ( orig_name ) , BD.dirpath ( dest_path ) ) ,
text = text ,
icon = " notice-warning " ,
icon = " notice-warning " ,
} )
} )
end
end
else
doPaste ( )
end
end
end
local function doPaste ( )
function FileManager : showCopyMoveSelectedFilesDialog ( close_callback )
local ok = self.cutfile and infoMoveFile ( ) or infoCopyFile ( )
local text , ok_text
if self.cutfile then
text = _ ( " Move selected files to the current folder? " )
ok_text = _ ( " Move " )
else
text = _ ( " Copy selected files to the current folder? " )
ok_text = _ ( " Copy " )
end
local confirmbox , check_button_overwrite
confirmbox = ConfirmBox : new {
text = text ,
ok_text = ok_text ,
ok_callback = function ( )
close_callback ( )
self : pasteSelectedFiles ( check_button_overwrite.checked )
end ,
}
check_button_overwrite = CheckButton : new {
text = _ ( " overwrite existing files " ) ,
checked = true ,
parent = confirmbox ,
}
confirmbox : addWidget ( check_button_overwrite )
UIManager : show ( confirmbox )
end
function FileManager : pasteSelectedFiles ( overwrite )
local dest_path = BaseUtil.realpath ( self.file_chooser . path )
local ok_files = { }
for orig_file in pairs ( self.selected_files ) do
local orig_name = BaseUtil.basename ( orig_file )
local dest_file = BaseUtil.joinPath ( dest_path , orig_name )
local ok
local dest_mode = lfs.attributes ( dest_file , " mode " )
if not dest_mode or ( dest_mode == " file " and overwrite ) then
if self.cutfile then
ok = self : moveFile ( orig_file , dest_path )
else
ok = self : copyRecursive ( orig_file , dest_path )
end
end
if ok then
if ok then
DocSettings.updateLocation ( orig_file , dest_file , not self.cutfile )
ok_files [ orig_file ] = true
self.selected_files [ orig_file ] = nil
end
end
local skipped_nb = util.tableSize ( self.selected_files )
if util.tableSize ( ok_files ) > 0 then
if self.cutfile then -- for move only
ReadHistory : updateItems ( ok_files , dest_path )
ReadCollection : updateItems ( ok_files , dest_path )
end
if skipped_nb > 0 then
self : onRefresh ( )
self : onRefresh ( )
self.clipboard = nil
end
end
end
end
if skipped_nb > 0 then -- keep select mode on
local mode = lfs.attributes ( dest_file , " mode " )
local text = self.cutfile and T ( N_ ( " 1 file was not moved " , " %1 files were not moved " , skipped_nb ) , skipped_nb )
if mode then
or T ( N_ ( " 1 file was not copied " , " %1 files were not copied " , skipped_nb ) , skipped_nb )
UIManager : show ( ConfirmBox : new {
UIManager : show ( InfoMessage : new {
text = mode == " file " and T ( _ ( " File already exists: \n %1 \n Overwrite file? " ) , BD.filename ( orig_name ) )
text = text ,
or T ( _ ( " Folder already exists: \n %1 \n Overwrite folder? " ) , BD.directory ( orig_name ) ) ,
icon = " notice-warning " ,
ok_text = _ ( " Overwrite " ) ,
ok_callback = function ( )
doPaste ( )
end ,
} )
} )
else
else
doPaste ( )
self : onToggleSelectMode ( )
end
end
end
end
@ -961,11 +1013,18 @@ function FileManager:createFolder()
input_dialog : onShowKeyboard ( )
input_dialog : onShowKeyboard ( )
end
end
function FileManager : showDeleteFileDialog ( file , post_delete_callback , pre_delete_callback )
function FileManager : showDeleteFileDialog ( filepath , post_delete_callback , pre_delete_callback )
local file_abs_path = BaseUtil.realpath ( file )
local file = BaseUtil.realpath ( filepath )
local is_file = lfs.attributes ( file_abs_path , " mode " ) == " file "
if file == nil then
UIManager : show ( InfoMessage : new {
text = T ( _ ( " File not found: \n %1 " ) , BD.filepath ( filepath ) ) ,
icon = " notice-warning " ,
} )
return
end
local is_file = isFile ( file )
local text = ( is_file and _ ( " Delete file permanently? " ) or _ ( " Delete folder permanently? " ) ) .. " \n \n " .. BD.filepath ( file )
local text = ( is_file and _ ( " Delete file permanently? " ) or _ ( " Delete folder permanently? " ) ) .. " \n \n " .. BD.filepath ( file )
if is_file and DocSettings : hasSidecarFile ( file_abs_path ) then
if is_file and DocSettings : hasSidecarFile ( file ) then
text = text .. " \n \n " .. _ ( " Book settings, highlights and notes will be deleted. " )
text = text .. " \n \n " .. _ ( " Book settings, highlights and notes will be deleted. " )
end
end
UIManager : show ( ConfirmBox : new {
UIManager : show ( ConfirmBox : new {
@ -983,35 +1042,54 @@ function FileManager:showDeleteFileDialog(file, post_delete_callback, pre_delete
end
end
function FileManager : deleteFile ( file , is_file )
function FileManager : deleteFile ( file , is_file )
local file_abs_path = BaseUtil.realpath ( file )
if file_abs_path == nil then
UIManager : show ( InfoMessage : new {
text = T ( _ ( " File not found: \n %1 " ) , BD.filepath ( file ) ) ,
icon = " notice-warning " ,
} )
return
end
local ok , err
if is_file then
if is_file then
ok , err = os.remove ( file_abs_path )
local ok = os.remove ( file )
else
if ok then
ok , err = BaseUtil.purgeDir ( file_abs_path )
DocSettings.updateLocation ( file ) -- delete sdr
end
if ok and not err then
if is_file then
DocSettings.updateLocation ( file )
ReadHistory : fileDeleted ( file )
ReadHistory : fileDeleted ( file )
else
ReadCollection : removeItem ( file )
ReadHistory : folderDeleted ( file )
return true
end
end
ReadCollection : removeItemByPath ( file , not is_file )
return true
else
else
local ok = BaseUtil.purgeDir ( file )
if ok then
ReadHistory : folderDeleted ( file ) -- will delete sdr
ReadCollection : removeItemsByPath ( file )
return true
end
end
UIManager : show ( InfoMessage : new {
text = T ( _ ( " Failed to delete: \n %1 " ) , BD.filepath ( file ) ) ,
icon = " notice-warning " ,
} )
end
function FileManager : deleteSelectedFiles ( )
local ok_files = { }
for orig_file in pairs ( self.selected_files ) do
local file_abs_path = BaseUtil.realpath ( orig_file )
local ok = file_abs_path and os.remove ( file_abs_path )
if ok then
DocSettings.updateLocation ( file_abs_path ) -- delete sdr
ok_files [ orig_file ] = true
self.selected_files [ orig_file ] = nil
end
end
local skipped_nb = util.tableSize ( self.selected_files )
if util.tableSize ( ok_files ) > 0 then
ReadHistory : removeItems ( ok_files )
ReadCollection : removeItems ( ok_files )
if skipped_nb > 0 then
self : onRefresh ( )
end
end
if skipped_nb > 0 then -- keep select mode on
UIManager : show ( InfoMessage : new {
UIManager : show ( InfoMessage : new {
text = T ( _ ( " Failed to delete: \n %1 " ) , BD.filepath ( file ) ) ,
text = T ( N_( " Failed to delete 1 file. " , " Failed to delete %1 files. " , skipped_nb ) , skipped_nb ) ,
icon = " notice-warning " ,
icon = " notice-warning " ,
} )
} )
else
self : onToggleSelectMode ( )
end
end
end
end
@ -1052,11 +1130,12 @@ function FileManager:renameFile(file, basename, is_file)
if self : moveFile ( file , dest ) then
if self : moveFile ( file , dest ) then
if is_file then
if is_file then
DocSettings.updateLocation ( file , dest )
DocSettings.updateLocation ( file , dest )
ReadHistory : updateItemByPath ( file , dest ) -- (will update "lastfile" if needed)
ReadHistory : updateItem ( file , dest ) -- (will update "lastfile" if needed)
ReadCollection : updateItem ( file , dest )
else
else
ReadHistory : updateItemsByPath ( file , dest )
ReadHistory : updateItemsByPath ( file , dest )
ReadCollection : updateItemsByPath ( file , dest )
end
end
ReadCollection : updateItemByPath ( file , dest )
self : onRefresh ( )
self : onRefresh ( )
else
else
UIManager : show ( InfoMessage : new {
UIManager : show ( InfoMessage : new {