Skip to content

Commit

Permalink
Merge pull request #21622 from ccordoba12/find-improvements
Browse files Browse the repository at this point in the history
PR: Make some UI/UX improvements to the Find pane
  • Loading branch information
ccordoba12 authored Dec 20, 2023
2 parents a71a7e0 + 1ca7003 commit 3cf7dc5
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 121 deletions.
2 changes: 1 addition & 1 deletion spyder/plugins/findinfiles/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def get_icon(cls):
def on_initialize(self):
self.create_action(
FindInFilesActions.FindInFiles,
text=_("Find in files"),
text=_("Search text in the Find pane"),
tip=_("Search text in multiple files"),
triggered=self.find,
register_shortcut=True,
Expand Down
6 changes: 4 additions & 2 deletions spyder/plugins/findinfiles/tests/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# Local imports
from spyder.config.manager import CONF
from spyder.plugins.findinfiles.plugin import FindInFiles
from spyder.plugins.findinfiles.widgets.combobox import SELECT_OTHER
from spyder.plugins.findinfiles.widgets.combobox import SearchInComboBoxItems


LOCATION = osp.realpath(osp.join(os.getcwd(), osp.dirname(__file__)))
Expand Down Expand Up @@ -59,7 +59,9 @@ def test_closing_plugin(findinfiles, qtbot, mocker, tmpdir):
'spyder.plugins.findinfiles.widgets.combobox.getexistingdirectory',
return_value=external_path
)
path_selection_combo.setCurrentIndex(SELECT_OTHER)
path_selection_combo.setCurrentIndex(
SearchInComboBoxItems.SelectAnotherDirectory
)

assert path_selection_combo.get_external_paths() == expected_results

Expand Down
141 changes: 86 additions & 55 deletions spyder/plugins/findinfiles/widgets/combobox.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@

# ---- Constants
# ----------------------------------------------------------------------------
CWD = 0
PROJECT = 1
FILE_PATH = 2
SELECT_OTHER = 4
CLEAR_LIST = 5
EXTERNAL_PATHS = 7
class SearchInComboBoxItems:
Cwd = 0
Project = 1
File = 2
FirstSeparator = 3
SelectAnotherDirectory = 4
ClearList = 5
SecondSeparator = 6
ExternalPaths = 7

MAX_PATH_HISTORY = 15


Expand All @@ -43,46 +47,35 @@ class SearchInComboBox(SpyderComboBox):
def __init__(self, external_path_history=[], parent=None, id_=None):
super().__init__(parent)
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.setToolTip(_('Search directory'))
self.setEditable(False)

self.path = ''
self.project_path = None
self.file_path = None
self.external_path = None
self.project_path = ''
self.file_path = ''
self.external_path = ''

if id_ is not None:
self.ID = id_

self.addItem(_("Current working directory"))
ttip = ("Search in all files and directories present on the current"
" Spyder path")
self.setItemData(0, ttip, Qt.ToolTipRole)

self.addItem(_("Project"))
ttip = _("Search in all files and directories present on the"
" current project path (if opened)")
self.setItemData(1, ttip, Qt.ToolTipRole)
self.model().item(1, 0).setEnabled(False)

self.addItem(_("File").replace('&', ''))
ttip = _("Search in current opened file")
self.setItemData(2, ttip, Qt.ToolTipRole)
self.model().item(SearchInComboBoxItems.Project, 0).setEnabled(False)

self.insertSeparator(3)
self.addItem(_("Current file").replace('&', ''))

self.addItem(_("Select other directory"))
ttip = _("Search in other folder present on the file system")
self.setItemData(4, ttip, Qt.ToolTipRole)
self.insertSeparator(SearchInComboBoxItems.FirstSeparator)

self.addItem(_("Clear this list"))
ttip = _("Clear the list of other directories")
self.setItemData(5, ttip, Qt.ToolTipRole)
self.addItem(_("Select another directory"))
self.addItem(_("Clear the list of other directories"))

