Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix duplicate check/merge entries dialog not triggered on import from… #10914

Merged
merged 10 commits into from
Feb 27, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
104 changes: 2 additions & 102 deletions src/main/java/org/jabref/gui/importer/ImportEntriesViewModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -142,48 +139,9 @@ public String getSourceString(BibEntry entry) {
* @param entriesToImport subset of the entries contained in parserResult
*/
public void importEntries(List<BibEntry> 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());
Expand All @@ -193,7 +151,7 @@ public void importEntries(List<BibEntry> entriesToImport, boolean shouldDownload
parserResult.getPath().map(path -> path.getFileName().toString()).orElse("unknown"),
parserResult.getDatabase().getEntries());

// JabRefGUI.getMainFrame().getCurrentLibraryTab().markBaseChanged();
buildImportHandlerThenImportEntries(entriesToImport);
Siedlerchr marked this conversation as resolved.
Show resolved Hide resolved
}

private void buildImportHandlerThenImportEntries(List<BibEntry> entriesToImport) {
Expand All @@ -205,8 +163,7 @@ private void buildImportHandlerThenImportEntries(List<BibEntry> entriesToImport)
stateManager,
dialogService,
taskExecutor);
importHandler.importEntries(entriesToImport);
dialogService.notify(Localization.lang("Number of entries successfully imported") + ": " + entriesToImport.size());
importHandler.importEntriesWithDuplicateCheck(selectedDb.getValue(), entriesToImport);
}

/**
Expand All @@ -226,61 +183,4 @@ private Optional<BibEntry> findInternalDuplicate(BibEntry entry) {
}
return Optional.empty();
}

public void resolveDuplicate(BibEntry entry) {
// First, try to find duplicate in the existing library
Optional<BibEntry> 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());
}
}
}
}
10 changes: 4 additions & 6 deletions src/main/resources/l10n/JabRef_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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:
Expand Down
Loading