diff --git a/CHANGELOG.md b/CHANGELOG.md index 4206bdbc693..ee15a83efb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,11 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv ### Added +- We introduced a settings parameters to manage citations' relations local storage time-to-live with a default value set to 30 days. [#11189](https://github.com/JabRef/jabref/issues/11189) + +### Changed + +- We improved the citations relations caching by implementing an offline storage. [#11189](https://github.com/JabRef/jabref/issues/11189) - We added a tooltip to keywords that resemble Math Subject Classification (MSC) codes. [#12944](https://github.com/JabRef/jabref/issues/12944) - We added a feature to convert keywords that resemble MSC codes to their descriptions. [#12944](https://github.com/JabRef/jabref/issues/12944) - We introduced a new command line application called `jabkit`. [#13012](https://github.com/JabRef/jabref/pull/13012) [#110](https://github.com/JabRef/jabref/issues/110) diff --git a/gradle.properties b/gradle.properties index 583f52980fb..25870ec2e93 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.vfs.watch=true # Hint by https://docs.gradle.org/current/userguide/performance.html#increase_the_heap_size # Otherwise, one gets "Java heap space" errors. -org.gradle.jvmargs=-Xmx6096M +org.gradle.jvmargs=-Xmx6g # hint by https://docs.gradle.org/current/userguide/performance.html#enable_configuration_cache # Blocked by https://github.com/beryx/badass-jlink-plugin/issues/304 diff --git a/jabgui/src/main/java/org/jabref/gui/JabRefGUI.java b/jabgui/src/main/java/org/jabref/gui/JabRefGUI.java index 21aed8e8bfa..b1af3c9aa24 100644 --- a/jabgui/src/main/java/org/jabref/gui/JabRefGUI.java +++ b/jabgui/src/main/java/org/jabref/gui/JabRefGUI.java @@ -30,6 +30,7 @@ import org.jabref.gui.util.WebViewStore; import org.jabref.logic.UiCommand; import org.jabref.logic.ai.AiService; +import org.jabref.logic.citation.SearchCitationsRelationsService; import org.jabref.logic.journals.JournalAbbreviationLoader; import org.jabref.logic.journals.JournalAbbreviationRepository; import org.jabref.logic.l10n.Localization; @@ -66,6 +67,8 @@ public class JabRefGUI extends Application { // AI Service handles chat messages etc. Therefore, it is tightly coupled to the GUI. private static AiService aiService; + // CitationsAndRelationsSearchService is here configured for a local machine and so to the GUI. + private static SearchCitationsRelationsService citationsAndRelationsSearchService; private static FileUpdateMonitor fileUpdateMonitor; private static StateManager stateManager; @@ -187,6 +190,14 @@ public void initialize() { dialogService, taskExecutor); Injector.setModelOrService(AiService.class, aiService); + + JabRefGUI.citationsAndRelationsSearchService = new SearchCitationsRelationsService( + preferences.getImporterPreferences(), + preferences.getImportFormatPreferences(), + preferences.getFieldPreferences(), + entryTypesManager + ); + Injector.setModelOrService(SearchCitationsRelationsService.class, citationsAndRelationsSearchService); } private void setupProxy() { @@ -407,6 +418,8 @@ public void stop() { stopBackgroundTasks(); LOGGER.trace("Shutting down thread pools"); shutdownThreadPools(); + LOGGER.trace("Closing citations and relations search service"); + citationsAndRelationsSearchService.close(); LOGGER.trace("Finished stop"); } diff --git a/jabgui/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java b/jabgui/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java index dfc7969d2f1..b66e4e67a67 100644 --- a/jabgui/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java +++ b/jabgui/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java @@ -56,6 +56,7 @@ import org.jabref.gui.util.UiTaskExecutor; import org.jabref.logic.ai.AiService; import org.jabref.logic.bibtex.TypedBibEntry; +import org.jabref.logic.citation.SearchCitationsRelationsService; import org.jabref.logic.help.HelpFile; import org.jabref.logic.importer.EntryBasedFetcher; import org.jabref.logic.importer.WebFetchers; @@ -118,6 +119,7 @@ public class EntryEditor extends BorderPane implements PreviewControls, AdaptVis @Inject private KeyBindingRepository keyBindingRepository; @Inject private JournalAbbreviationRepository journalAbbreviationRepository; @Inject private AiService aiService; + @Inject private SearchCitationsRelationsService searchCitationsRelationsService; private final List allPossibleTabs = new ArrayList<>(); @@ -323,7 +325,16 @@ private List createTabs() { tabs.add(new MathSciNetTab()); tabs.add(new FileAnnotationTab(stateManager)); tabs.add(new SciteTab(preferences, taskExecutor, dialogService)); - tabs.add(new CitationRelationsTab(dialogService, undoManager, stateManager, fileMonitor, preferences, taskExecutor, bibEntryTypesManager)); + tabs.add(new CitationRelationsTab( + dialogService, + undoManager, + stateManager, + fileMonitor, + preferences, + taskExecutor, + bibEntryTypesManager, + searchCitationsRelationsService + )); tabs.add(new RelatedArticlesTab(buildInfo, preferences, dialogService, stateManager, taskExecutor)); sourceTab = new SourceTab( undoManager, diff --git a/jabgui/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/BibEntryRelationsCache.java b/jabgui/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/BibEntryRelationsCache.java deleted file mode 100644 index 2bae9b9aadb..00000000000 --- a/jabgui/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/BibEntryRelationsCache.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.jabref.gui.entryeditor.citationrelationtab; - -import java.util.List; -import java.util.Map; - -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.identifier.DOI; - -import org.eclipse.jgit.util.LRUMap; - -public class BibEntryRelationsCache { - private static final Integer MAX_CACHED_ENTRIES = 100; - private static final Map> CITATIONS_MAP = new LRUMap<>(MAX_CACHED_ENTRIES, MAX_CACHED_ENTRIES); - private static final Map> REFERENCES_MAP = new LRUMap<>(MAX_CACHED_ENTRIES, MAX_CACHED_ENTRIES); - - public List getCitations(BibEntry entry) { - return CITATIONS_MAP.getOrDefault(entry.getDOI().map(DOI::asString).orElse(""), List.of()); - } - - public List getReferences(BibEntry entry) { - return REFERENCES_MAP.getOrDefault(entry.getDOI().map(DOI::asString).orElse(""), List.of()); - } - - public void cacheOrMergeCitations(BibEntry entry, List citations) { - entry.getDOI().ifPresent(doi -> CITATIONS_MAP.put(doi.asString(), citations)); - } - - public void cacheOrMergeReferences(BibEntry entry, List references) { - entry.getDOI().ifPresent(doi -> REFERENCES_MAP.putIfAbsent(doi.asString(), references)); - } - - public boolean citationsCached(BibEntry entry) { - return CITATIONS_MAP.containsKey(entry.getDOI().map(DOI::asString).orElse("")); - } - - public boolean referencesCached(BibEntry entry) { - return REFERENCES_MAP.containsKey(entry.getDOI().map(DOI::asString).orElse("")); - } -} diff --git a/jabgui/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/BibEntryRelationsRepository.java b/jabgui/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/BibEntryRelationsRepository.java deleted file mode 100644 index 9e7d6aff0f7..00000000000 --- a/jabgui/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/BibEntryRelationsRepository.java +++ /dev/null @@ -1,73 +0,0 @@ -package org.jabref.gui.entryeditor.citationrelationtab; - -import java.util.List; - -import org.jabref.logic.importer.FetcherException; -import org.jabref.logic.importer.fetcher.citation.semanticscholar.SemanticScholarFetcher; -import org.jabref.model.entry.BibEntry; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class BibEntryRelationsRepository { - private static final Logger LOGGER = LoggerFactory.getLogger(BibEntryRelationsRepository.class); - - private final SemanticScholarFetcher fetcher; - private final BibEntryRelationsCache cache; - - public BibEntryRelationsRepository(SemanticScholarFetcher fetcher, BibEntryRelationsCache cache) { - this.fetcher = fetcher; - this.cache = cache; - } - - public List getCitations(BibEntry entry) { - if (needToRefreshCitations(entry)) { - forceRefreshCitations(entry); - } - - return cache.getCitations(entry); - } - - public List getReferences(BibEntry entry) { - if (needToRefreshReferences(entry)) { - List references; - try { - references = fetcher.searchCiting(entry); - } catch (FetcherException e) { - LOGGER.error("Error while fetching references", e); - references = List.of(); - } - cache.cacheOrMergeReferences(entry, references); - } - - return cache.getReferences(entry); - } - - public void forceRefreshCitations(BibEntry entry) { - try { - List citations = fetcher.searchCitedBy(entry); - cache.cacheOrMergeCitations(entry, citations); - } catch (FetcherException e) { - LOGGER.error("Error while fetching citations", e); - } - } - - public boolean needToRefreshCitations(BibEntry entry) { - return !cache.citationsCached(entry); - } - - public boolean needToRefreshReferences(BibEntry entry) { - return !cache.referencesCached(entry); - } - - public void forceRefreshReferences(BibEntry entry) { - List references; - try { - references = fetcher.searchCiting(entry); - } catch (FetcherException e) { - LOGGER.error("Error while fetching references", e); - references = List.of(); - } - cache.cacheOrMergeReferences(entry, references); - } -} diff --git a/jabgui/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/CitationRelationsTab.java b/jabgui/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/CitationRelationsTab.java index 0c3a7994602..b883672d884 100644 --- a/jabgui/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/CitationRelationsTab.java +++ b/jabgui/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/CitationRelationsTab.java @@ -49,10 +49,10 @@ import org.jabref.logic.bibtex.BibEntryWriter; import org.jabref.logic.bibtex.FieldPreferences; import org.jabref.logic.bibtex.FieldWriter; +import org.jabref.logic.citation.SearchCitationsRelationsService; import org.jabref.logic.database.DuplicateCheck; import org.jabref.logic.exporter.BibWriter; import org.jabref.logic.importer.fetcher.citation.CitationFetcher; -import org.jabref.logic.importer.fetcher.citation.semanticscholar.SemanticScholarFetcher; import org.jabref.logic.l10n.Localization; import org.jabref.logic.os.OS; import org.jabref.logic.util.BackgroundTask; @@ -90,7 +90,7 @@ public class CitationRelationsTab extends EntryEditorTab { private final DialogService dialogService; private final GuiPreferences preferences; private final TaskExecutor taskExecutor; - private final BibEntryRelationsRepository bibEntryRelationsRepository; + private final SearchCitationsRelationsService searchCitationsRelationsService; private final CitationsRelationsTabViewModel citationsRelationsTabViewModel; private final DuplicateCheck duplicateCheck; private final BibEntryTypesManager entryTypesManager; @@ -103,7 +103,8 @@ public CitationRelationsTab(DialogService dialogService, FileUpdateMonitor fileUpdateMonitor, GuiPreferences preferences, TaskExecutor taskExecutor, - BibEntryTypesManager bibEntryTypesManager) { + BibEntryTypesManager bibEntryTypesManager, + SearchCitationsRelationsService searchCitationsRelationsService) { this.dialogService = dialogService; this.preferences = preferences; this.taskExecutor = taskExecutor; @@ -115,9 +116,16 @@ public CitationRelationsTab(DialogService dialogService, this.entryTypesManager = bibEntryTypesManager; this.duplicateCheck = new DuplicateCheck(entryTypesManager); - this.bibEntryRelationsRepository = new BibEntryRelationsRepository(new SemanticScholarFetcher(preferences.getImporterPreferences()), - new BibEntryRelationsCache()); - citationsRelationsTabViewModel = new CitationsRelationsTabViewModel(preferences, undoManager, stateManager, dialogService, fileUpdateMonitor, taskExecutor); + this.searchCitationsRelationsService = searchCitationsRelationsService; + + this.citationsRelationsTabViewModel = new CitationsRelationsTabViewModel( + preferences, + undoManager, + stateManager, + dialogService, + fileUpdateMonitor, + taskExecutor + ); } /** @@ -191,29 +199,48 @@ private SplitPane getPaneAndStartSearch(BibEntry entry) { citingVBox.getChildren().addAll(citingHBox, citingListView); citedByVBox.getChildren().addAll(citedByHBox, citedByListView); - refreshCitingButton.setOnMouseClicked(event -> searchForRelations( - entry, - citingListView, - abortCitingButton, - refreshCitingButton, - CitationFetcher.SearchType.CITES, - importCitingButton, - citingProgress, - true)); + refreshCitingButton.setOnMouseClicked(_ -> { + searchForRelations( + entry, + citingListView, + abortCitingButton, + refreshCitingButton, + CitationFetcher.SearchType.CITES, + importCitingButton, + citingProgress); + }); - refreshCitedByButton.setOnMouseClicked(event -> searchForRelations(entry, citedByListView, abortCitedButton, - refreshCitedByButton, CitationFetcher.SearchType.CITED_BY, importCitedByButton, citedByProgress, true)); + refreshCitedByButton.setOnMouseClicked(_ -> searchForRelations( + entry, + citedByListView, + abortCitedButton, + refreshCitedByButton, + CitationFetcher.SearchType.CITED_BY, + importCitedByButton, + citedByProgress)); // Create SplitPane to hold all nodes above SplitPane container = new SplitPane(citingVBox, citedByVBox); styleFetchedListView(citedByListView); styleFetchedListView(citingListView); - searchForRelations(entry, citingListView, abortCitingButton, refreshCitingButton, - CitationFetcher.SearchType.CITES, importCitingButton, citingProgress, false); - - searchForRelations(entry, citedByListView, abortCitedButton, refreshCitedByButton, - CitationFetcher.SearchType.CITED_BY, importCitedByButton, citedByProgress, false); + searchForRelations( + entry, + citingListView, + abortCitingButton, + refreshCitingButton, + CitationFetcher.SearchType.CITES, + importCitingButton, + citingProgress); + + searchForRelations( + entry, + citedByListView, + abortCitedButton, + refreshCitedByButton, + CitationFetcher.SearchType.CITED_BY, + importCitedByButton, + citedByProgress); return container; } @@ -242,7 +269,7 @@ private void styleFetchedListView(CheckListView listView) Button jumpTo = IconTheme.JabRefIcons.LINK.asButton(); jumpTo.setTooltip(new Tooltip(Localization.lang("Jump to entry in library"))); jumpTo.getStyleClass().add("addEntryButton"); - jumpTo.setOnMouseClicked(event -> jumpToEntry(entry)); + jumpTo.setOnMouseClicked(_ -> jumpToEntry(entry)); hContainer.setOnMouseClicked(event -> { if (event.getClickCount() == 2) { jumpToEntry(entry); @@ -252,7 +279,7 @@ private void styleFetchedListView(CheckListView listView) Button compareButton = IconTheme.JabRefIcons.MERGE_ENTRIES.asButton(); compareButton.setTooltip(new Tooltip(Localization.lang("Compare with existing entry"))); - compareButton.setOnMouseClicked(event -> openPossibleDuplicateEntriesWindow(entry, listView)); + compareButton.setOnMouseClicked(_ -> openPossibleDuplicateEntriesWindow(entry, listView)); vContainer.getChildren().add(compareButton); } else { ToggleButton addToggle = IconTheme.JabRefIcons.ADD.asToggleButton(); @@ -272,7 +299,7 @@ private void styleFetchedListView(CheckListView listView) if (entry.entry().getDOI().isPresent() || entry.entry().getField(StandardField.URL).isPresent()) { Button openWeb = IconTheme.JabRefIcons.OPEN_LINK.asButton(); openWeb.setTooltip(new Tooltip(Localization.lang("Open URL or DOI"))); - openWeb.setOnMouseClicked(event -> { + openWeb.setOnMouseClicked(_ -> { String url = entry.entry().getDOI().flatMap(DOI::getExternalURI).map(URI::toString) .or(() -> entry.entry().getField(StandardField.URL)).orElse(""); if (StringUtil.isNullOrEmpty(url)) { @@ -289,7 +316,7 @@ private void styleFetchedListView(CheckListView listView) Button showEntrySource = IconTheme.JabRefIcons.SOURCE.asButton(); showEntrySource.setTooltip(new Tooltip(Localization.lang("%0 source", "BibTeX"))); - showEntrySource.setOnMouseClicked(event -> showEntrySourceDialog(entry.entry())); + showEntrySource.setOnMouseClicked(_ -> showEntrySourceDialog(entry.entry())); vContainer.getChildren().addLast(showEntrySource); @@ -298,9 +325,9 @@ private void styleFetchedListView(CheckListView listView) return hContainer; }) - .withOnMouseClickedEvent((ee, event) -> { - if (!ee.isLocal()) { - listView.getCheckModel().toggleCheckState(ee); + .withOnMouseClickedEvent((citationRelationItem, _) -> { + if (!citationRelationItem.isLocal()) { + listView.getCheckModel().toggleCheckState(citationRelationItem); } }) .withPseudoClass(entrySelected, listView::getItemBooleanProperty) @@ -407,7 +434,7 @@ protected void bindToEntry(BibEntry entry) { */ private void searchForRelations(BibEntry entry, CheckListView listView, Button abortButton, Button refreshButton, CitationFetcher.SearchType searchType, Button importButton, - ProgressIndicator progress, boolean shouldRefresh) { + ProgressIndicator progress) { if (entry.getDOI().isEmpty()) { hideNodes(abortButton, progress); showNodes(refreshButton); @@ -421,46 +448,61 @@ private void searchForRelations(BibEntry entry, CheckListView> task; - - if (searchType == CitationFetcher.SearchType.CITES) { - task = BackgroundTask.wrap(() -> { - if (shouldRefresh) { - bibEntryRelationsRepository.forceRefreshReferences(entry); - } - return bibEntryRelationsRepository.getReferences(entry); - }); - citingTask = task; - } else { - task = BackgroundTask.wrap(() -> { - if (shouldRefresh) { - bibEntryRelationsRepository.forceRefreshCitations(entry); - } - return bibEntryRelationsRepository.getCitations(entry); - }); - citedByTask = task; - } - - task.onRunning(() -> prepareToSearchForRelations(abortButton, refreshButton, importButton, progress, task)) - .onSuccess(fetchedList -> onSearchForRelationsSucceed(entry, listView, abortButton, refreshButton, searchType, importButton, progress, fetchedList, observableList)) + this.createBackgroundTask(entry, searchType) + .consumeOnRunning(task -> prepareToSearchForRelations( + abortButton, refreshButton, importButton, progress, task + )) + .onSuccess(fetchedList -> onSearchForRelationsSucceed( + entry, + listView, + abortButton, + refreshButton, + searchType, + importButton, + progress, + fetchedList, + observableList + )) .onFailure(exception -> { LOGGER.error("Error while fetching citing Articles", exception); hideNodes(abortButton, progress, importButton); listView.setPlaceholder(new Label(Localization.lang("Error while fetching citing entries: %0", exception.getMessage()))); - refreshButton.setVisible(true); dialogService.notify(exception.getMessage()); }) .executeWith(taskExecutor); } + /** + * TODO: Make the method return a callable and let the calling method create the background task. + */ + private BackgroundTask> createBackgroundTask( + BibEntry entry, CitationFetcher.SearchType searchType + ) { + return switch (searchType) { + case CitationFetcher.SearchType.CITES -> { + citingTask = BackgroundTask.wrap( + () -> this.searchCitationsRelationsService.searchReferences(entry) + ); + yield citingTask; + } + case CitationFetcher.SearchType.CITED_BY -> { + citedByTask = BackgroundTask.wrap( + () -> this.searchCitationsRelationsService.searchCitations(entry) + ); + yield citedByTask; + } + }; + } + private void onSearchForRelationsSucceed(BibEntry entry, CheckListView listView, Button abortButton, Button refreshButton, CitationFetcher.SearchType searchType, Button importButton, diff --git a/jabgui/src/main/java/org/jabref/gui/preferences/websearch/WebSearchTab.java b/jabgui/src/main/java/org/jabref/gui/preferences/websearch/WebSearchTab.java index 2a9073041d0..6a2f75f83b4 100644 --- a/jabgui/src/main/java/org/jabref/gui/preferences/websearch/WebSearchTab.java +++ b/jabgui/src/main/java/org/jabref/gui/preferences/websearch/WebSearchTab.java @@ -26,6 +26,7 @@ import com.airhacks.afterburner.views.ViewLoader; import com.tobiasdiez.easybind.EasyBind; +import org.apache.logging.log4j.util.Strings; public class WebSearchTab extends AbstractPreferenceTabView implements PreferencesTab { @@ -36,6 +37,7 @@ public class WebSearchTab extends AbstractPreferenceTabView defaultPlainCitationParser; + @FXML private TextField citationsRelationStoreTTL; @FXML private CheckBox useCustomDOI; @FXML private TextField useCustomDOIName; @@ -88,6 +90,25 @@ public void initialize() { defaultPlainCitationParser.itemsProperty().bind(viewModel.plainCitationParsers()); defaultPlainCitationParser.valueProperty().bindBidirectional(viewModel.defaultPlainCitationParserProperty()); + viewModel.citationsRelationsStoreTTLProperty() + .addListener((_, _, newValue) -> { + if (newValue != null && !newValue.toString().equals(citationsRelationStoreTTL.getText())) { + citationsRelationStoreTTL.setText(newValue.toString()); + } + }); + citationsRelationStoreTTL + .textProperty() + .addListener((_, _, newValue) -> { + if (Strings.isBlank(newValue)) { + return; + } + if (!newValue.matches("\\d*")) { + citationsRelationStoreTTL.setText(newValue.replaceAll("\\D", "")); + return; + } + viewModel.citationsRelationsStoreTTLProperty().set(Integer.parseInt(newValue)); + }); + grobidEnabled.selectedProperty().bindBidirectional(viewModel.grobidEnabledProperty()); grobidURL.textProperty().bindBidirectional(viewModel.grobidURLProperty()); grobidURL.disableProperty().bind(grobidEnabled.selectedProperty().not()); @@ -121,7 +142,7 @@ public void initialize() { new ViewModelTableRowFactory() .install(apiKeySelectorTable); - apiKeySelectorTable.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { + apiKeySelectorTable.getSelectionModel().selectedItemProperty().addListener((_, oldValue, newValue) -> { if (oldValue != null) { updateFetcherApiKey(oldValue); } @@ -161,7 +182,7 @@ public void initialize() { apiKeySelectorTable.setItems(viewModel.fetcherApiKeys()); // Content is set later - viewModel.fetcherApiKeys().addListener((InvalidationListener) change -> { + viewModel.fetcherApiKeys().addListener((InvalidationListener) _ -> { if (!apiKeySelectorTable.getItems().isEmpty()) { apiKeySelectorTable.getSelectionModel().selectFirst(); } diff --git a/jabgui/src/main/java/org/jabref/gui/preferences/websearch/WebSearchTabViewModel.java b/jabgui/src/main/java/org/jabref/gui/preferences/websearch/WebSearchTabViewModel.java index e22198286b4..f5785fd2933 100644 --- a/jabgui/src/main/java/org/jabref/gui/preferences/websearch/WebSearchTabViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/preferences/websearch/WebSearchTabViewModel.java @@ -6,10 +6,12 @@ import java.util.stream.Collectors; import javafx.beans.property.BooleanProperty; +import javafx.beans.property.IntegerProperty; import javafx.beans.property.ListProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.ReadOnlyBooleanProperty; import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleListProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; @@ -49,6 +51,8 @@ public class WebSearchTabViewModel implements PreferenceTabViewModel { new SimpleListProperty<>(FXCollections.observableArrayList(PlainCitationParserChoice.values())); private final ObjectProperty defaultPlainCitationParser = new SimpleObjectProperty<>(); + private final IntegerProperty citationsRelationStoreTTL = new SimpleIntegerProperty(); + private final BooleanProperty addImportedEntries = new SimpleBooleanProperty(); private final StringProperty addImportedEntriesGroupName = new SimpleStringProperty(""); @@ -137,6 +141,7 @@ public void setValues() { addImportedEntries.setValue(libraryPreferences.isAddImportedEntriesEnabled()); addImportedEntriesGroupName.setValue(libraryPreferences.getAddImportedEntriesGroupName()); defaultPlainCitationParser.setValue(importerPreferences.getDefaultPlainCitationParser()); + citationsRelationStoreTTL.setValue(importerPreferences.getCitationsRelationsStoreTTL()); useCustomDOIProperty.setValue(doiPreferences.isUseCustom()); useCustomDOINameProperty.setValue(doiPreferences.getDefaultBaseURI()); @@ -174,6 +179,7 @@ public void storeSettings() { libraryPreferences.setAddImportedEntriesGroupName(addImportedEntriesGroupName.getValue()); } importerPreferences.setDefaultPlainCitationParser(defaultPlainCitationParser.getValue()); + importerPreferences.setCitationsRelationsStoreTTL(citationsRelationStoreTTL.getValue()); grobidPreferences.setGrobidEnabled(grobidEnabledProperty.getValue()); grobidPreferences.setGrobidUseAsked(grobidPreferences.isGrobidUseAsked()); @@ -260,6 +266,10 @@ public BooleanProperty getApikeyPersistProperty() { return apikeyPersistProperty; } + public IntegerProperty citationsRelationsStoreTTLProperty() { + return citationsRelationStoreTTL; + } + public void checkCustomApiKey() { final String apiKeyName = selectedApiKeyProperty.get().getName(); diff --git a/jabgui/src/main/resources/org/jabref/gui/preferences/websearch/WebSearchTab.fxml b/jabgui/src/main/resources/org/jabref/gui/preferences/websearch/WebSearchTab.fxml index 6675f474304..987561b711a 100644 --- a/jabgui/src/main/resources/org/jabref/gui/preferences/websearch/WebSearchTab.fxml +++ b/jabgui/src/main/resources/org/jabref/gui/preferences/websearch/WebSearchTab.fxml @@ -29,6 +29,10 @@