self.insertSeparator(6)
self.insertSeparator(SearchInComboBoxItems.SecondSeparator)

for path in external_path_history:
self.add_external_path(path)
if external_path_history:
for path in external_path_history:
self.add_external_path(path)
else:
self.set_state_other_dirs_items(False)

self.currentIndexChanged.connect(self.path_selection_changed)
self.view().installEventFilter(self)
Expand All @@ -96,33 +89,41 @@ def add_external_path(self, path):
"""
if not osp.exists(path):
return
self.set_state_other_dirs_items(True)
self.removeItem(self.findText(path))
self.addItem(path)
self.setItemData(self.count() - 1, path, Qt.ToolTipRole)
while self.count() > MAX_PATH_HISTORY + EXTERNAL_PATHS:
self.removeItem(EXTERNAL_PATHS)

while (
self.count() >
(MAX_PATH_HISTORY + SearchInComboBoxItems.ExternalPaths)
):
self.removeItem(SearchInComboBoxItems.ExternalPaths)

def get_external_paths(self):
"""Returns a list of the external paths listed in the combobox."""
return [str(self.itemText(i))
for i in range(EXTERNAL_PATHS, self.count())]
return [
str(self.itemText(i))
for i in range(SearchInComboBoxItems.ExternalPaths, self.count())
]

def clear_external_paths(self):
"""Remove all the external paths listed in the combobox."""
while self.count() > EXTERNAL_PATHS:
self.removeItem(EXTERNAL_PATHS)
while self.count() > SearchInComboBoxItems.ExternalPaths:
self.removeItem(SearchInComboBoxItems.ExternalPaths)
self.set_state_other_dirs_items(False)

def get_current_searchpath(self):
"""
Returns the path corresponding to the currently selected item
in the combobox.
"""
idx = self.currentIndex()
if idx == CWD:
if idx == SearchInComboBoxItems.Cwd:
return self.path
elif idx == PROJECT:
elif idx == SearchInComboBoxItems.Project:
return self.project_path
elif idx == FILE_PATH:
elif idx == SearchInComboBoxItems.File:
return self.file_path
else:
return self.external_path
Expand All @@ -131,15 +132,17 @@ def set_current_searchpath_index(self, index):
"""Set the current index of this combo box."""
if index is not None:
index = min(index, self.count() - 1)
index = CWD if index in [CLEAR_LIST, SELECT_OTHER] else index
if index in [SearchInComboBoxItems.ClearList,
SearchInComboBoxItems.SelectAnotherDirectory]:
index = SearchInComboBoxItems.Cwd
else:
index = CWD
index = SearchInComboBoxItems.Cwd

self.setCurrentIndex(index)

def is_file_search(self):
"""Returns whether the current search path is a file."""
if self.currentIndex() == FILE_PATH:
if self.currentIndex() == SearchInComboBoxItems.File:
return True
else:
return False
Expand All @@ -148,22 +151,22 @@ def is_file_search(self):
def path_selection_changed(self):
"""Handles when the current index of the combobox changes."""
idx = self.currentIndex()
if idx == SELECT_OTHER:
if idx == SearchInComboBoxItems.SelectAnotherDirectory:
external_path = self.select_directory()
if len(external_path) > 0:
self.add_external_path(external_path)
self.setCurrentIndex(self.count() - 1)
else:
self.setCurrentIndex(CWD)
elif idx == CLEAR_LIST:
self.setCurrentIndex(SearchInComboBoxItems.Cwd)
elif idx == SearchInComboBoxItems.ClearList:
reply = QMessageBox.question(
self, _("Clear other directories"),
_("Do you want to clear the list of other directories?"),
QMessageBox.Yes | QMessageBox.No)
if reply == QMessageBox.Yes:
self.clear_external_paths()
self.setCurrentIndex(CWD)
elif idx >= EXTERNAL_PATHS:
self.setCurrentIndex(SearchInComboBoxItems.Cwd)
elif idx >= SearchInComboBoxItems.ExternalPaths:
self.external_path = str(self.itemText(idx))

@Slot()
Expand All @@ -187,27 +190,55 @@ def set_project_path(self, path):
if the value of path is None.
"""
if path is None:
self.project_path = None
self.model().item(PROJECT, 0).setEnabled(False)
if self.currentIndex() == PROJECT:
self.setCurrentIndex(CWD)
self.project_path = ''
self.model().item(
SearchInComboBoxItems.Project, 0
).setEnabled(False)
if self.currentIndex() == SearchInComboBoxItems.Project:
self.setCurrentIndex(SearchInComboBoxItems.Cwd)
else:
path = osp.abspath(path)
self.project_path = path
self.model().item(PROJECT, 0).setEnabled(True)
self.model().item(
SearchInComboBoxItems.Project, 0
).setEnabled(True)

