Skip to content

Fix markbaseChanged for "imported entries"#15610

Merged
Siedlerchr merged 7 commits into
mainfrom
fix-changeddb-imported-entries
May 3, 2026
Merged

Fix markbaseChanged for "imported entries"#15610
Siedlerchr merged 7 commits into
mainfrom
fix-changeddb-imported-entries

Conversation

@koppor

@koppor koppor commented Apr 21, 2026

Copy link
Copy Markdown
Member

Follow-up to #14398

The code was at the very wrong place - it needs to be at org.jabref.gui.importer.actions.GUIPostOpenAction.

Otherwise, there is always a *.

The main reason for the * is that we create a fake BibDatabaseContext while opening. Maybe, will be fixed at #8298.

I used Claude Caude for the details, but I made the decisions.

Steps to test

  1. Enable "Add imported entries to group"
    grafik
  2. Open a bib file
  3. See that "imported entries" group is added without a change

Checklist

  • I own the copyright of the code submitted and I license it under the MIT license
  • I manually tested my changes in running JabRef (always required)
  • [/] I added JUnit tests for changes (if applicable)
  • [/] I added screenshots in the PR description (if change is visible to the user)
  • [/] I added a screenshot in the PR description showing a library with a single entry with me as author and as title the issue number
  • I described the change in CHANGELOG.md in a way that can be understood by the average user (if change is visible to the user)
  • [/] I checked the user documentation for up to dateness and submitted a pull request to our user documentation repository

koppor and others added 3 commits April 21, 2026 21:14
…mportEntriesAction

The group creation now runs as a post-open action on the ParserResult
before the GUI sets up, rather than on every active-database change.
isActionNecessary checks both the preference and whether the group
already exists; performAction creates the root group if absent and
inserts the import group at position 0.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@qodo-free-for-open-source-projects

Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Fix unwanted modification marker for imported entries group

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Move "imported entries" group creation to post-open action
• Prevent unwanted database modification marker when importing
• Simplify active database setter with Optional.ofNullable
• Remove duplicate group creation logic from view model
Diagram
flowchart LR
  A["File Opening"] -->|ParserResult| B["AddGroupImportEntriesAction"]
  B -->|isActionNecessary| C{"Check preference<br/>and group exists"}
  C -->|Yes| D["performAction:<br/>Create group at position 0"]
  D -->|Update MetaData| E["Database loaded<br/>without modification marker"]
  C -->|No| E
  F["GroupTreeViewModel"] -->|Removed| G["addGroupImportEntries logic"]
Loading

Grey Divider

File Changes

1. jabgui/src/main/java/org/jabref/gui/JabRefGuiStateManager.java ✨ Enhancement +3/-4

Simplify active database setter with Optional

• Added @Nullable import annotation
• Changed setActiveDatabase parameter to accept null values
• Simplified null handling using Optional.ofNullable instead of conditional logic

jabgui/src/main/java/org/jabref/gui/JabRefGuiStateManager.java


2. jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java Refactoring +15/-39

Remove imported entries group creation logic

• Removed addGroupImportEntries method entirely
• Removed group creation logic from onActiveDatabaseChanged
• Simplified database change handler to only update view model state
• Moved responsibility to post-open action phase

jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java


3. jabgui/src/main/java/org/jabref/gui/importer/actions/AddGroupImportEntriesAction.java ✨ Enhancement +46/-0

New post-open action for imported entries group

• New action class implementing GUIPostOpenAction interface
• isActionNecessary checks preference and verifies group doesn't exist
• performAction creates root group if absent and inserts import group at position 0
• Executes during file parsing before GUI setup to avoid modification marker

jabgui/src/main/java/org/jabref/gui/importer/actions/AddGroupImportEntriesAction.java


View more (2)
4. jabgui/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java ⚙️ Configuration changes +3/-1

Register imported entries action in post-open pipeline

• Added AddGroupImportEntriesAction to POST_OPEN_ACTIONS list
• Ensures group creation runs as part of standard post-open workflow

jabgui/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java


5. CHANGELOG.md 📝 Documentation +1/-0

Document imported entries group fix

• Added entry documenting fix for modification marker issue
• Describes resolution of unwanted library modification when importing entries group

CHANGELOG.md


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Imported group not created🐞 Bug ≡ Correctness
Description
The “Imported entries” group is now only created via OpenDatabaseAction post-open actions, so
libraries created via NewDatabaseAction never get the group even when the preference is enabled, and
importing into such libraries won’t assign entries to the group. This also breaks existing
GroupTreeViewModel tests that still assert the group is created during GroupTreeViewModel
initialization.
Code

jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java[R166-187]

