Skip to content
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

Enable triggering offline parsing explicitely #11565

Merged
merged 16 commits into from
Aug 4, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -28,6 +30,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 where a new unsaved library was not marked with an asterisk [#11519](https://github.com/JabRef/jabref/pull/11519)

### Removed
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 build-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
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>

<!-- ExtractBibtexDialog.fxml and ExtractBibtexDialogOffline.fxml are identical files -->
<?import javafx.scene.control.ButtonType?>
<?import javafx.scene.control.DialogPane?>
<?import javafx.scene.control.TextArea?>
Expand Down
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,66 @@

/**
* 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)
.controller(this)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why controller?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I thought, I could not it get to work without this... Strange. Removed.

.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);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to have this code here, because otherwise, I get

Caused by: java.lang.NullPointerException: Cannot invoke "javafx.scene.control.Button.setTooltip(javafx.scene.control.Tooltip)" because "buttonParse" is null

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
Loading