From b83d547af4ac0db3a4df350301c2a45487f81054 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Wed, 19 Feb 2020 00:34:41 +0100 Subject: [PATCH] Refactored CopyBibTeXKeyAndLinkAction, copyTitle, copyCiteKey, copyKey, copyKeyAndTitle to CopyMoreActions --- src/main/java/org/jabref/gui/BasePanel.java | 137 +---------- .../gui/edit/CopyBibTeXKeyAndLinkAction.java | 65 ----- .../org/jabref/gui/edit/CopyMoreAction.java | 228 ++++++++++++++++++ .../jabref/gui/maintable/RightClickMenu.java | 15 +- 4 files changed, 241 insertions(+), 204 deletions(-) delete mode 100644 src/main/java/org/jabref/gui/edit/CopyBibTeXKeyAndLinkAction.java create mode 100644 src/main/java/org/jabref/gui/edit/CopyMoreAction.java diff --git a/src/main/java/org/jabref/gui/BasePanel.java b/src/main/java/org/jabref/gui/BasePanel.java index 0546c35f67c..9ec4eddf7de 100644 --- a/src/main/java/org/jabref/gui/BasePanel.java +++ b/src/main/java/org/jabref/gui/BasePanel.java @@ -1,16 +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.stream.Collectors; import javax.swing.undo.CannotRedoException; import javax.swing.undo.CannotUndoException; @@ -34,7 +30,6 @@ import org.jabref.gui.cleanup.CleanupAction; import org.jabref.gui.collab.DatabaseChangeMonitor; import org.jabref.gui.collab.DatabaseChangePane; -import org.jabref.gui.edit.CopyBibTeXKeyAndLinkAction; import org.jabref.gui.edit.ReplaceStringAction; import org.jabref.gui.entryeditor.EntryEditor; import org.jabref.gui.exporter.SaveDatabaseAction; @@ -57,8 +52,6 @@ import org.jabref.gui.util.DefaultTaskExecutor; import org.jabref.logic.citationstyle.CitationStyleCache; 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; @@ -270,16 +263,16 @@ private void setupActions() { // 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); + // actions.put(Actions.COPY_KEY, this::copyKey); // The action for copying the selected entry's title. - actions.put(Actions.COPY_TITLE, this::copyTitle); + // 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); + // 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_KEY_AND_TITLE, this::copyKeyAndTitle); /* actions.put(Actions.COPY_CITATION_ASCII_DOC, () -> copyCitationToClipboard(CitationStyleOutputFormat.ASCII_DOC)); @@ -290,7 +283,7 @@ private void setupActions() { */ // 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.COPY_KEY_AND_LINK, new CopyBibTeXKeyAndLinkAction(mainTable, Globals.clipboardManager)); actions.put(Actions.MERGE_DATABASE, new AppendDatabaseAction(frame, this)); @@ -385,126 +378,6 @@ public void delete(BibEntry entry) { delete(false, Collections.singletonList(entry)); } - private void copyTitle() { - List selectedBibEntries = mainTable.getSelectedEntries(); - if (!selectedBibEntries.isEmpty()) { - // Collect all non-null titles. - List 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 bes = mainTable.getSelectedEntries(); - if (!bes.isEmpty()) { - List 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 bes = mainTable.getSelectedEntries(); - if (!bes.isEmpty()) { - List 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 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()))); - } - } - } - /** * 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. 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 entries = mainTable.getSelectedEntries(); - if (!entries.isEmpty()) { - StringBuilder sb = new StringBuilder(); - - List 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("%s", 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..b40353bc365 --- /dev/null +++ b/src/main/java/org/jabref/gui/edit/CopyMoreAction.java @@ -0,0 +1,228 @@ +package org.jabref.gui.edit; + +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.jabref.Globals; +import org.jabref.JabRefGUI; +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 StandardActions action; + private DialogService dialogService; + private StateManager stateManager; + private final ClipBoardManager clipBoardManager; + private 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; + } + + if (!Arrays.asList( + StandardActions.COPY_TITLE, + StandardActions.COPY_KEY, + StandardActions.COPY_CITE_KEY, + StandardActions.COPY_KEY_AND_TITLE, + StandardActions.COPY_KEY_AND_LINK) + .contains(action)) { + 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; + } + } + + private void copyTitle() { + List selectedBibEntries = stateManager.getSelectedEntries(); + + List 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") + " '" + 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 entries = stateManager.getSelectedEntries(); + + List keys = new ArrayList<>(entries.size()); + // Collect all non-null keys. + for (BibEntry entry : entries) { + entry.getCiteKeyOptional().ifPresent(keys::add); + } + 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") + " '" + 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 entries = stateManager.getSelectedEntries(); + List keys = new ArrayList<>(entries.size()); + + // Collect all non-null keys. + for (BibEntry entry : entries) { + entry.getCiteKeyOptional().ifPresent(keys::add); + } + 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") + " '" + 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 entries = stateManager.getSelectedEntries(); + + // ToDo: in a future version, 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 copied = 0; + // Collect all non-null keys. + for (BibEntry entry : entries) { + if (entry.hasCiteKey()) { + copied++; + keyAndTitle.append(layout.doLayout(entry, stateManager.getActiveDatabase().get().getDatabase())); + } + } + + if (copied == 0) { + dialogService.notify(Localization.lang("None of the selected entries have BibTeX keys.")); + return; + } + + clipBoardManager.setContent(keyAndTitle.toString()); + + if (copied == entries.size()) { + // All entries had keys. + dialogService.notify(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(keyAndTitle.toString()) + "'."); + } else { + dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", Integer.toString(entries.size() - copied), 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 entries = stateManager.getSelectedEntries(); + + StringBuilder keyAndLink = new StringBuilder(); + + List 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(""); + keyAndLink.append(url.isEmpty() ? key : String.format("%s", url, key)); + keyAndLink.append(OS.NEWLINE); + } + + clipBoardManager.setHtmlContent(keyAndLink.toString()); + + 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.toString()) + "'."); + } 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/maintable/RightClickMenu.java b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java index bd3d6f3245b..e7e8b4f875f 100644 --- a/src/main/java/org/jabref/gui/maintable/RightClickMenu.java +++ b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java @@ -13,6 +13,7 @@ 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.exporter.ExportToClipboardAction; import org.jabref.gui.filelist.AttachFileAction; import org.jabref.gui.keyboard.KeyBindingRepository; @@ -36,7 +37,7 @@ public static ContextMenu create(BibEntryTableViewModel entry, KeyBindingReposit ActionFactory factory = new ActionFactory(keyBindingRepository); contextMenu.getItems().add(factory.createMenuItem(StandardActions.COPY, new OldCommandWrapper(Actions.COPY, panel))); - contextMenu.getItems().add(createCopySubMenu(panel, factory, dialogService, stateManager)); + contextMenu.getItems().add(createCopySubMenu(panel, factory, dialogService, stateManager, preferencesService)); 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))); @@ -72,13 +73,13 @@ public static ContextMenu create(BibEntryTableViewModel entry, KeyBindingReposit return contextMenu; } - private static Menu createCopySubMenu(BasePanel panel, ActionFactory factory, DialogService dialogService, StateManager stateManager) { + 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();