private void onActiveDatabaseChanged(Optional<BibDatabaseContext> newDatabase) {
-        if (newDatabase.isPresent()) {
-            GroupNodeViewModel newRoot = newDatabase
-                    .map(BibDatabaseContext::getMetaData)
-                    .flatMap(MetaData::getGroups)
-                    .map(root -> new GroupNodeViewModel(newDatabase.get(), stateManager, taskExecutor, root, localDragboard, preferences))
-                    .orElse(GroupNodeViewModel.getAllEntriesGroup(newDatabase.get(), stateManager, taskExecutor, localDragboard, preferences));
-
-            rootGroup.setValue(newRoot);
-            if (stateManager.getSelectedGroups(newDatabase.get()).isEmpty()) {
-                stateManager.setSelectedGroups(newDatabase.get(), List.of(newRoot.getGroupNode()));
-            }
-            selectedGroups.setAll(
-                    stateManager.getSelectedGroups(newDatabase.get()).stream()
-                                .map(selectedGroup -> new GroupNodeViewModel(newDatabase.get(), stateManager, taskExecutor, selectedGroup, localDragboard, preferences))
-                                .collect(Collectors.toList()));
-        } else {
-            rootGroup.setValue(null);
-        }
    currentDatabase = newDatabase;
-        newDatabase.ifPresent(_ -> addGroupImportEntries(rootGroup.get()));
-    }
-
-    /// Creates the "Imported entries" group if enabled and missing.
-    /// Selection is disabled to prevent focus theft when switching tabs.
-    private void addGroupImportEntries(GroupNodeViewModel parent) {
-        if (!preferences.getLibraryPreferences().shouldAddImportedEntries()) {
+        if (newDatabase.isEmpty()) {
+            rootGroup.setValue(null);
        return;
    }
-        String groupName = preferences.getLibraryPreferences().getAddImportedEntriesGroupName();
-        boolean groupExists = parent.getGroupNode()
-                                    .getChildren()
-                                    .stream()
-                                    .map(GroupTreeNode::getGroup)
-                                    .anyMatch(grp -> grp instanceof ExplicitGroup && grp.getName().equalsIgnoreCase(groupName));
-        if (!groupExists) {
-            currentDatabase.ifPresent(db -> {
-                char keywordSeparator = preferences.getBibEntryPreferences().getKeywordSeparator();
-                AbstractGroup importEntriesGroup = new ExplicitGroup(groupName, GroupHierarchyType.INDEPENDENT, keywordSeparator);
-                GroupTreeNode newSubgroup = parent.addSubgroup(importEntriesGroup);
-                newSubgroup.moveTo(parent.getGroupNode(), 0);
-                writeGroupChangesToMetaData();
-            });
+        GroupNodeViewModel newRoot = newDatabase
+                .map(BibDatabaseContext::getMetaData)
+                .flatMap(MetaData::getGroups)
+                .map(root -> new GroupNodeViewModel(newDatabase.get(), stateManager, taskExecutor, root, localDragboard, preferences))
+                .orElse(GroupNodeViewModel.getAllEntriesGroup(newDatabase.get(), stateManager, taskExecutor, localDragboard, preferences));
+
+        rootGroup.setValue(newRoot);
+        if (stateManager.getSelectedGroups(newDatabase.get()).isEmpty()) {
+            stateManager.setSelectedGroups(newDatabase.get(), List.of(newRoot.getGroupNode()));
    }
+        selectedGroups.setAll(
+                stateManager.getSelectedGroups(newDatabase.get()).stream()
+                            .map(selectedGroup -> new GroupNodeViewModel(newDatabase.get(), stateManager, taskExecutor, selectedGroup, localDragboard, preferences))
+                            .collect(Collectors.toList()));
}
Evidence
GroupTreeViewModel no longer creates the “Imported entries” group on active database changes, while
AddGroupImportEntriesAction is only wired into the file-open pipeline (OpenDatabaseAction). New
libraries are created through NewDatabaseAction without running post-open actions, and ImportHandler
only adds entries to an already-existing group (it explicitly does not create it), so the feature
silently does nothing for new/untitled libraries. The existing unit test suite still expects
GroupTreeViewModel to create this group when enabled, which will now fail.

jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java[164-187]
jabgui/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java[57-66]
jabgui/src/main/java/org/jabref/gui/importer/NewDatabaseAction.java[23-28]
jabgui/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java[539-552]
jabgui/src/test/java/org/jabref/gui/groups/GroupTreeViewModelTest.java[205-226]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The “Imported entries” group is only created during the **file-open** flow (post-open actions), so **new/untitled libraries** never get the group when the preference is enabled. As a result, imports into new libraries won’t be assigned to the group, and existing unit tests expecting GroupTreeViewModel to create the group will fail.
### Issue Context
- Group creation was removed from `GroupTreeViewModel.onActiveDatabaseChanged`.
- `AddGroupImportEntriesAction` is only registered in `OpenDatabaseAction.POST_OPEN_ACTIONS`.
- `NewDatabaseAction` creates a new `BibDatabaseContext` and adds a tab, but does not run post-open actions.
- `ImportHandler.addToImportEntriesGroup` only adds to an existing group and will not create it.
### Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/importer/NewDatabaseAction.java[23-28]
- jabgui/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java[57-66]
- jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java[164-187]
- jabgui/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java[539-552]
- jabgui/src/test/java/org/jabref/gui/groups/GroupTreeViewModelTest.java[205-226]
### What to change
- Ensure the “Imported entries” group is created for **new libraries** too (e.g., invoke the same logic used by `AddGroupImportEntriesAction` during new-library creation, or add a shared helper that can be called from both open and new flows).
- Update/adjust the GroupTreeViewModel tests to reflect the new responsibility boundary (either restore creation in the view model for non-open flows, or change tests to validate group creation through the new action/hook).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Collectors.toList() used📘 Rule violation ⚙ Maintainability
Description
The newly added stream code uses collect(Collectors.toList()) where the modern Stream.toList()
would be clearer and consistent with the configured modern Java toolchain expectations. This
introduces an outdated Java idiom in new/modified code.
Code

jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java[R183-186]

+        selectedGroups.setAll(
+                stateManager.getSelectedGroups(newDatabase.get()).stream()
+                            .map(selectedGroup -> new GroupNodeViewModel(newDatabase.get(), stateManager, taskExecutor, selectedGroup, localDragboard, preferences))
+                            .collect(Collectors.toList()));
Evidence
PR Compliance ID 4 requires preferring modern Java APIs/idioms in new/changed code; the modified
lines use collect(Collectors.toList()) for a simple terminal collection where toList() is
available and preferred.

AGENTS.md
jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java[183-186]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New/modified code uses the older `collect(Collectors.toList())` idiom instead of the modern `Stream.toList()`.
## Issue Context
The project targets a modern Java toolchain and prefers newer standard library idioms when available.
## Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java[183-186]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Changelog entry wording unclear 📘 Rule violation ⚙ Maintainability
Description
The added CHANGELOG.md bullet is awkwardly phrased (fixed an issue for marking...) and may be
unclear to end users. This reduces the professionalism/readability of user-facing release notes.
Code

CHANGELOG.md[99]

+- We fixed an issue for marking a library as modified when "imported entries" group was enabled.
Evidence
PR Compliance IDs 31 and 37 require end-user oriented, professional, well-formatted release notes;
the added sentence contains a grammatical/phrasing issue that can confuse readers.

AGENTS.md
CHANGELOG.md[99-99]
Best Practice: Learned patterns

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The newly added CHANGELOG bullet is grammatically awkward and may not be easily understood by end users.
## Issue Context
CHANGELOG entries are user-facing release notes and should be professionally written and clear.
## Fix Focus Areas
- CHANGELOG.md[99-99]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@Siedlerchr

Copy link
Copy Markdown
Member

address the qodo points

@Siedlerchr Siedlerchr added this pull request to the merge queue May 3, 2026
@github-actions github-actions Bot added the status: to-be-merged PRs which are accepted and should go into the merge-queue. label May 3, 2026
Merged via the queue into main with commit 3fd3b07 May 3, 2026
57 of 58 checks passed
@Siedlerchr Siedlerchr deleted the fix-changeddb-imported-entries branch May 3, 2026 17:44
Siedlerchr added a commit to FynnianB/jabref that referenced this pull request May 4, 2026
…rity

* upstream/main: (204 commits)
  New Crowdin updates (JabRef#15669)
  Fix OpenRewrite (JabRef#15670)
  Udpate heylogs (and fix CHANGELOG.md) (JabRef#15671)
  Improve security and prevent shell injection for push2applications (JabRef#15628)
  Fix depdency analysis (JabRef#15668)
  Always use CI-local "gradle", instead of gradlew (JabRef#15667)
  Change OpenRewrite task to use rewriteDryRun (JabRef#15664)
  Add small documentation to parameter (JabRef#15666)
  Fix markbaseChanged for "imported entries" (JabRef#15610)
  Add forgotten --fresh
  chore(deps): update dependency com.github.ben-manes.caffeine:caffeine to v3.2.4 (JabRef#15662)
  chore(deps): update jackson monorepo to v3.1.3 (JabRef#15659)
  chore(deps): update dependency org.glassfish.hk2:hk2-utils to v4.0.1 (JabRef#15657)
  chore(deps): update dependency org.glassfish.hk2:hk2-locator to v4.0.1 (JabRef#15656)
  fix gemsfx missing icon resolving (JabRef#15655)
  chore(deps): update dependency org.glassfish.hk2:hk2-api to v4.0.1 (JabRef#15654)
  chore(deps): update dependency org.postgresql:postgresql to v42.7.11 (JabRef#15634)
  Chore(deps): Bump tools.jackson:jackson-bom in /versions (JabRef#15653)
  Chore(deps): Bump dev.langchain4j:langchain4j-bom in /versions (JabRef#15652)
  Chore(deps): Bump com.dlsc.gemsfx:gemsfx in /versions (JabRef#15651)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: to-be-merged PRs which are accepted and should go into the merge-queue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants