diff --git a/CHANGELOG.md b/CHANGELOG.md index 909aba23776..c942e0a1ed2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - We added a feature that allows the user to open all linked files of multiple selected entries by "Open file" option. [#6966](https://github.com/JabRef/jabref/issues/6966) - We added a keybinding preset for new entries. [#7705](https://github.com/JabRef/jabref/issues/7705) - We added a select all button for the library import function. [#7786](https://github.com/JabRef/jabref/issues/7786) +- We added auto-key-generation progress to the background task list. [#7267](https://github.com/JabRef/jabref/issues/7267) ### Changed diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index ecbb1fa02c6..ee01c038883 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -506,7 +506,7 @@ private Node createToolbar() { new HBox( pushToApplicationButton, - factory.createIconButton(StandardActions.GENERATE_CITE_KEYS, new GenerateCitationKeyAction(this, dialogService, stateManager)), + factory.createIconButton(StandardActions.GENERATE_CITE_KEYS, new GenerateCitationKeyAction(this, dialogService, stateManager, taskExecutor, prefs)), factory.createIconButton(StandardActions.CLEANUP_ENTRIES, new CleanupAction(this, prefs, dialogService, stateManager)) ), @@ -727,7 +727,7 @@ private MenuBar createMenu() { new SeparatorMenuItem(), factory.createMenuItem(StandardActions.REPLACE_ALL, new ReplaceStringAction(this, stateManager)), - factory.createMenuItem(StandardActions.GENERATE_CITE_KEYS, new GenerateCitationKeyAction(this, dialogService, stateManager)), + factory.createMenuItem(StandardActions.GENERATE_CITE_KEYS, new GenerateCitationKeyAction(this, dialogService, stateManager, taskExecutor, prefs)), new SeparatorMenuItem(), diff --git a/src/main/java/org/jabref/gui/citationkeypattern/GenerateCitationKeyAction.java b/src/main/java/org/jabref/gui/citationkeypattern/GenerateCitationKeyAction.java index 0c52d0374df..b70d511dd64 100644 --- a/src/main/java/org/jabref/gui/citationkeypattern/GenerateCitationKeyAction.java +++ b/src/main/java/org/jabref/gui/citationkeypattern/GenerateCitationKeyAction.java @@ -1,9 +1,9 @@ package org.jabref.gui.citationkeypattern; import java.util.List; +import java.util.function.Consumer; import org.jabref.gui.DialogService; -import org.jabref.gui.Globals; import org.jabref.gui.JabRefFrame; import org.jabref.gui.StateManager; import org.jabref.gui.actions.ActionHelper; @@ -11,9 +11,12 @@ import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableKeyChange; import org.jabref.gui.util.BackgroundTask; +import org.jabref.gui.util.DefaultTaskExecutor; +import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.citationkeypattern.CitationKeyGenerator; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.BibEntry; +import org.jabref.preferences.PreferencesService; public class GenerateCitationKeyAction extends SimpleCommand { @@ -24,10 +27,15 @@ public class GenerateCitationKeyAction extends SimpleCommand { private List entries; private boolean isCanceled; - public GenerateCitationKeyAction(JabRefFrame frame, DialogService dialogService, StateManager stateManager) { + private final TaskExecutor taskExecutor; + private final PreferencesService preferencesService; + + public GenerateCitationKeyAction(JabRefFrame frame, DialogService dialogService, StateManager stateManager, TaskExecutor taskExecutor, PreferencesService preferencesService) { this.frame = frame; this.dialogService = dialogService; this.stateManager = stateManager; + this.taskExecutor = taskExecutor; + this.preferencesService = preferencesService; this.executable.bind(ActionHelper.needsEntriesSelected(stateManager)); } @@ -45,20 +53,26 @@ public void execute() { checkOverwriteKeysChosen(); - BackgroundTask.wrap(this::generateKeys) - .executeWith(Globals.TASK_EXECUTOR); + if (!this.isCanceled) { + BackgroundTask backgroundTask = this.generateKeysInBackground(); + backgroundTask.showToUser(true); + backgroundTask.titleProperty().set(Localization.lang("Autogenerate citation keys")); + backgroundTask.messageProperty().set(Localization.lang("%0/%1 entries", 0, entries.size())); + + backgroundTask.executeWith(this.taskExecutor); + } } - public static boolean confirmOverwriteKeys(DialogService dialogService) { - if (Globals.prefs.getCitationKeyPatternPreferences().shouldWarnBeforeOverwriteCiteKey()) { + public static boolean confirmOverwriteKeys(DialogService dialogService, PreferencesService preferencesService) { + if (preferencesService.getCitationKeyPatternPreferences().shouldWarnBeforeOverwriteCiteKey()) { return dialogService.showConfirmationDialogWithOptOutAndWait( Localization.lang("Overwrite keys"), Localization.lang("One or more keys will be overwritten. Continue?"), Localization.lang("Overwrite keys"), Localization.lang("Cancel"), Localization.lang("Do not ask again"), - optOut -> Globals.prefs.storeCitationKeyPatternPreferences( - Globals.prefs.getCitationKeyPatternPreferences().withWarnBeforeOverwriteCiteKey(!optOut))); + optOut -> preferencesService.storeCitationKeyPatternPreferences( + preferencesService.getCitationKeyPatternPreferences().withWarnBeforeOverwriteCiteKey(!optOut))); } else { // Always overwrite keys by default return true; @@ -67,11 +81,11 @@ public static boolean confirmOverwriteKeys(DialogService dialogService) { private void checkOverwriteKeysChosen() { // We don't want to generate keys for entries which already have one thus remove the entries - if (Globals.prefs.getCitationKeyPatternPreferences().shouldAvoidOverwriteCiteKey()) { + if (this.preferencesService.getCitationKeyPatternPreferences().shouldAvoidOverwriteCiteKey()) { entries.removeIf(BibEntry::hasCitationKey); // if we're going to override some citation keys warn the user about it } else if (entries.parallelStream().anyMatch(BibEntry::hasCitationKey)) { - boolean overwriteKeys = confirmOverwriteKeys(dialogService); + boolean overwriteKeys = confirmOverwriteKeys(dialogService, this.preferencesService); // The user doesn't want to override citation keys if (!overwriteKeys) { @@ -80,30 +94,54 @@ private void checkOverwriteKeysChosen() { } } - private void generateKeys() { - if (isCanceled) { - return; - } - - stateManager.getActiveDatabase().ifPresent(databaseContext -> { - // generate the new citation keys for each entry - final NamedCompound compound = new NamedCompound(Localization.lang("Autogenerate citation keys")); - CitationKeyGenerator keyGenerator = - new CitationKeyGenerator(databaseContext, Globals.prefs.getCitationKeyPatternPreferences()); - for (BibEntry entry : entries) { - keyGenerator.generateAndSetKey(entry) - .ifPresent(fieldChange -> compound.addEdit(new UndoableKeyChange(fieldChange))); + private BackgroundTask generateKeysInBackground() { + return new BackgroundTask() { + + private NamedCompound compound; + + @Override + protected Void call() { + if (isCanceled) { + return null; + } + DefaultTaskExecutor.runInJavaFXThread(() -> { + updateProgress(0, entries.size()); + messageProperty().set(Localization.lang("%0/%1 entries", 0, entries.size())); + }); + stateManager.getActiveDatabase().ifPresent(databaseContext -> { + // generate the new citation keys for each entry + compound = new NamedCompound(Localization.lang("Autogenerate citation keys")); + CitationKeyGenerator keyGenerator = + new CitationKeyGenerator(databaseContext, preferencesService.getCitationKeyPatternPreferences()); + int entriesDone = 0; + for (BibEntry entry : entries) { + keyGenerator.generateAndSetKey(entry) + .ifPresent(fieldChange -> compound.addEdit(new UndoableKeyChange(fieldChange))); + entriesDone++; + int finalEntriesDone = entriesDone; + DefaultTaskExecutor.runInJavaFXThread(() -> { + updateProgress(finalEntriesDone, entries.size()); + messageProperty().set(Localization.lang("%0/%1 entries", finalEntriesDone, entries.size())); + }); + } + compound.end(); + }); + return null; } - compound.end(); - // register the undo event only if new citation keys were generated - if (compound.hasEdits()) { - frame.getUndoManager().addEdit(compound); + @Override + public BackgroundTask onSuccess(Consumer onSuccess) { + // register the undo event only if new citation keys were generated + if (compound.hasEdits()) { + frame.getUndoManager().addEdit(compound); + } + + frame.getCurrentLibraryTab().markBaseChanged(); + dialogService.notify(formatOutputMessage(Localization.lang("Generated citation key for"), entries.size())); + return super.onSuccess(onSuccess); } + }; - frame.getCurrentLibraryTab().markBaseChanged(); - dialogService.notify(formatOutputMessage(Localization.lang("Generated citation key for"), entries.size())); - }); } private String formatOutputMessage(String start, int count) { diff --git a/src/main/java/org/jabref/gui/citationkeypattern/GenerateCitationKeySingleAction.java b/src/main/java/org/jabref/gui/citationkeypattern/GenerateCitationKeySingleAction.java index b66beef36be..04678963e34 100644 --- a/src/main/java/org/jabref/gui/citationkeypattern/GenerateCitationKeySingleAction.java +++ b/src/main/java/org/jabref/gui/citationkeypattern/GenerateCitationKeySingleAction.java @@ -32,7 +32,7 @@ public GenerateCitationKeySingleAction(BibEntry entry, BibDatabaseContext databa @Override public void execute() { - if (!entry.hasCitationKey() || GenerateCitationKeyAction.confirmOverwriteKeys(dialogService)) { + if (!entry.hasCitationKey() || GenerateCitationKeyAction.confirmOverwriteKeys(dialogService, preferencesService)) { new CitationKeyGenerator(databaseContext, preferencesService.getCitationKeyPatternPreferences()) .generateAndSetKey(entry) .ifPresent(change -> undoManager.addEdit(new UndoableKeyChange(change))); diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index e3b0c2e9a8a..70740e2b357 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -7,6 +7,8 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ %0\ doesn't\ contain\ the\ term\ %1=%0 doesn't contain the term %1 +%0/%1\ entries=%0/%1 entries + %0\ export\ successful=%0 export successful %0\ matches\ the\ regular\ expression\ %1=%0 matches the regular expression %1