Skip to content

Commit

Permalink
Convert DuplicateResolverDialog to javafx (#4601)
Browse files Browse the repository at this point in the history
* Convert DuplicateResolverDialog to javafx

* add result

* change buttons to button types
simplify dialog
reset duplicate bibtex key search dialog for the moment

* fix help and move buttons to init
return null on default
  • Loading branch information
Siedlerchr authored Jan 26, 2019
1 parent aa3657c commit 16a68f3
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 157 deletions.
174 changes: 74 additions & 100 deletions src/main/java/org/jabref/gui/DuplicateResolverDialog.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
package org.jabref.gui;

import java.awt.BorderLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBar;
import javafx.scene.control.ButtonBar.ButtonData;
import javafx.scene.control.ButtonType;
import javafx.scene.layout.BorderPane;

import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JPanel;

import javafx.scene.Scene;

import org.jabref.gui.customjfx.CustomJFXPanel;
import org.jabref.gui.DuplicateResolverDialog.DuplicateResolverResult;
import org.jabref.gui.help.HelpAction;
import org.jabref.gui.importer.ImportInspectionDialog;
import org.jabref.gui.mergeentries.MergeEntries;
import org.jabref.gui.util.WindowLocation;
import org.jabref.gui.util.BaseDialog;
import org.jabref.logic.help.HelpFile;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.entry.BibEntry;
import org.jabref.preferences.JabRefPreferences;

public class DuplicateResolverDialog extends JabRefDialog {
public class DuplicateResolverDialog extends BaseDialog<DuplicateResolverResult> {

public enum DuplicateResolverType {
DUPLICATE_SEARCH,
Expand All @@ -30,7 +24,6 @@ public enum DuplicateResolverType {
}

public enum DuplicateResolverResult {
NOT_CHOSEN,
KEEP_BOTH,
KEEP_LEFT,
KEEP_RIGHT,
Expand All @@ -39,108 +32,89 @@ public enum DuplicateResolverResult {
BREAK
}

JButton helpButton = new HelpAction(Localization.lang("Help"), HelpFile.FIND_DUPLICATES).getHelpButton();
private final JButton cancel = new JButton(Localization.lang("Cancel"));
private final JButton merge = new JButton(Localization.lang("Keep merged entry only"));
private final JabRefFrame frame;
private final JPanel options = new JPanel();
private DuplicateResolverResult status = DuplicateResolverResult.NOT_CHOSEN;
private MergeEntries me;

public DuplicateResolverDialog(JabRefFrame frame, BibEntry one, BibEntry two, DuplicateResolverType type) {
super(Localization.lang("Possible duplicate entries"), true, DuplicateResolverDialog.class);
this.frame = frame;
init(one, two, type);
}

public DuplicateResolverDialog(ImportInspectionDialog dialog, BibEntry one, BibEntry two,
DuplicateResolverType type) {
super(dialog, Localization.lang("Possible duplicate entries"), true, DuplicateResolverDialog.class);
this.frame = dialog.getFrame();
this.setTitle(Localization.lang("Possible duplicate entries"));
init(one, two, type);
}

private void init(BibEntry one, BibEntry two, DuplicateResolverType type) {
JButton both;
JButton second;
JButton first;
JButton removeExact = null;
switch (type) {
case DUPLICATE_SEARCH:
first = new JButton(Localization.lang("Keep left"));
second = new JButton(Localization.lang("Keep right"));
both = new JButton(Localization.lang("Keep both"));
me = new MergeEntries(one, two, frame.getCurrentBasePanel().getBibDatabaseContext().getMode());
break;
case INSPECTION:
first = new JButton(Localization.lang("Remove old entry"));
second = new JButton(Localization.lang("Remove entry from import"));
both = new JButton(Localization.lang("Keep both"));
me = new MergeEntries(one, two, Localization.lang("Old entry"),
Localization.lang("From import"), frame.getCurrentBasePanel().getBibDatabaseContext().getMode());
break;
case DUPLICATE_SEARCH_WITH_EXACT:
first = new JButton(Localization.lang("Keep left"));
second = new JButton(Localization.lang("Keep right"));
both = new JButton(Localization.lang("Keep both"));
removeExact = new JButton(Localization.lang("Automatically remove exact duplicates"));
me = new MergeEntries(one, two, frame.getCurrentBasePanel().getBibDatabaseContext().getMode());
break;
default:
first = new JButton(Localization.lang("Import and remove old entry"));
second = new JButton(Localization.lang("Do not import entry"));
both = new JButton(Localization.lang("Import and keep old entry"));
me = new MergeEntries(one, two, Localization.lang("Old entry"),
Localization.lang("From import"), frame.getCurrentBasePanel().getBibDatabaseContext().getMode());
break;
}

if (removeExact != null) {
options.add(removeExact);
HelpAction helpCommand = new HelpAction(HelpFile.FIND_DUPLICATES);
ButtonType help = new ButtonType(Localization.lang("Help"), ButtonData.HELP);

ButtonType cancel = ButtonType.CANCEL;
ButtonType merge = new ButtonType(Localization.lang("Keep merged entry only"), ButtonData.APPLY);

ButtonBar options = new ButtonBar();
ButtonType both;
ButtonType second;
ButtonType first;
ButtonType removeExact = new ButtonType(Localization.lang("Automatically remove exact duplicates"), ButtonData.APPLY);
boolean removeExactVisible = false;

switch (type) {
case DUPLICATE_SEARCH:
first = new ButtonType(Localization.lang("Keep left"), ButtonData.APPLY);
second = new ButtonType(Localization.lang("Keep right"), ButtonData.APPLY);
both = new ButtonType(Localization.lang("Keep both"), ButtonData.APPLY);
me = new MergeEntries(one, two, frame.getCurrentBasePanel().getBibDatabaseContext().getMode());
break;
case INSPECTION:
first = new ButtonType(Localization.lang("Remove old entry"), ButtonData.APPLY);
second = new ButtonType(Localization.lang("Remove entry from import"), ButtonData.APPLY);
both = new ButtonType(Localization.lang("Keep both"), ButtonData.APPLY);
me = new MergeEntries(one, two, Localization.lang("Old entry"),
Localization.lang("From import"), frame.getCurrentBasePanel().getBibDatabaseContext().getMode());
break;
case DUPLICATE_SEARCH_WITH_EXACT:
first = new ButtonType(Localization.lang("Keep left"), ButtonData.APPLY);
second = new ButtonType(Localization.lang("Keep right"), ButtonData.APPLY);
both = new ButtonType(Localization.lang("Keep both"), ButtonData.APPLY);

removeExactVisible = true;

me = new MergeEntries(one, two, frame.getCurrentBasePanel().getBibDatabaseContext().getMode());
break;
default:
first = new ButtonType(Localization.lang("Import and remove old entry"), ButtonData.APPLY);
second = new ButtonType(Localization.lang("Do not import entry"), ButtonData.APPLY);
both = new ButtonType(Localization.lang("Import and keep old entry"), ButtonData.APPLY);
me = new MergeEntries(one, two, Localization.lang("Old entry"),
Localization.lang("From import"), frame.getCurrentBasePanel().getBibDatabaseContext().getMode());
break;
}
options.add(first);
options.add(second);
options.add(both);
options.add(merge);
options.add(Box.createHorizontalStrut(5));
options.add(cancel);
options.add(helpButton);

first.addActionListener(e -> buttonPressed(DuplicateResolverResult.KEEP_LEFT));
second.addActionListener(e -> buttonPressed(DuplicateResolverResult.KEEP_RIGHT));
both.addActionListener(e -> buttonPressed(DuplicateResolverResult.KEEP_BOTH));
merge.addActionListener(e -> buttonPressed(DuplicateResolverResult.KEEP_MERGE));
if (removeExact != null) {
removeExact.addActionListener(e -> buttonPressed(DuplicateResolverResult.AUTOREMOVE_EXACT));
if (removeExactVisible) {
this.getDialogPane().getButtonTypes().add(removeExact);
}

cancel.addActionListener(e -> buttonPressed(DuplicateResolverResult.BREAK));
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
buttonPressed(DuplicateResolverResult.BREAK);
}
});
this.getDialogPane().getButtonTypes().addAll(first, second, both, merge, cancel, help);

getContentPane().add(CustomJFXPanel.wrap(new Scene(me)));
getContentPane().add(options, BorderLayout.SOUTH);
pack();
BorderPane borderPane = new BorderPane(me);
borderPane.setBottom(options);

WindowLocation pw = new WindowLocation(this, JabRefPreferences.DUPLICATES_POS_X,
JabRefPreferences.DUPLICATES_POS_Y, JabRefPreferences.DUPLICATES_SIZE_X,
JabRefPreferences.DUPLICATES_SIZE_Y);
pw.displayWindowAtStoredLocation();
this.setResultConverter(button -> {

both.requestFocus();
}

private void buttonPressed(DuplicateResolverResult result) {
status = result;
dispose();
}
if (button.equals(first)) {
return DuplicateResolverResult.KEEP_LEFT;
} else if (button.equals(second)) {
return DuplicateResolverResult.KEEP_RIGHT;
} else if (button.equals(both)) {
return DuplicateResolverResult.KEEP_BOTH;
} else if (button.equals(merge)) {
return DuplicateResolverResult.KEEP_MERGE;
} else if (button.equals(removeExact)) {
return DuplicateResolverResult.AUTOREMOVE_EXACT;
}
return null;
});

public DuplicateResolverResult getSelected() {
return status;
getDialogPane().setContent(borderPane);
Button helpButton = (Button) this.getDialogPane().lookupButton(help);
helpButton.setOnAction(evt -> helpCommand.getCommand().execute());
}

public BibEntry getMergedEntry() {
Expand Down
60 changes: 28 additions & 32 deletions src/main/java/org/jabref/gui/DuplicateSearch.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import javax.swing.SwingUtilities;

import org.jabref.Globals;
import org.jabref.JabRefExecutorService;
import org.jabref.gui.DuplicateResolverDialog.DuplicateResolverResult;
Expand All @@ -37,15 +35,17 @@ public class DuplicateSearch extends SimpleCommand {
private final AtomicBoolean libraryAnalyzed = new AtomicBoolean();
private final AtomicBoolean autoRemoveExactDuplicates = new AtomicBoolean();
private final AtomicInteger duplicateCount = new AtomicInteger();
private final DialogService dialogService;

public DuplicateSearch(JabRefFrame frame) {
public DuplicateSearch(JabRefFrame frame, DialogService dialogService) {
this.frame = frame;
this.dialogService = dialogService;
}

@Override
public void execute() {
BasePanel panel = frame.getCurrentBasePanel();
panel.output(Localization.lang("Searching for duplicates..."));
dialogService.notify(Localization.lang("Searching for duplicates..."));

List<BibEntry> entries = panel.getDatabase().getEntries();
duplicates.clear();
Expand All @@ -57,8 +57,7 @@ public void execute() {
return;
}

JabRefExecutorService.INSTANCE
.executeInterruptableTask(() -> searchPossibleDuplicates(entries, panel.getBibDatabaseContext().getMode()), "DuplicateSearcher");
JabRefExecutorService.INSTANCE.executeInterruptableTask(() -> searchPossibleDuplicates(entries, panel.getBibDatabaseContext().getMode()), "DuplicateSearcher");
BackgroundTask.wrap(this::verifyDuplicates)
.onSuccess(this::handleDuplicates)
.executeWith(Globals.TASK_EXECUTOR);
Expand Down Expand Up @@ -124,13 +123,11 @@ private DuplicateSearchResult verifyDuplicates() {

private void askResolveStrategy(DuplicateSearchResult result, BibEntry first, BibEntry second, DuplicateResolverType resolverType) {
DuplicateResolverDialog dialog = new DuplicateResolverDialog(frame, first, second, resolverType);
dialog.setVisible(true);
dialog.dispose();

DuplicateResolverResult resolverResult = dialog.getSelected();
DuplicateResolverResult resolverResult = dialog.showAndWait().orElse(DuplicateResolverResult.BREAK);

if ((resolverResult == DuplicateResolverResult.KEEP_LEFT)
|| (resolverResult == DuplicateResolverResult.AUTOREMOVE_EXACT)) {
|| (resolverResult == DuplicateResolverResult.AUTOREMOVE_EXACT)) {
result.remove(second);
if (resolverResult == DuplicateResolverResult.AUTOREMOVE_EXACT) {
autoRemoveExactDuplicates.set(true); // Remember choice
Expand All @@ -150,31 +147,30 @@ private void handleDuplicates(DuplicateSearchResult result) {
return;
}

SwingUtilities.invokeLater(() -> {
BasePanel panel = frame.getCurrentBasePanel();
final NamedCompound compoundEdit = new NamedCompound(Localization.lang("duplicate removal"));
// Now, do the actual removal:
if (!result.getToRemove().isEmpty()) {
for (BibEntry entry : result.getToRemove()) {
panel.getDatabase().removeEntry(entry);
compoundEdit.addEdit(new UndoableRemoveEntry(panel.getDatabase(), entry, panel));
}
panel.markBaseChanged();
BasePanel panel = frame.getCurrentBasePanel();
final NamedCompound compoundEdit = new NamedCompound(Localization.lang("duplicate removal"));
// Now, do the actual removal:
if (!result.getToRemove().isEmpty()) {
for (BibEntry entry : result.getToRemove()) {
panel.getDatabase().removeEntry(entry);
compoundEdit.addEdit(new UndoableRemoveEntry(panel.getDatabase(), entry, panel));
}
// and adding merged entries:
if (!result.getToAdd().isEmpty()) {
for (BibEntry entry : result.getToAdd()) {
panel.getDatabase().insertEntry(entry);
compoundEdit.addEdit(new UndoableInsertEntry(panel.getDatabase(), entry));
}
panel.markBaseChanged();
panel.markBaseChanged();
}
// and adding merged entries:
if (!result.getToAdd().isEmpty()) {
for (BibEntry entry : result.getToAdd()) {
panel.getDatabase().insertEntry(entry);
compoundEdit.addEdit(new UndoableInsertEntry(panel.getDatabase(), entry));
}
panel.markBaseChanged();
}

dialogService.notify(Localization.lang("Duplicates found") + ": " + duplicateCount.get() + ' '
+ Localization.lang("pairs processed") + ": " + result.getDuplicateCount());
compoundEdit.end();
panel.getUndoManager().addEdit(compoundEdit);

panel.output(Localization.lang("Duplicates found") + ": " + duplicateCount.get() + ' '
+ Localization.lang("pairs processed") + ": " + result.getDuplicateCount());
compoundEdit.end();
panel.getUndoManager().addEdit(compoundEdit);
});
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jabref/gui/JabRefFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@ private MenuBar createMenu() {
}

quality.getItems().addAll(
factory.createMenuItem(StandardActions.FIND_DUPLICATES, new DuplicateSearch(this)),
factory.createMenuItem(StandardActions.FIND_DUPLICATES, new DuplicateSearch(this, dialogService)),
factory.createMenuItem(StandardActions.MERGE_ENTRIES, new MergeEntriesAction(this)),

new SeparatorMenuItem(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,11 @@ class ResolveDuplicateLabelDialog {
private boolean okPressed;
private boolean cancelPressed;


public ResolveDuplicateLabelDialog(BasePanel panel, String key, List<BibEntry> entries) {
diag = new JDialog((JFrame) null, Localization.lang("Duplicate BibTeX key"), true);

FormBuilder b = FormBuilder.create().layout(new FormLayout(
"left:pref, 4dlu, fill:pref", "p"));
"left:pref, 4dlu, fill:pref", "p"));
b.add(new JLabel(Localization.lang("Duplicate BibTeX key") + ": " + key)).xyw(1, 1, 3);
b.getPanel().setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

Expand All @@ -59,7 +58,7 @@ public ResolveDuplicateLabelDialog(BasePanel panel, String key, List<BibEntry> e
JCheckBox cb = new JCheckBox(Localization.lang("Generate BibTeX key"), !first);
b.appendRows("1dlu, p");
b.add(cb).xy(1, row);
PreviewPanel previewPanel = new PreviewPanel(null, null, Globals.getKeyPrefs(), Globals.prefs.getPreviewPreferences(), new FXDialogService(), ExternalFileTypes.getInstance());
PreviewPanel previewPanel = new PreviewPanel(null, panel.getBibDatabaseContext(), Globals.getKeyPrefs(), Globals.prefs.getPreviewPreferences(), new FXDialogService(), ExternalFileTypes.getInstance());
previewPanel.setEntry(entry);
JFXPanel container = CustomJFXPanel.wrap(new Scene(previewPanel));
container.setPreferredSize(new Dimension(800, 90));
Expand All @@ -86,8 +85,8 @@ public ResolveDuplicateLabelDialog(BasePanel panel, String key, List<BibEntry> e
diag.pack();

ok.addActionListener(e -> {
okPressed = true;
diag.dispose();
okPressed = true;
diag.dispose();
});

ignore.addActionListener(e -> diag.dispose());
Expand Down
Loading

0 comments on commit 16a68f3

Please sign in to comment.