Repository: spyder-ide/spyder
Pull request: PR: Fix case sensitivity and history when searching and replacing text in the Editor
<!--- Make sure to read the Contributing Guidelines:                   --->
<!--- https://github.com/spyder-ide/spyder/blob/master/CONTRIBUTING.md --->
<!--- and follow PEP 8, PEP 257 and Spyder's code style:               --->
<!--- https://github.com/spyder-ide/spyder/wiki/Dev:-Coding-Style      --->

## Description of Changes
Fix search and replace case sensitivity and history in editor 

<!--- Explain what you've done and why --->




### Issue(s) Resolved

<!--- List the issue(s) below, in the form "Fixes #1234"; one per line --->

Fixes #23597


### Affirmation

By submitting this Pull Request or typing my (user)name below,
I affirm the [Developer Certificate of Origin](https://developercertificate.org)
with respect to all commits and content included in this PR,
and understand I am releasing the same under Spyder's MIT (Expat) license.

<!--- TYPE YOUR USER/NAME AFTER THE FOLLOWING: --->
I certify the above statement is true and correct:
@jsbautista 
<!--- Thanks for your help making Spyder better for everyone! --->


Problem statement:
Search and replace case sensitivity and history in editor
So this is in the irritation category of "was that an intentional feature?". In (at least) Spyder 6.0.3 on Windows the history of search and replace terms in the editor is not case sensitive. This is annoying if you are trying to do a case sensitive search and replace!

Steps to reproduce:
1). Do a search and replace of "javascript" for "python"
2) Enable case sensitive searching
3) Now try to replace "JavaScript" with "Python"

Result, as you defocus each of the search and replace boxes the mixed case string is replaced with the lowercase version from history - thereby making the case sensitive search rather tricky....

Expected Behaviour:

The replacement of the search and replace terms from history should be case sensitive - at least if a case sensitive search is enabled and probably in all cases [no pun intended] anyway.

Hints from issue discussion:
Hi @gb119 thank you for the report! I think I was unable to reproduce this but maybe I'm not understanding correctly the steps to reproduce 🤔 Could it be possible for you to share a GIF/Video showing the behavior described? Let us know!
So this is is bit of stupid example but it demonstrates the problem... I'll leave the soundtrack of cursing to the imagination!
![Image](https://github.com/user-attachments/assets/7ee0eaa9-ecb4-4482-a91e-0c8bb7cb6a5a)
Thank you for the preview @gb119 ! I think I was able to reproduce this on my side too, quite a strange behavior indeed! As a way to reduce the appearance of this issue seems like pressing `Return`/`Enter` before changing the focus between inputs helps 🤔 We will check this on a future release :+1:

Commit message: Fix case sensitivity and history

Patch to review:
diff --git a/spyder/widgets/comboboxes.py b/spyder/widgets/comboboxes.py
index 2a5b9944469..e83bb003ba4 100644
--- a/spyder/widgets/comboboxes.py
+++ b/spyder/widgets/comboboxes.py
@@ -70,6 +70,14 @@ def event(self, event):
             self.sig_tab_pressed.emit(True)
             return True
         return super().event(event)
+    
+    def focusOutEvent(self, event):
+        
+        if self.add_current_text_if_valid():
+            self.selected()
+            self.hide_completer()
+
+        super().focusOutEvent(event)
 
     def keyPressEvent(self, event):
         """Qt Override.
@@ -108,10 +116,10 @@ def selected(self):
     def add_text(self, text):
         """Add text to combo box: add a new item if text is not found in
         combo box items."""
-        index = self.findText(text)
+        index = self.findText(text, Qt.MatchCaseSensitive)
         while index != -1:
             self.removeItem(index)
-            index = self.findText(text)
+            index = self.findText(text, Qt.MatchCaseSensitive)
         self.insertItem(0, text)
         index = self.findText('')
         if index != -1:


Code review comments:
diff_hunk: @@ -70,6 +70,14 @@ def event(self, event):
             self.sig_tab_pressed.emit(True)
             return True
         return super().event(event)
+    
+    def focusOutEvent(self, event):
+        
+        if self.add_current_text_if_valid():
+            self.selected()
+            self.hide_completer()
+
+        super().focusOutEvent(event)
path: spyder/widgets/comboboxes.py
text: @user1:
Seems like the Linux and macOS jobs are failing with the latest change. Checking them locally on Windows seems like the search line edit is not able to be refocused with the mouse but the changes kind of  fix the issue :thinking: I think that something like the following fixes the issue and also allows for the search line edit to regain focus with the mouse:

```suggestion

    def focusOutEvent(self, event):
        """Qt Override.

        Handle focus out event to prevent changing current text with some other
        entry in the history that could match the current text in a case insensitive manner.
        See spyder-ide/spyder#23597
        """
        self.add_current_text_if_valid()

        super().focusOutEvent(event)
```

Could you give the suggestion a try @author and see if that also works on your side? Let me know!

@user2:
@user1, is the `return` at the end of your suggestion really necessary? I thought handling Qt events doesn't return anything.

@user1:
I think you are right. Changed the suggestion removing the `return` to simply call `super` :+1:

@user2:
```suggestion
    
    def focusOutEvent(self, event):
        """
        Qt Override.

        Handle focus out event to prevent changing current text with some other
        entry in the history that could match the current text in a case
        insensitive manner.
        See spyder-ide/spyder#23597
        """
        self.add_current_text_if_valid()
        super().focusOutEvent(event)
```

Suggestion of @user1's suggestion with minor style improvements (please apply this one @author).