diff --git a/CHANGELOG.md b/CHANGELOG.md index 3de07a4b180..a7107b96821 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We added "All" option to the citation fetcher combo box, which queries all providers (CrossRef, OpenAlex, OpenCitations, SemanticScholar) and merges the results into a single deduplicated list. - We added a quick setting toggle to enable cover images download. [#15322](https://github.com/JabRef/jabref/pull/15322) - We now support refreshing existing CSL citations with respect to their in-text nature in the LibreOffice integration. [#15369](https://github.com/JabRef/jabref/pull/15369) +- We added [SearchRxiv](https://www.cabidigitallibrary.org/journal/searchrxiv) integration to the SLR feature. [#12618](https://github.com/JabRef/jabref/issues/12618) - Added context menu entry "Sort tabs alphabetically" to the library tabs. [#15425](https://github.com/JabRef/jabref/pull/15425) - We added a "Merge" action in the File menu to compare the current library with a selected BibTeX file and review changes. [#15401](https://github.com/JabRef/jabref/issues/15401) - We added integrity checks that warn when the `booktitle` field contains a year, a country/location, or page numbers that should live in dedicated fields. [#12271](https://github.com/JabRef/jabref/issues/12271) diff --git a/jabgui/src/main/java/org/jabref/gui/actions/ActionHelper.java b/jabgui/src/main/java/org/jabref/gui/actions/ActionHelper.java index a0536a134d1..cb5cf431f9b 100644 --- a/jabgui/src/main/java/org/jabref/gui/actions/ActionHelper.java +++ b/jabgui/src/main/java/org/jabref/gui/actions/ActionHelper.java @@ -10,6 +10,7 @@ import javafx.collections.ObservableList; import org.jabref.gui.StateManager; +import org.jabref.gui.slr.StudyCatalogItem; import org.jabref.logic.git.util.GitHandlerRegistry; import org.jabref.logic.preferences.CliPreferences; import org.jabref.logic.shared.DatabaseLocation; @@ -143,4 +144,10 @@ public static BooleanExpression hasLinkedFileForSelectedEntries(StateManager sta return BooleanExpression.booleanExpression(EasyBind.reduce(stateManager.getSelectedEntries(), entries -> entries.anyMatch(entry -> !entry.getFiles().isEmpty()))); } + + public static BooleanExpression noCatalogEnabled(ObservableList catalogs) { + return Bindings.createBooleanBinding( + () -> catalogs.stream().noneMatch(StudyCatalogItem::isEnabled), + catalogs); + } } diff --git a/jabgui/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java b/jabgui/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java index 4caac855d43..8d9df9e050d 100644 --- a/jabgui/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java +++ b/jabgui/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java @@ -25,6 +25,7 @@ import javafx.scene.input.MouseButton; import org.jabref.gui.DialogService; +import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.preferences.GuiPreferences; import org.jabref.gui.util.BaseDialog; @@ -36,16 +37,21 @@ import com.airhacks.afterburner.views.ViewLoader; import jakarta.inject.Inject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /// This class controls the user interface of the study definition management dialog. The UI elements and their layout /// are defined in the FXML file. public class ManageStudyDefinitionView extends BaseDialog { + private static final Logger LOGGER = LoggerFactory.getLogger(ManageStudyDefinitionView.class); + @FXML private TextField studyTitle; @FXML private TextField addAuthor; @FXML private TextField addResearchQuestion; @FXML private TextField addQuery; @FXML private TextField studyDirectory; @FXML private Button selectStudyDirectory; + @FXML private Button shareOnSearchRxivButton; @FXML private ButtonType saveSurveyButtonType; @FXML private Label helpIcon; @@ -177,6 +183,11 @@ private void initialize() { initQueriesTab(); initCatalogsTab(); initValidationBindings(); + shareOnSearchRxivButton.disableProperty().bind( + Bindings.or( + Bindings.isEmpty(viewModel.getQueries()), + ActionHelper.noCatalogEnabled(viewModel.getCatalogs()) + )); } private void updateDirectoryWarning(Path directory) { @@ -295,6 +306,11 @@ private void setupCommonPropertiesForTables(Node addControl, actionColumn.setResizable(false); } + @FXML + private void shareOnSearchRxiv() { + viewModel.shareOnSearchRxiv(pathToStudyDataDirectory); + } + private void setupCellFactories(TableColumn contentColumn, TableColumn actionColumn, Consumer removeAction) { diff --git a/jabgui/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java b/jabgui/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java index a4b2f0ffd8c..043ec755667 100644 --- a/jabgui/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java @@ -17,8 +17,10 @@ import org.jabref.gui.DialogService; import org.jabref.gui.WorkspacePreferences; +import org.jabref.gui.util.DirectoryDialogConfiguration; import org.jabref.logic.crawler.StudyRepository; import org.jabref.logic.crawler.StudyYamlParser; +import org.jabref.logic.exporter.SearchRxivExporter; import org.jabref.logic.git.GitHandler; import org.jabref.logic.git.preferences.GitPreferences; import org.jabref.logic.importer.ImportFormatPreferences; @@ -55,8 +57,10 @@ public class ManageStudyDefinitionViewModel { private final ObservableList authors = FXCollections.observableArrayList(); private final ObservableList researchQuestions = FXCollections.observableArrayList(); private final ObservableList queries = FXCollections.observableArrayList(); - private final ObservableList databases = FXCollections.observableArrayList(); - + // Observe changes to each item's enabledProperty so bindings re-evaluate when catalogs are toggled + private final ObservableList databases = FXCollections.observableArrayList( + item -> new javafx.beans.Observable[] {item.enabledProperty()} + ); // Hold the complement of databases for the selector private final SimpleStringProperty directory = new SimpleStringProperty(); @@ -218,12 +222,7 @@ public void addQuery(String query) { } public SlrStudyAndDirectory saveStudy() { - Study study = new Study( - authors, - title.getValueSafe(), - researchQuestions, - queries.stream().map(StudyQuery::new).collect(Collectors.toList()), - databases.stream().map(studyDatabaseItem -> new StudyDatabase(studyDatabaseItem.getName(), studyDatabaseItem.isEnabled())).filter(StudyDatabase::isEnabled).collect(Collectors.toList())); + Study study = buildStudy(); Path studyDirectory; final String studyDirectoryAsString = directory.getValueSafe(); try { @@ -257,6 +256,19 @@ public SlrStudyAndDirectory saveStudy() { return new SlrStudyAndDirectory(study, studyDirectory); } + /// Builds a {@link Study} from the current UI state without persisting it. + public Study buildStudy() { + return new Study( + authors, + title.getValueSafe(), + researchQuestions, + queries.stream().map(StudyQuery::new).collect(Collectors.toList()), + databases.stream() + .map(item -> new StudyDatabase(item.getName(), item.isEnabled())) + .filter(StudyDatabase::isEnabled) + .collect(Collectors.toList())); + } + public Property titleProperty() { return title; } @@ -316,4 +328,26 @@ public StringProperty queriesValidationMessageProperty() { public StringProperty catalogsValidationMessageProperty() { return catalogsValidationMessage; } + + public void shareOnSearchRxiv(Path initialDirectory) { + Study study = buildStudy(); + if (study.getDatabases().isEmpty()) { + dialogService.notify(Localization.lang("Please select at least one catalog.")); + return; + } + + DirectoryDialogConfiguration config = new DirectoryDialogConfiguration.Builder() + .withInitialDirectory(initialDirectory) + .build(); + + dialogService.showDirectorySelectionDialog(config).ifPresent(exportDirectory -> { + try { + new SearchRxivExporter().export(study, exportDirectory); + dialogService.notify(Localization.lang("Exported search queries for SearchRxiv.")); + } catch (IOException e) { + LOGGER.error("Could not export search queries for SearchRxiv", e); + dialogService.notify(Localization.lang("Could not export search queries.")); + } + }); + } } diff --git a/jabgui/src/main/resources/org/jabref/gui/slr/ManageStudyDefinition.fxml b/jabgui/src/main/resources/org/jabref/gui/slr/ManageStudyDefinition.fxml index cd6f78283e1..94026106707 100644 --- a/jabgui/src/main/resources/org/jabref/gui/slr/ManageStudyDefinition.fxml +++ b/jabgui/src/main/resources/org/jabref/gui/slr/ManageStudyDefinition.fxml @@ -270,15 +270,40 @@ -