use of org.jabref.gui.worker.AbstractWorker in project jabref by JabRef.
the class BasePanel method setupActions.
private void setupActions() {
SaveDatabaseAction saveAction = new SaveDatabaseAction(this);
CleanupAction cleanUpAction = new CleanupAction(this, Globals.prefs);
actions.put(Actions.UNDO, undoAction);
actions.put(Actions.REDO, redoAction);
actions.put(Actions.FOCUS_TABLE, (BaseAction) () -> {
mainTable.requestFocus();
});
// The action for opening an entry editor.
actions.put(Actions.EDIT, (BaseAction) selectionListener::editSignalled);
// The action for saving a database.
actions.put(Actions.SAVE, saveAction);
actions.put(Actions.SAVE_AS, (BaseAction) saveAction::saveAs);
actions.put(Actions.SAVE_SELECTED_AS, new SaveSelectedAction(SavePreferences.DatabaseSaveType.ALL));
actions.put(Actions.SAVE_SELECTED_AS_PLAIN, new SaveSelectedAction(SavePreferences.DatabaseSaveType.PLAIN_BIBTEX));
// The action for copying selected entries.
actions.put(Actions.COPY, (BaseAction) () -> copy());
actions.put(Actions.PRINT_PREVIEW, new PrintPreviewAction());
actions.put(Actions.CUT, (BaseAction) this::cut);
//when you modify this action be sure to adjust Actions.CUT,
//they are the same except of the Localization, delete confirmation and Actions.COPY call
actions.put(Actions.DELETE, (BaseAction) () -> delete(false));
// The action for pasting entries or cell contents.
// - more robust detection of available content flavors (doesn't only look at first one offered)
// - support for parsing string-flavor clipboard contents which are bibtex entries.
// This allows you to (a) paste entire bibtex entries from a text editor, web browser, etc
// (b) copy and paste entries between multiple instances of JabRef (since
// only the text representation seems to get as far as the X clipboard, at least on my system)
actions.put(Actions.PASTE, (BaseAction) () -> paste());
actions.put(Actions.SELECT_ALL, (BaseAction) mainTable::selectAll);
// The action for opening the preamble editor
actions.put(Actions.EDIT_PREAMBLE, (BaseAction) () -> {
if (preambleEditor == null) {
PreambleEditor form = new PreambleEditor(frame, BasePanel.this, bibDatabaseContext.getDatabase());
form.setLocationRelativeTo(frame);
form.setVisible(true);
preambleEditor = form;
} else {
preambleEditor.setVisible(true);
}
});
// The action for opening the string editor
actions.put(Actions.EDIT_STRINGS, (BaseAction) () -> {
if (stringDialog == null) {
StringDialog form = new StringDialog(frame, BasePanel.this, bibDatabaseContext.getDatabase());
form.setVisible(true);
stringDialog = form;
} else {
stringDialog.setVisible(true);
}
});
actions.put(FindUnlinkedFilesDialog.ACTION_COMMAND, (BaseAction) () -> {
final FindUnlinkedFilesDialog dialog = new FindUnlinkedFilesDialog(frame, frame, BasePanel.this);
dialog.setLocationRelativeTo(frame);
dialog.setVisible(true);
});
// The action for auto-generating keys.
actions.put(Actions.MAKE_KEY, new AbstractWorker() {
List<BibEntry> entries;
int numSelected;
boolean canceled;
// Run first, in EDT:
@Override
public void init() {
entries = getSelectedEntries();
numSelected = entries.size();
if (entries.isEmpty()) {
// None selected. Inform the user to select entries first.
JOptionPane.showMessageDialog(frame, Localization.lang("First select the entries you want keys to be generated for."), Localization.lang("Autogenerate BibTeX keys"), JOptionPane.INFORMATION_MESSAGE);
return;
}
frame.block();
output(formatOutputMessage(Localization.lang("Generating BibTeX key for"), numSelected));
}
// Run second, on a different thread:
@Override
public void run() {
// We don't want to generate keys for entries which already have one thus remove the entries
if (Globals.prefs.getBoolean(JabRefPreferences.AVOID_OVERWRITING_KEY)) {
entries.removeIf(BibEntry::hasCiteKey);
// if we're going to override some cite keys warn the user about it
} else if (Globals.prefs.getBoolean(JabRefPreferences.WARN_BEFORE_OVERWRITING_KEY)) {
if (entries.parallelStream().anyMatch(BibEntry::hasCiteKey)) {
CheckBoxMessage cbm = new CheckBoxMessage(Localization.lang("One or more keys will be overwritten. Continue?"), Localization.lang("Disable this confirmation dialog"), false);
final int answer = JOptionPane.showConfirmDialog(frame, cbm, Localization.lang("Overwrite keys"), JOptionPane.YES_NO_OPTION);
Globals.prefs.putBoolean(JabRefPreferences.WARN_BEFORE_OVERWRITING_KEY, !cbm.isSelected());
// The user doesn't want to overide cite keys
if (answer == JOptionPane.NO_OPTION) {
canceled = true;
return;
}
}
}
// generate the new cite keys for each entry
final NamedCompound ce = new NamedCompound(Localization.lang("Autogenerate BibTeX keys"));
AbstractBibtexKeyPattern citeKeyPattern = bibDatabaseContext.getMetaData().getCiteKeyPattern(Globals.prefs.getBibtexKeyPatternPreferences().getKeyPattern());
for (BibEntry entry : entries) {
String oldCiteKey = entry.getCiteKeyOptional().orElse("");
BibtexKeyPatternUtil.makeAndSetLabel(citeKeyPattern, bibDatabaseContext.getDatabase(), entry, Globals.prefs.getBibtexKeyPatternPreferences());
String newCiteKey = entry.getCiteKeyOptional().orElse("");
if (!oldCiteKey.equals(newCiteKey)) {
ce.addEdit(new UndoableKeyChange(entry, oldCiteKey, newCiteKey));
}
}
ce.end();
// register the undo event only if new cite keys were generated
if (ce.hasEdits()) {
getUndoManager().addEdit(ce);
}
}
// Run third, on EDT:
@Override
public void update() {
if (canceled) {
frame.unblock();
return;
}
markBaseChanged();
numSelected = entries.size();
////////////////////////////////////////////////////////////////////////////////
for (final BibEntry bibEntry : entries) {
SwingUtilities.invokeLater(() -> {
final int row = mainTable.findEntry(bibEntry);
if ((row >= 0) && (mainTable.getSelectedRowCount() < entries.size())) {
mainTable.addRowSelectionInterval(row, row);
}
});
}
////////////////////////////////////////////////////////////////////////////////
output(formatOutputMessage(Localization.lang("Generated BibTeX key for"), numSelected));
frame.unblock();
}
});
// The action for cleaning up entry.
actions.put(Actions.CLEANUP, cleanUpAction);
actions.put(Actions.MERGE_ENTRIES, (BaseAction) () -> new MergeEntriesDialog(BasePanel.this));
actions.put(Actions.SEARCH, (BaseAction) frame.getGlobalSearchBar()::focus);
actions.put(Actions.GLOBAL_SEARCH, (BaseAction) frame.getGlobalSearchBar()::performGlobalSearch);
// The action for copying the selected entry's key.
actions.put(Actions.COPY_KEY, (BaseAction) () -> copyKey());
// The action for copying the selected entry's title.
actions.put(Actions.COPY_TITLE, (BaseAction) () -> copyTitle());
// The action for copying a cite for the selected entry.
actions.put(Actions.COPY_CITE_KEY, (BaseAction) () -> copyCiteKey());
// The action for copying the BibTeX key and the title for the first selected entry
actions.put(Actions.COPY_KEY_AND_TITLE, (BaseAction) () -> copyKeyAndTitle());
actions.put(Actions.COPY_CITATION_ASCII_DOC, (BaseAction) () -> copyCitationToClipboard(CitationStyleOutputFormat.ASCII_DOC));
actions.put(Actions.COPY_CITATION_XSLFO, (BaseAction) () -> copyCitationToClipboard(CitationStyleOutputFormat.XSL_FO));
actions.put(Actions.COPY_CITATION_HTML, (BaseAction) () -> copyCitationToClipboard(CitationStyleOutputFormat.HTML));
actions.put(Actions.COPY_CITATION_RTF, (BaseAction) () -> copyCitationToClipboard(CitationStyleOutputFormat.RTF));
actions.put(Actions.COPY_CITATION_TEXT, (BaseAction) () -> copyCitationToClipboard(CitationStyleOutputFormat.TEXT));
// The action for copying the BibTeX keys as hyperlinks to the urls of the selected entries
actions.put(Actions.COPY_KEY_AND_LINK, new CopyBibTeXKeyAndLinkAction(mainTable));
actions.put(Actions.MERGE_DATABASE, new AppendDatabaseAction(frame, this));
actions.put(Actions.ADD_FILE_LINK, new AttachFileAction(this));
actions.put(Actions.OPEN_EXTERNAL_FILE, (BaseAction) () -> openExternalFile());
actions.put(Actions.OPEN_FOLDER, (BaseAction) () -> JabRefExecutorService.INSTANCE.execute(() -> {
final List<Path> files = FileUtil.getListOfLinkedFiles(mainTable.getSelectedEntries(), bibDatabaseContext.getFileDirectoriesAsPaths(Globals.prefs.getFileDirectoryPreferences()));
for (final Path f : files) {
try {
JabRefDesktop.openFolderAndSelectFile(f.toAbsolutePath());
} catch (IOException e) {
LOGGER.info("Could not open folder", e);
}
}
}));
actions.put(Actions.OPEN_CONSOLE, (BaseAction) () -> JabRefDesktop.openConsole(frame.getCurrentBasePanel().getBibDatabaseContext().getDatabaseFile().orElse(null)));
actions.put(Actions.PULL_CHANGES_FROM_SHARED_DATABASE, (BaseAction) () -> {
DBMSSynchronizer dbmsSynchronizer = frame.getCurrentBasePanel().getBibDatabaseContext().getDBMSSynchronizer();
dbmsSynchronizer.pullChanges();
});
actions.put(Actions.OPEN_URL, new OpenURLAction());
actions.put(Actions.MERGE_WITH_FETCHED_ENTRY, new MergeWithFetchedEntryAction(this));
actions.put(Actions.REPLACE_ALL, (BaseAction) () -> {
final ReplaceStringDialog rsd = new ReplaceStringDialog(frame);
rsd.setVisible(true);
if (!rsd.okPressed()) {
return;
}
int counter = 0;
final NamedCompound ce = new NamedCompound(Localization.lang("Replace string"));
if (rsd.selOnly()) {
for (BibEntry be : mainTable.getSelectedEntries()) {
counter += rsd.replace(be, ce);
}
} else {
for (BibEntry entry : bibDatabaseContext.getDatabase().getEntries()) {
counter += rsd.replace(entry, ce);
}
}
output(Localization.lang("Replaced") + ' ' + counter + ' ' + (counter == 1 ? Localization.lang("occurrence") : Localization.lang("occurrences")) + '.');
if (counter > 0) {
ce.end();
getUndoManager().addEdit(ce);
markBaseChanged();
}
});
actions.put(Actions.DUPLI_CHECK, (BaseAction) () -> JabRefExecutorService.INSTANCE.execute(new DuplicateSearch(BasePanel.this)));
actions.put(Actions.PLAIN_TEXT_IMPORT, (BaseAction) () -> {
EntryTypeDialog etd = new EntryTypeDialog(frame);
etd.setLocationRelativeTo(BasePanel.this);
etd.setVisible(true);
EntryType tp = etd.getChoice();
if (tp == null) {
return;
}
BibEntry bibEntry = new BibEntry(tp.getName());
TextInputDialog tidialog = new TextInputDialog(frame, bibEntry);
tidialog.setLocationRelativeTo(BasePanel.this);
tidialog.setVisible(true);
if (tidialog.okPressed()) {
UpdateField.setAutomaticFields(Collections.singletonList(bibEntry), false, false, Globals.prefs.getUpdateFieldPreferences());
insertEntry(bibEntry);
}
});
actions.put(Actions.MARK_ENTRIES, new MarkEntriesAction(frame, 0));
actions.put(Actions.UNMARK_ENTRIES, (BaseAction) () -> {
try {
List<BibEntry> bes = mainTable.getSelectedEntries();
if (bes.isEmpty()) {
output(Localization.lang("This operation requires one or more entries to be selected."));
return;
}
NamedCompound ce = new NamedCompound(Localization.lang("Unmark entries"));
for (BibEntry be : bes) {
EntryMarker.unmarkEntry(be, false, bibDatabaseContext.getDatabase(), ce);
}
ce.end();
getUndoManager().addEdit(ce);
markBaseChanged();
String outputStr;
if (bes.size() == 1) {
outputStr = Localization.lang("Unmarked selected entry");
} else {
outputStr = Localization.lang("Unmarked all %0 selected entries", Integer.toString(bes.size()));
}
output(outputStr);
} catch (Throwable ex) {
LOGGER.warn("Could not unmark", ex);
}
});
actions.put(Actions.UNMARK_ALL, (BaseAction) () -> {
NamedCompound ce = new NamedCompound(Localization.lang("Unmark all"));
for (BibEntry be : bibDatabaseContext.getDatabase().getEntries()) {
EntryMarker.unmarkEntry(be, false, bibDatabaseContext.getDatabase(), ce);
}
ce.end();
getUndoManager().addEdit(ce);
markBaseChanged();
output(Localization.lang("Unmarked all entries"));
});
// Note that we can't put the number of entries that have been reverted into the undoText as the concrete number cannot be injected
actions.put(new SpecialFieldValueViewModel(SpecialField.RELEVANCE.getValues().get(0)).getActionName(), new SpecialFieldViewModel(SpecialField.RELEVANCE).getSpecialFieldAction(SpecialField.RELEVANCE.getValues().get(0), frame));
actions.put(new SpecialFieldValueViewModel(SpecialField.QUALITY.getValues().get(0)).getActionName(), new SpecialFieldViewModel(SpecialField.QUALITY).getSpecialFieldAction(SpecialField.QUALITY.getValues().get(0), frame));
actions.put(new SpecialFieldValueViewModel(SpecialField.PRINTED.getValues().get(0)).getActionName(), new SpecialFieldViewModel(SpecialField.PRINTED).getSpecialFieldAction(SpecialField.PRINTED.getValues().get(0), frame));
for (SpecialFieldValue prio : SpecialField.PRIORITY.getValues()) {
actions.put(new SpecialFieldValueViewModel(prio).getActionName(), new SpecialFieldViewModel(SpecialField.PRIORITY).getSpecialFieldAction(prio, this.frame));
}
for (SpecialFieldValue rank : SpecialField.RANKING.getValues()) {
actions.put(new SpecialFieldValueViewModel(rank).getActionName(), new SpecialFieldViewModel(SpecialField.RANKING).getSpecialFieldAction(rank, this.frame));
}
for (SpecialFieldValue status : SpecialField.READ_STATUS.getValues()) {
actions.put(new SpecialFieldValueViewModel(status).getActionName(), new SpecialFieldViewModel(SpecialField.READ_STATUS).getSpecialFieldAction(status, this.frame));
}
actions.put(Actions.TOGGLE_PREVIEW, (BaseAction) () -> {
PreviewPreferences previewPreferences = Globals.prefs.getPreviewPreferences();
boolean enabled = !previewPreferences.isPreviewPanelEnabled();
PreviewPreferences newPreviewPreferences = previewPreferences.getBuilder().withPreviewPanelEnabled(enabled).build();
Globals.prefs.storePreviewPreferences(newPreviewPreferences);
setPreviewActiveBasePanels(enabled);
frame.setPreviewToggle(enabled);
});
actions.put(Actions.NEXT_PREVIEW_STYLE, (BaseAction) selectionListener::nextPreviewStyle);
actions.put(Actions.PREVIOUS_PREVIEW_STYLE, (BaseAction) selectionListener::previousPreviewStyle);
actions.put(Actions.MANAGE_SELECTORS, (BaseAction) () -> {
ContentSelectorDialog csd = new ContentSelectorDialog(frame, frame, BasePanel.this, false, null);
csd.setLocationRelativeTo(frame);
csd.setVisible(true);
});
actions.put(Actions.EXPORT_TO_CLIPBOARD, new ExportToClipboardAction(frame));
actions.put(Actions.SEND_AS_EMAIL, new SendAsEMailAction(frame));
actions.put(Actions.WRITE_XMP, new WriteXMPAction(this));
actions.put(Actions.ABBREVIATE_ISO, new AbbreviateAction(this, true));
actions.put(Actions.ABBREVIATE_MEDLINE, new AbbreviateAction(this, false));
actions.put(Actions.UNABBREVIATE, new UnabbreviateAction(this));
actions.put(Actions.AUTO_SET_FILE, new SynchronizeFileField(this));
actions.put(Actions.BACK, (BaseAction) BasePanel.this::back);
actions.put(Actions.FORWARD, (BaseAction) BasePanel.this::forward);
actions.put(Actions.RESOLVE_DUPLICATE_KEYS, new SearchFixDuplicateLabels(this));
actions.put(Actions.ADD_TO_GROUP, new GroupAddRemoveDialog(this, true, false));
actions.put(Actions.REMOVE_FROM_GROUP, new GroupAddRemoveDialog(this, false, false));
actions.put(Actions.MOVE_TO_GROUP, new GroupAddRemoveDialog(this, true, true));
actions.put(Actions.DOWNLOAD_FULL_TEXT, new FindFullTextAction(this));
}
use of org.jabref.gui.worker.AbstractWorker in project jabref by JabRef.
the class WriteXMPEntryEditorAction method actionPerformed.
@Override
public void actionPerformed(ActionEvent actionEvent) {
setEnabled(false);
panel.output(Localization.lang("Writing XMP-metadata..."));
panel.frame().setProgressBarIndeterminate(true);
panel.frame().setProgressBarVisible(true);
BibEntry entry = editor.getEntry();
// Make a list of all PDFs linked from this entry:
List<Path> files = entry.getFiles().stream().filter(file -> file.getFileType().equalsIgnoreCase("pdf")).map(file -> file.findIn(panel.getBibDatabaseContext(), Globals.prefs.getFileDirectoryPreferences())).filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList());
// We want to offload the actual work to a background thread, so we have a worker
// thread:
AbstractWorker worker = new WriteXMPWorker(files, entry);
// Using Spin, we get a thread that gets synchronously offloaded to a new thread,
// blocking the execution of this method:
worker.getWorker().run();
// After the worker thread finishes, we are unblocked and ready to print the
// status message:
panel.output(message);
panel.frame().setProgressBarVisible(false);
setEnabled(true);
}
use of org.jabref.gui.worker.AbstractWorker in project jabref by JabRef.
the class ExportAction method getExportAction.
/**
* Create an AbstractAction for performing an export operation.
*
* @param frame
* The JabRefFrame of this JabRef instance.
* @param selectedOnly
* true indicates that only selected entries should be exported,
* false indicates that all entries should be exported.
* @return The action.
*/
public static AbstractAction getExportAction(JabRefFrame frame, boolean selectedOnly) {
class InternalExportAction extends MnemonicAwareAction {
private final JabRefFrame frame;
private final boolean selectedOnly;
public InternalExportAction(JabRefFrame frame, boolean selectedOnly) {
this.frame = frame;
this.selectedOnly = selectedOnly;
putValue(Action.NAME, selectedOnly ? Localization.menuTitle("Export selected entries") : Localization.menuTitle("Export"));
}
@Override
public void actionPerformed(ActionEvent e) {
Map<String, ExportFormat> customFormats = Globals.prefs.customExports.getCustomExportFormats(Globals.prefs, Globals.journalAbbreviationLoader);
LayoutFormatterPreferences layoutPreferences = Globals.prefs.getLayoutFormatterPreferences(Globals.journalAbbreviationLoader);
SavePreferences savePreferences = SavePreferences.loadForExportFromPreferences(Globals.prefs);
ExportFormats.initAllExports(customFormats, layoutPreferences, savePreferences);
JFileChooser fc = ExportAction.createExportFileChooser(Globals.prefs.get(JabRefPreferences.EXPORT_WORKING_DIRECTORY));
fc.showSaveDialog(frame);
File file = fc.getSelectedFile();
if (file == null) {
return;
}
FileFilter ff = fc.getFileFilter();
if (ff instanceof ExportFileFilter) {
ExportFileFilter eff = (ExportFileFilter) ff;
String path = file.getPath();
if (!path.endsWith(eff.getExtension())) {
path = path + eff.getExtension();
}
file = new File(path);
if (file.exists()) {
// Warn that the file exists:
if (JOptionPane.showConfirmDialog(frame, Localization.lang("'%0' exists. Overwrite file?", file.getName()), Localization.lang("Export"), JOptionPane.OK_CANCEL_OPTION) != JOptionPane.OK_OPTION) {
return;
}
}
final IExportFormat format = eff.getExportFormat();
List<BibEntry> entries;
if (selectedOnly) {
// Selected entries
entries = frame.getCurrentBasePanel().getSelectedEntries();
} else {
// All entries
entries = frame.getCurrentBasePanel().getDatabase().getEntries();
}
// Set the global variable for this database's file directory before exporting,
// so formatters can resolve linked files correctly.
// (This is an ugly hack!)
Globals.prefs.fileDirForDatabase = frame.getCurrentBasePanel().getBibDatabaseContext().getFileDirectories(Globals.prefs.getFileDirectoryPreferences());
// Make sure we remember which filter was used, to set
// the default for next time:
Globals.prefs.put(JabRefPreferences.LAST_USED_EXPORT, format.getConsoleName());
Globals.prefs.put(JabRefPreferences.EXPORT_WORKING_DIRECTORY, file.getParent());
final File finFile = file;
final List<BibEntry> finEntries = entries;
AbstractWorker exportWorker = new AbstractWorker() {
String errorMessage;
@Override
public void run() {
try {
format.performExport(frame.getCurrentBasePanel().getBibDatabaseContext(), finFile.getPath(), frame.getCurrentBasePanel().getBibDatabaseContext().getMetaData().getEncoding().orElse(Globals.prefs.getDefaultEncoding()), finEntries);
} catch (Exception ex) {
LOGGER.warn("Problem exporting", ex);
if (ex.getMessage() == null) {
errorMessage = ex.toString();
} else {
errorMessage = ex.getMessage();
}
}
}
@Override
public void update() {
// No error message. Report success:
if (errorMessage == null) {
frame.output(Localization.lang("%0 export successful", format.getDisplayName()));
} else // ... or show an error dialog:
{
frame.output(Localization.lang("Could not save file.") + " - " + errorMessage);
// Need to warn the user that saving failed!
JOptionPane.showMessageDialog(frame, Localization.lang("Could not save file.") + "\n" + errorMessage, Localization.lang("Save library"), JOptionPane.ERROR_MESSAGE);
}
}
};
// Run the export action in a background thread:
exportWorker.getWorker().run();
// Run the update method:
exportWorker.update();
}
}
}
return new InternalExportAction(frame, selectedOnly);
}
Aggregations