Skip to content

Commit

Permalink
Enable triggering offline parsing explicitely (JabRef#11565)
Browse files Browse the repository at this point in the history
* Enable triggering offline parsing explicitely

- Refactor actions to inheritance instead of if-statements in a class
- Solved "fun" with inheritance and FXML
- Use %0 and offline/offline parameterization
- Rename "GROBID" to "Grobid"

* Add support to show clipboard contents

* Add reference to CHANGELOG.md

* "Inline" Localization.lang("offline") and Localization.lang("online")

* Some intermediate result. Feels really bad, therefore migrating to if/then

* Migrate to if/then

* Remove "(online)" suffix from button in toolbar

* Discard changes to build.gradle

* Discard changes to src/main/java/org/jabref/gui/bibtexextractor/ExtractBibtexDialog.fxml

* Remove obsolete .controller(this)

* Fix checkstyle

---------

Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>
  • Loading branch information
koppor and calixtus committed Aug 4, 2024
1 parent 2c8fc01 commit dc2e17a
Show file tree
Hide file tree
Showing 16 changed files with 218 additions and 125 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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)
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/org/jabref/gui/actions/ActionFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
6 changes: 4 additions & 2 deletions src/main/java/org/jabref/gui/actions/StandardActions.java
Original file line number Diff line number Diff line change
Expand Up @@ -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),

Expand Down Expand Up @@ -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),
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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;
Expand All @@ -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...")))
Expand All @@ -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<String, String> properties = new HashMap<>();
properties.put("EntryType", bibEntry.typeProperty().getValue().getName());
public StringProperty inputTextProperty() {
return this.inputTextProperty;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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));
}
}
Original file line number Diff line number Diff line change
@@ -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));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -22,45 +25,65 @@

/**
* 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<Void> {

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,
fileUpdateMonitor,
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());
});
}
}
Loading

0 comments on commit dc2e17a

Please sign in to comment.