From 833cf30f7eae5405e1da9a02e5db3b7b07247c0c Mon Sep 17 00:00:00 2001 From: Subhramit Basu Bhowmick Date: Thu, 22 Aug 2024 00:26:15 +0530 Subject: [PATCH] Persist selection of databases in SLR (#11635) * Attempt: Persist selection of databases * Use ObservableSet * ObservableList * set fetchers * Revise architecture * Revise test * Fix indent * Fix indent 2 * Add changelog entry * Fix indent * Update CHANGELOG.md * Chris' update Co-authored-by: Christoph * Update src/main/java/org/jabref/preferences/WorkspacePreferences.java Co-authored-by: Christoph * Update src/main/java/org/jabref/preferences/JabRefPreferences.java Co-authored-by: Christoph * !Remove duplicated line * Return ObservableList * Remove unused import * Rename foreach loop variable * Rename foreach loop variable * Rename fetcher->catalog * Fix overwriting of existing study catalogs * Merge upstream/main * Fix merge issue * Persist for edits on existing studies * Save preferences only on a "new run" or "save". --------- Co-authored-by: Christoph Co-authored-by: Oliver Kopp --- CHANGELOG.md | 1 + .../gui/slr/ManageStudyDefinitionView.java | 13 ++++++--- .../slr/ManageStudyDefinitionViewModel.java | 27 +++++++++++++++++-- .../jabref/preferences/JabRefPreferences.java | 8 +++++- .../preferences/WorkspacePreferences.java | 17 +++++++++++- .../ManageStudyDefinitionViewModelTest.java | 8 ++++-- 6 files changed, 65 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95f8168d7b0..0e7175ba2ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We enabled creating a new file link manually. [#11017](https://github.com/JabRef/jabref/issues/11017) - We added a toggle button to invert the selected groups. [#9073](https://github.com/JabRef/jabref/issues/9073) - We reintroduced the floating search in the main table. [#4237](https://github.com/JabRef/jabref/issues/4237) +- When starting a new SLR, the selected catalogs now persist within and across JabRef sessions. [koppor#614](https://github.com/koppor/jabref/issues/614) - We added a different background color to the search bar to indicate when the search syntax is wrong. [#11658](https://github.com/JabRef/jabref/pull/11658) ### Changed diff --git a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java index 934ea59ef54..0bba51c81d4 100644 --- a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java +++ b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java @@ -111,7 +111,7 @@ public ManageStudyDefinitionView(Path pathToStudyDataDirectory) { /** * This is used to edit an existing study. * - * @param study the study to edit + * @param study the study to edit * @param studyDirectory the directory of the study */ public ManageStudyDefinitionView(Study study, Path studyDirectory) { @@ -145,6 +145,7 @@ private void setupSaveSurveyButton(boolean isEdit) { setResultConverter(button -> { if (button == saveSurveyButtonType) { + viewModel.updateSelectedCatalogs(); return viewModel.saveStudy(); } // Cancel button will return null @@ -158,14 +159,16 @@ private void initialize() { viewModel = new ManageStudyDefinitionViewModel( prefs.getImportFormatPreferences(), prefs.getImporterPreferences(), - dialogService); + dialogService, + prefs); } else { viewModel = new ManageStudyDefinitionViewModel( study.get(), pathToStudyDataDirectory, prefs.getImportFormatPreferences(), prefs.getImporterPreferences(), - dialogService); + dialogService, + prefs); // The directory of the study cannot be changed studyDirectory.setEditable(false); @@ -237,6 +240,10 @@ private void initCatalogsTab() { }) .install(catalogTable); + if (study.isEmpty()) { + viewModel.initializeSelectedCatalogs(); + } + catalogColumn.setReorderable(false); catalogColumn.setCellFactory(TextFieldTableCell.forTableColumn()); diff --git a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java index 54267048793..58952be9502 100644 --- a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java +++ b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java @@ -32,6 +32,7 @@ import org.jabref.model.study.Study; import org.jabref.model.study.StudyDatabase; import org.jabref.model.study.StudyQuery; +import org.jabref.preferences.PreferencesService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -60,12 +61,15 @@ public class ManageStudyDefinitionViewModel { private final DialogService dialogService; + private final PreferencesService preferencesService; + /** * Constructor for a new study */ public ManageStudyDefinitionViewModel(ImportFormatPreferences importFormatPreferences, ImporterPreferences importerPreferences, - DialogService dialogService) { + DialogService dialogService, + PreferencesService preferencesService) { databases.addAll(WebFetchers.getSearchBasedFetchers(importFormatPreferences, importerPreferences) .stream() .map(SearchBasedFetcher::getName) @@ -78,6 +82,7 @@ public ManageStudyDefinitionViewModel(ImportFormatPreferences importFormatPrefer }) .toList()); this.dialogService = Objects.requireNonNull(dialogService); + this.preferencesService = Objects.requireNonNull(preferencesService); } /** @@ -90,7 +95,8 @@ public ManageStudyDefinitionViewModel(Study study, Path studyDirectory, ImportFormatPreferences importFormatPreferences, ImporterPreferences importerPreferences, - DialogService dialogService) { + DialogService dialogService, + PreferencesService preferencesService) { // copy the content of the study object into the UI fields authors.addAll(Objects.requireNonNull(study).getAuthors()); title.setValue(study.getTitle()); @@ -111,6 +117,7 @@ public ManageStudyDefinitionViewModel(Study study, this.directory.set(Objects.requireNonNull(studyDirectory).toString()); this.dialogService = Objects.requireNonNull(dialogService); + this.preferencesService = Objects.requireNonNull(preferencesService); } public StringProperty getTitle() { @@ -217,4 +224,20 @@ public void deleteQuestion(String item) { public void deleteQuery(String item) { queries.remove(item); } + + public void initializeSelectedCatalogs() { + List selectedCatalogs = preferencesService.getWorkspacePreferences().getSelectedSlrCatalogs(); + for (StudyCatalogItem catalog : databases) { + catalog.setEnabled(selectedCatalogs.contains(catalog.getName())); + } + } + + public void updateSelectedCatalogs() { + List selectedCatalogsList = databases.stream() + .filter(StudyCatalogItem::isEnabled) + .map(StudyCatalogItem::getName) + .collect(Collectors.toList()); + + preferencesService.getWorkspacePreferences().setSelectedSlrCatalogs(selectedCatalogsList); + } } diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index 3c2ed87b403..242d6bdbdc4 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -493,6 +493,9 @@ public class JabRefPreferences implements PreferencesService, AiApiKeyProvider { private static final Logger LOGGER = LoggerFactory.getLogger(JabRefPreferences.class); private static final Preferences PREFS_NODE = Preferences.userRoot().node("/org/jabref"); + // SLR + private static final String SELECTED_SLR_CATALOGS = "selectedSlrCatalogs"; + // The only instance of this class: private static JabRefPreferences singleton; /** @@ -2182,7 +2185,8 @@ public WorkspacePreferences getWorkspacePreferences() { getBoolean(OPEN_LAST_EDITED), getBoolean(SHOW_ADVANCED_HINTS), getBoolean(WARN_ABOUT_DUPLICATES_IN_INSPECTION), - getBoolean(CONFIRM_DELETE)); + getBoolean(CONFIRM_DELETE), + getStringList(SELECTED_SLR_CATALOGS)); EasyBind.listen(workspacePreferences.languageProperty(), (obs, oldValue, newValue) -> { put(LANGUAGE, newValue.getId()); @@ -2200,6 +2204,8 @@ public WorkspacePreferences getWorkspacePreferences() { EasyBind.listen(workspacePreferences.showAdvancedHintsProperty(), (obs, oldValue, newValue) -> putBoolean(SHOW_ADVANCED_HINTS, newValue)); EasyBind.listen(workspacePreferences.warnAboutDuplicatesInInspectionProperty(), (obs, oldValue, newValue) -> putBoolean(WARN_ABOUT_DUPLICATES_IN_INSPECTION, newValue)); EasyBind.listen(workspacePreferences.confirmDeleteProperty(), (obs, oldValue, newValue) -> putBoolean(CONFIRM_DELETE, newValue)); + workspacePreferences.getSelectedSlrCatalogs().addListener((ListChangeListener) change -> + putStringList(SELECTED_SLR_CATALOGS, workspacePreferences.getSelectedSlrCatalogs())); return workspacePreferences; } diff --git a/src/main/java/org/jabref/preferences/WorkspacePreferences.java b/src/main/java/org/jabref/preferences/WorkspacePreferences.java index 5dfdd7379ac..57d97a971b6 100644 --- a/src/main/java/org/jabref/preferences/WorkspacePreferences.java +++ b/src/main/java/org/jabref/preferences/WorkspacePreferences.java @@ -1,11 +1,15 @@ package org.jabref.preferences; +import java.util.List; + import javafx.beans.property.BooleanProperty; import javafx.beans.property.IntegerProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleObjectProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; import org.jabref.gui.theme.Theme; import org.jabref.logic.l10n.Language; @@ -21,6 +25,7 @@ public class WorkspacePreferences { private final BooleanProperty showAdvancedHints; private final BooleanProperty warnAboutDuplicatesInInspection; private final BooleanProperty confirmDelete; + private final ObservableList selectedSlrCatalogs; public WorkspacePreferences(Language language, boolean shouldOverrideDefaultFontSize, @@ -31,7 +36,8 @@ public WorkspacePreferences(Language language, boolean shouldOpenLastEdited, boolean showAdvancedHints, boolean warnAboutDuplicatesInInspection, - boolean confirmDelete) { + boolean confirmDelete, + List selectedSlrCatalogs) { this.language = new SimpleObjectProperty<>(language); this.shouldOverrideDefaultFontSize = new SimpleBooleanProperty(shouldOverrideDefaultFontSize); this.mainFontSize = new SimpleIntegerProperty(mainFontSize); @@ -42,6 +48,7 @@ public WorkspacePreferences(Language language, this.showAdvancedHints = new SimpleBooleanProperty(showAdvancedHints); this.warnAboutDuplicatesInInspection = new SimpleBooleanProperty(warnAboutDuplicatesInInspection); this.confirmDelete = new SimpleBooleanProperty(confirmDelete); + this.selectedSlrCatalogs = FXCollections.observableArrayList(selectedSlrCatalogs); } public Language getLanguage() { @@ -155,4 +162,12 @@ public BooleanProperty confirmDeleteProperty() { public void setConfirmDelete(boolean confirmDelete) { this.confirmDelete.set(confirmDelete); } + + public ObservableList getSelectedSlrCatalogs() { + return selectedSlrCatalogs; + } + + public void setSelectedSlrCatalogs(List catalogs) { + selectedSlrCatalogs.setAll(catalogs); + } } diff --git a/src/test/java/org/jabref/gui/slr/ManageStudyDefinitionViewModelTest.java b/src/test/java/org/jabref/gui/slr/ManageStudyDefinitionViewModelTest.java index ff18ea6dfd2..92890e0f816 100644 --- a/src/test/java/org/jabref/gui/slr/ManageStudyDefinitionViewModelTest.java +++ b/src/test/java/org/jabref/gui/slr/ManageStudyDefinitionViewModelTest.java @@ -8,6 +8,7 @@ import org.jabref.logic.importer.ImporterPreferences; import org.jabref.model.study.Study; import org.jabref.model.study.StudyDatabase; +import org.jabref.preferences.PreferencesService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -21,6 +22,7 @@ class ManageStudyDefinitionViewModelTest { private ImportFormatPreferences importFormatPreferences; private ImporterPreferences importerPreferences; private DialogService dialogService; + private PreferencesService preferencesService; @BeforeEach void setUp() { @@ -28,11 +30,12 @@ void setUp() { importFormatPreferences = mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS); importerPreferences = mock(ImporterPreferences.class, Answers.RETURNS_DEEP_STUBS); dialogService = mock(DialogService.class); + preferencesService = mock(PreferencesService.class); } @Test void emptyStudyConstructorFillsDatabasesCorrectly() { - ManageStudyDefinitionViewModel manageStudyDefinitionViewModel = new ManageStudyDefinitionViewModel(importFormatPreferences, importerPreferences, dialogService); + ManageStudyDefinitionViewModel manageStudyDefinitionViewModel = new ManageStudyDefinitionViewModel(importFormatPreferences, importerPreferences, dialogService, preferencesService); assertEquals(List.of( new StudyCatalogItem("ACM Portal", true), new StudyCatalogItem("ArXiv", false), @@ -103,6 +106,7 @@ private ManageStudyDefinitionViewModel getManageStudyDefinitionViewModel(Path te tempDir, importFormatPreferences, importerPreferences, - dialogService); + dialogService, + preferencesService); } }