From 26636e23475a726c5941443ed4b606fd07fc0851 Mon Sep 17 00:00:00 2001 From: Sara-S-Dev Date: Fri, 4 Jul 2025 11:17:18 +0300 Subject: [PATCH 1/8] gradle file changes --- jablib/build.gradle.kts | 2 +- settings.gradle.kts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/jablib/build.gradle.kts b/jablib/build.gradle.kts index a2de396828e..8ce87b71b57 100644 --- a/jablib/build.gradle.kts +++ b/jablib/build.gradle.kts @@ -18,7 +18,7 @@ plugins { // id("dev.jbang") version "0.2.0" // Workaround for https://github.com/jbangdev/jbang-gradle-plugin/issues/7 - id("com.github.koppor.jbang-gradle-plugin") version "fix-7-SNAPSHOT" + id("com.github.koppor.jbang-gradle-plugin") version "0.3.0-SNAPSHOT" } var version: String = project.findProperty("projVersion")?.toString() ?: "0.1.0" diff --git a/settings.gradle.kts b/settings.gradle.kts index 61d810ccdd9..c051adac1c5 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -15,7 +15,9 @@ pluginManagement { } } repositories { + mavenLocal() gradlePluginPortal() + mavenCentral() maven("https://jitpack.io") } } From 8e7591de3f88156826d023b59f21b84e07b27a14 Mon Sep 17 00:00:00 2001 From: Sara-S-Dev Date: Mon, 7 Jul 2025 09:30:58 +0300 Subject: [PATCH 2/8] refine file exists warning - Fixes #12565 --- CHANGELOG.md | 4 +- .../gui/fieldeditors/LinkedFileViewModel.java | 52 ++++++++++++++++--- 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca6ab160c7d..d09106eb9a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - When adding an entry to a library, a warning is displayed if said entry already exists in an active library. [#13261](https://github.com/JabRef/jabref/issues/13261) - We added the field `monthfiled` to the default list of fields to resolve BibTeX-Strings for [#13375](https://github.com/JabRef/jabref/issues/13375) - We added a new ID based fetcher for [EuropePMC](https://europepmc.org/). [#13389](https://github.com/JabRef/jabref/pull/13389) -- We added an initial [cite as you write](https://retorque.re/zotero-better-bibtex/citing/cayw/) endpoint. [#13187](https://github.com/JabRef/jabref/issues/13187) +- We added an initial [cite as you write](https://retorque.re/zotero-better-bibtex/citing/cayw/) endpoint. [#13187](https://github.com/JabRef/jabref/issues/13187)- ### Changed @@ -56,6 +56,8 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - When importing a PDF, there is no empty entry column shown in the multi merge dialog. [#13132](https://github.com/JabRef/jabref/issues/13132) - We added a progress dialog to the "Check consistency" action and progress output to the corresponding cli command. [#12487](https://github.com/JabRef/jabref/issues/12487) - We made the `check-consistency` command of the toolkit always return an exit code; 0 means no issues found, a non-zero exit code reflects any issues, which allows CI to fail in these cases [#13328](https://github.com/JabRef/jabref/issues/13328). +- Improved file exists warning dialog with clearer options and tooltips [#12565](https://github.com/JabRef/jabref/issues/12565)] + ### Fixed diff --git a/jabgui/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java b/jabgui/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java index 28337d51d02..58956b4f7eb 100644 --- a/jabgui/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java @@ -18,6 +18,11 @@ import javafx.beans.property.SimpleDoubleProperty; import javafx.beans.property.StringProperty; import javafx.scene.Node; +import javafx.scene.control.Button; +import javafx.scene.control.ButtonBar; +import javafx.scene.control.ButtonType; +import javafx.scene.control.Dialog; +import javafx.scene.control.Tooltip; import org.jabref.gui.AbstractViewModel; import org.jabref.gui.DialogService; @@ -37,6 +42,7 @@ import org.jabref.logic.externalfiles.LinkedFileHandler; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.TaskExecutor; +import org.jabref.logic.util.io.FileNameUniqueness; import org.jabref.logic.util.io.FileUtil; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; @@ -268,20 +274,54 @@ private void performRenameWithConflictCheck(String targetFileName) { boolean overwriteFile = false; if (existingFile.isPresent()) { - overwriteFile = dialogService.showConfirmationDialogAndWait( - Localization.lang("File exists"), - Localization.lang("'%0' exists. Overwrite file?", targetFileName), - Localization.lang("Overwrite")); + // Get existing file path and its directory + Path existingFilePath = existingFile.get(); + Path targetDirectory = existingFilePath.getParent(); + + // Suggest a non-conflicting file name + String suggestedFileName = FileNameUniqueness.getNonOverWritingFileName(targetDirectory, targetFileName); + + // Define available dialog options + ButtonType Replace = new ButtonType(Localization.lang("Replace"), ButtonBar.ButtonData.OTHER); + ButtonType keepBoth = new ButtonType(Localization.lang("Keep both"), ButtonBar.ButtonData.OTHER); + ButtonType provideAlternative = new ButtonType(Localization.lang("Provide alternative file name"), ButtonBar.ButtonData.OTHER); + ButtonType cancel = new ButtonType(Localization.lang("Cancel"), ButtonBar.ButtonData.OTHER); + + // Build the dialog window + Dialog dialog = new Dialog<>(); + dialog.setTitle(Localization.lang("File already exists")); + dialog.setContentText(Localization.lang("File name: \n'%0'", targetFileName)); + dialog.getDialogPane().getButtonTypes().addAll(Replace, keepBoth, provideAlternative, cancel); + + // Add tooltip to "Keep both" button with the suggested name + Button keepBothButton = (Button) dialog.getDialogPane().lookupButton(keepBoth); + if (keepBothButton != null) { + keepBothButton.setTooltip(new Tooltip(Localization.lang("New filename: %0", suggestedFileName))); + } - if (!overwriteFile) { + // Show dialog and handle user response + Optional result = dialog.showAndWait(); + + if (result.isEmpty() || result.get() == cancel) { + return; // User canceled + } else if (result.get() == Replace) { + overwriteFile = true; + } else if (result.get() == keepBoth) { + targetFileName = suggestedFileName; + } else if (result.get() == provideAlternative) { + askForNameAndRename(); return; } } try { + // Attempt the rename operation linkedFileHandler.renameToName(targetFileName, overwriteFile); } catch (IOException e) { - dialogService.showErrorDialogAndWait(Localization.lang("Rename failed"), Localization.lang("JabRef cannot access the file because it is being used by another process.")); + // Display an error dialog if file is locked or inaccessible + dialogService.showErrorDialogAndWait( + Localization.lang("Rename failed"), + Localization.lang("JabRef cannot access the file because it is being used by another process.")); } } From 06674e5146750df7cac33dda9fe5e2a4a8c8eb28 Mon Sep 17 00:00:00 2001 From: Sara-S-Dev Date: Mon, 7 Jul 2025 09:46:00 +0300 Subject: [PATCH 3/8] Revert unintended change to settings.gradle.kts --- settings.gradle.kts | 2 -- 1 file changed, 2 deletions(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 470c6be3b33..b9aed07ba92 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -15,9 +15,7 @@ pluginManagement { } } repositories { - mavenLocal() gradlePluginPortal() - mavenCentral() maven("https://jitpack.io") } } From fb8f71873e672d3b5e9149a2df6bd4a5930ee3b7 Mon Sep 17 00:00:00 2001 From: Sara-S-Dev Date: Mon, 7 Jul 2025 10:50:34 +0300 Subject: [PATCH 4/8] fix: add missing localization keys --- CHANGELOG.md | 3 +-- jablib/src/main/resources/l10n/JabRef_en.properties | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d09106eb9a3..f9573a4be7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - When adding an entry to a library, a warning is displayed if said entry already exists in an active library. [#13261](https://github.com/JabRef/jabref/issues/13261) - We added the field `monthfiled` to the default list of fields to resolve BibTeX-Strings for [#13375](https://github.com/JabRef/jabref/issues/13375) - We added a new ID based fetcher for [EuropePMC](https://europepmc.org/). [#13389](https://github.com/JabRef/jabref/pull/13389) -- We added an initial [cite as you write](https://retorque.re/zotero-better-bibtex/citing/cayw/) endpoint. [#13187](https://github.com/JabRef/jabref/issues/13187)- +- We added an initial [cite as you write](https://retorque.re/zotero-better-bibtex/citing/cayw/) endpoint. [#13187](https://github.com/JabRef/jabref/issues/13187) ### Changed @@ -58,7 +58,6 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We made the `check-consistency` command of the toolkit always return an exit code; 0 means no issues found, a non-zero exit code reflects any issues, which allows CI to fail in these cases [#13328](https://github.com/JabRef/jabref/issues/13328). - Improved file exists warning dialog with clearer options and tooltips [#12565](https://github.com/JabRef/jabref/issues/12565)] - ### Fixed - We added a fallback for the "Convert to biblatex" cleanup when it failed to populate the `date` field if `year` contained a full date in ISO format (e.g., `2011-11-11`). [#11868](https://github.com/JabRef/jabref/issues/11868) diff --git a/jablib/src/main/resources/l10n/JabRef_en.properties b/jablib/src/main/resources/l10n/JabRef_en.properties index 7a9e18dfa69..c1887e597f5 100644 --- a/jablib/src/main/resources/l10n/JabRef_en.properties +++ b/jablib/src/main/resources/l10n/JabRef_en.properties @@ -252,6 +252,11 @@ Do\ not\ abbreviate\ names=Do not abbreviate names Do\ not\ wrap\ when\ saving=Do not wrap when saving +File\ already\ exists=File already exists +File\ name\:\ \n'%0'=File name: \n'%0' +Provide\ alternative\ file\ name=Provide alternative file name + + Download\ file=Download file Download\ '%0'\ was\ a\ HTML\ file.\ Removed.=Download '%0' was a HTML file. Removed. From 6059ffeef9645b0df45a3a163b8e2621c62c2041 Mon Sep 17 00:00:00 2001 From: Sara-S-Dev Date: Mon, 7 Jul 2025 11:39:53 +0300 Subject: [PATCH 5/8] fix: add missing localization key for 'New filename' --- jablib/src/main/resources/l10n/JabRef_en.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/jablib/src/main/resources/l10n/JabRef_en.properties b/jablib/src/main/resources/l10n/JabRef_en.properties index c1887e597f5..d5493b8c3aa 100644 --- a/jablib/src/main/resources/l10n/JabRef_en.properties +++ b/jablib/src/main/resources/l10n/JabRef_en.properties @@ -254,6 +254,7 @@ Do\ not\ wrap\ when\ saving=Do not wrap when saving File\ already\ exists=File already exists File\ name\:\ \n'%0'=File name: \n'%0' +New\ filename\:\ %0=New filename: %0 Provide\ alternative\ file\ name=Provide alternative file name From 865f839bd847aeec1d8d4d7e85c248eaa2e2823e Mon Sep 17 00:00:00 2001 From: Sara-S-Dev Date: Mon, 14 Jul 2025 14:19:22 +0300 Subject: [PATCH 6/8] Refactor: Use JabRefDialogService instead of direct dialog creation --- .../java/org/jabref/gui/DialogService.java | 17 ++++++++++ .../org/jabref/gui/JabRefDialogService.java | 30 +++++++++++++++++ .../gui/fieldeditors/LinkedFileViewModel.java | 33 ++++++++++--------- 3 files changed, 65 insertions(+), 15 deletions(-) diff --git a/jabgui/src/main/java/org/jabref/gui/DialogService.java b/jabgui/src/main/java/org/jabref/gui/DialogService.java index 7248be47511..6ac9708018a 100644 --- a/jabgui/src/main/java/org/jabref/gui/DialogService.java +++ b/jabgui/src/main/java/org/jabref/gui/DialogService.java @@ -4,6 +4,7 @@ import java.nio.file.Path; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.function.Consumer; @@ -15,6 +16,7 @@ import javafx.scene.control.Dialog; import javafx.scene.control.DialogPane; import javafx.scene.control.TextInputDialog; +import javafx.scene.control.Tooltip; import javafx.util.StringConverter; import org.jabref.gui.util.BaseDialog; @@ -204,6 +206,21 @@ boolean showConfirmationDialogWithOptOutAndWait(String title, String content, Optional showCustomButtonDialogAndWait(Alert.AlertType type, String title, String content, ButtonType... buttonTypes); + /** + * This will create and display a new dialog showing a custom {@link DialogPane} + * using custom {@link ButtonType}s, and attaches optional {@link Tooltip}s to the buttons. + * Useful for providing additional context to the user through tooltips + * without cluttering the main dialog content. + * + * @return Optional with the pressed Button as ButtonType + */ + + Optional showCustomButtonDialogWithTooltipsAndWait(Alert.AlertType type, + String title, + String content, + Map tooltips, + ButtonType... buttonTypes); + /** * This will create and display a new dialog showing a custom {@link DialogPane} * and using custom {@link ButtonType}s. diff --git a/jabgui/src/main/java/org/jabref/gui/JabRefDialogService.java b/jabgui/src/main/java/org/jabref/gui/JabRefDialogService.java index 7e6595e5e19..82167f34bc0 100644 --- a/jabgui/src/main/java/org/jabref/gui/JabRefDialogService.java +++ b/jabgui/src/main/java/org/jabref/gui/JabRefDialogService.java @@ -7,9 +7,11 @@ import java.nio.file.Path; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.function.Consumer; +import javafx.application.Platform; import javafx.concurrent.Task; import javafx.geometry.Pos; import javafx.print.PrinterJob; @@ -27,6 +29,7 @@ import javafx.scene.control.Label; import javafx.scene.control.TextArea; import javafx.scene.control.TextInputDialog; +import javafx.scene.control.Tooltip; import javafx.scene.layout.HBox; import javafx.scene.layout.Region; import javafx.scene.layout.VBox; @@ -303,6 +306,33 @@ public Optional showCustomButtonDialogAndWait(AlertType type, String return alert.showAndWait(); } + @Override + public Optional showCustomButtonDialogWithTooltipsAndWait(AlertType type, + String title, + String content, + Map tooltips, + ButtonType... buttonTypes) { + // Use a non-editable Label instead of raw text to prevent editing + FXDialog alert = createDialog(type, title, ""); + Label contentLabel = new Label(content); + contentLabel.setWrapText(true); + alert.getDialogPane().setContent(contentLabel); + + alert.getDialogPane().getButtonTypes().setAll(buttonTypes); + + // Attach tooltips to buttons + Platform.runLater(() -> { + for (Map.Entry entry : tooltips.entrySet()) { + Button button = (Button) alert.getDialogPane().lookupButton(entry.getKey()); + if (button != null) { + button.setTooltip(new Tooltip(entry.getValue())); + } + } + }); + + return alert.showAndWait(); + } + @Override public Optional showCustomDialogAndWait(String title, DialogPane contentPane, ButtonType... buttonTypes) { diff --git a/jabgui/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java b/jabgui/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java index 58956b4f7eb..fd0bf9a53ff 100644 --- a/jabgui/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java @@ -5,7 +5,9 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.function.BiPredicate; @@ -18,6 +20,7 @@ import javafx.beans.property.SimpleDoubleProperty; import javafx.beans.property.StringProperty; import javafx.scene.Node; +import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.control.ButtonBar; import javafx.scene.control.ButtonType; @@ -269,7 +272,8 @@ public void renameFileToName(String targetFileName) { } } - private void performRenameWithConflictCheck(String targetFileName) { + public void performRenameWithConflictCheck(String targetFileName) { + // Check if a file with the same name already exists Optional existingFile = linkedFileHandler.findExistingFile(linkedFile, entry, targetFileName); boolean overwriteFile = false; @@ -282,29 +286,28 @@ private void performRenameWithConflictCheck(String targetFileName) { String suggestedFileName = FileNameUniqueness.getNonOverWritingFileName(targetDirectory, targetFileName); // Define available dialog options - ButtonType Replace = new ButtonType(Localization.lang("Replace"), ButtonBar.ButtonData.OTHER); + ButtonType replace = new ButtonType(Localization.lang("Replace"), ButtonBar.ButtonData.OTHER); ButtonType keepBoth = new ButtonType(Localization.lang("Keep both"), ButtonBar.ButtonData.OTHER); ButtonType provideAlternative = new ButtonType(Localization.lang("Provide alternative file name"), ButtonBar.ButtonData.OTHER); ButtonType cancel = new ButtonType(Localization.lang("Cancel"), ButtonBar.ButtonData.OTHER); - // Build the dialog window - Dialog dialog = new Dialog<>(); - dialog.setTitle(Localization.lang("File already exists")); - dialog.setContentText(Localization.lang("File name: \n'%0'", targetFileName)); - dialog.getDialogPane().getButtonTypes().addAll(Replace, keepBoth, provideAlternative, cancel); + // Define tooltips for dialog buttons + Map tooltips = new HashMap<>(); + tooltips.put(keepBoth, Localization.lang("New filename: %0", suggestedFileName)); - // Add tooltip to "Keep both" button with the suggested name - Button keepBothButton = (Button) dialog.getDialogPane().lookupButton(keepBoth); - if (keepBothButton != null) { - keepBothButton.setTooltip(new Tooltip(Localization.lang("New filename: %0", suggestedFileName))); - } + // Use JabRefDialogService to show a custom dialog with tooltips + Optional result = dialogService.showCustomButtonDialogWithTooltipsAndWait( + Alert.AlertType.CONFIRMATION, + Localization.lang("File already exists"), + Localization.lang("File name: \n'%0'", targetFileName), + tooltips, + replace, keepBoth, provideAlternative, cancel + ); // Show dialog and handle user response - Optional result = dialog.showAndWait(); - if (result.isEmpty() || result.get() == cancel) { return; // User canceled - } else if (result.get() == Replace) { + } else if (result.get() == replace) { overwriteFile = true; } else if (result.get() == keepBoth) { targetFileName = suggestedFileName; From 560174e91c1ba280507c5d6455458d9fc2cb6388 Mon Sep 17 00:00:00 2001 From: Sara-S-Dev Date: Mon, 14 Jul 2025 14:51:46 +0300 Subject: [PATCH 7/8] fixed checkstyle issue --- .../org/jabref/gui/fieldeditors/LinkedFileViewModel.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/jabgui/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java b/jabgui/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java index fd0bf9a53ff..82d6f4ab89d 100644 --- a/jabgui/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java @@ -21,11 +21,8 @@ import javafx.beans.property.StringProperty; import javafx.scene.Node; import javafx.scene.control.Alert; -import javafx.scene.control.Button; import javafx.scene.control.ButtonBar; import javafx.scene.control.ButtonType; -import javafx.scene.control.Dialog; -import javafx.scene.control.Tooltip; import org.jabref.gui.AbstractViewModel; import org.jabref.gui.DialogService; @@ -272,7 +269,7 @@ public void renameFileToName(String targetFileName) { } } - public void performRenameWithConflictCheck(String targetFileName) { + private void performRenameWithConflictCheck(String targetFileName) { // Check if a file with the same name already exists Optional existingFile = linkedFileHandler.findExistingFile(linkedFile, entry, targetFileName); boolean overwriteFile = false; From 6b0c0811ee1caa2cd826d137589855511e434cfe Mon Sep 17 00:00:00 2001 From: Sara-S-Dev Date: Mon, 14 Jul 2025 20:32:01 +0300 Subject: [PATCH 8/8] Use CANCEL_CLOSE for Cancel button --- .../java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jabgui/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java b/jabgui/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java index 82d6f4ab89d..9376fe9f989 100644 --- a/jabgui/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java @@ -286,7 +286,7 @@ private void performRenameWithConflictCheck(String targetFileName) { ButtonType replace = new ButtonType(Localization.lang("Replace"), ButtonBar.ButtonData.OTHER); ButtonType keepBoth = new ButtonType(Localization.lang("Keep both"), ButtonBar.ButtonData.OTHER); ButtonType provideAlternative = new ButtonType(Localization.lang("Provide alternative file name"), ButtonBar.ButtonData.OTHER); - ButtonType cancel = new ButtonType(Localization.lang("Cancel"), ButtonBar.ButtonData.OTHER); + ButtonType cancel = new ButtonType(Localization.lang("Cancel"), ButtonBar.ButtonData.CANCEL_CLOSE); // Define tooltips for dialog buttons Map tooltips = new HashMap<>();