diff --git a/CHANGELOG.md b/CHANGELOG.md
index e957d5cc76a..dc911099c31 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -100,6 +100,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
- We fixed an issue where recently opened files were not displayed in the main menu properly. [#9042](https://github.com/JabRef/jabref/issues/9042)
- We fixed an issue where the DOI lookup would show an error when a DOI was found for an entry. [#11850](https://github.com/JabRef/jabref/issues/11850)
- We fixed an issue where Tab cannot be used to jump to next field in some single-line fields. [#11785](https://github.com/JabRef/jabref/issues/11785)
+- We fixed an issue where we display warning message for moving attached open files. [#10121](https://github.com/JabRef/jabref/issues/10121)
- We fixed an issue where it was not possible to select selecting content of other user's comments.[#11106](https://github.com/JabRef/jabref/issues/11106)
- We fixed an issue where web search preferences "Custom API key" table modifications not discarded. [#11925](https://github.com/JabRef/jabref/issues/11925)
- We fixed an issue where trying to open a library from a failed mounted directory on Mac would cause an error. [#10548](https://github.com/JabRef/jabref/issues/10548)
diff --git a/src/main/java/org/jabref/gui/cleanup/CleanupAction.java b/src/main/java/org/jabref/gui/cleanup/CleanupAction.java
index 9fdac23cd88..b09d82e6f5f 100644
--- a/src/main/java/org/jabref/gui/cleanup/CleanupAction.java
+++ b/src/main/java/org/jabref/gui/cleanup/CleanupAction.java
@@ -1,11 +1,15 @@
package org.jabref.gui.cleanup;
+import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;
+import java.util.stream.Collectors;
import javax.swing.undo.UndoManager;
+import javafx.application.Platform;
+
import org.jabref.gui.DialogService;
import org.jabref.gui.LibraryTab;
import org.jabref.gui.StateManager;
@@ -13,6 +17,7 @@
import org.jabref.gui.actions.SimpleCommand;
import org.jabref.gui.undo.NamedCompound;
import org.jabref.gui.undo.UndoableFieldChange;
+import org.jabref.logic.JabRefException;
import org.jabref.logic.cleanup.CleanupPreferences;
import org.jabref.logic.cleanup.CleanupWorker;
import org.jabref.logic.l10n.Localization;
@@ -31,6 +36,7 @@ public class CleanupAction extends SimpleCommand {
private final StateManager stateManager;
private final TaskExecutor taskExecutor;
private final UndoManager undoManager;
+ private final List failures;
private boolean isCanceled;
private int modifiedEntriesCount;
@@ -47,6 +53,7 @@ public CleanupAction(Supplier tabSupplier,
this.stateManager = stateManager;
this.taskExecutor = taskExecutor;
this.undoManager = undoManager;
+ this.failures = new ArrayList<>();
this.executable.bind(ActionHelper.needsEntriesSelected(stateManager));
}
@@ -105,7 +112,8 @@ private void doCleanup(BibDatabaseContext databaseContext, CleanupPreferences pr
CleanupWorker cleaner = new CleanupWorker(
databaseContext,
preferences.getFilePreferences(),
- preferences.getTimestampPreferences());
+ preferences.getTimestampPreferences()
+ );
List changes = cleaner.cleanup(preset, entry);
@@ -113,6 +121,8 @@ private void doCleanup(BibDatabaseContext databaseContext, CleanupPreferences pr
for (FieldChange change : changes) {
ce.addEdit(new UndoableFieldChange(change));
}
+
+ failures.addAll(cleaner.getFailures());
}
private void showResults() {
@@ -135,17 +145,36 @@ private void showResults() {
}
private void cleanup(BibDatabaseContext databaseContext, CleanupPreferences cleanupPreferences) {
+ this.failures.clear();
+ NamedCompound ce = new NamedCompound(Localization.lang("Cleanup entries"));
+
for (BibEntry entry : stateManager.getSelectedEntries()) {
// undo granularity is on entry level
- NamedCompound ce = new NamedCompound(Localization.lang("Cleanup entry"));
-
doCleanup(databaseContext, cleanupPreferences, entry, ce);
- ce.end();
if (ce.hasEdits()) {
modifiedEntriesCount++;
- undoManager.addEdit(ce);
}
}
+
+ ce.end();
+
+ if (ce.hasEdits()) {
+ undoManager.addEdit(ce);
+ }
+
+ if (!failures.isEmpty()) {
+ showFailures(failures);
+ }
+ }
+
+ private void showFailures(List failures) {
+ String message = failures.stream()
+ .map(exception -> "- " + exception.getLocalizedMessage())
+ .collect(Collectors.joining("\n"));
+
+ Platform.runLater(() ->
+ dialogService.showErrorDialogAndWait(Localization.lang("File Move Errors"), message)
+ );
}
}
diff --git a/src/main/java/org/jabref/gui/cleanup/CleanupSingleAction.java b/src/main/java/org/jabref/gui/cleanup/CleanupSingleAction.java
index 4688ca6c67a..6f9ffc08892 100644
--- a/src/main/java/org/jabref/gui/cleanup/CleanupSingleAction.java
+++ b/src/main/java/org/jabref/gui/cleanup/CleanupSingleAction.java
@@ -5,12 +5,15 @@
import javax.swing.undo.UndoManager;
+import javafx.application.Platform;
+
import org.jabref.gui.DialogService;
import org.jabref.gui.StateManager;
import org.jabref.gui.actions.ActionHelper;
import org.jabref.gui.actions.SimpleCommand;
import org.jabref.gui.undo.NamedCompound;
import org.jabref.gui.undo.UndoableFieldChange;
+import org.jabref.logic.JabRefException;
import org.jabref.logic.cleanup.CleanupPreferences;
import org.jabref.logic.cleanup.CleanupWorker;
import org.jabref.logic.l10n.Localization;
@@ -81,7 +84,8 @@ private void doCleanup(BibDatabaseContext databaseContext, CleanupPreferences pr
CleanupWorker cleaner = new CleanupWorker(
databaseContext,
preferences.getFilePreferences(),
- preferences.getTimestampPreferences());
+ preferences.getTimestampPreferences()
+ );
List changes = cleaner.cleanup(preset, entry);
@@ -89,6 +93,10 @@ private void doCleanup(BibDatabaseContext databaseContext, CleanupPreferences pr
for (FieldChange change : changes) {
ce.addEdit(new UndoableFieldChange(change));
}
+
+ if (!cleaner.getFailures().isEmpty()) {
+ this.showFailures(cleaner.getFailures());
+ }
}
private void cleanup(BibDatabaseContext databaseContext, CleanupPreferences cleanupPreferences) {
@@ -102,4 +110,14 @@ private void cleanup(BibDatabaseContext databaseContext, CleanupPreferences clea
undoManager.addEdit(ce);
}
}
+
+ private void showFailures(List failures) {
+ StringBuilder sb = new StringBuilder();
+ for (JabRefException exception : failures) {
+ sb.append("- ").append(exception.getLocalizedMessage()).append("\n");
+ }
+ Platform.runLater(() ->
+ dialogService.showErrorDialogAndWait(Localization.lang("File Move Errors"), sb.toString())
+ );
+ }
}
diff --git a/src/main/java/org/jabref/logic/cleanup/CleanupWorker.java b/src/main/java/org/jabref/logic/cleanup/CleanupWorker.java
index e9b01ad7081..8f15e8a4d5a 100644
--- a/src/main/java/org/jabref/logic/cleanup/CleanupWorker.java
+++ b/src/main/java/org/jabref/logic/cleanup/CleanupWorker.java
@@ -5,6 +5,7 @@
import java.util.Objects;
import org.jabref.logic.FilePreferences;
+import org.jabref.logic.JabRefException;
import org.jabref.logic.preferences.TimestampPreferences;
import org.jabref.model.FieldChange;
import org.jabref.model.database.BibDatabaseContext;
@@ -15,11 +16,13 @@ public class CleanupWorker {
private final BibDatabaseContext databaseContext;
private final FilePreferences filePreferences;
private final TimestampPreferences timestampPreferences;
+ private final List failures;
public CleanupWorker(BibDatabaseContext databaseContext, FilePreferences filePreferences, TimestampPreferences timestampPreferences) {
this.databaseContext = databaseContext;
this.filePreferences = filePreferences;
this.timestampPreferences = timestampPreferences;
+ this.failures = new ArrayList<>();
}
public List cleanup(CleanupPreferences preset, BibEntry entry) {
@@ -27,10 +30,12 @@ public List cleanup(CleanupPreferences preset, BibEntry entry) {
Objects.requireNonNull(entry);
List jobs = determineCleanupActions(preset);
-
List changes = new ArrayList<>();
for (CleanupJob job : jobs) {
changes.addAll(job.cleanup(entry));
+ if (job instanceof MoveFilesCleanup cleanup) {
+ failures.addAll(cleanup.getIoExceptions());
+ }
}
return changes;
@@ -86,4 +91,8 @@ private CleanupJob toJob(CleanupPreferences.CleanupStep action) {
throw new UnsupportedOperationException(action.name());
};
}
+
+ public List getFailures() {
+ return failures;
+ }
}
diff --git a/src/main/java/org/jabref/logic/cleanup/MoveFilesCleanup.java b/src/main/java/org/jabref/logic/cleanup/MoveFilesCleanup.java
index c55fb8a090d..3f7419239c4 100644
--- a/src/main/java/org/jabref/logic/cleanup/MoveFilesCleanup.java
+++ b/src/main/java/org/jabref/logic/cleanup/MoveFilesCleanup.java
@@ -1,13 +1,16 @@
package org.jabref.logic.cleanup;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import org.jabref.logic.FilePreferences;
+import org.jabref.logic.JabRefException;
import org.jabref.logic.externalfiles.LinkedFileHandler;
+import org.jabref.logic.l10n.Localization;
import org.jabref.model.FieldChange;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
@@ -26,10 +29,12 @@ public class MoveFilesCleanup implements CleanupJob {
private final BibDatabaseContext databaseContext;
private final FilePreferences filePreferences;
+ private final List ioExceptions;
public MoveFilesCleanup(BibDatabaseContext databaseContext, FilePreferences filePreferences) {
this.databaseContext = Objects.requireNonNull(databaseContext);
this.filePreferences = Objects.requireNonNull(filePreferences);
+ this.ioExceptions = new ArrayList<>();
}
@Override
@@ -43,6 +48,7 @@ public List cleanup(BibEntry entry) {
changed = fileHandler.moveToDefaultDirectory() || changed;
} catch (IOException exception) {
LOGGER.error("Error while moving file {}", file.getLink(), exception);
+ ioExceptions.add(new JabRefException(Localization.lang("Could not move file %0. Please close this file and retry.", file.getLink()), exception));
}
}
@@ -53,4 +59,8 @@ public List cleanup(BibEntry entry) {
return Collections.emptyList();
}
+
+ public List getIoExceptions() {
+ return ioExceptions;
+ }
}
diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties
index aa3b4174b58..7505818e8fe 100644
--- a/src/main/resources/l10n/JabRef_en.properties
+++ b/src/main/resources/l10n/JabRef_en.properties
@@ -2800,3 +2800,6 @@ Store\ url\ for\ downloaded\ file=Store url for downloaded file
Compare\ with\ existing\ entry=Compare with existing entry
Library\ Entry=Library Entry
Citation\ Entry=Citation Entry
+
+File\ Move\ Errors=File Move Errors
+Could\ not\ move\ file\ %0.\ Please\ close\ this\ file\ and\ retry.=Could not move file %0. Please close this file and retry.