package org.jabref.gui.actions;
import java.util.List;
import java.util.Objects;
import javax.swing.JOptionPane;
import org.jabref.Globals;
import org.jabref.gui.BasePanel;
import org.jabref.gui.JabRefFrame;
import org.jabref.gui.cleanup.CleanupPresetPanel;
import org.jabref.gui.undo.NamedCompound;
import org.jabref.gui.undo.UndoableFieldChange;
import org.jabref.gui.util.component.CheckBoxMessage;
import org.jabref.gui.worker.AbstractWorker;
import org.jabref.logic.cleanup.CleanupPreset;
import org.jabref.logic.cleanup.CleanupWorker;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.FieldChange;
import org.jabref.model.entry.BibEntry;
import org.jabref.preferences.JabRefPreferences;
public class CleanupAction extends AbstractWorker {
private final BasePanel panel;
private final JabRefFrame frame;
/**
* Global variable to count unsuccessful renames
*/
private int unsuccessfulRenames;
private boolean canceled;
private int modifiedEntriesCount;
private final JabRefPreferences preferences;
public CleanupAction(BasePanel panel, JabRefPreferences preferences) {
this.panel = panel;
this.frame = panel.frame();
this.preferences = Objects.requireNonNull(preferences);
}
@Override
public void init() {
canceled = false;
modifiedEntriesCount = 0;
if (panel.getSelectedEntries().isEmpty()) { // None selected. Inform the user to select entries first.
JOptionPane.showMessageDialog(frame, Localization.lang("First select entries to clean up."),
Localization.lang("Cleanup entry"), JOptionPane.INFORMATION_MESSAGE);
canceled = true;
return;
}
frame.block();
panel.output(Localization.lang("Doing a cleanup for %0 entries...",
Integer.toString(panel.getSelectedEntries().size())));
}
@Override
public void run() {
if (canceled) {
return;
}
CleanupPresetPanel presetPanel = new CleanupPresetPanel(panel.getBibDatabaseContext(),
CleanupPreset.loadFromPreferences(preferences));
int choice = showDialog(presetPanel);
if (choice != JOptionPane.OK_OPTION) {
canceled = true;
return;
}
CleanupPreset cleanupPreset = presetPanel.getCleanupPreset();
cleanupPreset.storeInPreferences(preferences);
if (cleanupPreset.isRenamePDF() && Globals.prefs.getBoolean(JabRefPreferences.ASK_AUTO_NAMING_PDFS_AGAIN)) {
CheckBoxMessage cbm = new CheckBoxMessage(
Localization.lang("Auto-generating PDF-Names does not support undo. Continue?"),
Localization.lang("Disable this confirmation dialog"), false);
int answer = JOptionPane.showConfirmDialog(frame, cbm, Localization.lang("Autogenerate PDF Names"),
JOptionPane.YES_NO_OPTION);
if (cbm.isSelected()) {
Globals.prefs.putBoolean(JabRefPreferences.ASK_AUTO_NAMING_PDFS_AGAIN, false);
}
if (answer == JOptionPane.NO_OPTION) {
canceled = true;
return;
}
}
for (BibEntry entry : panel.getSelectedEntries()) {
// undo granularity is on entry level
NamedCompound ce = new NamedCompound(Localization.lang("Cleanup entry"));
doCleanup(cleanupPreset, entry, ce);
ce.end();
if (ce.hasEdits()) {
modifiedEntriesCount++;
panel.getUndoManager().addEdit(ce);
}
}
}
@Override
public void update() {
if (canceled) {
frame.unblock();
return;
}
if (unsuccessfulRenames > 0) { //Rename failed for at least one entry
JOptionPane.showMessageDialog(frame,
Localization.lang("File rename failed for %0 entries.", Integer.toString(unsuccessfulRenames)),
Localization.lang("Autogenerate PDF Names"), JOptionPane.INFORMATION_MESSAGE);
}
if (modifiedEntriesCount > 0) {
panel.updateEntryEditorIfShowing();
panel.markBaseChanged();
}
String message;
switch (modifiedEntriesCount) {
case 0:
message = Localization.lang("No entry needed a clean up");
break;
case 1:
message = Localization.lang("One entry needed a clean up");
break;
default:
message = Localization.lang("%0 entries needed a clean up", Integer.toString(modifiedEntriesCount));
break;
}
panel.output(message);
frame.unblock();
}
private int showDialog(CleanupPresetPanel presetPanel) {
String dialogTitle = Localization.lang("Cleanup entries");
Object[] messages = {Localization.lang("What would you like to clean up?"), presetPanel.getScrollPane()};
return JOptionPane.showConfirmDialog(frame, messages, dialogTitle, JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE);
}
/**
* Runs the cleanup on the entry and records the change.
*/
private void doCleanup(CleanupPreset preset, BibEntry entry, NamedCompound ce) {
// Create and run cleaner
CleanupWorker cleaner = new CleanupWorker(panel.getBibDatabaseContext(), preferences.getCleanupPreferences(
Globals.journalAbbreviationLoader));
List<FieldChange> changes = cleaner.cleanup(preset, entry);
unsuccessfulRenames = cleaner.getUnsuccessfulRenames();
if (changes.isEmpty()) {
return;
}
// Register undo action
for (FieldChange change : changes) {
ce.addEdit(new UndoableFieldChange(change));
}
}
}