confirmations
This commit is contained in:
parent
b28b090fa9
commit
b05a6fa3b7
@ -25,6 +25,7 @@ public class FileOperations {
|
|||||||
|
|
||||||
long totalSize = calculateTotalSize(items);
|
long totalSize = calculateTotalSize(items);
|
||||||
final long[] currentCopied = {0};
|
final long[] currentCopied = {0};
|
||||||
|
final OverwriteResponse[] globalResponse = {null};
|
||||||
|
|
||||||
for (FileItem item : items) {
|
for (FileItem item : items) {
|
||||||
if (callback != null && callback.isCancelled()) break;
|
if (callback != null && callback.isCancelled()) break;
|
||||||
@ -34,10 +35,22 @@ public class FileOperations {
|
|||||||
// If target is the same as source (copying to the same directory), rename target
|
// If target is the same as source (copying to the same directory), rename target
|
||||||
if (source.getAbsolutePath().equals(target.getAbsolutePath())) {
|
if (source.getAbsolutePath().equals(target.getAbsolutePath())) {
|
||||||
target = new File(targetDirectory, "copy-of-" + source.getName());
|
target = new File(targetDirectory, "copy-of-" + source.getName());
|
||||||
|
} else if (target.exists()) {
|
||||||
|
if (globalResponse[0] == OverwriteResponse.NO_TO_ALL) continue;
|
||||||
|
if (globalResponse[0] != OverwriteResponse.YES_TO_ALL) {
|
||||||
|
OverwriteResponse res = callback.confirmOverwrite(target);
|
||||||
|
if (res == OverwriteResponse.CANCEL) break;
|
||||||
|
if (res == OverwriteResponse.NO_TO_ALL) {
|
||||||
|
globalResponse[0] = OverwriteResponse.NO_TO_ALL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (res == OverwriteResponse.NO) continue;
|
||||||
|
if (res == OverwriteResponse.YES_TO_ALL) globalResponse[0] = OverwriteResponse.YES_TO_ALL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source.isDirectory()) {
|
if (source.isDirectory()) {
|
||||||
copyDirectory(source.toPath(), target.toPath(), totalSize, currentCopied, callback);
|
copyDirectory(source.toPath(), target.toPath(), totalSize, currentCopied, callback, globalResponse);
|
||||||
} else {
|
} else {
|
||||||
copyFileWithProgress(source.toPath(), target.toPath(), totalSize, currentCopied, callback);
|
copyFileWithProgress(source.toPath(), target.toPath(), totalSize, currentCopied, callback);
|
||||||
}
|
}
|
||||||
@ -87,7 +100,7 @@ public class FileOperations {
|
|||||||
Files.setLastModifiedTime(target, Files.getLastModifiedTime(source));
|
Files.setLastModifiedTime(target, Files.getLastModifiedTime(source));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void copyDirectory(Path source, Path target, long totalSize, final long[] totalCopied, ProgressCallback callback) throws IOException {
|
private static void copyDirectory(Path source, Path target, long totalSize, final long[] totalCopied, ProgressCallback callback, final OverwriteResponse[] globalResponse) throws IOException {
|
||||||
Files.walkFileTree(source, new SimpleFileVisitor<Path>() {
|
Files.walkFileTree(source, new SimpleFileVisitor<Path>() {
|
||||||
@Override
|
@Override
|
||||||
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
||||||
@ -100,6 +113,21 @@ public class FileOperations {
|
|||||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||||
if (callback != null && callback.isCancelled()) return FileVisitResult.TERMINATE;
|
if (callback != null && callback.isCancelled()) return FileVisitResult.TERMINATE;
|
||||||
Path targetFile = target.resolve(source.relativize(file));
|
Path targetFile = target.resolve(source.relativize(file));
|
||||||
|
|
||||||
|
if (Files.exists(targetFile)) {
|
||||||
|
if (globalResponse[0] == OverwriteResponse.NO_TO_ALL) return FileVisitResult.CONTINUE;
|
||||||
|
if (globalResponse[0] != OverwriteResponse.YES_TO_ALL) {
|
||||||
|
OverwriteResponse res = callback.confirmOverwrite(targetFile.toFile());
|
||||||
|
if (res == OverwriteResponse.CANCEL) return FileVisitResult.TERMINATE;
|
||||||
|
if (res == OverwriteResponse.NO_TO_ALL) {
|
||||||
|
globalResponse[0] = OverwriteResponse.NO_TO_ALL;
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
if (res == OverwriteResponse.NO) return FileVisitResult.CONTINUE;
|
||||||
|
if (res == OverwriteResponse.YES_TO_ALL) globalResponse[0] = OverwriteResponse.YES_TO_ALL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
copyFileWithProgress(file, targetFile, totalSize, totalCopied, callback);
|
copyFileWithProgress(file, targetFile, totalSize, totalCopied, callback);
|
||||||
return FileVisitResult.CONTINUE;
|
return FileVisitResult.CONTINUE;
|
||||||
}
|
}
|
||||||
@ -116,6 +144,7 @@ public class FileOperations {
|
|||||||
|
|
||||||
int current = 0;
|
int current = 0;
|
||||||
int total = items.size();
|
int total = items.size();
|
||||||
|
final OverwriteResponse[] globalResponse = {null};
|
||||||
|
|
||||||
for (FileItem item : items) {
|
for (FileItem item : items) {
|
||||||
if (callback != null && callback.isCancelled()) break;
|
if (callback != null && callback.isCancelled()) break;
|
||||||
@ -123,6 +152,20 @@ public class FileOperations {
|
|||||||
File source = item.getFile();
|
File source = item.getFile();
|
||||||
File target = new File(targetDirectory, source.getName());
|
File target = new File(targetDirectory, source.getName());
|
||||||
|
|
||||||
|
if (target.exists() && !source.getAbsolutePath().equals(target.getAbsolutePath())) {
|
||||||
|
if (globalResponse[0] == OverwriteResponse.NO_TO_ALL) continue;
|
||||||
|
if (globalResponse[0] != OverwriteResponse.YES_TO_ALL) {
|
||||||
|
OverwriteResponse res = callback.confirmOverwrite(target);
|
||||||
|
if (res == OverwriteResponse.CANCEL) break;
|
||||||
|
if (res == OverwriteResponse.NO_TO_ALL) {
|
||||||
|
globalResponse[0] = OverwriteResponse.NO_TO_ALL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (res == OverwriteResponse.NO) continue;
|
||||||
|
if (res == OverwriteResponse.YES_TO_ALL) globalResponse[0] = OverwriteResponse.YES_TO_ALL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
callback.onProgress(current, total, source.getName());
|
callback.onProgress(current, total, source.getName());
|
||||||
}
|
}
|
||||||
@ -374,9 +417,14 @@ public class FileOperations {
|
|||||||
/**
|
/**
|
||||||
* Callback for operation progress
|
* Callback for operation progress
|
||||||
*/
|
*/
|
||||||
|
public enum OverwriteResponse {
|
||||||
|
YES, NO, YES_TO_ALL, NO_TO_ALL, CANCEL
|
||||||
|
}
|
||||||
|
|
||||||
public interface ProgressCallback {
|
public interface ProgressCallback {
|
||||||
void onProgress(long current, long total, String currentFile);
|
void onProgress(long current, long total, String currentFile);
|
||||||
default boolean isCancelled() { return false; }
|
default boolean isCancelled() { return false; }
|
||||||
|
default OverwriteResponse confirmOverwrite(File file) { return OverwriteResponse.YES; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1566,33 +1566,59 @@ public class FilePanelTab extends JPanel {
|
|||||||
|
|
||||||
File targetDir = getCurrentDirectory();
|
File targetDir = getCurrentDirectory();
|
||||||
Window parentWindow = SwingUtilities.getWindowAncestor(this);
|
Window parentWindow = SwingUtilities.getWindowAncestor(this);
|
||||||
String operationName = action == ClipboardService.ClipboardAction.CUT ? "Moving" : "Copying";
|
String titleName = action == ClipboardService.ClipboardAction.CUT ? "Moving" : "Copying";
|
||||||
ProgressDialog progressDialog = new ProgressDialog(parentWindow instanceof Frame ? (Frame)parentWindow : null, operationName);
|
ProgressDialog progressDialog = new ProgressDialog(parentWindow instanceof Frame ? (Frame)parentWindow : null, titleName);
|
||||||
|
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
|
FileOperations.ProgressCallback callback = new FileOperations.ProgressCallback() {
|
||||||
|
@Override
|
||||||
|
public void onProgress(long current, long total, String currentFile) {
|
||||||
|
progressDialog.updateProgress(current, total, currentFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return progressDialog.isCancelled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileOperations.OverwriteResponse confirmOverwrite(File file) {
|
||||||
|
final FileOperations.OverwriteResponse[] result = new FileOperations.OverwriteResponse[1];
|
||||||
|
try {
|
||||||
|
SwingUtilities.invokeAndWait(() -> {
|
||||||
|
Object[] options = {"Yes", "Yes to All", "No", "No to All", "Cancel"};
|
||||||
|
int n = JOptionPane.showOptionDialog(progressDialog,
|
||||||
|
"File already exists: " + file.getName() + "\nOverwrite?",
|
||||||
|
"Overwrite Confirmation",
|
||||||
|
JOptionPane.DEFAULT_OPTION,
|
||||||
|
JOptionPane.QUESTION_MESSAGE,
|
||||||
|
null,
|
||||||
|
options,
|
||||||
|
options[0]);
|
||||||
|
|
||||||
|
switch (n) {
|
||||||
|
case 0: result[0] = FileOperations.OverwriteResponse.YES; break;
|
||||||
|
case 1: result[0] = FileOperations.OverwriteResponse.YES_TO_ALL; break;
|
||||||
|
case 2: result[0] = FileOperations.OverwriteResponse.NO; break;
|
||||||
|
case 3: result[0] = FileOperations.OverwriteResponse.NO_TO_ALL; break;
|
||||||
|
default:
|
||||||
|
result[0] = FileOperations.OverwriteResponse.CANCEL;
|
||||||
|
progressDialog.cancel();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
result[0] = FileOperations.OverwriteResponse.CANCEL;
|
||||||
|
}
|
||||||
|
return result[0];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (action == ClipboardService.ClipboardAction.CUT) {
|
if (action == ClipboardService.ClipboardAction.CUT) {
|
||||||
FileOperations.move(itemsToPaste, targetDir, new FileOperations.ProgressCallback() {
|
FileOperations.move(itemsToPaste, targetDir, callback);
|
||||||
@Override
|
|
||||||
public void onProgress(long current, long total, String currentFile) {
|
|
||||||
progressDialog.updateProgress(current, total, currentFile);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return progressDialog.isCancelled();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
FileOperations.copy(itemsToPaste, targetDir, new FileOperations.ProgressCallback() {
|
FileOperations.copy(itemsToPaste, targetDir, callback);
|
||||||
@Override
|
|
||||||
public void onProgress(long current, long total, String currentFile) {
|
|
||||||
progressDialog.updateProgress(current, total, currentFile);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return progressDialog.isCancelled();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
progressDialog.dispose();
|
progressDialog.dispose();
|
||||||
|
|||||||
@ -1781,6 +1781,38 @@ public class MainWindow extends JFrame {
|
|||||||
public boolean isCancelled() {
|
public boolean isCancelled() {
|
||||||
return progressDialog.isCancelled();
|
return progressDialog.isCancelled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileOperations.OverwriteResponse confirmOverwrite(File file) {
|
||||||
|
final FileOperations.OverwriteResponse[] result = new FileOperations.OverwriteResponse[1];
|
||||||
|
try {
|
||||||
|
SwingUtilities.invokeAndWait(() -> {
|
||||||
|
Object[] options = {"Yes", "Yes to All", "No", "No to All", "Cancel"};
|
||||||
|
int n = JOptionPane.showOptionDialog(progressDialog,
|
||||||
|
"File already exists: " + file.getName() + "\nOverwrite?",
|
||||||
|
"Overwrite Confirmation",
|
||||||
|
JOptionPane.DEFAULT_OPTION,
|
||||||
|
JOptionPane.QUESTION_MESSAGE,
|
||||||
|
null,
|
||||||
|
options,
|
||||||
|
options[0]);
|
||||||
|
|
||||||
|
switch (n) {
|
||||||
|
case 0: result[0] = FileOperations.OverwriteResponse.YES; break;
|
||||||
|
case 1: result[0] = FileOperations.OverwriteResponse.YES_TO_ALL; break;
|
||||||
|
case 2: result[0] = FileOperations.OverwriteResponse.NO; break;
|
||||||
|
case 3: result[0] = FileOperations.OverwriteResponse.NO_TO_ALL; break;
|
||||||
|
default:
|
||||||
|
result[0] = FileOperations.OverwriteResponse.CANCEL;
|
||||||
|
progressDialog.cancel();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
result[0] = FileOperations.OverwriteResponse.CANCEL;
|
||||||
|
}
|
||||||
|
return result[0];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Run operation in a background thread
|
// Run operation in a background thread
|
||||||
|
|||||||
@ -75,6 +75,10 @@ public class ProgressDialog extends JDialog {
|
|||||||
setLocationRelativeTo(owner);
|
setLocationRelativeTo(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void cancel() {
|
||||||
|
cancelled = true;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean displayAsBytes = false;
|
private boolean displayAsBytes = false;
|
||||||
|
|
||||||
public void setDisplayAsBytes(boolean displayAsBytes) {
|
public void setDisplayAsBytes(boolean displayAsBytes) {
|
||||||
|
|||||||
BIN
src/main/resources/Copilot_20260117_114947.png
Normal file
BIN
src/main/resources/Copilot_20260117_114947.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 MiB |
BIN
src/main/resources/copy-of-Copilot_20260117_114947.png
Normal file
BIN
src/main/resources/copy-of-Copilot_20260117_114947.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 MiB |
Loading…
x
Reference in New Issue
Block a user