diff --git a/CHANGELOG.md b/CHANGELOG.md index 357bc35ca9c..08c81da59b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We changed the arrangement of the lists in the "Citation relations" tab. `Cites` are now on the left and `Cited by` on the right [#10572](https://github.com/JabRef/jabref/pull/10752) - Sub libraries based on `aux` file can now also be generated if some citations are not found library. [#10775](https://github.com/JabRef/jabref/pull/10775) - We rearranged the tab order in the entry editor and renamed the "Scite Tab" to "Citation information". [#10821](https://github.com/JabRef/jabref/issues/10821) +- We changed the duplicate handling in the Import entries dialog. Potential duplicate entries are marked with an icon and importing will now trigger the merge dialog [#10914](https://github.com/JabRef/jabref/pull/10914) - We made the command "Push to TexShop" more robust to allow cite commands with a character before the first slash. [forum#2699](https://discourse.jabref.org/t/push-to-texshop-mac/2699/17?u=siedlerchr) - We only show the notification "Saving library..." if the library contains more than 2000 entries. [#9803](https://github.com/JabRef/jabref/issues/9803) - We enhanced the dialog for adding new fields in the content selector with a selection box containing a list of standard fields. [#10912](https://github.com/JabRef/jabref/pull/10912) diff --git a/src/main/java/org/jabref/gui/importer/ImportEntriesDialog.java b/src/main/java/org/jabref/gui/importer/ImportEntriesDialog.java index 152df4e5446..b7f81b7ad2a 100644 --- a/src/main/java/org/jabref/gui/importer/ImportEntriesDialog.java +++ b/src/main/java/org/jabref/gui/importer/ImportEntriesDialog.java @@ -158,10 +158,10 @@ private void initialize() { BackgroundTask.wrap(() -> viewModel.hasDuplicate(entry)).onSuccess(duplicateFound -> { if (duplicateFound) { - Button duplicateButton = IconTheme.JabRefIcons.DUPLICATE.asButton(); - duplicateButton.setTooltip(new Tooltip(Localization.lang("Possible duplicate of existing entry. Click to resolve."))); - duplicateButton.setOnAction(event -> viewModel.resolveDuplicate(entry)); - container.getChildren().add(1, duplicateButton); + Node icon = IconTheme.JabRefIcons.ERROR.getGraphicNode(); + Tooltip tooltip = new Tooltip(Localization.lang("Possible duplicate of existing entry. Will be resolved on import.")); + Tooltip.install(icon, tooltip); + container.getChildren().add(icon); } }).executeWith(taskExecutor); diff --git a/src/main/java/org/jabref/gui/importer/ImportEntriesViewModel.java b/src/main/java/org/jabref/gui/importer/ImportEntriesViewModel.java index a0f926cf370..9a65909d44a 100644 --- a/src/main/java/org/jabref/gui/importer/ImportEntriesViewModel.java +++ b/src/main/java/org/jabref/gui/importer/ImportEntriesViewModel.java @@ -17,9 +17,7 @@ import org.jabref.gui.AbstractViewModel; import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; -import org.jabref.gui.duplicationFinder.DuplicateResolverDialog; import org.jabref.gui.externalfiles.ImportHandler; -import org.jabref.gui.fieldeditors.LinkedFileViewModel; import org.jabref.gui.util.BackgroundTask; import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.bibtex.BibEntryWriter; @@ -33,7 +31,6 @@ import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.BibEntryTypesManager; -import org.jabref.model.entry.LinkedFile; import org.jabref.model.util.FileUpdateMonitor; import org.jabref.preferences.PreferencesService; @@ -142,48 +139,9 @@ public String getSourceString(BibEntry entry) { * @param entriesToImport subset of the entries contained in parserResult */ public void importEntries(List entriesToImport, boolean shouldDownloadFiles) { - // Check if we are supposed to warn about duplicates. - // If so, then see if there are duplicates, and warn if yes. - if (preferences.getImporterPreferences().shouldWarnAboutDuplicatesOnImport()) { - BackgroundTask.wrap(() -> entriesToImport.stream() - .anyMatch(this::hasDuplicate)).onSuccess(duplicateFound -> { - if (duplicateFound) { - boolean continueImport = dialogService.showConfirmationDialogWithOptOutAndWait(Localization.lang("Duplicates found"), - Localization.lang("There are possible duplicates that haven't been resolved. Continue?"), - Localization.lang("Continue with import"), - Localization.lang("Cancel import"), - Localization.lang("Do not ask again"), - optOut -> preferences.getImporterPreferences().setWarnAboutDuplicatesOnImport(!optOut)); - - if (!continueImport) { - dialogService.notify(Localization.lang("Import canceled")); - } else { - buildImportHandlerThenImportEntries(entriesToImport); - } - } else { - buildImportHandlerThenImportEntries(entriesToImport); - } - }).executeWith(taskExecutor); - } else { - buildImportHandlerThenImportEntries(entriesToImport); - } - // Remember the selection in the dialog preferences.getFilePreferences().setDownloadLinkedFiles(shouldDownloadFiles); - if (shouldDownloadFiles) { - for (BibEntry bibEntry : entriesToImport) { - bibEntry.getFiles().stream().filter(LinkedFile::isOnlineLink).forEach(linkedFile -> - new LinkedFileViewModel( - linkedFile, - bibEntry, - databaseContext, - taskExecutor, - dialogService, - preferences).download()); - } - } - new DatabaseMerger(preferences.getBibEntryPreferences().getKeywordSeparator()).mergeStrings( databaseContext.getDatabase(), parserResult.getDatabase()); @@ -193,7 +151,7 @@ public void importEntries(List entriesToImport, boolean shouldDownload parserResult.getPath().map(path -> path.getFileName().toString()).orElse("unknown"), parserResult.getDatabase().getEntries()); -// JabRefGUI.getMainFrame().getCurrentLibraryTab().markBaseChanged(); + buildImportHandlerThenImportEntries(entriesToImport); } private void buildImportHandlerThenImportEntries(List entriesToImport) { @@ -205,8 +163,7 @@ private void buildImportHandlerThenImportEntries(List entriesToImport) stateManager, dialogService, taskExecutor); - importHandler.importEntries(entriesToImport); - dialogService.notify(Localization.lang("Number of entries successfully imported") + ": " + entriesToImport.size()); + importHandler.importEntriesWithDuplicateCheck(selectedDb.getValue(), entriesToImport); } /** @@ -226,61 +183,4 @@ private Optional findInternalDuplicate(BibEntry entry) { } return Optional.empty(); } - - public void resolveDuplicate(BibEntry entry) { - // First, try to find duplicate in the existing library - Optional other = new DuplicateCheck(entryTypesManager).containsDuplicate(databaseContext.getDatabase(), entry, databaseContext.getMode()); - if (other.isPresent()) { - DuplicateResolverDialog dialog = new DuplicateResolverDialog(other.get(), - entry, DuplicateResolverDialog.DuplicateResolverType.IMPORT_CHECK, databaseContext, stateManager, dialogService, preferences); - - DuplicateResolverDialog.DuplicateResolverResult result = dialogService.showCustomDialogAndWait(dialog) - .orElse(DuplicateResolverDialog.DuplicateResolverResult.BREAK); - - if (result == DuplicateResolverDialog.DuplicateResolverResult.KEEP_LEFT) { - // TODO: Remove old entry. Or... add it to a list of entries - // to be deleted. We only delete - // it after Ok is clicked. - // entriesToDelete.add(other.get()); - } else if (result == DuplicateResolverDialog.DuplicateResolverResult.KEEP_RIGHT) { - // Remove the entry from the import inspection dialog. - entries.remove(entry); - } else if (result == DuplicateResolverDialog.DuplicateResolverResult.KEEP_BOTH) { - // Do nothing. - } else if (result == DuplicateResolverDialog.DuplicateResolverResult.KEEP_MERGE) { - // TODO: Remove old entry. Or... add it to a list of entries - // to be deleted. We only delete - // it after Ok is clicked. - // entriesToDelete.add(other.get()); - - // Replace entry by merged entry - entries.add(dialog.getMergedEntry()); - entries.remove(entry); - } - return; - } - // Second, check if the duplicate is of another entry in the import: - other = findInternalDuplicate(entry); - if (other.isPresent()) { - DuplicateResolverDialog diag = new DuplicateResolverDialog(entry, - other.get(), DuplicateResolverDialog.DuplicateResolverType.DUPLICATE_SEARCH, databaseContext, stateManager, dialogService, preferences); - - DuplicateResolverDialog.DuplicateResolverResult answer = dialogService.showCustomDialogAndWait(diag) - .orElse(DuplicateResolverDialog.DuplicateResolverResult.BREAK); - if (answer == DuplicateResolverDialog.DuplicateResolverResult.KEEP_LEFT) { - // Remove other entry - entries.remove(other.get()); - } else if (answer == DuplicateResolverDialog.DuplicateResolverResult.KEEP_RIGHT) { - // Remove entry - entries.remove(entry); - } else if (answer == DuplicateResolverDialog.DuplicateResolverResult.KEEP_BOTH) { - // Do nothing - } else if (answer == DuplicateResolverDialog.DuplicateResolverResult.KEEP_MERGE) { - // Replace both entries by merged entry - entries.add(diag.getMergedEntry()); - entries.remove(entry); - entries.remove(other.get()); - } - } - } } diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 596f60838cb..26eb731b57d 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -633,7 +633,10 @@ Please\ restart\ JabRef\ for\ preferences\ to\ take\ effect.=Please restart JabR Possible\ duplicate\ entries=Possible duplicate entries -Possible\ duplicate\ of\ existing\ entry.\ Click\ to\ resolve.=Possible duplicate of existing entry. Click to resolve. +Possible\ duplicate\ of\ existing\ entry.\ Will\ be\ resolved\ on\ import.=Possible duplicate of existing entry. Will be resolved on import. + +Import\ canceled=Import canceled + Preferences=Preferences @@ -894,8 +897,6 @@ The\ label\ of\ the\ string\ cannot\ contain\ the\ '\#'\ character.=The label of The\ output\ option\ depends\ on\ a\ valid\ import\ option.=The output option depends on a valid import option. -There\ are\ possible\ duplicates\ that\ haven't\ been\ resolved.\ Continue?=There are possible duplicates that haven't been resolved. Continue? - This\ operation\ requires\ all\ selected\ entries\ to\ have\ citation\ keys\ defined.=This operation requires all selected entries to have citation keys defined. This\ operation\ requires\ one\ or\ more\ entries\ to\ be\ selected.=This operation requires one or more entries to be selected. @@ -1968,9 +1969,6 @@ Export\ format\ name\:=Export format name\: Cleared\ connection\ settings=Cleared connection settings Error\ adding\ discovered\ CitationStyles=Error adding discovered CitationStyles (more)=(more) -Cancel\ import=Cancel import -Continue\ with\ import=Continue with import -Import\ canceled=Import canceled Select\ all\ new\ entries=Select all new entries Select\ all\ entries=Select all entries Total\ items\ found\:=Total items found: