Skip to content

Fix for group focus after removing the filter (14084)#14883

Merged
koppor merged 13 commits intoJabRef:mainfrom
ZiadAbdElFatah:fix-for-issue-14084
Feb 2, 2026
Merged

Fix for group focus after removing the filter (14084)#14883
koppor merged 13 commits intoJabRef:mainfrom
ZiadAbdElFatah:fix-for-issue-14084

Conversation

@ZiadAbdElFatah
Copy link
Copy Markdown
Contributor

@ZiadAbdElFatah ZiadAbdElFatah commented Jan 20, 2026

User description

Closes 14084

I saved the group selected after applying a filter, and when the filter changes, I made sure that the new filter isn't empty to ensure the case of clearing, if it is empty I assign the group selected before as the current selected one.

Steps to test

1.image
2.image
3.image

Mandatory checks


PR Type

Bug fix


Description

  • Preserves group selection when clearing filter text

  • Saves selected groups before filter change, restores if filter becomes empty

  • Uses Platform.runLater to ensure UI update after filter change

  • Removes unnecessary ENABLE_JAVADOC_FORMATTING configuration option


Diagram Walkthrough

flowchart LR
  A["User clears filter"] --> B["Save current selected groups"]
  B --> C["Apply new empty filter"]
  C --> D["Restore previous selection"]
  D --> E["Update group tree view"]
Loading

File Walkthrough

Relevant files
Bug fix
GroupTreeView.java
Restore group selection on filter clear                                   

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

  • Saves selected groups before applying filter changes
  • Checks if new filter is empty or null
  • Restores previous group selection when filter is cleared
  • Uses Platform.runLater for thread-safe UI updates
+10/-0   
Configuration changes
Project.xml
Remove javadoc formatting configuration                                   

.idea/codeStyles/Project.xml

  • Removes ENABLE_JAVADOC_FORMATTING configuration option
+0/-1     

@github-actions
Copy link
Copy Markdown
Contributor

Hey @ZiadAbdElFatah! 👋

Thank you for contributing to JabRef!

We have automated checks in place, based on which you will soon get feedback if any of them are failing. We also use Qodo for review assistance. It will update your pull request description with a review help and offer suggestions to improve the pull request.

After all automated checks pass, a maintainer will also review your contribution. Once that happens, you can go through their comments in the "Files changed" tab and act on them, or reply to the conversation if you have further inputs. You can read about the whole pull request process in our contribution guide.

Please ensure that your pull request is in line with our AI Usage Policy and make necessary disclosures.

@github-actions github-actions Bot added first contrib status: changes-required Pull requests that are not yet complete labels Jan 20, 2026
@ZiadAbdElFatah
Copy link
Copy Markdown
Contributor Author

I need help here.
I think i accomplished the main goal of the issue, as I tried many cases and all the results were as expected, but i got these github errors that i don't understand, so i don't know what should i do.

Your code currently does not meet JabRef's code guidelines. IntelliJ auto format covers some cases. There seem to be issues with your code style and autoformat configuration. Please reformat your code (Ctrl+Alt+L) and commit, then push.

I tried to reformat my code but when typed (Ctrl+Alt+L) it changed some lines that are not the lines i wrote, and also didn't change any of the lines i wrote.

@ZiadAbdElFatah
Copy link
Copy Markdown
Contributor Author

This is my first pr with JabRef, i went with the docs step by step, in this step of checkstyle setup
image
after enabling JavaDoc formatting this file change happened
https://github.com/JabRef/jabref/pull/14883/files#diff-11745b49c51a1ecde7d4d4cffda53d76594e6711ec81bf1148a05942b0438141

When i tried to restore the file to its original state the JavaDoc formatting is disabled.
image
image

I din't know if this is a bug or what.

@ZiadAbdElFatah ZiadAbdElFatah marked this pull request as ready for review January 21, 2026 10:57
@ZiadAbdElFatah ZiadAbdElFatah marked this pull request as draft January 21, 2026 10:57
@qodo-free-for-open-source-projects
Copy link
Copy Markdown
Contributor

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

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🟡
🎫 #14084
🟢 Keep the group focused/selected after clearing the search filter in the group interface
When a user clears the search field, the previously selected group should remain selected
The implementation should handle the filter clearing scenario specifically
Verify that the group selection is properly restored in the UI after clearing the search
filter through manual testing
Confirm that the Platform.runLater timing is appropriate and doesn't cause UI flickering
or race conditions
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status:
Generic variable naming: Variable newFilter is a generic name that doesn't clearly express its purpose as a
search filter text value

Referred Code
final String newFilter = searchField.getText();
viewModel.filterTextProperty().setValue(newFilter);

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Missing error handling: No error handling for potential exceptions when restoring previous selection in
Platform.runLater or when accessing prevSelected list

Referred Code
Platform.runLater(() -> {
    viewModel.selectedGroupsProperty().setAll(prevSelected);
});

Learn more about managing compliance generic rules or creating your own custom rules

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-free-for-open-source-projects
Copy link
Copy Markdown
Contributor

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

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix incorrect group selection restoration

Refactor the group filter logic to correctly restore the group selection. Save
the selection when filtering begins and restore it from the saved state when the
filter is cleared.

jabgui/src/main/java/org/jabref/gui/groups/GroupTreeView.java [218-231]

-final Timer searchTask = FxTimer.create(Duration.ofMillis(400), () -> {
-    LOGGER.debug("Run group search {}", searchField.getText());
+private List<GroupNodeViewModel> selectionBeforeFiltering;
+...
+// In initialize() method
+...
+    final Timer searchTask = FxTimer.create(Duration.ofMillis(400), () -> {
+        LOGGER.debug("Run group search {}", searchField.getText());
+        final String newFilter = searchField.getText();
+        viewModel.filterTextProperty().setValue(newFilter);
 
-    final List<GroupNodeViewModel> prevSelected = new ArrayList<>(viewModel.selectedGroupsProperty());
-    viewModel.filterTextProperty().setValue(searchField.textProperty().getValue());
-    final String newFilter = searchField.getText();
-    viewModel.filterTextProperty().setValue(newFilter);
+        if (newFilter.isEmpty()) {
+            Platform.runLater(() -> {
+                if (selectionBeforeFiltering != null) {
+                    viewModel.selectedGroupsProperty().setAll(selectionBeforeFiltering);
+                }
+            });
+        }
+    });
+    searchField.textProperty().addListener((observable, oldValue, newValue) -> {
+        if (oldValue.isEmpty() && !newValue.isEmpty()) {
+            // We are starting to filter, so we save the current selection
+            selectionBeforeFiltering = new ArrayList<>(viewModel.selectedGroupsProperty());
+        }
+        searchTask.restart();
+    });
 
-    if (newFilter == null || newFilter.isEmpty()) {
-        Platform.runLater(() -> {
-            viewModel.selectedGroupsProperty().setAll(prevSelected);
-        });
-    }
-});
-

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a critical logic flaw in the PR's implementation where the previously selected group is not restored correctly, and it provides a robust solution.

High
  • Update

@ZiadAbdElFatah ZiadAbdElFatah marked this pull request as ready for review January 21, 2026 15:17
@qodo-free-for-open-source-projects
Copy link
Copy Markdown
Contributor

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🟢
🎫 #14084
🟢 Keep the group focused/selected after clearing the search filter in the group interface
When a user clears the search field, the previously selected group should remain selected
The group tree should maintain its selection state when transitioning from filtered to
unfiltered view
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status:
Generic variable name: Variable prevSelected uses abbreviated naming that reduces readability; should be
previouslySelectedGroups to clearly express its purpose

