-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Feature: Add "Copy Field Content" submenu to entry context menu #13280
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
9687367
38a72ce
56cb497
e07c314
578c2bb
63f0037
31383f4
ca0b2fe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,12 @@ public enum StandardActions implements Action { | |
COPY_CITATION_HTML(Localization.lang("Copy citation (html)"), KeyBinding.COPY_PREVIEW), | ||
COPY_CITATION_TEXT(Localization.lang("Copy citation (text)")), | ||
COPY_CITATION_PREVIEW(Localization.lang("Copy preview"), KeyBinding.COPY_PREVIEW), | ||
COPY_FIELD_CONTENT(Localization.lang("Copy field content")), | ||
COPY_FIELD_AUTHOR(Localization.lang("author")), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The label 'author' should be in sentence case, but it is already in lowercase. Ensure consistency with other labels which are in sentence case. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this ever displayed, the screenshots don't contain lower cased. |
||
COPY_FIELD_JOURNAL(Localization.lang("journal")), | ||
COPY_FIELD_DATE(Localization.lang("date")), | ||
COPY_FIELD_KEYWORDS(Localization.lang("keywords")), | ||
COPY_FIELD_ABSTRACT(Localization.lang("abstract")), | ||
EXPORT_TO_CLIPBOARD(Localization.lang("Export to clipboard"), IconTheme.JabRefIcons.EXPORT_TO_CLIPBOARD), | ||
EXPORT_SELECTED_TO_CLIPBOARD(Localization.lang("Export selected entries to clipboard"), IconTheme.JabRefIcons.EXPORT_TO_CLIPBOARD), | ||
COPY(Localization.lang("Copy"), IconTheme.JabRefIcons.COPY, KeyBinding.COPY), | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -72,6 +72,16 @@ public void execute() { | |
copyKeyAndLink(); | ||
case COPY_DOI, COPY_DOI_URL -> | ||
copyDoi(); | ||
case COPY_FIELD_AUTHOR -> | ||
copyField(StandardField.AUTHOR, Localization.lang("authors")); | ||
case COPY_FIELD_JOURNAL -> | ||
copyJournalField(); | ||
case COPY_FIELD_DATE -> | ||
copyField(StandardField.DATE, Localization.lang("dates")); | ||
case COPY_FIELD_KEYWORDS -> | ||
copyField(StandardField.KEYWORDS, Localization.lang("keywords")); | ||
case COPY_FIELD_ABSTRACT -> | ||
copyField(StandardField.ABSTRACT, Localization.lang("abstracts")); | ||
default -> | ||
LOGGER.info("Unknown copy command."); | ||
} | ||
|
@@ -264,4 +274,70 @@ private void copyKeyAndLink() { | |
Long.toString(entries.size() - entriesWithKey.size()), Integer.toString(entries.size()))); | ||
} | ||
} | ||
|
||
private void copyField(StandardField field, String fieldDisplayName) { | ||
List<BibEntry> selectedBibEntries = stateManager.getSelectedEntries(); | ||
|
||
List<String> fieldValues = selectedBibEntries.stream() | ||
.filter(bibEntry -> bibEntry.getField(field).isPresent()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You need to du Did you check for date handling? You know, there is |
||
.map(bibEntry -> bibEntry.getField(field).orElse("")) | ||
.filter(value -> !value.isEmpty()) | ||
.collect(Collectors.toList()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use |
||
|
||
if (fieldValues.isEmpty()) { | ||
dialogService.notify(Localization.lang("None of the selected entries have %0.", fieldDisplayName)); | ||
return; | ||
} | ||
|
||
final String copiedContent = String.join("\n", fieldValues); | ||
clipBoardManager.setContent(copiedContent); | ||
|
||
if (fieldValues.size() == selectedBibEntries.size()) { | ||
// All entries had the field. | ||
dialogService.notify(Localization.lang("Copied '%0' to clipboard.", | ||
JabRefDialogService.shortenDialogMessage(copiedContent))); | ||
} else { | ||
dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined %2.", | ||
Integer.toString(selectedBibEntries.size() - fieldValues.size()), | ||
Integer.toString(selectedBibEntries.size()), | ||
fieldDisplayName)); | ||
} | ||
} | ||
|
||
private void copyJournalField() { | ||
List<BibEntry> selectedBibEntries = stateManager.getSelectedEntries(); | ||
|
||
List<String> journalValues = selectedBibEntries.stream() | ||
.filter(bibEntry -> | ||
bibEntry.getField(StandardField.JOURNAL).isPresent() || | ||
bibEntry.getField(StandardField.JOURNALTITLE).isPresent()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use |
||
.map(bibEntry -> { | ||
// Prefer journal over journaltitle for consistency | ||
if (bibEntry.getField(StandardField.JOURNAL).isPresent()) { | ||
return bibEntry.getField(StandardField.JOURNAL).orElse(""); | ||
} else { | ||
return bibEntry.getField(StandardField.JOURNALTITLE).orElse(""); | ||
} | ||
}) | ||
.filter(value -> !value.isEmpty()) | ||
.collect(Collectors.toList()); | ||
|
||
if (journalValues.isEmpty()) { | ||
dialogService.notify(Localization.lang("None of the selected entries have journal names.")); | ||
return; | ||
} | ||
|
||
final String copiedContent = String.join("\n", journalValues); | ||
clipBoardManager.setContent(copiedContent); | ||
|
||
if (journalValues.size() == selectedBibEntries.size()) { | ||
// All entries had journal fields. | ||
dialogService.notify(Localization.lang("Copied '%0' to clipboard.", | ||
JabRefDialogService.shortenDialogMessage(copiedContent))); | ||
} else { | ||
dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined journal names.", | ||
Integer.toString(selectedBibEntries.size() - journalValues.size()), | ||
Integer.toString(selectedBibEntries.size()))); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -178,6 +178,8 @@ private static Menu createCopySubMenu(ActionFactory factory, | |
|
||
copySpecialMenu.getItems().addAll( | ||
factory.createMenuItem(StandardActions.COPY_TITLE, new CopyMoreAction(StandardActions.COPY_TITLE, dialogService, stateManager, clipBoardManager, preferences, abbreviationRepository)), | ||
createCopyFieldContentSubMenu(factory, dialogService, stateManager, clipBoardManager, preferences, abbreviationRepository), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The method createCopyFieldContentSubMenu is added but lacks any null checks or use of Optional for its parameters, which could lead to NullPointerExceptions if any parameter is null. |
||
new SeparatorMenuItem(), | ||
factory.createMenuItem(StandardActions.COPY_KEY, new CopyMoreAction(StandardActions.COPY_KEY, dialogService, stateManager, clipBoardManager, preferences, abbreviationRepository)), | ||
factory.createMenuItem(StandardActions.COPY_CITE_KEY, new CopyMoreAction(StandardActions.COPY_CITE_KEY, dialogService, stateManager, clipBoardManager, preferences, abbreviationRepository)), | ||
factory.createMenuItem(StandardActions.COPY_KEY_AND_TITLE, new CopyMoreAction(StandardActions.COPY_KEY_AND_TITLE, dialogService, stateManager, clipBoardManager, preferences, abbreviationRepository)), | ||
|
@@ -204,6 +206,30 @@ private static Menu createCopySubMenu(ActionFactory factory, | |
return copySpecialMenu; | ||
} | ||
|
||
private static Menu createCopyFieldContentSubMenu(ActionFactory factory, | ||
DialogService dialogService, | ||
StateManager stateManager, | ||
ClipBoardManager clipBoardManager, | ||
GuiPreferences preferences, | ||
JournalAbbreviationRepository abbreviationRepository) { | ||
Menu copyFieldContentMenu = factory.createMenu(StandardActions.COPY_FIELD_CONTENT); | ||
|
||
// Ensure we never return null | ||
if (copyFieldContentMenu == null) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using exceptions for normal control flow is not recommended. Instead of checking for null and throwing an exception, ensure that the method creating the menu never returns null. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is this? Just remove the whole if block. |
||
throw new IllegalStateException("Failed to create Copy Field Content menu"); | ||
} | ||
|
||
copyFieldContentMenu.getItems().addAll( | ||
factory.createMenuItem(StandardActions.COPY_FIELD_AUTHOR, new CopyMoreAction(StandardActions.COPY_FIELD_AUTHOR, dialogService, stateManager, clipBoardManager, preferences, abbreviationRepository)), | ||
factory.createMenuItem(StandardActions.COPY_FIELD_JOURNAL, new CopyMoreAction(StandardActions.COPY_FIELD_JOURNAL, dialogService, stateManager, clipBoardManager, preferences, abbreviationRepository)), | ||
factory.createMenuItem(StandardActions.COPY_FIELD_DATE, new CopyMoreAction(StandardActions.COPY_FIELD_DATE, dialogService, stateManager, clipBoardManager, preferences, abbreviationRepository)), | ||
factory.createMenuItem(StandardActions.COPY_FIELD_KEYWORDS, new CopyMoreAction(StandardActions.COPY_FIELD_KEYWORDS, dialogService, stateManager, clipBoardManager, preferences, abbreviationRepository)), | ||
factory.createMenuItem(StandardActions.COPY_FIELD_ABSTRACT, new CopyMoreAction(StandardActions.COPY_FIELD_ABSTRACT, dialogService, stateManager, clipBoardManager, preferences, abbreviationRepository)) | ||
); | ||
|
||
return copyFieldContentMenu; | ||
} | ||
|
||
private static Menu createSendSubMenu(ActionFactory factory, | ||
DialogService dialogService, | ||
StateManager stateManager, | ||
|
Uh oh!
There was an error while loading. Please reload this page.