def set_state_other_dirs_items(self, enabled):
"""
Set the enabled/visible state of items that change when other
directories are added/removed to/from the combobox.
"""
# The second separator needs to be visible only when the user has added
# other directories.
self.view().setRowHidden(
SearchInComboBoxItems.SecondSeparator, not enabled
)

# The ClearList item needs to be disabled if the user has not added
# other directories
self.model().item(
SearchInComboBoxItems.ClearList, 0
).setEnabled(enabled)

def eventFilter(self, widget, event):
"""Used to handle key events on the QListView of the combobox."""
if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Delete:
index = self.view().currentIndex().row()
if index >= EXTERNAL_PATHS:
if index >= SearchInComboBoxItems.ExternalPaths:
# Remove item and update the view.
self.removeItem(index)
self.showPopup()

# Set the view selection so that it doesn't bounce around.
new_index = min(self.count() - 1, index)
new_index = 0 if new_index < EXTERNAL_PATHS else new_index
if new_index < SearchInComboBoxItems.ExternalPaths:
new_index = SearchInComboBoxItems.Cwd
self.set_state_other_dirs_items(False)
self.hidePopup()

self.view().setCurrentIndex(self.model().index(new_index, 0))
self.setCurrentIndex(new_index)

return True

return super().eventFilter(widget, event)
19 changes: 11 additions & 8 deletions spyder/plugins/findinfiles/widgets/main_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ def __init__(self, name=None, plugin=None, parent=None):
self._search_in_label_width = None
self._exclude_label_width = None
self._is_shown = False
self._is_first_time = False

search_text = self.get_conf('search_text', '')
path_history = self.get_conf('path_history', [])
Expand Down Expand Up @@ -348,22 +349,18 @@ def setup(self):
self.set_max_results_action,
menu=menu,
)
self.set_pane_empty()

def set_pane_empty(self):
if self.result_browser.data:
self.stacked_widget.setCurrentWidget(self.result_browser)
else:
self.stacked_widget.setCurrentWidget(self.pane_empty)
# Set pane_empty widget at the beginning
self.stacked_widget.setCurrentWidget(self.pane_empty)

def update_actions(self):
self.find_action.setIcon(self.create_icon(
'stop' if self.running else 'find'))
'stop' if self.running else 'find')
)

if self.extras_toolbar and self.more_options_action:
self.extras_toolbar.setVisible(
self.more_options_action.isChecked())
self.set_pane_empty()

@on_conf_change(option='more_options')
def on_more_options_update(self, value):
Expand Down Expand Up @@ -645,6 +642,12 @@ def find(self):
If there is no search running, this will start the search. If there is
a search running, this will stop it.
"""
# Show result_browser the first time a user performs a search and leave
# it shown afterwards.
if not self._is_first_time:
self.stacked_widget.setCurrentWidget(self.result_browser)
self._is_first_time = True

if self.running:
self.stop()
else:
Expand Down
Loading

0 comments on commit 3cf7dc5

Please sign in to comment.