diff --git a/CHANGELOG.md b/CHANGELOG.md index c24c3ff848e..a7d501653c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We added support for selecting and using CSL Styles in JabRef's OpenOffice/LibreOffice integration for inserting bibliographic and in-text citations into a document. [#2146](https://github.com/JabRef/jabref/issues/2146), [#8893](https://github.com/JabRef/jabref/issues/8893) - We added Tools > New library based on references in PDF file... to create a new library based on the references section in a PDF file. [#11522](https://github.com/JabRef/jabref/pull/11522) - When converting the references section of a paper (PDF file), more than the last page is treated. [#11522](https://github.com/JabRef/jabref/pull/11522) +- Added the functionality to invoke offline reference parsing explicitly. [#11565](https://github.com/JabRef/jabref/pull/11565) +- The dialog for [adding an entry using reference text](https://docs.jabref.org/collect/newentryfromplaintext) is now filled with the clipboard contents as default. [#11565](https://github.com/JabRef/jabref/pull/11565) - Added minimal support for [biblatex data annotation](https://mirrors.ctan.org/macros/latex/contrib/biblatex/doc/biblatex.pdf#subsection.3.7) fields in `.layout` files. [#11505](https://github.com/JabRef/jabref/issues/11505) - Added saving of selected options in the [Lookup -> Search for unlinked local files dialog](https://docs.jabref.org/collect/findunlinkedfiles#link-the-pdfs-to-your-bib-library). [#11439](https://github.com/JabRef/jabref/issues/11439) @@ -29,6 +31,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We fixed an issue where the "Check for updates" preference was not saved. [#11485](https://github.com/JabRef/jabref/pull/11485) - We fixed an issue where an exception was thrown after changing "show preview as a tab" in the preferences. [#11515](https://github.com/JabRef/jabref/pull/11515) +- We fixed an issue that online and offline mode for new library creation were handled incorrectly. [#11565](https://github.com/JabRef/jabref/pull/11565) - We fixed an issue with colors in the search bar when dark theme is enabled. [#11569](https://github.com/JabRef/jabref/issues/11569) - We fixed an issue where a new unsaved library was not marked with an asterisk. [#11519](https://github.com/JabRef/jabref/pull/11519) - We fixed an issue where JabRef starts without window decorations. [#11440](https://github.com/JabRef/jabref/pull/11440) diff --git a/src/main/java/org/jabref/gui/actions/ActionFactory.java b/src/main/java/org/jabref/gui/actions/ActionFactory.java index 22f29628fff..74f1b25e740 100644 --- a/src/main/java/org/jabref/gui/actions/ActionFactory.java +++ b/src/main/java/org/jabref/gui/actions/ActionFactory.java @@ -146,7 +146,9 @@ public Button createIconButton(Action action, Command command) { button.graphicProperty().unbind(); action.getIcon().ifPresent(icon -> button.setGraphic(icon.getGraphicNode())); - button.setFocusTraversable(false); // Prevent the buttons from stealing the focus + // Prevent the buttons from stealing the focus + button.setFocusTraversable(false); + return button; } diff --git a/src/main/java/org/jabref/gui/actions/StandardActions.java b/src/main/java/org/jabref/gui/actions/StandardActions.java index 5c247a32147..1ec41a584f8 100644 --- a/src/main/java/org/jabref/gui/actions/StandardActions.java +++ b/src/main/java/org/jabref/gui/actions/StandardActions.java @@ -93,7 +93,7 @@ public enum StandardActions implements Action { PARSE_LATEX(Localization.lang("Search for citations in LaTeX files..."), IconTheme.JabRefIcons.LATEX_CITATIONS), NEW_SUB_LIBRARY_FROM_AUX(Localization.lang("New sublibrary based on AUX file") + "...", Localization.lang("New BibTeX sublibrary") + Localization.lang("This feature generates a new library based on which entries are needed in an existing LaTeX document."), IconTheme.JabRefIcons.NEW), - NEW_LIBRARY_FROM_PDF_ONLINE(Localization.lang("New library based on references in PDF file... (online)"), Localization.lang("This feature generates a new library based on the list of references in a PDF file. Thereby, it uses GROBID's functionality."), IconTheme.JabRefIcons.NEW), + NEW_LIBRARY_FROM_PDF_ONLINE(Localization.lang("New library based on references in PDF file... (online)"), Localization.lang("This feature generates a new library based on the list of references in a PDF file. Thereby, it uses Grobid's functionality."), IconTheme.JabRefIcons.NEW), NEW_LIBRARY_FROM_PDF_OFFLINE(Localization.lang("New library based on references in PDF file... (offline)"), Localization.lang("This feature generates a new library based on the list of references in a PDF file. Thereby, it uses JabRef's built-in functionality."), IconTheme.JabRefIcons.NEW), WRITE_METADATA_TO_PDF(Localization.lang("Write metadata to PDF files"), Localization.lang("Will write metadata to the PDFs linked from selected entries."), KeyBinding.WRITE_METADATA_TO_PDF), @@ -135,7 +135,9 @@ public enum StandardActions implements Action { NEW_ENTRY(Localization.lang("New entry"), IconTheme.JabRefIcons.ADD_ENTRY, KeyBinding.NEW_ENTRY), NEW_ARTICLE(Localization.lang("New article"), IconTheme.JabRefIcons.ADD_ARTICLE), - NEW_ENTRY_FROM_PLAIN_TEXT(Localization.lang("New entry from plain text"), IconTheme.JabRefIcons.NEW_ENTRY_FROM_PLAIN_TEXT, KeyBinding.NEW_ENTRY_FROM_PLAIN_TEXT), + NEW_ENTRY_FROM_PLAIN_TEXT(Localization.lang("New entry from plain text"), IconTheme.JabRefIcons.NEW_ENTRY_FROM_PLAIN_TEXT), + NEW_ENTRY_FROM_PLAIN_TEXT_ONLINE(Localization.lang("New entry from plain text (online)"), IconTheme.JabRefIcons.NEW_ENTRY_FROM_PLAIN_TEXT, KeyBinding.NEW_ENTRY_FROM_PLAIN_TEXT_ONLINE), + NEW_ENTRY_FROM_PLAIN_TEXT_OFFLINE(Localization.lang("New entry from plain text (offline)"), IconTheme.JabRefIcons.NEW_ENTRY_FROM_PLAIN_TEXT), LIBRARY_PROPERTIES(Localization.lang("Library properties")), FIND_DUPLICATES(Localization.lang("Find duplicates"), IconTheme.JabRefIcons.FIND_DUPLICATES), MERGE_ENTRIES(Localization.lang("Merge entries"), IconTheme.JabRefIcons.MERGE_ENTRIES, KeyBinding.MERGE_ENTRIES), diff --git a/src/main/java/org/jabref/gui/bibtexextractor/BibtexExtractorViewModel.java b/src/main/java/org/jabref/gui/bibtexextractor/BibtexExtractorViewModel.java index 333c7dd0cb0..bd65490779a 100644 --- a/src/main/java/org/jabref/gui/bibtexextractor/BibtexExtractorViewModel.java +++ b/src/main/java/org/jabref/gui/bibtexextractor/BibtexExtractorViewModel.java @@ -1,8 +1,6 @@ package org.jabref.gui.bibtexextractor; -import java.util.HashMap; import java.util.List; -import java.util.Map; import javax.swing.undo.UndoManager; @@ -25,24 +23,33 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * View model for the feature "Extract BibTeX from plain text". + * Handles both online and offline case. + * + * @implNote Instead of using inheritance, we do if/else checks. + */ public class BibtexExtractorViewModel { private static final Logger LOGGER = LoggerFactory.getLogger(BibtexExtractorViewModel.class); - private final StringProperty inputTextProperty = new SimpleStringProperty(""); + private final boolean onlineMode; private final DialogService dialogService; private final PreferencesService preferencesService; private final TaskExecutor taskExecutor; - private final ImportHandler importHandler; - public BibtexExtractorViewModel(BibDatabaseContext bibdatabaseContext, - DialogService dialogService, - PreferencesService preferencesService, - FileUpdateMonitor fileUpdateMonitor, - TaskExecutor taskExecutor, - UndoManager undoManager, - StateManager stateManager) { + private final ImportHandler importHandler; + private final StringProperty inputTextProperty = new SimpleStringProperty(""); + public BibtexExtractorViewModel(boolean onlineMode, + BibDatabaseContext bibdatabaseContext, + DialogService dialogService, + PreferencesService preferencesService, + FileUpdateMonitor fileUpdateMonitor, + TaskExecutor taskExecutor, + UndoManager undoManager, + StateManager stateManager) { + this.onlineMode = onlineMode; this.dialogService = dialogService; this.preferencesService = preferencesService; this.taskExecutor = taskExecutor; @@ -56,25 +63,20 @@ public BibtexExtractorViewModel(BibDatabaseContext bibdatabaseContext, taskExecutor); } - public StringProperty inputTextProperty() { - return this.inputTextProperty; - } - public void startParsing() { - if (preferencesService.getGrobidPreferences().isGrobidEnabled()) { - parseUsingGrobid(); + if (onlineMode) { + startParsingOnline(); } else { - parseUsingBibtexExtractor(); + startParsingOffline(); } } - private void parseUsingBibtexExtractor() { + private void startParsingOffline() { BibEntry parsedEntry = new BibtexExtractor().extract(inputTextProperty.getValue()); importHandler.importEntries(List.of(parsedEntry)); - trackNewEntry(parsedEntry, "ParseWithBibTeXExtractor"); } - private void parseUsingGrobid() { + private void startParsingOnline() { GrobidCitationFetcher grobidCitationFetcher = new GrobidCitationFetcher(preferencesService.getGrobidPreferences(), preferencesService.getImportFormatPreferences()); BackgroundTask.wrap(() -> grobidCitationFetcher.performSearch(inputTextProperty.getValue())) .onRunning(() -> dialogService.notify(Localization.lang("Your text is being parsed..."))) @@ -90,14 +92,10 @@ private void parseUsingGrobid() { .onSuccess(parsedEntries -> { dialogService.notify(Localization.lang("%0 entries were parsed from your query.", String.valueOf(parsedEntries.size()))); importHandler.importEntries(parsedEntries); - for (BibEntry bibEntry : parsedEntries) { - trackNewEntry(bibEntry, "ParseWithGrobid"); - } }).executeWith(taskExecutor); } - private void trackNewEntry(BibEntry bibEntry, String eventMessage) { - Map properties = new HashMap<>(); - properties.put("EntryType", bibEntry.typeProperty().getValue().getName()); + public StringProperty inputTextProperty() { + return this.inputTextProperty; } } diff --git a/src/main/java/org/jabref/gui/bibtexextractor/ExtractBibtexAction.java b/src/main/java/org/jabref/gui/bibtexextractor/ExtractBibtexAction.java deleted file mode 100644 index 70c693a5fe9..00000000000 --- a/src/main/java/org/jabref/gui/bibtexextractor/ExtractBibtexAction.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.jabref.gui.bibtexextractor; - -import org.jabref.gui.DialogService; -import org.jabref.gui.StateManager; -import org.jabref.gui.actions.SimpleCommand; -import org.jabref.gui.importer.GrobidOptInDialogHelper; -import org.jabref.preferences.PreferencesService; - -import com.airhacks.afterburner.injection.Injector; - -import static org.jabref.gui.actions.ActionHelper.needsDatabase; - -public class ExtractBibtexAction extends SimpleCommand { - - PreferencesService preferencesService; - DialogService dialogService; - - public ExtractBibtexAction(DialogService dialogService, PreferencesService preferencesService, StateManager stateManager) { - this.preferencesService = preferencesService; - this.dialogService = dialogService; - this.executable.bind(needsDatabase(stateManager)); - } - - @Override - public void execute() { - DialogService dialogService = Injector.instantiateModelOrService(DialogService.class); - GrobidOptInDialogHelper.showAndWaitIfUserIsUndecided(dialogService, preferencesService.getGrobidPreferences()); - dialogService.showCustomDialogAndWait(new ExtractBibtexDialog()); - } -} diff --git a/src/main/java/org/jabref/gui/bibtexextractor/ExtractBibtexActionOffline.java b/src/main/java/org/jabref/gui/bibtexextractor/ExtractBibtexActionOffline.java new file mode 100644 index 00000000000..ddd1eba3dda --- /dev/null +++ b/src/main/java/org/jabref/gui/bibtexextractor/ExtractBibtexActionOffline.java @@ -0,0 +1,22 @@ +package org.jabref.gui.bibtexextractor; + +import org.jabref.gui.DialogService; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.SimpleCommand; + +import static org.jabref.gui.actions.ActionHelper.needsDatabase; + +public class ExtractBibtexActionOffline extends SimpleCommand { + + private final DialogService dialogService; + + public ExtractBibtexActionOffline(DialogService dialogService, StateManager stateManager) { + this.dialogService = dialogService; + this.executable.bind(needsDatabase(stateManager)); + } + + @Override + public void execute() { + dialogService.showCustomDialogAndWait(new ExtractBibtexDialog(false)); + } +} diff --git a/src/main/java/org/jabref/gui/bibtexextractor/ExtractBibtexActionOnline.java b/src/main/java/org/jabref/gui/bibtexextractor/ExtractBibtexActionOnline.java new file mode 100644 index 00000000000..fae2e4219b4 --- /dev/null +++ b/src/main/java/org/jabref/gui/bibtexextractor/ExtractBibtexActionOnline.java @@ -0,0 +1,37 @@ +package org.jabref.gui.bibtexextractor; + +import javafx.beans.binding.Bindings; + +import org.jabref.gui.DialogService; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.SimpleCommand; +import org.jabref.gui.importer.GrobidOptInDialogHelper; +import org.jabref.preferences.PreferencesService; + +import static org.jabref.gui.actions.ActionHelper.needsDatabase; + +public class ExtractBibtexActionOnline extends SimpleCommand { + + private final PreferencesService preferencesService; + private final DialogService dialogService; + + public ExtractBibtexActionOnline(DialogService dialogService, PreferencesService preferencesService, StateManager stateManager, boolean requiresGrobid) { + this.preferencesService = preferencesService; + this.dialogService = dialogService; + if (requiresGrobid) { + this.executable.bind( + Bindings.and( + preferencesService.getGrobidPreferences().grobidEnabledProperty(), + needsDatabase(stateManager) + )); + } else { + this.executable.bind(needsDatabase(stateManager)); + } + } + + @Override + public void execute() { + boolean useGrobid = GrobidOptInDialogHelper.showAndWaitIfUserIsUndecided(dialogService, preferencesService.getGrobidPreferences()); + dialogService.showCustomDialogAndWait(new ExtractBibtexDialog(useGrobid)); + } +} diff --git a/src/main/java/org/jabref/gui/bibtexextractor/ExtractBibtexDialog.java b/src/main/java/org/jabref/gui/bibtexextractor/ExtractBibtexDialog.java index c3d8638608f..e5bac90244a 100644 --- a/src/main/java/org/jabref/gui/bibtexextractor/ExtractBibtexDialog.java +++ b/src/main/java/org/jabref/gui/bibtexextractor/ExtractBibtexDialog.java @@ -2,18 +2,21 @@ import javax.swing.undo.UndoManager; +import javafx.application.Platform; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.ButtonType; import javafx.scene.control.TextArea; import javafx.scene.control.Tooltip; +import org.jabref.gui.ClipBoardManager; import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; import org.jabref.gui.util.BaseDialog; import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.l10n.Localization; import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.strings.StringUtil; import org.jabref.model.util.FileUpdateMonitor; import org.jabref.preferences.PreferencesService; @@ -22,38 +25,42 @@ /** * GUI Dialog for the feature "Extract BibTeX from plain text". + * Handles both online and offline case. + * + * @implNote Instead of using inheritance, we do if/else checks. + * */ public class ExtractBibtexDialog extends BaseDialog { - private final Button buttonParse; - @FXML private TextArea input; + @Inject protected StateManager stateManager; + @Inject protected DialogService dialogService; + @Inject protected FileUpdateMonitor fileUpdateMonitor; + @Inject protected TaskExecutor taskExecutor; + @Inject protected UndoManager undoManager; + @Inject protected PreferencesService preferencesService; + + @FXML protected TextArea input; + private final boolean onlineMode; + @FXML private ButtonType parseButtonType; - private BibtexExtractorViewModel viewModel; - @Inject private StateManager stateManager; - @Inject private DialogService dialogService; - @Inject private FileUpdateMonitor fileUpdateMonitor; - @Inject private TaskExecutor taskExecutor; - @Inject private UndoManager undoManager; - @Inject private PreferencesService preferencesService; - public ExtractBibtexDialog() { + public ExtractBibtexDialog(boolean onlineMode) { + this.onlineMode = onlineMode; ViewLoader.view(this) .load() .setAsDialogPane(this); - this.setTitle(Localization.lang("Plain References Parser")); - input.setPromptText(Localization.lang("Please enter the plain references to extract from separated by double empty lines.")); - input.selectAll(); - - buttonParse = (Button) getDialogPane().lookupButton(parseButtonType); - buttonParse.setTooltip(new Tooltip((Localization.lang("Starts the extraction and adds the resulting entries to the currently opened database")))); - buttonParse.setOnAction(event -> viewModel.startParsing()); - buttonParse.disableProperty().bind(viewModel.inputTextProperty().isEmpty()); + if (onlineMode) { + this.setTitle(Localization.lang("Plain References Parser (online)")); + } else { + this.setTitle(Localization.lang("Plain References Parser (offline)")); + } } @FXML private void initialize() { BibDatabaseContext database = stateManager.getActiveDatabase().orElseThrow(() -> new NullPointerException("Database null")); - this.viewModel = new BibtexExtractorViewModel( + BibtexExtractorViewModel viewModel = new BibtexExtractorViewModel( + onlineMode, database, dialogService, preferencesService, @@ -61,6 +68,22 @@ private void initialize() { taskExecutor, undoManager, stateManager); + input.textProperty().bindBidirectional(viewModel.inputTextProperty()); + String clipText = ClipBoardManager.getContents(); + if (StringUtil.isBlank(clipText)) { + input.setPromptText(Localization.lang("Please enter the plain references to extract from separated by double empty lines.")); + } else { + input.setText(clipText); + input.selectAll(); + } + + Platform.runLater(() -> { + input.requestFocus(); + Button buttonParse = (Button) getDialogPane().lookupButton(parseButtonType); + buttonParse.setTooltip(new Tooltip((Localization.lang("Starts the extraction and adds the resulting entries to the currently opened database")))); + buttonParse.setOnAction(event -> viewModel.startParsing()); + buttonParse.disableProperty().bind(viewModel.inputTextProperty().isEmpty()); + }); } } diff --git a/src/main/java/org/jabref/gui/frame/MainMenu.java b/src/main/java/org/jabref/gui/frame/MainMenu.java index a7b7aab0e6a..380ff6d27e9 100644 --- a/src/main/java/org/jabref/gui/frame/MainMenu.java +++ b/src/main/java/org/jabref/gui/frame/MainMenu.java @@ -16,7 +16,8 @@ import org.jabref.gui.actions.ActionFactory; import org.jabref.gui.actions.StandardActions; import org.jabref.gui.auximport.NewSubLibraryAction; -import org.jabref.gui.bibtexextractor.ExtractBibtexAction; +import org.jabref.gui.bibtexextractor.ExtractBibtexActionOffline; +import org.jabref.gui.bibtexextractor.ExtractBibtexActionOnline; import org.jabref.gui.citationkeypattern.GenerateCitationKeyAction; import org.jabref.gui.cleanup.CleanupAction; import org.jabref.gui.copyfiles.CopyFilesAction; @@ -51,7 +52,8 @@ import org.jabref.gui.journals.AbbreviateAction; import org.jabref.gui.libraryproperties.LibraryPropertiesAction; import org.jabref.gui.linkedfile.RedownloadMissingFilesAction; -import org.jabref.gui.maintable.NewLibraryFromPdfAction; +import org.jabref.gui.maintable.NewLibraryFromPdfActionOffline; +import org.jabref.gui.maintable.NewLibraryFromPdfActionOnline; import org.jabref.gui.mergeentries.MergeEntriesAction; import org.jabref.gui.preferences.ShowPreferencesAction; import org.jabref.gui.preview.CopyCitationAction; @@ -81,8 +83,6 @@ import org.jabref.model.util.FileUpdateMonitor; import org.jabref.preferences.PreferencesService; -import com.tobiasdiez.easybind.EasyBind; - public class MainMenu extends MenuBar { private final JabRefFrame frame; private final FileHistoryMenu fileHistoryMenu; @@ -227,10 +227,11 @@ private void createMenu() { } }); - // @formatter:off + MenuItem newEntryFromPlainTextOnline = factory.createMenuItem(StandardActions.NEW_ENTRY_FROM_PLAIN_TEXT_ONLINE, new ExtractBibtexActionOnline(dialogService, preferencesService, stateManager, true)); library.getItems().addAll( factory.createMenuItem(StandardActions.NEW_ENTRY, new NewEntryAction(frame::getCurrentLibraryTab, dialogService, preferencesService, stateManager)), - factory.createMenuItem(StandardActions.NEW_ENTRY_FROM_PLAIN_TEXT, new ExtractBibtexAction(dialogService, preferencesService, stateManager)), + newEntryFromPlainTextOnline, + factory.createMenuItem(StandardActions.NEW_ENTRY_FROM_PLAIN_TEXT_OFFLINE, new ExtractBibtexActionOffline(dialogService, stateManager)), factory.createMenuItem(StandardActions.DELETE_ENTRY, new EditAction(StandardActions.DELETE_ENTRY, frame::getCurrentLibraryTab, stateManager, undoManager)), new SeparatorMenuItem(), @@ -276,17 +277,11 @@ private void createMenu() { final MenuItem pushToApplicationMenuItem = factory.createMenuItem(pushToApplicationCommand.getAction(), pushToApplicationCommand); pushToApplicationCommand.registerReconfigurable(pushToApplicationMenuItem); - NewLibraryFromPdfAction newLibraryFromPdfAction = new NewLibraryFromPdfAction(frame, stateManager, dialogService, preferencesService, taskExecutor); - // Action used twice, because it distinguishes internally between online and offline - // We want the UI to show "online" and "offline" explicitly - MenuItem newLibraryFromPdfMenuItemOnline = factory.createMenuItem(StandardActions.NEW_LIBRARY_FROM_PDF_ONLINE, newLibraryFromPdfAction); - MenuItem newLibraryFromPdfMenuItemOffline = factory.createMenuItem(StandardActions.NEW_LIBRARY_FROM_PDF_OFFLINE, newLibraryFromPdfAction); - tools.getItems().addAll( factory.createMenuItem(StandardActions.PARSE_LATEX, new ParseLatexAction(stateManager)), factory.createMenuItem(StandardActions.NEW_SUB_LIBRARY_FROM_AUX, new NewSubLibraryAction(frame, stateManager, dialogService)), - newLibraryFromPdfMenuItemOnline, - newLibraryFromPdfMenuItemOffline, + factory.createMenuItem(StandardActions.NEW_LIBRARY_FROM_PDF_ONLINE, new NewLibraryFromPdfActionOnline(frame, stateManager, dialogService, preferencesService, taskExecutor)), + factory.createMenuItem(StandardActions.NEW_LIBRARY_FROM_PDF_OFFLINE, new NewLibraryFromPdfActionOffline(frame, stateManager, dialogService, preferencesService, taskExecutor)), new SeparatorMenuItem(), @@ -315,8 +310,6 @@ private void createMenu() { factory.createMenuItem(StandardActions.REDOWNLOAD_MISSING_FILES, new RedownloadMissingFilesAction(stateManager, dialogService, preferencesService.getFilePreferences(), taskExecutor)) ); - EasyBind.subscribe(preferencesService.getGrobidPreferences().grobidEnabledProperty(), newLibraryFromPdfMenuItemOnline::setVisible); - SidePaneType webSearchPane = SidePaneType.WEB_SEARCH; SidePaneType groupsPane = SidePaneType.GROUPS; SidePaneType openOfficePane = SidePaneType.OPEN_OFFICE; diff --git a/src/main/java/org/jabref/gui/frame/MainToolBar.java b/src/main/java/org/jabref/gui/frame/MainToolBar.java index 1bd99a42342..25e42ff908b 100644 --- a/src/main/java/org/jabref/gui/frame/MainToolBar.java +++ b/src/main/java/org/jabref/gui/frame/MainToolBar.java @@ -20,7 +20,7 @@ import org.jabref.gui.actions.ActionFactory; import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.StandardActions; -import org.jabref.gui.bibtexextractor.ExtractBibtexAction; +import org.jabref.gui.bibtexextractor.ExtractBibtexActionOnline; import org.jabref.gui.citationkeypattern.GenerateCitationKeyAction; import org.jabref.gui.cleanup.CleanupAction; import org.jabref.gui.edit.EditAction; @@ -103,6 +103,10 @@ private void createToolBar() { // Setup Toolbar + // The action itself asks the user if it is OK to use Grobid (in some cases). + // Therefore, the condition of enablement is "only" if a library is opened. (Parameter "false") + Button newEntryFromPlainTextOnlineButton = factory.createIconButton(StandardActions.NEW_ENTRY_FROM_PLAIN_TEXT, new ExtractBibtexActionOnline(dialogService, preferencesService, stateManager, false)); + getItems().addAll( new HBox( factory.createIconButton(StandardActions.NEW_LIBRARY, new NewDatabaseAction(frame, preferencesService)), @@ -119,7 +123,7 @@ private void createToolBar() { factory.createIconButton(StandardActions.NEW_ARTICLE, new NewEntryAction(frame::getCurrentLibraryTab, StandardEntryType.Article, dialogService, preferencesService, stateManager)), factory.createIconButton(StandardActions.NEW_ENTRY, new NewEntryAction(frame::getCurrentLibraryTab, dialogService, preferencesService, stateManager)), createNewEntryFromIdButton(), - factory.createIconButton(StandardActions.NEW_ENTRY_FROM_PLAIN_TEXT, new ExtractBibtexAction(dialogService, preferencesService, stateManager)), + newEntryFromPlainTextOnlineButton, factory.createIconButton(StandardActions.DELETE_ENTRY, new EditAction(StandardActions.DELETE_ENTRY, frame::getCurrentLibraryTab, stateManager, undoManager))), new Separator(Orientation.VERTICAL), diff --git a/src/main/java/org/jabref/gui/keyboard/KeyBinding.java b/src/main/java/org/jabref/gui/keyboard/KeyBinding.java index 07ac871d22a..40bbc0ca7e0 100644 --- a/src/main/java/org/jabref/gui/keyboard/KeyBinding.java +++ b/src/main/java/org/jabref/gui/keyboard/KeyBinding.java @@ -71,7 +71,7 @@ public enum KeyBinding { NEW_ARTICLE("New article", Localization.lang("New article"), "ctrl+shift+A", KeyBindingCategory.BIBTEX), NEW_BOOK("New book", Localization.lang("New book"), "ctrl+shift+B", KeyBindingCategory.BIBTEX), NEW_ENTRY("New entry", Localization.lang("New entry"), "ctrl+N", KeyBindingCategory.BIBTEX), - NEW_ENTRY_FROM_PLAIN_TEXT("New entry from plain text", Localization.lang("New entry from plain text"), "ctrl+shift+N", KeyBindingCategory.BIBTEX), + NEW_ENTRY_FROM_PLAIN_TEXT_ONLINE("New entry from plain text", Localization.lang("New entry from plain text (online)"), "ctrl+shift+N", KeyBindingCategory.BIBTEX), NEW_INBOOK("New inbook", Localization.lang("New inbook"), "ctrl+shift+I", KeyBindingCategory.BIBTEX), NEW_MASTERSTHESIS("New mastersthesis", Localization.lang("New mastersthesis"), "ctrl+shift+M", KeyBindingCategory.BIBTEX), NEW_PHDTHESIS("New phdthesis", Localization.lang("New phdthesis"), "ctrl+shift+T", KeyBindingCategory.BIBTEX), diff --git a/src/main/java/org/jabref/gui/maintable/NewLibraryFromPdfAction.java b/src/main/java/org/jabref/gui/maintable/NewLibraryFromPdfAction.java index 67d7c844d4a..dc872022ffc 100644 --- a/src/main/java/org/jabref/gui/maintable/NewLibraryFromPdfAction.java +++ b/src/main/java/org/jabref/gui/maintable/NewLibraryFromPdfAction.java @@ -11,8 +11,6 @@ import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.importer.ParserResult; -import org.jabref.logic.importer.fileformat.BibliographyFromPdfImporter; -import org.jabref.logic.importer.util.GrobidService; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.StandardFileType; import org.jabref.model.database.BibDatabaseContext; @@ -28,19 +26,15 @@ *
  • Mode choice A: online or offline
  • *
  • Mode choice B: complete entry or single file (the latter is not implemented)
  • * - *

    - * The mode is selected by the preferences whether to use Grobid or not. - *

    - * The different modes should be implemented as sub classes. Moreover, there are synergies with {@link ExtractReferencesAction}. However, this was too complicated. */ -public class NewLibraryFromPdfAction extends SimpleCommand { +public abstract class NewLibraryFromPdfAction extends SimpleCommand { private static final Logger LOGGER = LoggerFactory.getLogger(NewLibraryFromPdfAction .class); + protected final PreferencesService preferencesService; + private final LibraryTabContainer libraryTabContainer; private final StateManager stateManager; private final DialogService dialogService; - private final PreferencesService preferencesService; - private final BibliographyFromPdfImporter bibliographyFromPdfImporter; private final TaskExecutor taskExecutor; public NewLibraryFromPdfAction( @@ -53,8 +47,6 @@ public NewLibraryFromPdfAction( this.stateManager = stateManager; this.dialogService = dialogService; this.preferencesService = preferencesService; - // Instruct the importer to keep the numbers (instead of generating keys) - this.bibliographyFromPdfImporter = new BibliographyFromPdfImporter(); this.taskExecutor = taskExecutor; } @@ -84,15 +76,5 @@ public void execute() { }); } - private Callable getParserResultCallable(Path path) { - Callable parserResultCallable; - boolean online = this.preferencesService.getGrobidPreferences().isGrobidEnabled(); - if (online) { - parserResultCallable = () -> new ParserResult( - new GrobidService(this.preferencesService.getGrobidPreferences()).processReferences(path, preferencesService.getImportFormatPreferences())); - } else { - parserResultCallable = () -> bibliographyFromPdfImporter.importDatabase(path); - } - return parserResultCallable; - } + protected abstract Callable getParserResultCallable(Path path); } diff --git a/src/main/java/org/jabref/gui/maintable/NewLibraryFromPdfActionOffline.java b/src/main/java/org/jabref/gui/maintable/NewLibraryFromPdfActionOffline.java new file mode 100644 index 00000000000..610b677e208 --- /dev/null +++ b/src/main/java/org/jabref/gui/maintable/NewLibraryFromPdfActionOffline.java @@ -0,0 +1,29 @@ +package org.jabref.gui.maintable; + +import java.nio.file.Path; +import java.util.concurrent.Callable; + +import org.jabref.gui.DialogService; +import org.jabref.gui.LibraryTabContainer; +import org.jabref.gui.StateManager; +import org.jabref.gui.util.TaskExecutor; +import org.jabref.logic.importer.ParserResult; +import org.jabref.logic.importer.fileformat.BibliographyFromPdfImporter; +import org.jabref.preferences.PreferencesService; + +public class NewLibraryFromPdfActionOffline extends NewLibraryFromPdfAction { + + private final BibliographyFromPdfImporter bibliographyFromPdfImporter; + + public NewLibraryFromPdfActionOffline(LibraryTabContainer libraryTabContainer, StateManager stateManager, DialogService dialogService, PreferencesService preferencesService, TaskExecutor taskExecutor) { + super(libraryTabContainer, stateManager, dialogService, preferencesService, taskExecutor); + + // Use the importer keeping the numbers (instead of generating keys; which is the other constructor) + this.bibliographyFromPdfImporter = new BibliographyFromPdfImporter(); + } + + @Override + protected Callable getParserResultCallable(Path path) { + return () -> bibliographyFromPdfImporter.importDatabase(path); + } +} diff --git a/src/main/java/org/jabref/gui/maintable/NewLibraryFromPdfActionOnline.java b/src/main/java/org/jabref/gui/maintable/NewLibraryFromPdfActionOnline.java new file mode 100644 index 00000000000..b462edbbee6 --- /dev/null +++ b/src/main/java/org/jabref/gui/maintable/NewLibraryFromPdfActionOnline.java @@ -0,0 +1,25 @@ +package org.jabref.gui.maintable; + +import java.nio.file.Path; +import java.util.concurrent.Callable; + +import org.jabref.gui.DialogService; +import org.jabref.gui.LibraryTabContainer; +import org.jabref.gui.StateManager; +import org.jabref.gui.util.TaskExecutor; +import org.jabref.logic.importer.ParserResult; +import org.jabref.logic.importer.util.GrobidService; +import org.jabref.preferences.PreferencesService; + +public class NewLibraryFromPdfActionOnline extends NewLibraryFromPdfAction { + + public NewLibraryFromPdfActionOnline(LibraryTabContainer libraryTabContainer, StateManager stateManager, DialogService dialogService, PreferencesService preferencesService, TaskExecutor taskExecutor) { + super(libraryTabContainer, stateManager, dialogService, preferencesService, taskExecutor); + } + + @Override + protected Callable getParserResultCallable(Path path) { + return () -> new ParserResult( + new GrobidService(this.preferencesService.getGrobidPreferences()).processReferences(path, preferencesService.getImportFormatPreferences())); + } +} diff --git a/src/main/java/org/jabref/gui/preferences/keybindings/presets/NewEntryBindingPreset.java b/src/main/java/org/jabref/gui/preferences/keybindings/presets/NewEntryBindingPreset.java index c86f0647cc0..dc4993e67ab 100644 --- a/src/main/java/org/jabref/gui/preferences/keybindings/presets/NewEntryBindingPreset.java +++ b/src/main/java/org/jabref/gui/preferences/keybindings/presets/NewEntryBindingPreset.java @@ -25,7 +25,7 @@ public Map getKeyBindings() { keyBindings.put(KeyBinding.NEW_ARTICLE, "ctrl+shift+A"); keyBindings.put(KeyBinding.NEW_BOOK, "ctrl+shift+B"); keyBindings.put(KeyBinding.NEW_ENTRY, "ctrl+N"); - keyBindings.put(KeyBinding.NEW_ENTRY_FROM_PLAIN_TEXT, "ctrl+shift+N"); + keyBindings.put(KeyBinding.NEW_ENTRY_FROM_PLAIN_TEXT_ONLINE, "ctrl+shift+N"); keyBindings.put(KeyBinding.NEW_INBOOK, "ctrl+shift+I"); keyBindings.put(KeyBinding.NEW_INPROCEEDINGS, "ctrl+shift+C"); keyBindings.put(KeyBinding.NEW_MASTERSTHESIS, "ctrl+shift+M"); diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 74bb5fb8922..f1ec220d820 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -327,10 +327,10 @@ Export\ preferences\ to\ file=Export preferences to file Export\ to\ clipboard=Export to clipboard Export\ to\ text\ file.=Export to text file. -Extract\ references\ from\ file\ (online)=Extract references from file (online) Extract\ references\ from\ file\ (offline)=Extract references from file (offline) -Extract\ References\ (online)=Extract References (online) +Extract\ references\ from\ file\ (online)=Extract references from file (online) Extract\ References\ (offline)=Extract References (offline) +Extract\ References\ (online)=Extract References (online) Processing\ PDF(s)=Processing PDF(s) Processing\ a\ large\ number\ of\ files=Processing a large number of files You\ are\ about\ to\ process\ %0\ files.\ Continue?=You are about to process %0 files. Continue? @@ -894,7 +894,7 @@ found\ in\ AUX\ file=found in AUX file nested\ AUX\ files=nested AUX files New\ library\ based\ on\ references\ in\ PDF\ file...\ (offline)=New library based on references in PDF file... (offline) New\ library\ based\ on\ references\ in\ PDF\ file...\ (online)=New library based on references in PDF file... (online) -This\ feature\ generates\ a\ new\ library\ based\ on\ the\ list\ of\ references\ in\ a\ PDF\ file.\ Thereby,\ it\ uses\ GROBID's\ functionality.=This feature generates a new library based on the list of references in a PDF file. Thereby, it uses GROBID's functionality. +This\ feature\ generates\ a\ new\ library\ based\ on\ the\ list\ of\ references\ in\ a\ PDF\ file.\ Thereby,\ it\ uses\ Grobid's\ functionality.=This feature generates a new library based on the list of references in a PDF file. Thereby, it uses Grobid's functionality. This\ feature\ generates\ a\ new\ library\ based\ on\ the\ list\ of\ references\ in\ a\ PDF\ file.\ Thereby,\ it\ uses\ JabRef's\ built-in\ functionality.=This feature generates a new library based on the list of references in a PDF file. Thereby, it uses JabRef's built-in functionality. Sublibrary\ from\ AUX\ to\ BibTeX=Sublibrary from AUX to BibTeX New\ BibTeX\ sublibrary=New BibTeX sublibrary @@ -1941,6 +1941,8 @@ JabRef\ resources=JabRef resources Manage\ journal\ abbreviations=Manage journal abbreviations Manage\ protected\ terms=Manage protected terms New\ entry\ from\ plain\ text=New entry from plain text +New\ entry\ from\ plain\ text\ (offline)=New entry from plain text (offline) +New\ entry\ from\ plain\ text\ (online)=New entry from plain text (online) Import\ by\ ID=Import by ID Enter\ a\ valid\ ID=Enter a valid ID New\ sublibrary\ based\ on\ AUX\ file=New sublibrary based on AUX file @@ -2112,7 +2114,8 @@ Escape\ dollar\ sign=Escape dollar sign 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 +Plain\ References\ Parser\ (offline)=Plain References Parser (offline) +Plain\ References\ Parser\ (online)=Plain References Parser (online) 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 %0\ entries\ were\ parsed\ from\ your\ query.=%0 entries were parsed from your query.