Referred Code
final List<GroupNodeViewModel> prevSelected = new ArrayList<>(viewModel.selectedGroupsProperty());
viewModel.filterTextProperty().setValue(searchField.textProperty().getValue());

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-free-for-open-source-projects
Copy link
Copy Markdown
Contributor

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

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
General
Remove redundant property setting call
Suggestion Impact:The suggestion was implemented. The redundant call to viewModel.filterTextProperty().setValue() on line 222 was removed. The commit also improved the code by introducing a new variable 'filterText' to store the value from searchField.textProperty().getValue() and using it consistently, which aligns with the suggestion's intent to eliminate redundancy.

code diff:

-            final List<GroupNodeViewModel> prevSelected = new ArrayList<>(viewModel.selectedGroupsProperty());
+            final List<GroupNodeViewModel> previouslySelectedGroup = new ArrayList<>(viewModel.selectedGroupsProperty());
             viewModel.filterTextProperty().setValue(searchField.textProperty().getValue());
-            final String newFilter = searchField.getText();
-            viewModel.filterTextProperty().setValue(newFilter);
-
-            if (newFilter == null || newFilter.isEmpty()) {
+            final String filterText = searchField.textProperty().getValue();
+            if (filterText == null || filterText.isEmpty()) {

Remove the redundant call to viewModel.filterTextProperty().setValue() as it is
called twice with the same value.

jabgui/src/main/java/org/jabref/gui/groups/GroupTreeView.java [221-224]

 final List<GroupNodeViewModel> prevSelected = new ArrayList<>(viewModel.selectedGroupsProperty());
-viewModel.filterTextProperty().setValue(searchField.textProperty().getValue());
 final String newFilter = searchField.getText();
 viewModel.filterTextProperty().setValue(newFilter);

[Suggestion processed]

Suggestion importance[1-10]: 4

__

Why: The suggestion correctly identifies that filterTextProperty is set twice with the same value. Removing the redundant call on line 222 improves code clarity and is a good practice, although its performance impact is negligible.

Low
  • More

@github-actions github-actions Bot removed the status: changes-required Pull requests that are not yet complete label Jan 21, 2026
@ZiadAbdElFatah
Copy link
Copy Markdown
Contributor Author

Ignore the comments above, i saw this #14860 got merged, so i updated the branch and everything is fine now.

@koppor koppor added the status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers label Jan 23, 2026
final String filterText = searchField.textProperty().getValue();
if (filterText == null || filterText.isEmpty()) {
Platform.runLater(() -> {
viewModel.selectedGroupsProperty().setAll(previouslySelectedGroup);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this work even if the current group is not shown? -- Java comment needed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I just tried it and noticed that if the current group is not shown, it can't be selected.

final List<GroupNodeViewModel> previouslySelectedGroup = new ArrayList<>(viewModel.selectedGroupsProperty());
viewModel.filterTextProperty().setValue(searchField.textProperty().getValue());
final String filterText = searchField.textProperty().getValue();
if (filterText == null || filterText.isEmpty()) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can filterText be null in some cases? I know that AI generates this code, but I want to add some confidence.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I would like to add confidence too. So well, for the code logic it is 100% my logic no any AI logic here. For the code itself, I wrote the code at first and gave it to ChatGPT to review it, it told me to add filterText == null to be more secure so i added it.
I don't have AI agent integrated in intillij so there will not be any code generated with AI only, and be sure that I will not submit a single line of code without fully understand it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would like to add confidence too.

What is the result? Logger used? Breakpoint used?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would like to add confidence too.

What is the result? Logger used? Breakpoint used?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Is this reply on the correct comment?
If it is so, I don't really relate.

LOGGER.debug("Run group search {}", searchField.getText());

final List<GroupNodeViewModel> previouslySelectedGroup = new ArrayList<>(viewModel.selectedGroupsProperty());
viewModel.filterTextProperty().setValue(searchField.textProperty().getValue());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Isn't the main reason at the listeners running when setValue is called?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

After implementing the solution in this pr, I spent about two days trying to fix the problem from its core and tried to fix the listeners that interact with the selected groups after changing the filter but I couldn't find it, but I am still trying.
A hint would be appreciated a lot.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If we keep this solution, a short Java comment should be put above

Maybe

/// Ensure that group selection is kept after clearance of search

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I like the solution, because it also helps when typing something in the field.

@github-actions github-actions Bot added status: changes-required Pull requests that are not yet complete and removed status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers labels Jan 27, 2026
@ZiadAbdElFatah
Copy link
Copy Markdown
Contributor Author

I think this solution is better, where the selection stays as long as the user decides to change it. Whether the selected group is shown or not.

@github-actions github-actions Bot removed the status: changes-required Pull requests that are not yet complete label Jan 28, 2026
@ZiadAbdElFatah ZiadAbdElFatah requested a review from koppor January 28, 2026 15:55
@github-actions github-actions Bot added status: changes-required Pull requests that are not yet complete and removed status: changes-required Pull requests that are not yet complete labels Jan 28, 2026
@koppor koppor added the status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers label Jan 30, 2026
@koppor
Copy link
Copy Markdown
Member

koppor commented Jan 30, 2026

@ZiadAbdElFatah Please add a CHANGELOG.md entry.

Copy link
Copy Markdown
Member

@koppor koppor left a comment

Choose a reason for hiding this comment

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

Add CHANGELOG.md entry - and a small java comment, then this is good to go.

LOGGER.debug("Run group search {}", searchField.getText());

final List<GroupNodeViewModel> previouslySelectedGroup = new ArrayList<>(viewModel.selectedGroupsProperty());
viewModel.filterTextProperty().setValue(searchField.textProperty().getValue());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If we keep this solution, a short Java comment should be put above

Maybe

/// Ensure that group selection is kept after clearance of search

LOGGER.debug("Run group search {}", searchField.getText());

final List<GroupNodeViewModel> previouslySelectedGroup = new ArrayList<>(viewModel.selectedGroupsProperty());
viewModel.filterTextProperty().setValue(searchField.textProperty().getValue());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I like the solution, because it also helps when typing something in the field.

@github-actions github-actions Bot added status: changes-required Pull requests that are not yet complete and removed status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers labels Jan 30, 2026
@ZiadAbdElFatah
Copy link
Copy Markdown
Contributor Author

ZiadAbdElFatah commented Jan 30, 2026

Add CHANGELOG.md entry - and a small java comment, then this is good to go.

Ok, that is nice. I am sorry I will be out today, once I return tomorrow I will make these changes.
Thanks for your help.

@ZiadAbdElFatah ZiadAbdElFatah requested a review from koppor January 31, 2026 00:17
@github-actions
Copy link
Copy Markdown
Contributor

Your pull request conflicts with the target branch.

Please merge with your code. For a step-by-step guide to resolve merge conflicts, see https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/resolving-a-merge-conflict-using-the-command-line.

@github-actions github-actions Bot removed the status: changes-required Pull requests that are not yet complete label Jan 31, 2026
@ZiadAbdElFatah
Copy link
Copy Markdown
Contributor Author

@koppor sorry for the mention, but is there anything else remaining to merge this pr?

Comment thread CHANGELOG.md Outdated
@koppor koppor enabled auto-merge February 2, 2026 09:16
@koppor koppor added this pull request to the merge queue Feb 2, 2026
@github-actions github-actions Bot added the status: to-be-merged PRs which are accepted and should go into the merge-queue. label Feb 2, 2026
Merged via the queue into JabRef:main with commit 50cdffe Feb 2, 2026
52 checks passed
@ZiadAbdElFatah ZiadAbdElFatah deleted the fix-for-issue-14084 branch February 2, 2026 10:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

first contrib Review effort 2/5 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.

Keep group focussed after clear search

2 participants