diff --git a/src/main/java/org/jabref/gui/BasePanel.java b/src/main/java/org/jabref/gui/BasePanel.java index efec6542ab0..ff5baf2606d 100644 --- a/src/main/java/org/jabref/gui/BasePanel.java +++ b/src/main/java/org/jabref/gui/BasePanel.java @@ -1,17 +1,12 @@ package org.jabref.gui; -import java.io.IOException; -import java.io.StringReader; import java.nio.file.Path; -import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; import javax.swing.undo.CannotRedoException; import javax.swing.undo.CannotUndoException; @@ -35,14 +30,10 @@ import org.jabref.gui.cleanup.CleanupAction; import org.jabref.gui.collab.DatabaseChangeMonitor; import org.jabref.gui.collab.DatabaseChangePane; -import org.jabref.gui.desktop.JabRefDesktop; -import org.jabref.gui.edit.CopyBibTeXKeyAndLinkAction; import org.jabref.gui.edit.ReplaceStringAction; import org.jabref.gui.entryeditor.EntryEditor; import org.jabref.gui.exporter.SaveDatabaseAction; -import org.jabref.gui.exporter.WriteXMPAction; import org.jabref.gui.externalfiles.DownloadFullTextAction; -import org.jabref.gui.externalfiletype.ExternalFileType; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.importer.actions.AppendDatabaseAction; import org.jabref.gui.journals.AbbreviateAction; @@ -50,30 +41,18 @@ import org.jabref.gui.journals.UnabbreviateAction; import org.jabref.gui.maintable.MainTable; import org.jabref.gui.maintable.MainTableDataModel; -import org.jabref.gui.mergeentries.MergeEntriesAction; -import org.jabref.gui.mergeentries.MergeWithFetchedEntryAction; -import org.jabref.gui.preview.CitationStyleToClipboardWorker; import org.jabref.gui.specialfields.SpecialFieldDatabaseChangeListener; -import org.jabref.gui.specialfields.SpecialFieldValueViewModel; -import org.jabref.gui.specialfields.SpecialFieldViewModel; import org.jabref.gui.undo.CountingUndoManager; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableFieldChange; import org.jabref.gui.undo.UndoableInsertEntries; import org.jabref.gui.undo.UndoableRemoveEntries; import org.jabref.gui.util.DefaultTaskExecutor; -import org.jabref.gui.worker.SendAsEMailAction; import org.jabref.logic.citationstyle.CitationStyleCache; -import org.jabref.logic.citationstyle.CitationStyleOutputFormat; import org.jabref.logic.l10n.Localization; -import org.jabref.logic.layout.Layout; -import org.jabref.logic.layout.LayoutHelper; import org.jabref.logic.pdf.FileAnnotationCache; import org.jabref.logic.search.SearchQuery; import org.jabref.logic.util.UpdateField; -import org.jabref.logic.util.io.FileFinder; -import org.jabref.logic.util.io.FileFinders; -import org.jabref.logic.util.io.FileUtil; import org.jabref.model.FieldChange; import org.jabref.model.database.BibDatabase; import org.jabref.model.database.BibDatabaseContext; @@ -85,15 +64,10 @@ import org.jabref.model.database.shared.DatabaseLocation; import org.jabref.model.database.shared.DatabaseSynchronizer; import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.FileFieldParser; -import org.jabref.model.entry.LinkedFile; import org.jabref.model.entry.event.EntriesEventSource; import org.jabref.model.entry.event.EntryChangedEvent; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.FieldFactory; -import org.jabref.model.entry.field.SpecialField; -import org.jabref.model.entry.field.SpecialFieldValue; -import org.jabref.model.entry.field.StandardField; import org.jabref.preferences.JabRefPreferences; import com.google.common.eventbus.Subscribe; @@ -259,21 +233,6 @@ private void setupActions() { actions.put(Actions.SAVE_SELECTED_AS_PLAIN, saveAction::saveSelectedAsPlain); - // The action for copying selected entries. - actions.put(Actions.COPY, this::copy); - - actions.put(Actions.CUT, this::cut); - - actions.put(Actions.DELETE, () -> 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, this::paste); - actions.put(Actions.SELECT_ALL, mainTable.getSelectionModel()::selectAll); // The action for auto-generating keys. @@ -282,90 +241,15 @@ private void setupActions() { // The action for cleaning up entry. actions.put(Actions.CLEANUP, cleanUpAction); - actions.put(Actions.MERGE_ENTRIES, () -> new MergeEntriesAction(frame, Globals.stateManager).execute()); - - // The action for copying the selected entry's key. - actions.put(Actions.COPY_KEY, this::copyKey); - - // The action for copying the selected entry's title. - actions.put(Actions.COPY_TITLE, this::copyTitle); - - // The action for copying a cite for the selected entry. - actions.put(Actions.COPY_CITE_KEY, this::copyCiteKey); - - // The action for copying the BibTeX key and the title for the first selected entry - actions.put(Actions.COPY_KEY_AND_TITLE, this::copyKeyAndTitle); - - actions.put(Actions.COPY_CITATION_ASCII_DOC, () -> copyCitationToClipboard(CitationStyleOutputFormat.ASCII_DOC)); - actions.put(Actions.COPY_CITATION_XSLFO, () -> copyCitationToClipboard(CitationStyleOutputFormat.XSL_FO)); - actions.put(Actions.COPY_CITATION_HTML, () -> copyCitationToClipboard(CitationStyleOutputFormat.HTML)); - actions.put(Actions.COPY_CITATION_RTF, () -> copyCitationToClipboard(CitationStyleOutputFormat.RTF)); - actions.put(Actions.COPY_CITATION_TEXT, () -> 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, Globals.clipboardManager)); - actions.put(Actions.MERGE_DATABASE, new AppendDatabaseAction(frame, this)); - actions.put(Actions.OPEN_EXTERNAL_FILE, this::openExternalFile); - - actions.put(Actions.OPEN_FOLDER, () -> JabRefExecutorService.INSTANCE.execute(() -> { - final List<Path> files = FileUtil.getListOfLinkedFiles(mainTable.getSelectedEntries(), bibDatabaseContext.getFileDirectoriesAsPaths(Globals.prefs.getFilePreferences())); - 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, () -> JabRefDesktop.openConsole(frame.getCurrentBasePanel().getBibDatabaseContext().getDatabaseFile().orElse(null))); - actions.put(Actions.PULL_CHANGES_FROM_SHARED_DATABASE, () -> { DatabaseSynchronizer dbmsSynchronizer = frame.getCurrentBasePanel().getBibDatabaseContext().getDBMSSynchronizer(); dbmsSynchronizer.pullChanges(); }); - actions.put(Actions.OPEN_URL, new OpenURLAction()); - - actions.put(Actions.MERGE_WITH_FETCHED_ENTRY, new MergeWithFetchedEntryAction(this, frame.getDialogService())); - actions.put(Actions.REPLACE_ALL, () -> (new ReplaceStringAction(this)).execute()); - actions.put(new SpecialFieldValueViewModel(SpecialField.RELEVANCE.getValues().get(0)).getCommand(), - new SpecialFieldViewModel(SpecialField.RELEVANCE, undoManager).getSpecialFieldAction(SpecialField.RELEVANCE.getValues().get(0), frame)); - - actions.put(new SpecialFieldValueViewModel(SpecialField.QUALITY.getValues().get(0)).getCommand(), - new SpecialFieldViewModel(SpecialField.QUALITY, undoManager).getSpecialFieldAction(SpecialField.QUALITY.getValues().get(0), frame)); - - actions.put(new SpecialFieldValueViewModel(SpecialField.PRINTED.getValues().get(0)).getCommand(), - new SpecialFieldViewModel(SpecialField.PRINTED, undoManager).getSpecialFieldAction(SpecialField.PRINTED.getValues().get(0), frame)); - - for (SpecialFieldValue prio : SpecialField.PRIORITY.getValues()) { - actions.put(new SpecialFieldValueViewModel(prio).getCommand(), - new SpecialFieldViewModel(SpecialField.PRIORITY, undoManager).getSpecialFieldAction(prio, this.frame)); - } - for (SpecialFieldValue rank : SpecialField.RANKING.getValues()) { - actions.put(new SpecialFieldValueViewModel(rank).getCommand(), - new SpecialFieldViewModel(SpecialField.RANKING, undoManager).getSpecialFieldAction(rank, this.frame)); - } - for (SpecialFieldValue status : SpecialField.READ_STATUS.getValues()) { - actions.put(new SpecialFieldValueViewModel(status).getCommand(), - new SpecialFieldViewModel(SpecialField.READ_STATUS, undoManager).getSpecialFieldAction(status, this.frame)); - } - - actions.put(Actions.NEXT_PREVIEW_STYLE, () -> { - entryEditor.nextPreviewStyle(); - }); - actions.put(Actions.PREVIOUS_PREVIEW_STYLE, () -> { - entryEditor.previousPreviewStyle(); - }); - - actions.put(Actions.SEND_AS_EMAIL, new SendAsEMailAction(frame)); - - actions.put(Actions.WRITE_XMP, new WriteXMPAction(this)::execute); - actions.put(Actions.ABBREVIATE_DEFAULT, new AbbreviateAction(this, AbbreviationType.DEFAULT)); actions.put(Actions.ABBREVIATE_MEDLINE, new AbbreviateAction(this, AbbreviationType.MEDLINE)); actions.put(Actions.ABBREVIATE_SHORTEST_UNIQUE, new AbbreviateAction(this, AbbreviationType.SHORTEST_UNIQUE)); @@ -374,16 +258,6 @@ private void setupActions() { actions.put(Actions.DOWNLOAD_FULL_TEXT, new DownloadFullTextAction(this)::execute); } - /** - * Generates and copies citations based on the selected entries to the clipboard - * - * @param outputFormat the desired {@link CitationStyleOutputFormat} - */ - private void copyCitationToClipboard(CitationStyleOutputFormat outputFormat) { - CitationStyleToClipboardWorker worker = new CitationStyleToClipboardWorker(this, outputFormat, dialogService, Globals.clipboardManager, Globals.prefs.getPreviewPreferences()); - worker.copyCitationStyleToClipboard(Globals.TASK_EXECUTOR); - } - /** * Removes the selected entries from the database * @@ -423,157 +297,6 @@ public void delete(BibEntry entry) { delete(false, Collections.singletonList(entry)); } - private void copyTitle() { - List<BibEntry> selectedBibEntries = mainTable.getSelectedEntries(); - if (!selectedBibEntries.isEmpty()) { - // Collect all non-null titles. - List<String> titles = selectedBibEntries.stream() - .filter(bibEntry -> bibEntry.getTitle().isPresent()) - .map(bibEntry -> bibEntry.getTitle().get()) - .collect(Collectors.toList()); - - if (titles.isEmpty()) { - output(Localization.lang("None of the selected entries have titles.")); - return; - } - final String copiedTitles = String.join("\n", titles); - Globals.clipboardManager.setContent(copiedTitles); - - if (titles.size() == selectedBibEntries.size()) { - // All entries had titles. - output(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(copiedTitles) + "'."); - } else { - output(Localization.lang("Warning: %0 out of %1 entries have undefined title.", Integer.toString(selectedBibEntries.size() - titles.size()), Integer.toString(selectedBibEntries.size()))); - } - } - } - - private void copyCiteKey() { - List<BibEntry> bes = mainTable.getSelectedEntries(); - if (!bes.isEmpty()) { - List<String> keys = new ArrayList<>(bes.size()); - // Collect all non-null keys. - for (BibEntry be : bes) { - be.getCiteKeyOptional().ifPresent(keys::add); - } - if (keys.isEmpty()) { - output(Localization.lang("None of the selected entries have BibTeX keys.")); - return; - } - - String citeCommand = Optional.ofNullable(Globals.prefs.get(JabRefPreferences.CITE_COMMAND)) - .filter(cite -> cite.contains("\\")) // must contain \ - .orElse("\\cite"); - final String copiedCiteCommand = citeCommand + "{" + String.join(",", keys) + '}'; - Globals.clipboardManager.setContent(copiedCiteCommand); - - if (keys.size() == bes.size()) { - // All entries had keys. - output(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(copiedCiteCommand) + "'."); - } else { - output(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", Integer.toString(bes.size() - keys.size()), Integer.toString(bes.size()))); - } - } - } - - private void copyKey() { - List<BibEntry> bes = mainTable.getSelectedEntries(); - if (!bes.isEmpty()) { - List<String> keys = new ArrayList<>(bes.size()); - // Collect all non-null keys. - for (BibEntry be : bes) { - be.getCiteKeyOptional().ifPresent(keys::add); - } - if (keys.isEmpty()) { - output(Localization.lang("None of the selected entries have BibTeX keys.")); - return; - } - - final String copiedKeys = String.join(",", keys); - Globals.clipboardManager.setContent(copiedKeys); - - if (keys.size() == bes.size()) { - // All entries had keys. - output(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(copiedKeys) + "'."); - } else { - output(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", Integer.toString(bes.size() - keys.size()), Integer.toString(bes.size()))); - } - } - } - - private void copyKeyAndTitle() { - List<BibEntry> bes = mainTable.getSelectedEntries(); - if (!bes.isEmpty()) { - // OK: in a future version, this string should be configurable to allow arbitrary exports - StringReader sr = new StringReader("\\bibtexkey - \\begin{title}\\format[RemoveBrackets]{\\title}\\end{title}\n"); - Layout layout; - try { - layout = new LayoutHelper(sr, Globals.prefs.getLayoutFormatterPreferences(Globals.journalAbbreviationLoader)) - .getLayoutFromText(); - } catch (IOException e) { - LOGGER.info("Could not get layout", e); - return; - } - - StringBuilder sb = new StringBuilder(); - - int copied = 0; - // Collect all non-null keys. - for (BibEntry be : bes) { - if (be.hasCiteKey()) { - copied++; - sb.append(layout.doLayout(be, bibDatabaseContext.getDatabase())); - } - } - - if (copied == 0) { - output(Localization.lang("None of the selected entries have BibTeX keys.")); - return; - } - - final String copiedKeysAndTitles = sb.toString(); - Globals.clipboardManager.setContent(copiedKeysAndTitles); - - if (copied == bes.size()) { - // All entries had keys. - output(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(copiedKeysAndTitles) + "'."); - } else { - output(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", Integer.toString(bes.size() - copied), Integer.toString(bes.size()))); - } - } - } - - private void openExternalFile() { - final List<BibEntry> selectedEntries = mainTable.getSelectedEntries(); - if (selectedEntries.size() != 1) { - output(Localization.lang("This operation requires exactly one item to be selected.")); - return; - } - JabRefExecutorService.INSTANCE.execute(() -> { - final BibEntry entry = selectedEntries.get(0); - if (!entry.hasField(StandardField.FILE)) { - // no bibtex field - new SearchAndOpenFile(entry, BasePanel.this).searchAndOpen(); - return; - } - - List<LinkedFile> files = new ArrayList<>(); - entry.getField(StandardField.FILE).map(FileFieldParser::parse).ifPresent(files::addAll); - - if (files.isEmpty()) { - // content in BibTeX field is not readable - new SearchAndOpenFile(entry, BasePanel.this).searchAndOpen(); - return; - } - LinkedFile flEntry = files.get(0); - try { - JabRefDesktop.openExternalFileAnyFormat(this.getBibDatabaseContext(), flEntry.getLink(), ExternalFileTypes.getInstance().fromLinkedFile(flEntry, true)); - } catch (IOException ex) { - dialogService.showErrorDialogAndWait(ex); - } - }); - } - /** * This method is called from JabRefFrame if a database specific action is requested by the user. Runs the command * if it is defined, or prints an error message to the standard error stream. @@ -1077,47 +800,6 @@ public void cut() { mainTable.cut(); } - private static class SearchAndOpenFile { - - private final BibEntry entry; - private final BasePanel basePanel; - - public SearchAndOpenFile(final BibEntry entry, final BasePanel basePanel) { - this.entry = entry; - this.basePanel = basePanel; - } - - public void searchAndOpen() { - if (!Globals.prefs.getBoolean(JabRefPreferences.RUN_AUTOMATIC_FILE_SEARCH)) { - /* The search can lead to an unexpected 100% CPU usage which is perceived - as a bug, if the search incidentally starts at a directory with lots - of stuff below. It is now disabled by default. */ - return; - } - - final Set<ExternalFileType> types = ExternalFileTypes.getInstance().getExternalFileTypeSelection(); - final List<Path> dirs = basePanel.getBibDatabaseContext().getFileDirectoriesAsPaths(Globals.prefs.getFilePreferences()); - final List<String> extensions = types.stream().map(ExternalFileType::getExtension).collect(Collectors.toList()); - - // Run the search operation: - FileFinder fileFinder = FileFinders.constructFromConfiguration(Globals.prefs.getAutoLinkPreferences()); - try { - List<Path> files = fileFinder.findAssociatedFiles(entry, dirs, extensions); - if (!files.isEmpty()) { - Path file = files.get(0); - Optional<ExternalFileType> type = ExternalFileTypes.getInstance().getExternalFileTypeByFile(file); - if (type.isPresent()) { - JabRefDesktop.openExternalFileAnyFormat(file, basePanel.getBibDatabaseContext(), type); - basePanel.output(Localization.lang("External viewer called") + '.'); - } - } - } catch (IOException ex) { - LOGGER.error("Problems with finding/or opening files ", ex); - basePanel.output(Localization.lang("Error") + ": " + ex.getMessage()); - } - } - } - private class GroupTreeListener { @Subscribe @@ -1200,60 +882,6 @@ public void action() { } } - private class OpenURLAction implements BaseAction { - - @Override - public void action() { - final List<BibEntry> bes = mainTable.getSelectedEntries(); - if (bes.size() == 1) { - Field field = StandardField.DOI; - Optional<String> link = bes.get(0).getField(StandardField.DOI); - if (bes.get(0).hasField(StandardField.URL)) { - link = bes.get(0).getField(StandardField.URL); - field = StandardField.URL; - } - if (link.isPresent()) { - try { - JabRefDesktop.openExternalViewer(bibDatabaseContext, link.get(), field); - output(Localization.lang("External viewer called") + '.'); - } catch (IOException ex) { - output(Localization.lang("Error") + ": " + ex.getMessage()); - } - } else { - // No URL or DOI found in the "url" and "doi" fields. - // Look for web links in the "file" field as a fallback: - - List<LinkedFile> files = bes.get(0).getFiles(); - - Optional<LinkedFile> linkedFile = files.stream() - .filter(file -> (StandardField.URL.getName().equalsIgnoreCase(file.getFileType()) - || StandardField.PS.getName().equalsIgnoreCase(file.getFileType()) - || StandardField.PDF.getName().equalsIgnoreCase(file.getFileType()))) - .findFirst(); - - if (linkedFile.isPresent()) { - - try { - - JabRefDesktop.openExternalFileAnyFormat(bibDatabaseContext, - linkedFile.get().getLink(), - ExternalFileTypes.getInstance().fromLinkedFile(linkedFile.get(), true)); - - output(Localization.lang("External viewer called") + '.'); - } catch (IOException e) { - output(Localization.lang("Could not open link")); - LOGGER.info("Could not open link", e); - } - } else { - output(Localization.lang("No URL defined") + '.'); - } - } - } else { - output(Localization.lang("This operation requires exactly one item to be selected.")); - } - } - } - private class RedoAction implements BaseAction { @Override diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index c7bc0a63088..8ef016891a6 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -30,7 +30,6 @@ import javafx.scene.control.SplitPane; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; -import javafx.scene.control.TextInputControl; import javafx.scene.control.ToolBar; import javafx.scene.control.Tooltip; import javafx.scene.control.skin.TabPaneSkin; @@ -60,14 +59,18 @@ import org.jabref.gui.dialogs.AutosaveUIManager; import org.jabref.gui.documentviewer.ShowDocumentViewerAction; import org.jabref.gui.duplicationFinder.DuplicateSearch; +import org.jabref.gui.edit.CopyMoreAction; +import org.jabref.gui.edit.EditAction; import org.jabref.gui.edit.ManageKeywordsAction; import org.jabref.gui.edit.MassSetFieldsAction; import org.jabref.gui.edit.OpenBrowserAction; +import org.jabref.gui.entryeditor.PreviewSwitchAction; import org.jabref.gui.exporter.ExportCommand; import org.jabref.gui.exporter.ExportToClipboardAction; import org.jabref.gui.exporter.ManageCustomExportsAction; import org.jabref.gui.exporter.SaveAllAction; import org.jabref.gui.exporter.SaveDatabaseAction; +import org.jabref.gui.exporter.WriteXMPAction; import org.jabref.gui.externalfiles.AutoLinkFilesAction; import org.jabref.gui.externalfiles.FindUnlinkedFilesAction; import org.jabref.gui.externalfiletype.EditExternalFileTypesAction; @@ -89,9 +92,11 @@ import org.jabref.gui.keyboard.KeyBinding; import org.jabref.gui.libraryproperties.LibraryPropertiesAction; import org.jabref.gui.menus.FileHistoryMenu; +import org.jabref.gui.mergeentries.MergeEntriesAction; import org.jabref.gui.metadata.BibtexStringEditorAction; import org.jabref.gui.metadata.PreambleEditor; import org.jabref.gui.preferences.ShowPreferencesAction; +import org.jabref.gui.preview.CopyCitationAction; import org.jabref.gui.protectedterms.ManageProtectedTermsAction; import org.jabref.gui.push.PushToApplicationAction; import org.jabref.gui.push.PushToApplicationsManager; @@ -104,6 +109,7 @@ import org.jabref.gui.util.DefaultTaskExecutor; import org.jabref.logic.autosaveandbackup.AutosaveManager; import org.jabref.logic.autosaveandbackup.BackupManager; +import org.jabref.logic.citationstyle.CitationStyleOutputFormat; import org.jabref.logic.importer.IdFetcher; import org.jabref.logic.importer.ParserResult; import org.jabref.logic.importer.WebFetchers; @@ -481,13 +487,13 @@ private Node createToolbar() { factory.createIconButton(StandardActions.NEW_ARTICLE, new NewEntryAction(this, StandardEntryType.Article, dialogService, Globals.prefs, stateManager)), factory.createIconButton(StandardActions.NEW_ENTRY, new NewEntryAction(this, dialogService, Globals.prefs, stateManager)), factory.createIconButton(StandardActions.NEW_ENTRY_FROM_PLAIN_TEXT, new ExtractBibtexAction(stateManager)), - factory.createIconButton(StandardActions.DELETE_ENTRY, new OldDatabaseCommandWrapper(Actions.DELETE, this, stateManager)), + factory.createIconButton(StandardActions.DELETE_ENTRY, new EditAction(StandardActions.DELETE_ENTRY, this, stateManager)), new Separator(Orientation.VERTICAL), factory.createIconButton(StandardActions.UNDO, new OldDatabaseCommandWrapper(Actions.UNDO, this, stateManager)), factory.createIconButton(StandardActions.REDO, new OldDatabaseCommandWrapper(Actions.REDO, this, stateManager)), - factory.createIconButton(StandardActions.CUT, new OldDatabaseCommandWrapper(Actions.CUT, this, stateManager)), - factory.createIconButton(StandardActions.COPY, new OldDatabaseCommandWrapper(Actions.COPY, this, stateManager)), - factory.createIconButton(StandardActions.PASTE, new OldDatabaseCommandWrapper(Actions.PASTE, this, stateManager)), + factory.createIconButton(StandardActions.CUT, new EditAction(StandardActions.CUT,this, stateManager)), + factory.createIconButton(StandardActions.COPY, new EditAction(StandardActions.COPY,this, stateManager)), + factory.createIconButton(StandardActions.PASTE, new EditAction(StandardActions.PASTE,this, stateManager)), new Separator(Orientation.VERTICAL), pushToApplicationButton, factory.createIconButton(StandardActions.GENERATE_CITE_KEYS, new OldDatabaseCommandWrapper(Actions.MAKE_KEY, this, stateManager)), @@ -571,6 +577,9 @@ public void init() { } }); + // Wait for the scene to be created, otherwise focusOwnerProperty is not provided + Platform.runLater(() -> stateManager.focusOwnerProperty().bind( + EasyBind.map(mainStage.getScene().focusOwnerProperty(), Optional::ofNullable))); /* * The following state listener makes sure focus is registered with the * correct database when the user switches tabs. Without this, @@ -700,19 +709,19 @@ private MenuBar createMenu() { new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.CUT, new EditAction(Actions.CUT)), + factory.createMenuItem(StandardActions.CUT, new EditAction(StandardActions.CUT, this, stateManager)), - factory.createMenuItem(StandardActions.COPY, new EditAction(Actions.COPY)), + factory.createMenuItem(StandardActions.COPY, new EditAction(StandardActions.COPY, this, stateManager)), factory.createSubMenu(StandardActions.COPY_MORE, - factory.createMenuItem(StandardActions.COPY_TITLE, new OldDatabaseCommandWrapper(Actions.COPY_TITLE, this, stateManager)), - factory.createMenuItem(StandardActions.COPY_KEY, new OldDatabaseCommandWrapper(Actions.COPY_KEY, this, stateManager)), - factory.createMenuItem(StandardActions.COPY_CITE_KEY, new OldDatabaseCommandWrapper(Actions.COPY_CITE_KEY, this, stateManager)), - factory.createMenuItem(StandardActions.COPY_KEY_AND_TITLE, new OldDatabaseCommandWrapper(Actions.COPY_KEY_AND_TITLE, this, stateManager)), - factory.createMenuItem(StandardActions.COPY_KEY_AND_LINK, new OldDatabaseCommandWrapper(Actions.COPY_KEY_AND_LINK, this, stateManager)), - factory.createMenuItem(StandardActions.COPY_CITATION_PREVIEW, new OldDatabaseCommandWrapper(Actions.COPY_CITATION_HTML, this, stateManager)), + factory.createMenuItem(StandardActions.COPY_TITLE, new CopyMoreAction(StandardActions.COPY_TITLE, dialogService, stateManager, Globals.clipboardManager, prefs)), + factory.createMenuItem(StandardActions.COPY_KEY, new CopyMoreAction(StandardActions.COPY_KEY, dialogService, stateManager, Globals.clipboardManager, prefs)), + factory.createMenuItem(StandardActions.COPY_CITE_KEY, new CopyMoreAction(StandardActions.COPY_CITE_KEY, dialogService, stateManager, Globals.clipboardManager, prefs)), + factory.createMenuItem(StandardActions.COPY_KEY_AND_TITLE, new CopyMoreAction(StandardActions.COPY_KEY_AND_TITLE, dialogService, stateManager, Globals.clipboardManager, prefs)), + factory.createMenuItem(StandardActions.COPY_KEY_AND_LINK, new CopyMoreAction(StandardActions.COPY_KEY_AND_LINK, dialogService, stateManager, Globals.clipboardManager, prefs)), + factory.createMenuItem(StandardActions.COPY_CITATION_PREVIEW, new CopyCitationAction(CitationStyleOutputFormat.HTML, dialogService, stateManager, Globals.clipboardManager, prefs.getPreviewPreferences())), factory.createMenuItem(StandardActions.EXPORT_SELECTED_TO_CLIPBOARD, new ExportToClipboardAction(this, dialogService))), - factory.createMenuItem(StandardActions.PASTE, new EditAction(Actions.PASTE)), + factory.createMenuItem(StandardActions.PASTE, new EditAction(StandardActions.PASTE, this, stateManager)), new SeparatorMenuItem(), @@ -727,12 +736,14 @@ private MenuBar createMenu() { if (Globals.prefs.getBoolean(JabRefPreferences.SPECIALFIELDSENABLED)) { edit.getItems().addAll( new SeparatorMenuItem(), - SpecialFieldMenuItemFactory.createSpecialFieldMenuForActiveDatabase(SpecialField.RANKING, factory, undoManager), - SpecialFieldMenuItemFactory.getSpecialFieldSingleItemForActiveDatabase(SpecialField.RELEVANCE, factory), - SpecialFieldMenuItemFactory.getSpecialFieldSingleItemForActiveDatabase(SpecialField.QUALITY, factory), - SpecialFieldMenuItemFactory.getSpecialFieldSingleItemForActiveDatabase(SpecialField.PRINTED, factory), - SpecialFieldMenuItemFactory.createSpecialFieldMenuForActiveDatabase(SpecialField.PRIORITY, factory, undoManager), - SpecialFieldMenuItemFactory.createSpecialFieldMenuForActiveDatabase(SpecialField.READ_STATUS, factory, undoManager) + // ToDo: SpecialField needs the active BasePanel to mark it as changed. + // Refactor BasePanel, should mark the BibDatabaseContext or the UndoManager as dirty instead! + SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.RANKING, factory, this, dialogService, stateManager), + SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.RELEVANCE, factory, this, dialogService, stateManager), + SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.QUALITY, factory, this, dialogService, stateManager), + SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.PRINTED, factory, this, dialogService, stateManager), + SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.PRIORITY, factory, this, dialogService, stateManager), + SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.READ_STATUS, factory, this, dialogService, stateManager) ); } @@ -740,7 +751,7 @@ private MenuBar createMenu() { library.getItems().addAll( factory.createMenuItem(StandardActions.NEW_ENTRY, new NewEntryAction(this, dialogService, Globals.prefs, stateManager)), factory.createMenuItem(StandardActions.NEW_ENTRY_FROM_PLAIN_TEXT, new ExtractBibtexAction(stateManager)), - factory.createMenuItem(StandardActions.DELETE_ENTRY, new OldDatabaseCommandWrapper(Actions.DELETE, this, stateManager)), + factory.createMenuItem(StandardActions.DELETE_ENTRY, new EditAction(StandardActions.DELETE_ENTRY, this, stateManager)), new SeparatorMenuItem(), @@ -759,6 +770,7 @@ private MenuBar createMenu() { quality.getItems().addAll( factory.createMenuItem(StandardActions.FIND_DUPLICATES, new DuplicateSearch(this, dialogService, stateManager)), + factory.createMenuItem(StandardActions.MERGE_ENTRIES, new MergeEntriesAction(this, dialogService, stateManager)), factory.createMenuItem(StandardActions.CHECK_INTEGRITY, new IntegrityCheckAction(this, stateManager, Globals.TASK_EXECUTOR)), factory.createMenuItem(StandardActions.CLEANUP_ENTRIES, new OldDatabaseCommandWrapper(Actions.CLEANUP, this, stateManager)), @@ -792,7 +804,7 @@ private MenuBar createMenu() { new SeparatorMenuItem(), factory.createMenuItem(StandardActions.FIND_UNLINKED_FILES, new FindUnlinkedFilesAction(this, stateManager)), - factory.createMenuItem(StandardActions.WRITE_XMP, new OldDatabaseCommandWrapper(Actions.WRITE_XMP, this, stateManager)), + factory.createMenuItem(StandardActions.WRITE_XMP, new WriteXMPAction(stateManager, dialogService)), factory.createMenuItem(StandardActions.COPY_LINKED_FILES, new CopyFilesAction(stateManager, this.getDialogService())), new SeparatorMenuItem(), @@ -802,7 +814,7 @@ private MenuBar createMenu() { new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.SEND_AS_EMAIL, new OldDatabaseCommandWrapper(Actions.SEND_AS_EMAIL, this, stateManager)), + factory.createMenuItem(StandardActions.SEND_AS_EMAIL, new SendAsEMailAction(dialogService, stateManager)), pushToApplicationMenuItem ); @@ -820,14 +832,14 @@ private MenuBar createMenu() { new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.NEXT_PREVIEW_STYLE, new OldDatabaseCommandWrapper(Actions.NEXT_PREVIEW_STYLE, this, stateManager)), - factory.createMenuItem(StandardActions.PREVIOUS_PREVIEW_STYLE, new OldDatabaseCommandWrapper(Actions.PREVIOUS_PREVIEW_STYLE, this, stateManager)), + factory.createMenuItem(StandardActions.NEXT_PREVIEW_STYLE, new PreviewSwitchAction(PreviewSwitchAction.Direction.NEXT, this, stateManager)), + factory.createMenuItem(StandardActions.PREVIOUS_PREVIEW_STYLE, new PreviewSwitchAction(PreviewSwitchAction.Direction.PREVIOUS, this, stateManager)), new SeparatorMenuItem(), factory.createMenuItem(StandardActions.SHOW_PDF_VIEWER, new ShowDocumentViewerAction()), factory.createMenuItem(StandardActions.EDIT_ENTRY, new OldDatabaseCommandWrapper(Actions.EDIT, this, stateManager)), - factory.createMenuItem(StandardActions.OPEN_CONSOLE, new OldDatabaseCommandWrapper(Actions.OPEN_CONSOLE, this, stateManager)) + factory.createMenuItem(StandardActions.OPEN_CONSOLE, new OpenConsoleAction(stateManager)) ); }); @@ -1246,63 +1258,6 @@ public void execute() { } } - /** - * Class for handling general actions; cut, copy and paste. The focused component is kept track of by - * Globals.focusListener, and we call the action stored under the relevant name in its action map. - */ - private class EditAction extends SimpleCommand { - - private final Actions command; - - public EditAction(Actions command) { - this.command = command; - } - - @Override - public String toString() { - return this.command.toString(); - } - - @Override - public void execute() { - Node focusOwner = mainStage.getScene().getFocusOwner(); - if (focusOwner != null) { - if (focusOwner instanceof TextInputControl) { - // Focus is on text field -> copy/paste/cut selected text - TextInputControl textInput = (TextInputControl) focusOwner; - switch (command) { - case COPY: - textInput.copy(); - break; - case CUT: - textInput.cut(); - break; - case PASTE: - // handled by FX in TextInputControl#paste - break; - default: - throw new IllegalStateException("Only cut/copy/paste supported but got " + command); - } - } else { - // Not sure what is selected -> copy/paste/cut selected entries - switch (command) { - case COPY: - getCurrentBasePanel().copy(); - break; - case CUT: - getCurrentBasePanel().cut(); - break; - case PASTE: - // handled by FX in TextInputControl#paste - break; - default: - throw new IllegalStateException("Only cut/copy/paste supported but got " + command); - } - } - } - } - } - private class CloseDatabaseAction extends SimpleCommand { @Override diff --git a/src/main/java/org/jabref/gui/OpenConsoleAction.java b/src/main/java/org/jabref/gui/OpenConsoleAction.java new file mode 100644 index 00000000000..ce634dd73e5 --- /dev/null +++ b/src/main/java/org/jabref/gui/OpenConsoleAction.java @@ -0,0 +1,34 @@ +package org.jabref.gui; + +import java.io.IOException; + +import org.jabref.gui.actions.ActionHelper; +import org.jabref.gui.actions.SimpleCommand; +import org.jabref.gui.desktop.JabRefDesktop; +import org.jabref.model.database.BibDatabaseContext; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OpenConsoleAction extends SimpleCommand { + + private static final Logger LOGGER = LoggerFactory.getLogger(OpenConsoleAction.class); + private final StateManager stateManager; + + public OpenConsoleAction(StateManager stateManager) { + this.stateManager = stateManager; + + this.executable.bind(ActionHelper.needsDatabase(stateManager)); + } + + @Override + public void execute() { + stateManager.getActiveDatabase().flatMap(BibDatabaseContext::getDatabasePath).ifPresent(path -> { + try { + JabRefDesktop.openConsole(path.toFile()); + } catch (IOException e) { + LOGGER.info("Could not open console", e); + } + }); + } +} diff --git a/src/main/java/org/jabref/gui/worker/SendAsEMailAction.java b/src/main/java/org/jabref/gui/SendAsEMailAction.java similarity index 65% rename from src/main/java/org/jabref/gui/worker/SendAsEMailAction.java rename to src/main/java/org/jabref/gui/SendAsEMailAction.java index 24877673394..08f412b6a28 100644 --- a/src/main/java/org/jabref/gui/worker/SendAsEMailAction.java +++ b/src/main/java/org/jabref/gui/SendAsEMailAction.java @@ -1,4 +1,4 @@ -package org.jabref.gui.worker; +package org.jabref.gui; import java.awt.Desktop; import java.io.IOException; @@ -9,15 +9,15 @@ import java.util.List; import org.jabref.Globals; -import org.jabref.gui.BasePanel; -import org.jabref.gui.JabRefFrame; -import org.jabref.gui.actions.BaseAction; +import org.jabref.gui.actions.ActionHelper; +import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.desktop.JabRefDesktop; import org.jabref.gui.util.BackgroundTask; import org.jabref.logic.bibtex.BibEntryWriter; import org.jabref.logic.bibtex.FieldWriter; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.io.FileUtil; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.preferences.JabRefPreferences; @@ -34,49 +34,50 @@ * are opened. This feature is disabled by default and can be switched on at * preferences/external programs */ -public class SendAsEMailAction implements BaseAction { +public class SendAsEMailAction extends SimpleCommand { private static final Logger LOGGER = LoggerFactory.getLogger(SendAsEMailAction.class); - private final JabRefFrame frame; + private DialogService dialogService; + private StateManager stateManager; - public SendAsEMailAction(JabRefFrame frame) { - this.frame = frame; + public SendAsEMailAction(DialogService dialogService, StateManager stateManager) { + this.dialogService = dialogService; + this.stateManager = stateManager; + + this.executable.bind(ActionHelper.needsEntriesSelected(stateManager)); } @Override - public void action() { + public void execute() { BackgroundTask.wrap(this::sendEmail) - .onSuccess(frame.getDialogService()::notify) + .onSuccess(dialogService::notify) .onFailure(e -> { String message = Localization.lang("Error creating email"); LOGGER.warn(message, e); - frame.getDialogService().notify(message); + dialogService.notify(message); }) .executeWith(Globals.TASK_EXECUTOR); } private String sendEmail() throws Exception { - if (!Desktop.isDesktopSupported()) { + if (!Desktop.isDesktopSupported() || stateManager.getActiveDatabase().isEmpty()) { return Localization.lang("Error creating email"); } - BasePanel panel = frame.getCurrentBasePanel(); - if (panel == null) { - throw new IllegalStateException("Base panel is not available."); - } - if (panel.getSelectedEntries().isEmpty()) { + if (stateManager.getSelectedEntries().isEmpty()) { return Localization.lang("This operation requires one or more entries to be selected."); } - StringWriter sw = new StringWriter(); - List<BibEntry> bes = panel.getSelectedEntries(); + StringWriter rawEntries = new StringWriter(); + BibDatabaseContext databaseContext = stateManager.getActiveDatabase().get(); + List<BibEntry> entries = stateManager.getSelectedEntries(); // write the entries using sw, which is used later to form the email content BibEntryWriter bibtexEntryWriter = new BibEntryWriter(new FieldWriter(Globals.prefs.getFieldWriterPreferences()), Globals.entryTypesManager); - for (BibEntry entry : bes) { + for (BibEntry entry : entries) { try { - bibtexEntryWriter.write(entry, sw, panel.getBibDatabaseContext().getMode()); + bibtexEntryWriter.write(entry, rawEntries, databaseContext.getMode()); } catch (IOException e) { LOGGER.warn("Problem creating BibTeX file for mailing.", e); } @@ -88,20 +89,19 @@ private String sendEmail() throws Exception { // the unofficial "mailto:attachment" property boolean openFolders = JabRefPreferences.getInstance().getBoolean(JabRefPreferences.OPEN_FOLDERS_OF_ATTACHED_FILES); - List<Path> fileList = FileUtil.getListOfLinkedFiles(bes, frame.getCurrentBasePanel().getBibDatabaseContext() - .getFileDirectoriesAsPaths(Globals.prefs.getFilePreferences())); - for (Path f : fileList) { - attachments.add(f.toAbsolutePath().toString()); + List<Path> fileList = FileUtil.getListOfLinkedFiles(entries, databaseContext.getFileDirectoriesAsPaths(Globals.prefs.getFilePreferences())); + for (Path path : fileList) { + attachments.add(path.toAbsolutePath().toString()); if (openFolders) { try { - JabRefDesktop.openFolderAndSelectFile(f.toAbsolutePath()); + JabRefDesktop.openFolderAndSelectFile(path.toAbsolutePath()); } catch (IOException e) { LOGGER.debug("Cannot open file", e); } } } - String mailTo = "?Body=".concat(sw.getBuffer().toString()); + String mailTo = "?Body=".concat(rawEntries.getBuffer().toString()); mailTo = mailTo.concat("&Subject="); mailTo = mailTo.concat(JabRefPreferences.getInstance().get(JabRefPreferences.EMAIL_SUBJECT)); for (String path : attachments) { @@ -114,6 +114,6 @@ private String sendEmail() throws Exception { Desktop desktop = Desktop.getDesktop(); desktop.mail(uriMailTo); - return String.format("%s: %d", Localization.lang("Entries added to an email"), bes.size()); + return String.format("%s: %d", Localization.lang("Entries added to an email"), entries.size()); } } diff --git a/src/main/java/org/jabref/gui/StateManager.java b/src/main/java/org/jabref/gui/StateManager.java index c09f97244f0..19a45f94c71 100644 --- a/src/main/java/org/jabref/gui/StateManager.java +++ b/src/main/java/org/jabref/gui/StateManager.java @@ -13,6 +13,7 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.collections.ObservableMap; +import javafx.scene.Node; import org.jabref.gui.util.OptionalObjectProperty; import org.jabref.logic.search.SearchQuery; @@ -27,6 +28,7 @@ * - currently selected group * - active search * - active number of search results + * - focus owner */ public class StateManager { @@ -36,6 +38,7 @@ public class StateManager { private final ObservableMap<BibDatabaseContext, ObservableList<GroupTreeNode>> selectedGroups = FXCollections.observableHashMap(); private final OptionalObjectProperty<SearchQuery> activeSearchQuery = OptionalObjectProperty.empty(); private final ObservableMap<BibDatabaseContext, IntegerProperty> searchResultMap = FXCollections.observableHashMap(); + private final OptionalObjectProperty<Node> focusOwner = OptionalObjectProperty.empty(); public StateManager() { activeGroups.bind(Bindings.valueAt(selectedGroups, activeDatabase.orElse(null))); @@ -99,4 +102,8 @@ public void clearSearchQuery() { public void setSearchQuery(SearchQuery searchQuery) { activeSearchQuery.setValue(Optional.of(searchQuery)); } + + public OptionalObjectProperty<Node> focusOwnerProperty() { return focusOwner; } + + public Optional<Node> getFocusOwner() { return focusOwner.get(); } } diff --git a/src/main/java/org/jabref/gui/actions/ActionHelper.java b/src/main/java/org/jabref/gui/actions/ActionHelper.java index dfd66772a3a..01e23d67e22 100644 --- a/src/main/java/org/jabref/gui/actions/ActionHelper.java +++ b/src/main/java/org/jabref/gui/actions/ActionHelper.java @@ -1,9 +1,14 @@ package org.jabref.gui.actions; +import java.util.Collections; +import java.util.List; + import javafx.beans.binding.Bindings; import javafx.beans.binding.BooleanExpression; import org.jabref.gui.StateManager; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.Field; public class ActionHelper { public static BooleanExpression needsDatabase(StateManager stateManager) { @@ -13,4 +18,22 @@ public static BooleanExpression needsDatabase(StateManager stateManager) { public static BooleanExpression needsEntriesSelected(StateManager stateManager) { return Bindings.isNotEmpty(stateManager.getSelectedEntries()); } + + public static BooleanExpression needsEntriesSelected(int numberOfEntries, StateManager stateManager) { + return Bindings.createBooleanBinding( + () -> stateManager.getSelectedEntries().size() == numberOfEntries, + stateManager.getSelectedEntries()); + } + + public static BooleanExpression isFieldSetForSelectedEntry(Field field, StateManager stateManager) { + return isAnyFieldSetForSelectedEntry(Collections.singletonList(field), stateManager); + } + + public static BooleanExpression isAnyFieldSetForSelectedEntry(List<Field> fields, StateManager stateManager) { + BibEntry entry = stateManager.getSelectedEntries().get(0); + return Bindings.createBooleanBinding( + () -> entry.getFields().stream().anyMatch(fields::contains), + entry.getFieldsObservable(), + stateManager.getSelectedEntries()); + } } diff --git a/src/main/java/org/jabref/gui/actions/Actions.java b/src/main/java/org/jabref/gui/actions/Actions.java index 49040b8e00b..f606eec20a1 100644 --- a/src/main/java/org/jabref/gui/actions/Actions.java +++ b/src/main/java/org/jabref/gui/actions/Actions.java @@ -10,19 +10,6 @@ public enum Actions { ABBREVIATE_SHORTEST_UNIQUE, ADD_FILE_LINK, CLEANUP, - COPY, - COPY_CITATION_ASCII_DOC, - COPY_CITATION_XSLFO, - COPY_CITATION_HTML, - COPY_CITATION_RTF, - COPY_CITATION_TEXT, - COPY_KEY, - COPY_CITE_KEY, - COPY_KEY_AND_TITLE, - COPY_KEY_AND_LINK, - COPY_TITLE, - CUT, - DELETE, DOWNLOAD_FULL_TEXT, EDIT, EDIT_PREAMBLE, @@ -31,15 +18,6 @@ public enum Actions { MAKE_KEY, MANAGE_SELECTORS, MERGE_DATABASE, - MERGE_ENTRIES, - MERGE_WITH_FETCHED_ENTRY, - NEXT_PREVIEW_STYLE, - OPEN_CONSOLE, - OPEN_EXTERNAL_FILE, - OPEN_FOLDER, - OPEN_URL, - PASTE, - PREVIOUS_PREVIEW_STYLE, PULL_CHANGES_FROM_SHARED_DATABASE, REDO, REPLACE_ALL, @@ -47,26 +25,7 @@ public enum Actions { SAVE_AS, SAVE_SELECTED_AS_PLAIN, SELECT_ALL, - SEND_AS_EMAIL, TOGGLE_GROUPS, UNABBREVIATE, - UNDO, - WRITE_XMP, - PRINT_PREVIEW, - TOGGLE_PRINTED, - CLEAR_PRIORITY, - SET_PRIORITY_1, - SET_PRIORITY_2, - SET_PRIORITY_3, - TOGGLE_QUALITY_ASSURED, - CLEAR_RANK, - SET_RANK_1, - SET_RANK_2, - SET_RANK_3, - SET_RANK_4, - SET_RANK_5, - CLEAR_READ_STATUS, - SET_READ_STATUS_TO_READ, - SET_READ_STATUS_TO_SKIMMED, - TOGGLE_RELEVANCE + UNDO } diff --git a/src/main/java/org/jabref/gui/actions/JabRefAction.java b/src/main/java/org/jabref/gui/actions/JabRefAction.java index f04deb1157c..dfdc35330b2 100644 --- a/src/main/java/org/jabref/gui/actions/JabRefAction.java +++ b/src/main/java/org/jabref/gui/actions/JabRefAction.java @@ -58,7 +58,10 @@ private String getActionName(Action action, Command command) { return action.getText(); } else { String commandName = command.getClass().getSimpleName(); - if ((command instanceof OldDatabaseCommandWrapper) || (command instanceof OldCommandWrapper) || commandName.contains("EditAction")) { + if ((command instanceof OldDatabaseCommandWrapper) + || commandName.contains("EditAction") + || commandName.contains("CopyMoreAction") + || commandName.contains("CopyCitationAction")) { return command.toString(); } else { return commandName; diff --git a/src/main/java/org/jabref/gui/actions/OldCommandWrapper.java b/src/main/java/org/jabref/gui/actions/OldCommandWrapper.java deleted file mode 100644 index 028e0b153bb..00000000000 --- a/src/main/java/org/jabref/gui/actions/OldCommandWrapper.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.jabref.gui.actions; - -import javafx.beans.property.ReadOnlyDoubleProperty; - -import org.jabref.gui.BasePanel; -import org.jabref.gui.util.BindingsHelper; - -import de.saxsys.mvvmfx.utils.commands.CommandBase; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This wraps the old Swing commands so that they fit into the new infrastructure. - * In the long term, this class should be removed. - */ -@Deprecated -public class OldCommandWrapper extends CommandBase { - - private static final Logger LOGGER = LoggerFactory.getLogger(OldCommandWrapper.class); - - private final Actions command; - private final BasePanel panel; - - public OldCommandWrapper(Actions command, BasePanel panel) { - this.command = command; - this.panel = panel; - } - - @Override - public void execute() { - try { - panel.runCommand(command); - } catch (Throwable ex) { - LOGGER.debug("Cannot execute command " + command + ".", ex); - } - } - - @Override - public double getProgress() { - return 0; - } - - @Override - public ReadOnlyDoubleProperty progressProperty() { - return null; - } - - public void setExecutable(boolean executable) { - this.executable.bind(BindingsHelper.constantOf(executable)); - } - - @Override - public String toString() { - return this.command.toString(); - } -} diff --git a/src/main/java/org/jabref/gui/actions/OldCommandWrapperForActiveDatabase.java b/src/main/java/org/jabref/gui/actions/OldCommandWrapperForActiveDatabase.java deleted file mode 100644 index 23c2f6b86c9..00000000000 --- a/src/main/java/org/jabref/gui/actions/OldCommandWrapperForActiveDatabase.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.jabref.gui.actions; - -import javafx.beans.property.ReadOnlyDoubleProperty; - -import org.jabref.JabRefGUI; -import org.jabref.gui.util.BindingsHelper; - -import de.saxsys.mvvmfx.utils.commands.CommandBase; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This wraps the old Swing commands so that they fit into the new infrastructure. - * In the long term, this class should be removed. - */ -@Deprecated -public class OldCommandWrapperForActiveDatabase extends CommandBase { - - private static final Logger LOGGER = LoggerFactory.getLogger(OldCommandWrapperForActiveDatabase.class); - - private final Actions command; - - public OldCommandWrapperForActiveDatabase(Actions command) { - this.command = command; - } - - @Override - public void execute() { - try { - JabRefGUI.getMainFrame().getCurrentBasePanel().runCommand(command); - } catch (Throwable ex) { - LOGGER.debug("Cannot execute command " + command + ".", ex); - } - } - - @Override - public double getProgress() { - return 0; - } - - @Override - public ReadOnlyDoubleProperty progressProperty() { - return null; - } - - public void setExecutable(boolean executable) { - this.executable.bind(BindingsHelper.constantOf(executable)); - } -} diff --git a/src/main/java/org/jabref/gui/edit/CopyBibTeXKeyAndLinkAction.java b/src/main/java/org/jabref/gui/edit/CopyBibTeXKeyAndLinkAction.java deleted file mode 100644 index 86e0912400a..00000000000 --- a/src/main/java/org/jabref/gui/edit/CopyBibTeXKeyAndLinkAction.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.jabref.gui.edit; - -import java.util.List; -import java.util.stream.Collectors; - -import org.jabref.JabRefGUI; -import org.jabref.gui.ClipBoardManager; -import org.jabref.gui.JabRefDialogService; -import org.jabref.gui.actions.BaseAction; -import org.jabref.gui.maintable.MainTable; -import org.jabref.gui.util.DefaultTaskExecutor; -import org.jabref.logic.l10n.Localization; -import org.jabref.logic.util.OS; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.field.StandardField; - -/** - * This class will copy each selected entry's BibTeX key as a hyperlink to its url to the clipboard. - * In case an entry doesn't have a BibTeX key it will not be copied. - * In case an entry doesn't have an url this will only copy the BibTeX key. - */ -public class CopyBibTeXKeyAndLinkAction implements BaseAction { - - private final MainTable mainTable; - private final ClipBoardManager clipboardManager; - - public CopyBibTeXKeyAndLinkAction(MainTable mainTable, ClipBoardManager clipboardManager) { - this.mainTable = mainTable; - this.clipboardManager = clipboardManager; - } - - @Override - public void action() throws Exception { - List<BibEntry> entries = mainTable.getSelectedEntries(); - if (!entries.isEmpty()) { - StringBuilder sb = new StringBuilder(); - - List<BibEntry> entriesWithKey = entries.stream().filter(BibEntry::hasCiteKey).collect(Collectors.toList()); - - if (entriesWithKey.isEmpty()) { - JabRefGUI.getMainFrame().getDialogService().notify(Localization.lang("None of the selected entries have BibTeX keys.")); - return; - } - - for (BibEntry entry : entriesWithKey) { - String key = entry.getCiteKeyOptional().get(); - String url = entry.getField(StandardField.URL).orElse(""); - sb.append(url.isEmpty() ? key : String.format("<a href=\"%s\">%s</a>", url, key)); - sb.append(OS.NEWLINE); - } - final String keyAndLink = sb.toString(); - DefaultTaskExecutor.runInJavaFXThread(() -> clipboardManager.setHtmlContent(keyAndLink)); - - int copied = entriesWithKey.size(); - int toCopy = entries.size(); - if (copied == toCopy) { - // All entries had keys. - JabRefGUI.getMainFrame().getDialogService().notify(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(keyAndLink) + "'."); - } else { - JabRefGUI.getMainFrame().getDialogService().notify(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", - Long.toString(toCopy - copied), Integer.toString(toCopy))); - } - } - } -} diff --git a/src/main/java/org/jabref/gui/edit/CopyMoreAction.java b/src/main/java/org/jabref/gui/edit/CopyMoreAction.java new file mode 100644 index 00000000000..c2bb13170d0 --- /dev/null +++ b/src/main/java/org/jabref/gui/edit/CopyMoreAction.java @@ -0,0 +1,238 @@ +package org.jabref.gui.edit; + +import java.io.IOException; +import java.io.StringReader; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.jabref.Globals; +import org.jabref.gui.ClipBoardManager; +import org.jabref.gui.DialogService; +import org.jabref.gui.JabRefDialogService; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.ActionHelper; +import org.jabref.gui.actions.SimpleCommand; +import org.jabref.gui.actions.StandardActions; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.layout.Layout; +import org.jabref.logic.layout.LayoutHelper; +import org.jabref.logic.util.OS; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.StandardField; +import org.jabref.preferences.JabRefPreferences; +import org.jabref.preferences.PreferencesService; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CopyMoreAction extends SimpleCommand { + + private static final Logger LOGGER = LoggerFactory.getLogger(CopyMoreAction.class); + private final StandardActions action; + private final DialogService dialogService; + private final StateManager stateManager; + private final ClipBoardManager clipBoardManager; + private final PreferencesService preferencesService; + + public CopyMoreAction(StandardActions action, DialogService dialogService, StateManager stateManager, ClipBoardManager clipBoardManager, PreferencesService preferencesService) { + this.action = action; + this.dialogService = dialogService; + this.stateManager = stateManager; + this.clipBoardManager = clipBoardManager; + this.preferencesService = preferencesService; + + this.executable.bind(ActionHelper.needsEntriesSelected(stateManager)); + } + + @Override + public void execute() { + if (stateManager.getActiveDatabase().isEmpty() || stateManager.getSelectedEntries().isEmpty()) { + return; + } + + switch (action) { + case COPY_TITLE: + copyTitle(); + break; + case COPY_KEY: + copyKey(); + break; + case COPY_CITE_KEY: + copyCiteKey(); + break; + case COPY_KEY_AND_TITLE: + copyKeyAndTitle(); + break; + case COPY_KEY_AND_LINK: + copyKeyAndLink(); + break; + default: + LOGGER.info("Unknown copy command."); + break; + } + } + + private void copyTitle() { + List<BibEntry> selectedBibEntries = stateManager.getSelectedEntries(); + + List<String> titles = selectedBibEntries.stream() + .filter(bibEntry -> bibEntry.getTitle().isPresent()) + .map(bibEntry -> bibEntry.getTitle().get()) + .collect(Collectors.toList()); + + if (titles.isEmpty()) { + dialogService.notify(Localization.lang("None of the selected entries have titles.")); + return; + } + + final String copiedTitles = String.join("\n", titles); + clipBoardManager.setContent(copiedTitles); + + if (titles.size() == selectedBibEntries.size()) { + // All entries had titles. + dialogService.notify(Localization.lang("Copied '%0' to clipboard.", + JabRefDialogService.shortenDialogMessage(copiedTitles))); + } else { + dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined title.", + Integer.toString(selectedBibEntries.size() - titles.size()), Integer.toString(selectedBibEntries.size()))); + } + } + + private void copyKey() { + List<BibEntry> entries = stateManager.getSelectedEntries(); + + // Collect all non-null keys. + List<String> keys = entries.stream() + .filter(entry -> entry.getCiteKeyOptional().isPresent()) + .map(entry -> entry.getCiteKeyOptional().get()) + .collect(Collectors.toList()); + + if (keys.isEmpty()) { + dialogService.notify(Localization.lang("None of the selected entries have BibTeX keys.")); + return; + } + + final String copiedKeys = String.join(",", keys); + clipBoardManager.setContent(copiedKeys); + + if (keys.size() == entries.size()) { + // All entries had keys. + dialogService.notify(Localization.lang("Copied '%0' to clipboard.", + JabRefDialogService.shortenDialogMessage(copiedKeys))); + } else { + dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", + Integer.toString(entries.size() - keys.size()), Integer.toString(entries.size()))); + } + } + + private void copyCiteKey() { + List<BibEntry> entries = stateManager.getSelectedEntries(); + + // Collect all non-null keys. + List<String> keys = entries.stream() + .filter(entry -> entry.getCiteKeyOptional().isPresent()) + .map(entry -> entry.getCiteKeyOptional().get()) + .collect(Collectors.toList()); + + if (keys.isEmpty()) { + dialogService.notify(Localization.lang("None of the selected entries have BibTeX keys.")); + return; + } + + String citeCommand = Optional.ofNullable(Globals.prefs.get(JabRefPreferences.CITE_COMMAND)) + .filter(cite -> cite.contains("\\")) // must contain \ + .orElse("\\cite"); + + final String copiedCiteCommand = citeCommand + "{" + String.join(",", keys) + '}'; + clipBoardManager.setContent(copiedCiteCommand); + + if (keys.size() == entries.size()) { + // All entries had keys. + dialogService.notify(Localization.lang("Copied '%0' to clipboard.", + JabRefDialogService.shortenDialogMessage(copiedCiteCommand))); + } else { + dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", + Integer.toString(entries.size() - keys.size()), Integer.toString(entries.size()))); + } + } + + private void copyKeyAndTitle() { + List<BibEntry> entries = stateManager.getSelectedEntries(); + + // ToDo: this string should be configurable to allow arbitrary exports + StringReader layoutString = new StringReader("\\bibtexkey - \\begin{title}\\format[RemoveBrackets]{\\title}\\end{title}\n"); + Layout layout; + try { + layout = new LayoutHelper(layoutString, preferencesService.getLayoutFormatterPreferences(Globals.journalAbbreviationLoader)).getLayoutFromText(); + } catch (IOException e) { + LOGGER.info("Could not get layout.", e); + return; + } + + StringBuilder keyAndTitle = new StringBuilder(); + + int entriesWithKeys = 0; + // Collect all non-null keys. + for (BibEntry entry : entries) { + if (entry.hasCiteKey()) { + entriesWithKeys++; + keyAndTitle.append(layout.doLayout(entry, stateManager.getActiveDatabase().get().getDatabase())); + } + } + + if (entriesWithKeys == 0) { + dialogService.notify(Localization.lang("None of the selected entries have BibTeX keys.")); + return; + } + + clipBoardManager.setContent(keyAndTitle.toString()); + + if (entriesWithKeys == entries.size()) { + // All entries had keys. + dialogService.notify(Localization.lang("Copied '%0' to clipboard.", + JabRefDialogService.shortenDialogMessage(keyAndTitle.toString()))); + } else { + dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", + Integer.toString(entries.size() - entriesWithKeys), Integer.toString(entries.size()))); + } + } + + /** + * This method will copy each selected entry's BibTeX key as a hyperlink to its url to the clipboard. In case an + * entry doesn't have a BibTeX key it will not be copied. In case an entry doesn't have an url this will only copy + * the BibTeX key. + */ + private void copyKeyAndLink() { + List<BibEntry> entries = stateManager.getSelectedEntries(); + + StringBuilder keyAndLink = new StringBuilder(); + + List<BibEntry> entriesWithKey = entries.stream() + .filter(BibEntry::hasCiteKey) + .collect(Collectors.toList()); + + if (entriesWithKey.isEmpty()) { + dialogService.notify(Localization.lang("None of the selected entries have BibTeX keys.")); + return; + } + + for (BibEntry entry : entriesWithKey) { + String key = entry.getCiteKeyOptional().get(); + String url = entry.getField(StandardField.URL).orElse(""); + keyAndLink.append(url.isEmpty() ? key : String.format("<a href=\"%s\">%s</a>", url, key)); + keyAndLink.append(OS.NEWLINE); + } + + clipBoardManager.setHtmlContent(keyAndLink.toString()); + + if (entriesWithKey.size() == entries.size()) { + // All entries had keys. + dialogService.notify(Localization.lang("Copied '%0' to clipboard.", + JabRefDialogService.shortenDialogMessage(keyAndLink.toString()))); + } else { + dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", + Long.toString(entries.size() - entriesWithKey.size()), Integer.toString(entries.size()))); + } + } +} diff --git a/src/main/java/org/jabref/gui/edit/EditAction.java b/src/main/java/org/jabref/gui/edit/EditAction.java new file mode 100644 index 00000000000..e48add2b08c --- /dev/null +++ b/src/main/java/org/jabref/gui/edit/EditAction.java @@ -0,0 +1,76 @@ +package org.jabref.gui.edit; + +import javafx.scene.control.TextInputControl; + +import org.jabref.gui.JabRefFrame; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.ActionHelper; +import org.jabref.gui.actions.SimpleCommand; +import org.jabref.gui.actions.StandardActions; + +/** + * Class for handling general actions; cut, copy and paste. The focused component is kept track of by + * Globals.focusListener, and we call the action stored under the relevant name in its action map. + */ +public class EditAction extends SimpleCommand { + + private final JabRefFrame frame; + private final StandardActions action; + private final StateManager stateManager; + + public EditAction(StandardActions action, JabRefFrame frame, StateManager stateManager) { + this.action = action; + this.frame = frame; + this.stateManager = stateManager; + + this.executable.bind(ActionHelper.needsEntriesSelected(stateManager)); + } + + @Override + public String toString() { + return this.action.toString(); + } + + @Override + public void execute() { + stateManager.getFocusOwner().ifPresent(focusOwner -> { + if (focusOwner instanceof TextInputControl) { + // Focus is on text field -> copy/paste/cut selected text + TextInputControl textInput = (TextInputControl) focusOwner; + switch (action) { + case COPY: + textInput.copy(); + break; + case CUT: + textInput.cut(); + break; + case PASTE: + // handled by FX in TextInputControl#paste + break; + default: + throw new IllegalStateException("Only cut/copy/paste supported in TextInputControl but got " + action); + } + } else { + // Not sure what is selected -> copy/paste/cut selected entries + + // ToDo: Should be handled by BibDatabaseContext instead of BasePanel + switch (action) { + case COPY: + frame.getCurrentBasePanel().copy(); + break; + case CUT: + frame.getCurrentBasePanel().cut(); + break; + case PASTE: + // handled by FX in TextInputControl#paste + break; + case DELETE_ENTRY: + frame.getCurrentBasePanel().delete(false); + break; + default: + throw new IllegalStateException("Only cut/copy/paste supported but got " + action); + } + } + }); + } +} diff --git a/src/main/java/org/jabref/gui/entryeditor/PreviewSwitchAction.java b/src/main/java/org/jabref/gui/entryeditor/PreviewSwitchAction.java new file mode 100644 index 00000000000..03247c4fdd0 --- /dev/null +++ b/src/main/java/org/jabref/gui/entryeditor/PreviewSwitchAction.java @@ -0,0 +1,31 @@ +package org.jabref.gui.entryeditor; + +import org.jabref.gui.JabRefFrame; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.SimpleCommand; + +import static org.jabref.gui.actions.ActionHelper.needsDatabase; + +public class PreviewSwitchAction extends SimpleCommand { + + public enum Direction { PREVIOUS, NEXT } + + private final JabRefFrame frame; + private final Direction direction; + + public PreviewSwitchAction(Direction direction, JabRefFrame frame, StateManager stateManager) { + this.frame = frame; + this.direction = direction; + + this.executable.bind(needsDatabase(stateManager)); + } + + @Override + public void execute() { + if (direction == Direction.NEXT) { + frame.getCurrentBasePanel().getEntryEditor().nextPreviewStyle(); + } else { + frame.getCurrentBasePanel().getEntryEditor().previousPreviewStyle(); + } + } +} diff --git a/src/main/java/org/jabref/gui/exporter/WriteXMPAction.java b/src/main/java/org/jabref/gui/exporter/WriteXMPAction.java index 6b4c736c9e0..46c7166c67c 100644 --- a/src/main/java/org/jabref/gui/exporter/WriteXMPAction.java +++ b/src/main/java/org/jabref/gui/exporter/WriteXMPAction.java @@ -21,9 +21,9 @@ import javafx.stage.Stage; import org.jabref.Globals; -import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; import org.jabref.gui.FXDialog; +import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.util.BackgroundTask; import org.jabref.logic.l10n.Localization; @@ -31,25 +31,28 @@ import org.jabref.model.database.BibDatabase; import org.jabref.model.entry.BibEntry; +import static org.jabref.gui.actions.ActionHelper.needsDatabase; + public class WriteXMPAction extends SimpleCommand { - private final BasePanel basePanel; - private OptionsDialog optionsDialog; + private final StateManager stateManager; + private final DialogService dialogService; - private Collection<BibEntry> entries; + private OptionsDialog optionsDialog; private BibDatabase database; + private Collection<BibEntry> entries; private boolean shouldContinue = true; - private int skipped; private int entriesChanged; private int errors; - private final DialogService dialogService; - public WriteXMPAction(BasePanel basePanel) { - this.basePanel = basePanel; - dialogService = basePanel.frame().getDialogService(); + public WriteXMPAction(StateManager stateManager, DialogService dialogService) { + this.stateManager = stateManager; + this.dialogService = dialogService; + + this.executable.bind(needsDatabase(stateManager)); } @Override @@ -60,9 +63,13 @@ public void execute() { } public void init() { - database = basePanel.getDatabase(); + if (stateManager.getActiveDatabase().isEmpty()) { + return; + } + + database = stateManager.getActiveDatabase().get().getDatabase(); // Get entries and check if it makes sense to perform this operation - entries = basePanel.getSelectedEntries(); + entries = stateManager.getSelectedEntries(); if (entries.isEmpty()) { @@ -97,7 +104,7 @@ public void init() { } private void writeXMP() { - if (!shouldContinue) { + if (!shouldContinue || stateManager.getActiveDatabase().isEmpty()) { return; } @@ -105,7 +112,7 @@ private void writeXMP() { // 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(basePanel.getBibDatabaseContext(), Globals.prefs.getFilePreferences())) + .map(file -> file.findIn(stateManager.getActiveDatabase().get(), Globals.prefs.getFilePreferences())) .filter(Optional::isPresent) .map(Optional::get) .collect(Collectors.toList()); diff --git a/src/main/java/org/jabref/gui/filelist/AttachFileAction.java b/src/main/java/org/jabref/gui/filelist/AttachFileAction.java index 51fa192c115..e11bff8b4dc 100644 --- a/src/main/java/org/jabref/gui/filelist/AttachFileAction.java +++ b/src/main/java/org/jabref/gui/filelist/AttachFileAction.java @@ -1,12 +1,12 @@ package org.jabref.gui.filelist; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Optional; -import org.jabref.Globals; import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.fieldeditors.LinkedFilesEditorViewModel; @@ -14,32 +14,45 @@ import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.logic.l10n.Localization; import org.jabref.model.FieldChange; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.LinkedFile; -import org.jabref.preferences.JabRefPreferences; +import org.jabref.preferences.PreferencesService; public class AttachFileAction extends SimpleCommand { private final BasePanel panel; + private final StateManager stateManager; private final DialogService dialogService; + private final PreferencesService preferencesService; - public AttachFileAction(BasePanel panel, DialogService dialogService) { + public AttachFileAction(BasePanel panel, DialogService dialogService, StateManager stateManager, PreferencesService preferencesService) { this.panel = panel; + this.stateManager = stateManager; this.dialogService = dialogService; + this.preferencesService = preferencesService; + + this.executable.bind(ActionHelper.needsEntriesSelected(1, stateManager)); } @Override public void execute() { - if (panel.getSelectedEntries().size() != 1) { + if (stateManager.getActiveDatabase().isEmpty()) { + dialogService.notify(Localization.lang("This operation requires an open library.")); + return; + } + + if (stateManager.getSelectedEntries().size() != 1) { dialogService.notify(Localization.lang("This operation requires exactly one item to be selected.")); return; } - BibEntry entry = panel.getSelectedEntries().get(0); + BibDatabaseContext databaseContext = stateManager.getActiveDatabase().get(); + + BibEntry entry = stateManager.getSelectedEntries().get(0); - Path workingDirectory = panel.getBibDatabaseContext() - .getFirstExistingFileDir(Globals.prefs.getFilePreferences()) - .orElse(Paths.get(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY))); + Path workingDirectory = databaseContext.getFirstExistingFileDir(preferencesService.getFilePreferences()) + .orElse(preferencesService.getWorkingDir()); FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() .withInitialDirectory(workingDirectory) @@ -47,7 +60,7 @@ public void execute() { dialogService.showFileOpenDialog(fileDialogConfiguration).ifPresent(newFile -> { LinkedFile linkedFile = LinkedFilesEditorViewModel.fromFile(newFile, - panel.getBibDatabaseContext().getFileDirectoriesAsPaths(Globals.prefs.getFilePreferences()), + databaseContext.getFileDirectoriesAsPaths(preferencesService.getFilePreferences()), ExternalFileTypes.getInstance()); LinkedFileEditDialogView dialog = new LinkedFileEditDialogView(linkedFile); diff --git a/src/main/java/org/jabref/gui/maintable/MainTable.java b/src/main/java/org/jabref/gui/maintable/MainTable.java index 935470b1599..2293be5e914 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTable.java +++ b/src/main/java/org/jabref/gui/maintable/MainTable.java @@ -85,7 +85,7 @@ public MainTable(MainTableDataModel model, JabRefFrame frame, panel.showAndEdit(entry.getEntry()); } }) - .withContextMenu(entry -> RightClickMenu.create(entry, keyBindingRepository, panel, frame.getDialogService())) + .withContextMenu(entry -> RightClickMenu.create(entry, keyBindingRepository, panel, frame.getDialogService(), Globals.stateManager, Globals.prefs)) .setOnDragDetected(this::handleOnDragDetected) .setOnDragDropped(this::handleOnDragDropped) .setOnDragOver(this::handleOnDragOver) diff --git a/src/main/java/org/jabref/gui/maintable/OpenExternalFileAction.java b/src/main/java/org/jabref/gui/maintable/OpenExternalFileAction.java new file mode 100644 index 00000000000..6579eed3102 --- /dev/null +++ b/src/main/java/org/jabref/gui/maintable/OpenExternalFileAction.java @@ -0,0 +1,56 @@ +package org.jabref.gui.maintable; + +import java.util.List; + +import org.jabref.Globals; +import org.jabref.gui.DialogService; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.ActionHelper; +import org.jabref.gui.actions.SimpleCommand; +import org.jabref.gui.externalfiletype.ExternalFileTypes; +import org.jabref.gui.fieldeditors.LinkedFileViewModel; +import org.jabref.logic.l10n.Localization; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.StandardField; +import org.jabref.preferences.PreferencesService; + +public class OpenExternalFileAction extends SimpleCommand { + + private final DialogService dialogService; + private final StateManager stateManager; + private final PreferencesService preferencesService; + + public OpenExternalFileAction(DialogService dialogService, StateManager stateManager, PreferencesService preferencesService) { + this.dialogService = dialogService; + this.stateManager = stateManager; + this.preferencesService = preferencesService; + + this.executable.bind(ActionHelper.isFieldSetForSelectedEntry(StandardField.FILE, stateManager) + .and(ActionHelper.needsEntriesSelected(1, stateManager))); + } + + @Override + public void execute() { + stateManager.getActiveDatabase().ifPresent(databaseContext -> { + final List<BibEntry> selectedEntries = stateManager.getSelectedEntries(); + + if (selectedEntries.size() != 1) { + dialogService.notify(Localization.lang("This operation requires exactly one item to be selected.")); + return; + } + + final BibEntry entry = selectedEntries.get(0); + + LinkedFileViewModel linkedFileViewModel = new LinkedFileViewModel( + entry.getFiles().get(0), + entry, + databaseContext, + Globals.TASK_EXECUTOR, + dialogService, + preferencesService.getXMPPreferences(), + preferencesService.getFilePreferences(), + ExternalFileTypes.getInstance()); + linkedFileViewModel.open(); + }); + } +} diff --git a/src/main/java/org/jabref/gui/maintable/OpenFolderAction.java b/src/main/java/org/jabref/gui/maintable/OpenFolderAction.java new file mode 100644 index 00000000000..a2c3c211785 --- /dev/null +++ b/src/main/java/org/jabref/gui/maintable/OpenFolderAction.java @@ -0,0 +1,43 @@ +package org.jabref.gui.maintable; + +import org.jabref.Globals; +import org.jabref.gui.DialogService; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.ActionHelper; +import org.jabref.gui.actions.SimpleCommand; +import org.jabref.gui.externalfiletype.ExternalFileTypes; +import org.jabref.gui.fieldeditors.LinkedFileViewModel; +import org.jabref.model.entry.field.StandardField; +import org.jabref.preferences.PreferencesService; + +public class OpenFolderAction extends SimpleCommand { + + private final DialogService dialogService; + private final StateManager stateManager; + private final PreferencesService preferencesService; + + public OpenFolderAction(DialogService dialogService, StateManager stateManager, PreferencesService preferencesService) { + this.dialogService = dialogService; + this.stateManager = stateManager; + this.preferencesService = preferencesService; + + this.executable.bind(ActionHelper.isFieldSetForSelectedEntry(StandardField.FILE, stateManager)); + } + + @Override + public void execute() { + stateManager.getActiveDatabase().ifPresent(databaseContext -> + stateManager.getSelectedEntries().forEach(entry -> { + LinkedFileViewModel linkedFileViewModel = new LinkedFileViewModel( + entry.getFiles().get(0), + entry, + databaseContext, + Globals.TASK_EXECUTOR, + dialogService, + preferencesService.getXMPPreferences(), + preferencesService.getFilePreferences(), + ExternalFileTypes.getInstance()); + linkedFileViewModel.openFolder(); + })); + } +} diff --git a/src/main/java/org/jabref/gui/maintable/OpenUrlAction.java b/src/main/java/org/jabref/gui/maintable/OpenUrlAction.java new file mode 100644 index 00000000000..cfcd40b262c --- /dev/null +++ b/src/main/java/org/jabref/gui/maintable/OpenUrlAction.java @@ -0,0 +1,72 @@ +package org.jabref.gui.maintable; + +import java.io.IOException; +import java.util.List; +import java.util.Optional; + +import javafx.beans.binding.BooleanExpression; + +import org.jabref.gui.DialogService; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.ActionHelper; +import org.jabref.gui.actions.SimpleCommand; +import org.jabref.gui.desktop.JabRefDesktop; +import org.jabref.logic.l10n.Localization; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.Field; +import org.jabref.model.entry.field.StandardField; + +public class OpenUrlAction extends SimpleCommand { + + private final DialogService dialogService; + private final StateManager stateManager; + + public OpenUrlAction(DialogService dialogService, StateManager stateManager) { + this.dialogService = dialogService; + this.stateManager = stateManager; + + BooleanExpression fieldIsSet = ActionHelper.isAnyFieldSetForSelectedEntry( + List.of(StandardField.URL, StandardField.DOI, StandardField.URI, StandardField.EPRINT), + stateManager); + this.executable.bind(ActionHelper.needsEntriesSelected(1, stateManager).and(fieldIsSet)); + } + + @Override + public void execute() { + stateManager.getActiveDatabase().ifPresent(databaseContext -> { + final List<BibEntry> entries = stateManager.getSelectedEntries(); + + if (entries.size() != 1) { + dialogService.notify(Localization.lang("This operation requires exactly one item to be selected.")); + return; + } + + BibEntry entry = entries.get(0); + + // ToDo: Create dialog or menu to chose which one to open + // URL - DOI - DOI - EPRINT + Optional<String> link = entry.getField(StandardField.EPRINT); + Field field = StandardField.EPRINT; + if (entry.hasField(StandardField.URI)) { + link = entry.getField(StandardField.URI); + field = StandardField.URI; + } + if (entry.hasField(StandardField.DOI)) { + link = entry.getField(StandardField.DOI); + field = StandardField.DOI; + } + if (entry.hasField(StandardField.URL)) { + link = entry.getField(StandardField.URL); + field = StandardField.URL; + } + + if (link.isPresent()) { + try { + JabRefDesktop.openExternalViewer(databaseContext, link.get(), field); + } catch (IOException e) { + dialogService.showErrorDialogAndWait(Localization.lang("Unable to open link."), e); + } + } + }); + } +} diff --git a/src/main/java/org/jabref/gui/maintable/RightClickMenu.java b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java index 7029810a2fa..279211c7457 100644 --- a/src/main/java/org/jabref/gui/maintable/RightClickMenu.java +++ b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java @@ -1,8 +1,5 @@ package org.jabref.gui.maintable; -import java.util.Collections; -import java.util.List; - import javafx.scene.control.ContextMenu; import javafx.scene.control.Menu; import javafx.scene.control.SeparatorMenuItem; @@ -10,134 +7,98 @@ import org.jabref.Globals; import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; +import org.jabref.gui.SendAsEMailAction; +import org.jabref.gui.StateManager; import org.jabref.gui.actions.ActionFactory; -import org.jabref.gui.actions.Actions; -import org.jabref.gui.actions.OldCommandWrapper; import org.jabref.gui.actions.StandardActions; +import org.jabref.gui.edit.CopyMoreAction; +import org.jabref.gui.edit.EditAction; import org.jabref.gui.exporter.ExportToClipboardAction; import org.jabref.gui.filelist.AttachFileAction; import org.jabref.gui.keyboard.KeyBindingRepository; import org.jabref.gui.menus.ChangeEntryTypeMenu; -import org.jabref.gui.mergeentries.FetchAndMergeEntry; +import org.jabref.gui.mergeentries.MergeEntriesAction; +import org.jabref.gui.mergeentries.MergeWithFetchedEntryAction; +import org.jabref.gui.preview.CopyCitationAction; import org.jabref.gui.specialfields.SpecialFieldMenuItemFactory; +import org.jabref.logic.citationstyle.CitationStyleOutputFormat; import org.jabref.logic.citationstyle.CitationStylePreviewLayout; import org.jabref.logic.citationstyle.PreviewLayout; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.SpecialField; -import org.jabref.model.entry.field.StandardField; import org.jabref.preferences.JabRefPreferences; +import org.jabref.preferences.PreferencesService; import org.jabref.preferences.PreviewPreferences; public class RightClickMenu { - public static ContextMenu create(BibEntryTableViewModel entry, KeyBindingRepository keyBindingRepository, BasePanel panel, DialogService dialogService) { + public static ContextMenu create(BibEntryTableViewModel entry, KeyBindingRepository keyBindingRepository, BasePanel panel, DialogService dialogService, StateManager stateManager, PreferencesService preferencesService) { ContextMenu contextMenu = new ContextMenu(); ActionFactory factory = new ActionFactory(keyBindingRepository); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.COPY, new OldCommandWrapper(Actions.COPY, panel))); - contextMenu.getItems().add(createCopySubMenu(panel, factory, dialogService)); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.PASTE, new OldCommandWrapper(Actions.PASTE, panel))); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.CUT, new OldCommandWrapper(Actions.CUT, panel))); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.DELETE, new OldCommandWrapper(Actions.DELETE, panel))); + contextMenu.getItems().add(factory.createMenuItem(StandardActions.COPY, new EditAction(StandardActions.COPY, panel.frame(), stateManager))); + contextMenu.getItems().add(createCopySubMenu(panel, factory, dialogService, stateManager, preferencesService)); + contextMenu.getItems().add(factory.createMenuItem(StandardActions.PASTE, new EditAction(StandardActions.PASTE, panel.frame(), stateManager))); + contextMenu.getItems().add(factory.createMenuItem(StandardActions.CUT, new EditAction(StandardActions.CUT, panel.frame(), stateManager))); + contextMenu.getItems().add(factory.createMenuItem(StandardActions.DELETE_ENTRY, new EditAction(StandardActions.DELETE_ENTRY, panel.frame(), stateManager))); contextMenu.getItems().add(new SeparatorMenuItem()); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.SEND_AS_EMAIL, new OldCommandWrapper(Actions.SEND_AS_EMAIL, panel))); + contextMenu.getItems().add(factory.createMenuItem(StandardActions.SEND_AS_EMAIL, new SendAsEMailAction(dialogService, stateManager))); contextMenu.getItems().add(new SeparatorMenuItem()); if (Globals.prefs.getBoolean(JabRefPreferences.SPECIALFIELDSENABLED)) { - contextMenu.getItems().add(SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.RANKING, factory, panel)); - contextMenu.getItems().add(SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.RELEVANCE, factory, panel)); - contextMenu.getItems().add(SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.QUALITY, factory, panel)); - contextMenu.getItems().add(SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.PRINTED, factory, panel)); - contextMenu.getItems().add(SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.PRIORITY, factory, panel)); - contextMenu.getItems().add(SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.READ_STATUS, factory, panel)); + // ToDo: SpecialField needs the active BasePanel to mark it as changed. + // Refactor BasePanel, should mark the BibDatabaseContext or the UndoManager as dirty instead! + contextMenu.getItems().add(SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.RANKING, factory, panel.frame(), dialogService, stateManager)); + contextMenu.getItems().add(SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.RELEVANCE, factory, panel.frame(), dialogService, stateManager)); + contextMenu.getItems().add(SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.QUALITY, factory, panel.frame(), dialogService, stateManager)); + contextMenu.getItems().add(SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.PRINTED, factory, panel.frame(), dialogService, stateManager)); + contextMenu.getItems().add(SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.PRIORITY, factory, panel.frame(), dialogService, stateManager)); + contextMenu.getItems().add(SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.READ_STATUS, factory, panel.frame(), dialogService, stateManager)); } contextMenu.getItems().add(new SeparatorMenuItem()); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.OPEN_FOLDER, getOpenFolderCommand(panel))); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.OPEN_EXTERNAL_FILE, getOpenExternalFileCommand(panel))); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.OPEN_URL, getOpenUrlCommand(panel))); + contextMenu.getItems().add(factory.createMenuItem(StandardActions.OPEN_FOLDER, new OpenFolderAction(dialogService, stateManager, preferencesService))); + contextMenu.getItems().add(factory.createMenuItem(StandardActions.OPEN_EXTERNAL_FILE, new OpenExternalFileAction(dialogService, stateManager, preferencesService))); + contextMenu.getItems().add(factory.createMenuItem(StandardActions.OPEN_URL, new OpenUrlAction(dialogService, stateManager))); contextMenu.getItems().add(new SeparatorMenuItem()); contextMenu.getItems().add(new ChangeEntryTypeMenu().getChangeEntryTypeMenu(entry.getEntry(), panel.getBibDatabaseContext(), panel.getUndoManager())); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.MERGE_WITH_FETCHED_ENTRY, getFetchEntryData(panel))); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.ATTACH_FILE, new AttachFileAction(panel, dialogService))); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.MERGE_ENTRIES, mergeEntries(panel))); + contextMenu.getItems().add(factory.createMenuItem(StandardActions.MERGE_WITH_FETCHED_ENTRY, new MergeWithFetchedEntryAction(panel, dialogService, stateManager))); + contextMenu.getItems().add(factory.createMenuItem(StandardActions.ATTACH_FILE, new AttachFileAction(panel, dialogService, stateManager, preferencesService))); + // ToDo: Refactor BasePanel, see ahead. + contextMenu.getItems().add(factory.createMenuItem(StandardActions.MERGE_ENTRIES, new MergeEntriesAction(panel.frame(), dialogService, stateManager))); return contextMenu; } - private static OldCommandWrapper mergeEntries(BasePanel panel) { - OldCommandWrapper command = new OldCommandWrapper(Actions.MERGE_ENTRIES, panel); - command.setExecutable(panel.getMainTable().getSelectedEntries().size() == 2); - return command; - } - - private static OldCommandWrapper getFetchEntryData(BasePanel panel) { - OldCommandWrapper command = new OldCommandWrapper(Actions.MERGE_WITH_FETCHED_ENTRY, panel); - command.setExecutable(isAnyFieldSetForSelectedEntry(FetchAndMergeEntry.SUPPORTED_FIELDS, panel)); - return command; - } - - private static OldCommandWrapper getOpenUrlCommand(BasePanel panel) { - OldCommandWrapper command = new OldCommandWrapper(Actions.OPEN_URL, panel); - command.setExecutable(isFieldSetForSelectedEntry(StandardField.URL, panel) || isFieldSetForSelectedEntry(StandardField.DOI, panel)); - return command; - } - - private static OldCommandWrapper getOpenExternalFileCommand(BasePanel panel) { - OldCommandWrapper command = new OldCommandWrapper(Actions.OPEN_EXTERNAL_FILE, panel); - command.setExecutable(isFieldSetForSelectedEntry(StandardField.FILE, panel)); - return command; - } - - private static OldCommandWrapper getOpenFolderCommand(BasePanel panel) { - OldCommandWrapper command = new OldCommandWrapper(Actions.OPEN_FOLDER, panel); - command.setExecutable(isFieldSetForSelectedEntry(StandardField.FILE, panel)); - return command; - } - - private static Menu createCopySubMenu(BasePanel panel, ActionFactory factory, DialogService dialogService) { + private static Menu createCopySubMenu(BasePanel panel, ActionFactory factory, DialogService dialogService, StateManager stateManager, PreferencesService preferencesService) { Menu copySpecialMenu = factory.createMenu(StandardActions.COPY_MORE); - copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_TITLE, new OldCommandWrapper(Actions.COPY_TITLE, panel))); - copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_KEY, new OldCommandWrapper(Actions.COPY_KEY, panel))); - copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITE_KEY, new OldCommandWrapper(Actions.COPY_CITE_KEY, panel))); - copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_KEY_AND_TITLE, new OldCommandWrapper(Actions.COPY_KEY_AND_TITLE, panel))); - copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_KEY_AND_LINK, new OldCommandWrapper(Actions.COPY_KEY_AND_LINK, panel))); + copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_TITLE, new CopyMoreAction(StandardActions.COPY_TITLE, dialogService, stateManager, Globals.clipboardManager, preferencesService))); + copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_KEY, new CopyMoreAction(StandardActions.COPY_KEY, dialogService, stateManager, Globals.clipboardManager, preferencesService))); + copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITE_KEY, new CopyMoreAction(StandardActions.COPY_CITE_KEY, dialogService, stateManager, Globals.clipboardManager, preferencesService))); + copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_KEY_AND_TITLE, new CopyMoreAction(StandardActions.COPY_KEY_AND_TITLE, dialogService, stateManager, Globals.clipboardManager, preferencesService))); + copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_KEY_AND_LINK, new CopyMoreAction(StandardActions.COPY_KEY_AND_LINK, dialogService, stateManager, Globals.clipboardManager, preferencesService))); // the submenu will behave dependent on what style is currently selected (citation/preview) PreviewPreferences previewPreferences = Globals.prefs.getPreviewPreferences(); PreviewLayout style = previewPreferences.getCurrentPreviewStyle(); if (style instanceof CitationStylePreviewLayout) { - copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_HTML, new OldCommandWrapper(Actions.COPY_CITATION_HTML, panel))); + copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_HTML, new CopyCitationAction(CitationStyleOutputFormat.HTML, dialogService, stateManager, Globals.clipboardManager, previewPreferences))); Menu copyCitationMenu = factory.createMenu(StandardActions.COPY_CITATION_MORE); - copyCitationMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_TEXT, new OldCommandWrapper(Actions.COPY_CITATION_TEXT, panel))); - copyCitationMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_RTF, new OldCommandWrapper(Actions.COPY_CITATION_RTF, panel))); - copyCitationMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_ASCII_DOC, new OldCommandWrapper(Actions.COPY_CITATION_ASCII_DOC, panel))); - copyCitationMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_XSLFO, new OldCommandWrapper(Actions.COPY_CITATION_XSLFO, panel))); + copyCitationMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_TEXT, new CopyCitationAction(CitationStyleOutputFormat.TEXT, dialogService, stateManager, Globals.clipboardManager, previewPreferences))); + copyCitationMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_RTF, new CopyCitationAction(CitationStyleOutputFormat.RTF, dialogService, stateManager, Globals.clipboardManager, previewPreferences))); + copyCitationMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_ASCII_DOC, new CopyCitationAction(CitationStyleOutputFormat.ASCII_DOC, dialogService, stateManager, Globals.clipboardManager, previewPreferences))); + copyCitationMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_XSLFO, new CopyCitationAction(CitationStyleOutputFormat.XSL_FO, dialogService, stateManager, Globals.clipboardManager, previewPreferences))); copySpecialMenu.getItems().add(copyCitationMenu); } else { - copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_PREVIEW, new OldCommandWrapper(Actions.COPY_CITATION_HTML, panel))); + copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_PREVIEW, new CopyCitationAction(CitationStyleOutputFormat.HTML, dialogService, stateManager, Globals.clipboardManager, previewPreferences))); } copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.EXPORT_TO_CLIPBOARD, new ExportToClipboardAction(panel, dialogService))); return copySpecialMenu; } - - private static boolean isFieldSetForSelectedEntry(Field field, BasePanel panel) { - return isAnyFieldSetForSelectedEntry(Collections.singletonList(field), panel); - } - - private static boolean isAnyFieldSetForSelectedEntry(List<Field> fields, BasePanel panel) { - if (panel.getMainTable().getSelectedEntries().size() == 1) { - BibEntry entry = panel.getMainTable().getSelectedEntries().get(0); - return !Collections.disjoint(fields, entry.getFields()); - } - return false; - } } diff --git a/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java b/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java index baca427159e..7ccc29e2515 100644 --- a/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java +++ b/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java @@ -4,43 +4,47 @@ import java.util.List; import java.util.Optional; -import org.jabref.gui.BasePanel; +import org.jabref.Globals; import org.jabref.gui.DialogService; import org.jabref.gui.JabRefFrame; import org.jabref.gui.StateManager; +import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableInsertEntries; import org.jabref.gui.undo.UndoableRemoveEntries; import org.jabref.logic.l10n.Localization; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; -import static org.jabref.gui.actions.ActionHelper.needsDatabase; - public class MergeEntriesAction extends SimpleCommand { - private final JabRefFrame jabRefFrame; + private final JabRefFrame frame; private final DialogService dialogService; + private final StateManager stateManager; - public MergeEntriesAction(JabRefFrame jabRefFrame, StateManager stateManager) { - this.jabRefFrame = jabRefFrame; - this.dialogService = jabRefFrame.getDialogService(); + public MergeEntriesAction(JabRefFrame frame, DialogService dialogService, StateManager stateManager) { + this.frame = frame; + this.dialogService = dialogService; + this.stateManager = stateManager; - this.executable.bind(needsDatabase(stateManager)); + this.executable.bind(ActionHelper.needsEntriesSelected(2, stateManager)); } @Override public void execute() { - BasePanel basePanel = jabRefFrame.getCurrentBasePanel(); + if (stateManager.getActiveDatabase().isEmpty()) { + return; + } + BibDatabaseContext databaseContext = stateManager.getActiveDatabase().get(); // Check if there are two entries selected - List<BibEntry> selectedEntries = basePanel.getSelectedEntries(); + List<BibEntry> selectedEntries = stateManager.getSelectedEntries(); if (selectedEntries.size() != 2) { // Inform the user to select entries first. dialogService.showInformationDialogAndWait( Localization.lang("Merge entries"), Localization.lang("You have to choose exactly two entries to merge.")); - return; } @@ -52,17 +56,20 @@ public void execute() { dlg.setTitle(Localization.lang("Merge entries")); Optional<BibEntry> mergedEntry = dlg.showAndWait(); if (mergedEntry.isPresent()) { - basePanel.insertEntry(mergedEntry.get()); + // ToDo: BibDatabase::insertEntry does not contain logic to mark the BasePanel as changed and to mark + // entries with a timestamp, only BasePanel::insertEntry does. Workaround for the moment is to get the + // BasePanel from the constructor injected JabRefFrame. Should be refactored and extracted! + frame.getCurrentBasePanel().insertEntry(mergedEntry.get()); // Create a new entry and add it to the undo stack // Remove the other two entries and add them to the undo stack (which is not working...) NamedCompound ce = new NamedCompound(Localization.lang("Merge entries")); - ce.addEdit(new UndoableInsertEntries(basePanel.getDatabase(), mergedEntry.get())); + ce.addEdit(new UndoableInsertEntries(databaseContext.getDatabase(), mergedEntry.get())); List<BibEntry> entriesToRemove = Arrays.asList(one, two); - ce.addEdit(new UndoableRemoveEntries(basePanel.getDatabase(), entriesToRemove)); - basePanel.getDatabase().removeEntries(entriesToRemove); + ce.addEdit(new UndoableRemoveEntries(databaseContext.getDatabase(), entriesToRemove)); + databaseContext.getDatabase().removeEntries(entriesToRemove); ce.end(); - basePanel.getUndoManager().addEdit(ce); + Globals.undoManager.addEdit(ce); // ToDo: Rework UndoManager and extract Globals dialogService.notify(Localization.lang("Merged entries")); } else { diff --git a/src/main/java/org/jabref/gui/mergeentries/MergeWithFetchedEntryAction.java b/src/main/java/org/jabref/gui/mergeentries/MergeWithFetchedEntryAction.java index 2b2edf17017..e67c42b0df2 100644 --- a/src/main/java/org/jabref/gui/mergeentries/MergeWithFetchedEntryAction.java +++ b/src/main/java/org/jabref/gui/mergeentries/MergeWithFetchedEntryAction.java @@ -3,32 +3,38 @@ import org.jabref.Globals; import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; -import org.jabref.gui.actions.BaseAction; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.ActionHelper; +import org.jabref.gui.actions.SimpleCommand; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.OrFields; import org.jabref.model.entry.field.StandardField; -public class MergeWithFetchedEntryAction implements BaseAction { +public class MergeWithFetchedEntryAction extends SimpleCommand { private final BasePanel basePanel; private final DialogService dialogService; + private final StateManager stateManager; - public MergeWithFetchedEntryAction(BasePanel basePanel, DialogService dialogService) { + public MergeWithFetchedEntryAction(BasePanel basePanel, DialogService dialogService, StateManager stateManager) { this.basePanel = basePanel; this.dialogService = dialogService; + this.stateManager = stateManager; + + this.executable.bind(ActionHelper.needsEntriesSelected(1, stateManager) + .and(ActionHelper.isAnyFieldSetForSelectedEntry(FetchAndMergeEntry.SUPPORTED_FIELDS, stateManager))); } @Override - public void action() { - if (basePanel.getMainTable().getSelectedEntries().size() == 1) { - BibEntry originalEntry = basePanel.getMainTable().getSelectedEntries().get(0); - new FetchAndMergeEntry(basePanel, Globals.TASK_EXECUTOR).fetchAndMerge(originalEntry); - } else { + public void execute() { + if (stateManager.getSelectedEntries().size() != 1) { dialogService.showInformationDialogAndWait( Localization.lang("Merge entry with %0 information", new OrFields(StandardField.DOI, StandardField.ISBN, StandardField.EPRINT).getDisplayName()), Localization.lang("This operation requires exactly one item to be selected.")); - } + + BibEntry originalEntry = stateManager.getSelectedEntries().get(0); + new FetchAndMergeEntry(basePanel, Globals.TASK_EXECUTOR).fetchAndMerge(originalEntry); } } diff --git a/src/main/java/org/jabref/gui/preview/CitationStyleToClipboardWorker.java b/src/main/java/org/jabref/gui/preview/CopyCitationAction.java similarity index 89% rename from src/main/java/org/jabref/gui/preview/CitationStyleToClipboardWorker.java rename to src/main/java/org/jabref/gui/preview/CopyCitationAction.java index 23a4f056d36..46e671147c2 100644 --- a/src/main/java/org/jabref/gui/preview/CitationStyleToClipboardWorker.java +++ b/src/main/java/org/jabref/gui/preview/CopyCitationAction.java @@ -3,16 +3,18 @@ import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import javafx.scene.input.ClipboardContent; import org.jabref.Globals; -import org.jabref.gui.BasePanel; import org.jabref.gui.ClipBoardManager; import org.jabref.gui.DialogService; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.ActionHelper; +import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.util.BackgroundTask; -import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.citationstyle.CitationStyleGenerator; import org.jabref.logic.citationstyle.CitationStyleOutputFormat; import org.jabref.logic.citationstyle.CitationStylePreviewLayout; @@ -32,33 +34,35 @@ * Copies the selected entries and formats them with the selected citation style (or preview), then it is copied to the clipboard. * This worker cannot be reused. */ -public class CitationStyleToClipboardWorker { +public class CopyCitationAction extends SimpleCommand { - private static final Logger LOGGER = LoggerFactory.getLogger(CitationStyleToClipboardWorker.class); + private static final Logger LOGGER = LoggerFactory.getLogger(CopyCitationAction.class); - private final BasePanel basePanel; private final List<BibEntry> selectedEntries; + private final StateManager stateManager; private final PreviewLayout style; private final String previewStyle; private final CitationStyleOutputFormat outputFormat; private final DialogService dialogService; private final ClipBoardManager clipBoardManager; - public CitationStyleToClipboardWorker(BasePanel basePanel, CitationStyleOutputFormat outputFormat, DialogService dialogService, ClipBoardManager clipBoardManager, PreviewPreferences previewPreferences) { - this.basePanel = basePanel; - this.selectedEntries = basePanel.getSelectedEntries(); + public CopyCitationAction(CitationStyleOutputFormat outputFormat, DialogService dialogService, StateManager stateManager, ClipBoardManager clipBoardManager, PreviewPreferences previewPreferences) { + this.selectedEntries = stateManager.getSelectedEntries(); this.style = previewPreferences.getCurrentPreviewStyle(); this.previewStyle = previewPreferences.getPreviewStyle(); this.outputFormat = outputFormat; this.clipBoardManager = clipBoardManager; this.dialogService = dialogService; + this.stateManager = stateManager; + + this.executable.bind(ActionHelper.needsEntriesSelected(stateManager)); } - public void copyCitationStyleToClipboard(TaskExecutor taskExecutor) { + public void execute() { BackgroundTask.wrap(this::generateCitations) .onFailure(ex -> LOGGER.error("Error while copying citations to the clipboard", ex)) .onSuccess(this::setClipBoardContent) - .executeWith(taskExecutor); + .executeWith(Globals.TASK_EXECUTOR); } private List<String> generateCitations() throws IOException { @@ -71,13 +75,17 @@ private List<String> generateCitations() throws IOException { if (styleSource != null) { return CitationStyleGenerator.generateCitations(selectedEntries, styleSource, outputFormat); } else { + if (stateManager.getActiveDatabase().isEmpty()) { + return Collections.emptyList(); + } + StringReader sr = new StringReader(previewStyle.replace("__NEWLINE__", "\n")); LayoutFormatterPreferences layoutFormatterPreferences = Globals.prefs.getLayoutFormatterPreferences(Globals.journalAbbreviationLoader); Layout layout = new LayoutHelper(sr, layoutFormatterPreferences).getLayoutFromText(); List<String> citations = new ArrayList<>(selectedEntries.size()); for (BibEntry entry : selectedEntries) { - citations.add(layout.doLayout(entry, basePanel.getDatabase())); + citations.add(layout.doLayout(entry, stateManager.getActiveDatabase().get().getDatabase())); } return citations; } diff --git a/src/main/java/org/jabref/gui/specialfields/SpecialFieldAction.java b/src/main/java/org/jabref/gui/specialfields/SpecialFieldAction.java index 395e14a28c7..1df63214b07 100644 --- a/src/main/java/org/jabref/gui/specialfields/SpecialFieldAction.java +++ b/src/main/java/org/jabref/gui/specialfields/SpecialFieldAction.java @@ -4,8 +4,11 @@ import java.util.Objects; import org.jabref.Globals; +import org.jabref.gui.DialogService; import org.jabref.gui.JabRefFrame; -import org.jabref.gui.actions.BaseAction; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.ActionHelper; +import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableFieldChange; import org.jabref.logic.l10n.Localization; @@ -17,16 +20,16 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class SpecialFieldAction implements BaseAction { +public class SpecialFieldAction extends SimpleCommand { private static final Logger LOGGER = LoggerFactory.getLogger(SpecialFieldAction.class); private final JabRefFrame frame; private final SpecialField specialField; private final String value; private final boolean nullFieldIfValueIsTheSame; - private final String undoText; - + private final DialogService dialogService; + private final StateManager stateManager; /** * @param nullFieldIfValueIsTheSame - false also causes that doneTextPattern has two place holders %0 for the value and %1 for the sum of entries @@ -36,18 +39,24 @@ public SpecialFieldAction( SpecialField specialField, String value, boolean nullFieldIfValueIsTheSame, - String undoText) { + String undoText, + DialogService dialogService, + StateManager stateManager) { this.frame = frame; this.specialField = specialField; this.value = value; this.nullFieldIfValueIsTheSame = nullFieldIfValueIsTheSame; this.undoText = undoText; + this.dialogService = dialogService; + this.stateManager = stateManager; + + this.executable.bind(ActionHelper.needsEntriesSelected(stateManager)); } @Override - public void action() { + public void execute() { try { - List<BibEntry> bes = frame.getCurrentBasePanel().getSelectedEntries(); + List<BibEntry> bes = stateManager.getSelectedEntries(); if ((bes == null) || bes.isEmpty()) { return; } @@ -70,7 +79,7 @@ public void action() { } else { outText = getTextDone(specialField, value, Integer.toString(bes.size())); } - frame.getDialogService().notify(outText); + dialogService.notify(outText); } else { // if user does not change anything with his action, we do not do anything either // even no output message @@ -83,7 +92,7 @@ public void action() { private String getTextDone(SpecialField field, String... params) { Objects.requireNonNull(params); - SpecialFieldViewModel viewModel = new SpecialFieldViewModel(field, frame.getCurrentBasePanel().getUndoManager()); + SpecialFieldViewModel viewModel = new SpecialFieldViewModel(field, frame.getUndoManager()); if (field.isSingleValueField() && (params.length == 1) && (params[0] != null)) { // Single value fields can be toggled only diff --git a/src/main/java/org/jabref/gui/specialfields/SpecialFieldMenuItemFactory.java b/src/main/java/org/jabref/gui/specialfields/SpecialFieldMenuItemFactory.java index 5cfa023b231..72c51d825bb 100644 --- a/src/main/java/org/jabref/gui/specialfields/SpecialFieldMenuItemFactory.java +++ b/src/main/java/org/jabref/gui/specialfields/SpecialFieldMenuItemFactory.java @@ -7,40 +7,34 @@ import javafx.scene.control.Menu; import javafx.scene.control.MenuItem; -import org.jabref.gui.BasePanel; +import org.jabref.Globals; +import org.jabref.gui.DialogService; +import org.jabref.gui.JabRefFrame; +import org.jabref.gui.StateManager; import org.jabref.gui.actions.ActionFactory; -import org.jabref.gui.actions.OldCommandWrapper; -import org.jabref.gui.actions.OldCommandWrapperForActiveDatabase; import org.jabref.model.entry.field.SpecialField; import org.jabref.model.entry.field.SpecialFieldValue; import de.saxsys.mvvmfx.utils.commands.Command; public class SpecialFieldMenuItemFactory { - public static MenuItem getSpecialFieldSingleItem(SpecialField field, ActionFactory factory, BasePanel panel) { + public static MenuItem getSpecialFieldSingleItem(SpecialField field, ActionFactory factory, JabRefFrame frame, DialogService dialogService, StateManager stateManager) { SpecialFieldValueViewModel specialField = new SpecialFieldValueViewModel(field.getValues().get(0)); - return factory.createMenuItem(specialField.getAction(), new OldCommandWrapper(specialField.getCommand(), panel)); + return factory.createMenuItem(specialField.getAction(), + new SpecialFieldViewModel(field, Globals.undoManager).getSpecialFieldAction(field.getValues().get(0), frame, dialogService, stateManager)); } - public static MenuItem getSpecialFieldSingleItemForActiveDatabase(SpecialField field, ActionFactory factory) { - SpecialFieldValueViewModel specialField = new SpecialFieldValueViewModel(field.getValues().get(0)); - return factory.createMenuItem(specialField.getAction(), new OldCommandWrapperForActiveDatabase(specialField.getCommand())); - } - - public static Menu createSpecialFieldMenu(SpecialField field, ActionFactory factory, BasePanel panel) { - return createSpecialFieldMenu(field, factory, panel.getUndoManager(), specialField -> new OldCommandWrapper(specialField.getCommand(), panel)); - } - - public static Menu createSpecialFieldMenuForActiveDatabase(SpecialField field, ActionFactory factory, UndoManager undoManager) { - return createSpecialFieldMenu(field, factory, undoManager, specialField -> new OldCommandWrapperForActiveDatabase(specialField.getCommand())); + public static Menu createSpecialFieldMenu(SpecialField field, ActionFactory factory, JabRefFrame frame, DialogService dialogService, StateManager stateManager) { + return createSpecialFieldMenu(field, factory, Globals.undoManager, specialField -> + new SpecialFieldViewModel(field, Globals.undoManager).getSpecialFieldAction(specialField.getValue(), frame, dialogService, stateManager)); } public static Menu createSpecialFieldMenu(SpecialField field, ActionFactory factory, UndoManager undoManager, Function<SpecialFieldValueViewModel, Command> commandFactory) { SpecialFieldViewModel viewModel = new SpecialFieldViewModel(field, undoManager); Menu menu = factory.createMenu(viewModel.getAction()); - for (SpecialFieldValue val : field.getValues()) { - SpecialFieldValueViewModel specialField = new SpecialFieldValueViewModel(val); - menu.getItems().add(factory.createMenuItem(specialField.getAction(), commandFactory.apply(specialField))); + for (SpecialFieldValue Value : field.getValues()) { + SpecialFieldValueViewModel valueViewModel = new SpecialFieldValueViewModel(Value); + menu.getItems().add(factory.createMenuItem(valueViewModel.getAction(), commandFactory.apply(valueViewModel))); } return menu; } diff --git a/src/main/java/org/jabref/gui/specialfields/SpecialFieldValueViewModel.java b/src/main/java/org/jabref/gui/specialfields/SpecialFieldValueViewModel.java index 1a56592791f..2565adcfa42 100644 --- a/src/main/java/org/jabref/gui/specialfields/SpecialFieldValueViewModel.java +++ b/src/main/java/org/jabref/gui/specialfields/SpecialFieldValueViewModel.java @@ -4,7 +4,6 @@ import java.util.Optional; import org.jabref.gui.actions.Action; -import org.jabref.gui.actions.Actions; import org.jabref.gui.actions.StandardActions; import org.jabref.gui.icon.JabRefIcon; import org.jabref.logic.l10n.Localization; @@ -71,45 +70,6 @@ public String getToolTipText() { } } - public Actions getCommand() { - switch (value) { - case PRINTED: - return Actions.TOGGLE_PRINTED; - case CLEAR_PRIORITY: - return Actions.CLEAR_PRIORITY; - case PRIORITY_HIGH: - return Actions.SET_PRIORITY_1; - case PRIORITY_MEDIUM: - return Actions.SET_PRIORITY_2; - case PRIORITY_LOW: - return Actions.SET_PRIORITY_3; - case QUALITY_ASSURED: - return Actions.TOGGLE_QUALITY_ASSURED; - case CLEAR_RANK: - return Actions.CLEAR_RANK; - case RANK_1: - return Actions.SET_RANK_1; - case RANK_2: - return Actions.SET_RANK_2; - case RANK_3: - return Actions.SET_RANK_3; - case RANK_4: - return Actions.SET_RANK_4; - case RANK_5: - return Actions.SET_RANK_5; - case CLEAR_READ_STATUS: - return Actions.CLEAR_READ_STATUS; - case READ: - return Actions.SET_READ_STATUS_TO_READ; - case SKIMMED: - return Actions.SET_READ_STATUS_TO_SKIMMED; - case RELEVANT: - return Actions.TOGGLE_RELEVANCE; - default: - throw new IllegalArgumentException("There is no action name for special field value " + value); - } - } - public Action getAction() { switch (value) { case PRINTED: @@ -145,7 +105,7 @@ public Action getAction() { case RELEVANT: return StandardActions.RELEVANT; default: - throw new IllegalArgumentException("There is no tooltip localization for special field value " + value); + throw new IllegalArgumentException("There is no action name for special field value " + value); } } } diff --git a/src/main/java/org/jabref/gui/specialfields/SpecialFieldViewModel.java b/src/main/java/org/jabref/gui/specialfields/SpecialFieldViewModel.java index 455e1708c71..55c50a8324c 100644 --- a/src/main/java/org/jabref/gui/specialfields/SpecialFieldViewModel.java +++ b/src/main/java/org/jabref/gui/specialfields/SpecialFieldViewModel.java @@ -7,7 +7,9 @@ import javax.swing.undo.UndoManager; import org.jabref.Globals; +import org.jabref.gui.DialogService; import org.jabref.gui.JabRefFrame; +import org.jabref.gui.StateManager; import org.jabref.gui.actions.Action; import org.jabref.gui.actions.StandardActions; import org.jabref.gui.icon.JabRefIcon; @@ -32,12 +34,14 @@ public SpecialField getField() { return field; } - public SpecialFieldAction getSpecialFieldAction(SpecialFieldValue value, JabRefFrame frame) { + public SpecialFieldAction getSpecialFieldAction(SpecialFieldValue value, JabRefFrame frame, DialogService dialogService, StateManager stateManager) { return new SpecialFieldAction(frame, field, value.getFieldValue().orElse(null), // if field contains only one value, it has to be nulled // otherwise, another setting does not empty the field field.getValues().size() == 1, - getLocalization()); + getLocalization(), + dialogService, + stateManager); } public JabRefIcon getIcon() { diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 576ec67ee0d..5c3d694d816 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -170,7 +170,6 @@ Could\ not\ import\ preferences=Could not import preferences Could\ not\ instantiate\ %0=Could not instantiate %0 Could\ not\ instantiate\ %0\ %1=Could not instantiate %0 %1 Could\ not\ instantiate\ %0.\ Have\ you\ chosen\ the\ correct\ package\ path?=Could not instantiate %0. Have you chosen the correct package path? -Could\ not\ open\ link=Could not open link Could\ not\ print\ preview=Could not print preview @@ -331,8 +330,6 @@ External\ file\ links=External file links External\ programs=External programs -External\ viewer\ called=External viewer called - Field=Field field=field @@ -566,7 +563,6 @@ No\ journal\ names\ could\ be\ unabbreviated.=No journal names could be unabbrev Open\ PDF=Open PDF -No\ URL\ defined=No URL defined not=not not\ found=not found @@ -2091,6 +2087,9 @@ Keyword\ delimiter=Keyword delimiter Hierarchical\ keyword\ delimiter=Hierarchical keyword delimiter Escape\ ampersands=Escape ampersands +Copied\ '%0'\ to\ clipboard.=Copied '%0' to clipboard. +This\ operation\ requires\ an\ open\ library.=This operation requires an open library. + Plain\ References\ Parser=Plain References Parser Please\ enter\ the\ plain\ references\ to\ extract\ from\ separated\ by\ double\ empty\ lines.=Please enter the plain references to extract from separated by double empty lines. Add\ to\ current\ library=Add to current library diff --git a/src/test/java/org/jabref/gui/preview/CitationStyleToClipboardWorkerTest.java b/src/test/java/org/jabref/gui/preview/CopyCitationActionTest.java similarity index 94% rename from src/test/java/org/jabref/gui/preview/CitationStyleToClipboardWorkerTest.java rename to src/test/java/org/jabref/gui/preview/CopyCitationActionTest.java index 82501d0e182..7dec89193c5 100644 --- a/src/test/java/org/jabref/gui/preview/CitationStyleToClipboardWorkerTest.java +++ b/src/test/java/org/jabref/gui/preview/CopyCitationActionTest.java @@ -11,7 +11,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -class CitationStyleToClipboardWorkerTest { +class CopyCitationActionTest { @Test void processPreviewText() throws Exception { @@ -39,7 +39,7 @@ void processPreviewText() throws Exception { OS.NEWLINE + "Abstract: This entry describes a test scenario which may be useful in JabRef. By providing a test entry it is possible to see how certain things will look in this graphical BIB-file mananger. "; - ClipboardContent clipboardContent = CitationStyleToClipboardWorker.processPreview(Arrays.asList(citation, citation)); + ClipboardContent clipboardContent = CopyCitationAction.processPreview(Arrays.asList(citation, citation)); String actual = clipboardContent.getString(); assertEquals(expected, actual); @@ -92,7 +92,7 @@ void processPreviewHtml() throws Exception { "</dd>" + OS.NEWLINE + "<p></p></font>"; - ClipboardContent clipboardContent = CitationStyleToClipboardWorker.processPreview(Arrays.asList(citation, citation)); + ClipboardContent clipboardContent = CopyCitationAction.processPreview(Arrays.asList(citation, citation)); String actual = clipboardContent.getString(); assertEquals(expected, actual); } @@ -103,7 +103,7 @@ void processText() throws Exception { "[1]B. Smith, B. Jones, and J. Williams, “Title of the test entry,” BibTeX Journal, vol. 34, no. 3, pp. 45–67, Jul. 2016." + OS.NEWLINE; String citation = "[1]B. Smith, B. Jones, and J. Williams, “Title of the test entry,” BibTeX Journal, vol. 34, no. 3, pp. 45–67, Jul. 2016." + OS.NEWLINE; - ClipboardContent textTransferable = CitationStyleToClipboardWorker.processText(Arrays.asList(citation, citation)); + ClipboardContent textTransferable = CopyCitationAction.processText(Arrays.asList(citation, citation)); String actual = textTransferable.getString(); assertEquals(expected, actual); @@ -118,7 +118,7 @@ void processRtf() throws Exception { "}"; String citation = "[1]\\tab B. Smith, B. Jones, and J. Williams, \\uc0\\u8220{}Title of the test entry,\\uc0\\u8221{} {\\i{}BibTeX Journal}, vol. 34, no. 3, pp. 45\\uc0\\u8211{}67, Jul. 2016." + OS.NEWLINE; - ClipboardContent content = CitationStyleToClipboardWorker.processRtf(Arrays.asList(citation, citation)); + ClipboardContent content = CopyCitationAction.processRtf(Arrays.asList(citation, citation)); Object actual = content.getRtf(); assertEquals(expected, actual); @@ -191,7 +191,7 @@ void processXslFo() throws Exception { " </fo:table>" + OS.NEWLINE + "</fo:block>" + OS.NEWLINE; - ClipboardContent xmlTransferable = CitationStyleToClipboardWorker.processXslFo(Arrays.asList(citation, citation)); + ClipboardContent xmlTransferable = CopyCitationAction.processXslFo(Arrays.asList(citation, citation)); Object actual = xmlTransferable.get(ClipBoardManager.XML); assertEquals(expected, actual); @@ -221,7 +221,7 @@ void processHtmlAsHtml() throws Exception { String citation = " <div class=\"csl-entry\">" + OS.NEWLINE + " <div class=\"csl-left-margin\">[1]</div><div class=\"csl-right-inline\">B. Smith, B. Jones, and J. Williams, “Title of the test entry,” <i>BibTeX Journal</i>, vol. 34, no. 3, pp. 45–67, Jul. 2016.</div>" + OS.NEWLINE + " </div>" + OS.NEWLINE; - ClipboardContent htmlTransferable = CitationStyleToClipboardWorker.processHtml(Arrays.asList(citation, citation)); + ClipboardContent htmlTransferable = CopyCitationAction.processHtml(Arrays.asList(citation, citation)); Object actual = htmlTransferable.getHtml(); assertEquals(expected, actual);