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 2 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 @@ -15,6 +15,8 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
- 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 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 the functionality to invoke offline reference parsing explicitly.
- The dialog for [adding an entry using reference text](https://docs.jabref.org/collect/newentryfromplaintext) is now filled with the clipboard contents as default.
- 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)

### Changed
Expand All @@ -27,6 +29,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.
- 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
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ sourceSets {
}

repositories {
mavenLocal()
Copy link
Member

Choose a reason for hiding this comment

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

remove

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 needed mavenLocal() to be able to load the patched version org.jabref:afterburner.fx:2.0.0-SNAPSHOT.

Not required any more.

mavenCentral()
maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots/' }
maven { url 'https://jitpack.io' }
Expand Down Expand Up @@ -214,7 +215,7 @@ dependencies {
implementation 'jakarta.annotation:jakarta.annotation-api:2.1.1'
implementation 'jakarta.inject:jakarta.inject-api:2.0.1'

implementation('org.jabref:afterburner.fx:2.0.0') {
implementation('org.jabref:afterburner.fx:2.0.0-SNAPSHOT') {
exclude group: 'org.openjfx'
}
implementation 'org.kordamp.ikonli:ikonli-javafx:12.3.1'
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
11 changes: 6 additions & 5 deletions src/main/java/org/jabref/gui/actions/StandardActions.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ public enum StandardActions implements Action {
REBUILD_FULLTEXT_SEARCH_INDEX(Localization.lang("Rebuild fulltext search index"), IconTheme.JabRefIcons.FILE),
REDOWNLOAD_MISSING_FILES(Localization.lang("Redownload missing files"), IconTheme.JabRefIcons.DOWNLOAD),
OPEN_EXTERNAL_FILE(Localization.lang("Open file"), IconTheme.JabRefIcons.FILE, KeyBinding.OPEN_FILE),
EXTRACT_FILE_REFERENCES_ONLINE(Localization.lang("Extract references from file (online)"), IconTheme.JabRefIcons.FILE_STAR),
EXTRACT_FILE_REFERENCES_OFFLINE(Localization.lang("Extract references from file (offline)"), IconTheme.JabRefIcons.FILE_STAR),
EXTRACT_FILE_REFERENCES_ONLINE(Localization.lang("Extract references from file (%0)", Localization.lang("offline")), IconTheme.JabRefIcons.FILE_STAR),
koppor marked this conversation as resolved.
Show resolved Hide resolved
EXTRACT_FILE_REFERENCES_OFFLINE(Localization.lang("Extract references from file (%0)", Localization.lang("offline")), IconTheme.JabRefIcons.FILE_STAR),
OPEN_URL(Localization.lang("Open URL or DOI"), IconTheme.JabRefIcons.WWW, KeyBinding.OPEN_URL_OR_DOI),
SEARCH_SHORTSCIENCE(Localization.lang("Search ShortScience")),
MERGE_WITH_FETCHED_ENTRY(Localization.lang("Get bibliographic data from %0", "DOI/ISBN/...")),
Expand Down Expand Up @@ -93,8 +93,8 @@ 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_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),
NEW_LIBRARY_FROM_PDF_ONLINE(Localization.lang("New library based on references in PDF file... (%0)", Localization.lang("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... (%0)", Localization.lang("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),

START_NEW_STUDY(Localization.lang("Start new systematic literature review")),
Expand Down Expand Up @@ -135,7 +135,8 @@ 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_ONLINE(Localization.lang("New entry from plain text (%0)", Localization.lang("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 (%0)", Localization.lang("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,9 +1,5 @@
package org.jabref.gui.bibtexextractor;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.undo.UndoManager;

import javafx.beans.property.SimpleStringProperty;
Expand All @@ -12,28 +8,15 @@
import org.jabref.gui.DialogService;
import org.jabref.gui.StateManager;
import org.jabref.gui.externalfiles.ImportHandler;
import org.jabref.gui.util.BackgroundTask;
import org.jabref.gui.util.TaskExecutor;
import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.fetcher.GrobidCitationFetcher;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.util.FileUpdateMonitor;
import org.jabref.preferences.PreferencesService;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class BibtexExtractorViewModel {

private static final Logger LOGGER = LoggerFactory.getLogger(BibtexExtractorViewModel.class);
public abstract class BibtexExtractorViewModel {
koppor marked this conversation as resolved.
Show resolved Hide resolved

private final StringProperty inputTextProperty = new SimpleStringProperty("");
private final DialogService dialogService;
private final PreferencesService preferencesService;
private final TaskExecutor taskExecutor;
private final ImportHandler importHandler;
protected final ImportHandler importHandler;
protected final StringProperty inputTextProperty = new SimpleStringProperty("");

public BibtexExtractorViewModel(BibDatabaseContext bibdatabaseContext,
DialogService dialogService,
Expand All @@ -42,10 +25,6 @@ public BibtexExtractorViewModel(BibDatabaseContext bibdatabaseContext,
TaskExecutor taskExecutor,
UndoManager undoManager,
StateManager stateManager) {

this.dialogService = dialogService;
this.preferencesService = preferencesService;
this.taskExecutor = taskExecutor;
this.importHandler = new ImportHandler(
bibdatabaseContext,
preferencesService,
Expand All @@ -60,44 +39,5 @@ public StringProperty inputTextProperty() {
return this.inputTextProperty;
}

public void startParsing() {
if (preferencesService.getGrobidPreferences().isGrobidEnabled()) {
parseUsingGrobid();
} else {
parseUsingBibtexExtractor();
}
}

private void parseUsingBibtexExtractor() {
BibEntry parsedEntry = new BibtexExtractor().extract(inputTextProperty.getValue());
importHandler.importEntries(List.of(parsedEntry));
trackNewEntry(parsedEntry, "ParseWithBibTeXExtractor");
}

private void parseUsingGrobid() {
GrobidCitationFetcher grobidCitationFetcher = new GrobidCitationFetcher(preferencesService.getGrobidPreferences(), preferencesService.getImportFormatPreferences());
BackgroundTask.wrap(() -> grobidCitationFetcher.performSearch(inputTextProperty.getValue()))
.onRunning(() -> dialogService.notify(Localization.lang("Your text is being parsed...")))
.onFailure(e -> {
if (e instanceof FetcherException) {
String msg = Localization.lang("There are connection issues with a JabRef server. Detailed information: %0",
e.getMessage());
dialogService.notify(msg);
} else {
LOGGER.warn("Missing exception handling.", e);
}
})
.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 abstract void startParsing();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.jabref.gui.bibtexextractor;

import javax.swing.undo.UndoManager;

import org.jabref.gui.DialogService;
import org.jabref.gui.StateManager;
import org.jabref.gui.util.BackgroundTask;
import org.jabref.gui.util.TaskExecutor;
import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.fetcher.GrobidCitationFetcher;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.util.FileUpdateMonitor;
import org.jabref.preferences.PreferencesService;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class BibtexExtractorViewModelGrobid extends BibtexExtractorViewModel {

private static final Logger LOGGER = LoggerFactory.getLogger(BibtexExtractorViewModelGrobid.class);

private final DialogService dialogService;
private final PreferencesService preferencesService;
private final TaskExecutor taskExecutor;

public BibtexExtractorViewModelGrobid(BibDatabaseContext bibdatabaseContext,
DialogService dialogService,
PreferencesService preferencesService,
FileUpdateMonitor fileUpdateMonitor,
TaskExecutor taskExecutor,
UndoManager undoManager,
StateManager stateManager) {
super(bibdatabaseContext, dialogService, preferencesService, fileUpdateMonitor, taskExecutor, undoManager, stateManager);
this.dialogService = dialogService;
this.preferencesService = preferencesService;
this.taskExecutor = taskExecutor;
}

@Override
public void startParsing() {
GrobidCitationFetcher grobidCitationFetcher = new GrobidCitationFetcher(preferencesService.getGrobidPreferences(), preferencesService.getImportFormatPreferences());
BackgroundTask.wrap(() -> grobidCitationFetcher.performSearch(inputTextProperty.getValue()))
.onRunning(() -> dialogService.notify(Localization.lang("Your text is being parsed...")))
.onFailure(e -> {
if (e instanceof FetcherException) {
String msg = Localization.lang("There are connection issues with a JabRef server. Detailed information: %0",
e.getMessage());
dialogService.notify(msg);
} else {
LOGGER.warn("Missing exception handling.", e);
}
})
.onSuccess(parsedEntries -> {
dialogService.notify(Localization.lang("%0 entries were parsed from your query.", String.valueOf(parsedEntries.size())));
importHandler.importEntries(parsedEntries);
}).executeWith(taskExecutor);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.jabref.gui.bibtexextractor;

import java.util.List;

import javax.swing.undo.UndoManager;

import org.jabref.gui.DialogService;
import org.jabref.gui.StateManager;
import org.jabref.gui.util.TaskExecutor;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.util.FileUpdateMonitor;
import org.jabref.preferences.PreferencesService;

public class BibtexExtractorViewModelOffline extends BibtexExtractorViewModel {

public BibtexExtractorViewModelOffline(BibDatabaseContext bibdatabaseContext,
DialogService dialogService,
PreferencesService preferencesService,
FileUpdateMonitor fileUpdateMonitor,
TaskExecutor taskExecutor,
UndoManager undoManager,
StateManager stateManager) {
super(bibdatabaseContext, dialogService, preferencesService, fileUpdateMonitor, taskExecutor, undoManager, stateManager);
}

@Override
public void startParsing() {
BibEntry parsedEntry = new BibtexExtractor().extract(inputTextProperty.getValue());
importHandler.importEntries(List.of(parsedEntry));
}
}

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 ExtractBibtexDialogOffline());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
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());
if (useGrobid) {
dialogService.showCustomDialogAndWait(new ExtractBibtexDialogGrobid());
} else {
dialogService.showCustomDialogAndWait(new ExtractBibtexDialogOffline());
}
}
}
Loading
Loading