--- a/src/eric7/UI/FindFileWidget.py Mon Jan 08 11:50:27 2024 +0100 +++ b/src/eric7/UI/FindFileWidget.py Wed Jan 10 09:42:15 2024 +0100 @@ -7,6 +7,7 @@ Module implementing a dialog to search for text in files. """ +import json import os import re import time @@ -83,12 +84,15 @@ super().__init__(parent) self.setupUi(self) + self.__project = project + self.layout().setContentsMargins(0, 3, 0, 0) self.caseToolButton.setIcon(EricPixmapCache.getIcon("caseSensitive")) self.wordToolButton.setIcon(EricPixmapCache.getIcon("wholeWord")) self.escapeToolButton.setIcon(EricPixmapCache.getIcon("esc-code")) self.regexpToolButton.setIcon(EricPixmapCache.getIcon("regexp")) + self.filtersConfigButton.setIcon(EricPixmapCache.getIcon("edit")) self.dirPicker.setMode(EricPathPickerModes.DIRECTORY_MODE) self.dirPicker.setInsertPolicy(QComboBox.InsertPolicy.InsertAtTop) @@ -148,8 +152,7 @@ ) ) - self.__project = project - + self.__populateFiltersSelector() self.populateFileCategories() # ensure the file type tab is the current one @@ -174,6 +177,32 @@ self.__replaceMode = True self.__toggleReplaceMode() + def __populateFiltersSelector(self): + """ + Private method to (re-)populate the file filters selector. + """ + currentFilter = self.filterComboBox.currentText() + self.filterComboBox.clear() + + # add standard entries + self.filterComboBox.addItem("") + self.filterComboBox.addItem(self.tr("All Files"), "*") + + # add configured entries + # filters is a dictionary with the filter text as key and the pattern as value + self.__filters = json.loads( + Preferences.getSettings().value("FindFileWidget/FileFilters", "{}") + # noqa: M613 + ) + for fileFilter in sorted(self.__filters): + self.filterComboBox.addItem(fileFilter, self.__filters[filter]) + + # reselect the current entry + index = self.filterComboBox.findText(currentFilter) + if index == -1: + index = 0 + self.filterComboBox.setCurrentIndex(index) + def populateFileCategories(self): """ Public method to populate the search file categories list. @@ -370,6 +399,21 @@ # only one of regexp or escape can be selected self.escapeToolButton.setChecked(False) + @pyqtSlot() + def on_filtersConfigButton_clicked(self): + """ + Private slot to edit the list of defined file filter entries. + """ + from .FindFileFiltersEditDialog import FindFileFiltersEditDialog + + dlg = FindFileFiltersEditDialog(self.__filters, self) + if dlg.exec() == QDialog.DialogCode.Accepted: + filters = dlg.getFilters() + Preferences.getSettings().setValue( + "FindFileWidget/FileFilters", json.dumps(filters) + ) + self.__populateFiltersSelector() + @pyqtSlot(str) def on_findtextCombo_editTextChanged(self, text): """ @@ -431,13 +475,13 @@ """ self.__enableFindButton() - @pyqtSlot(str) - def on_filterEdit_textEdited(self, text): + @pyqtSlot(int) + def on_filterComboBox_currentIndexChanged(self, index): """ - Private slot to handle the textChanged signal of the file filter edit. + Private slot to handle the selection of a file filter. - @param text (ignored) - @type str + @param index index of the selected entry + @type int """ self.__enableFindButton() @@ -455,7 +499,11 @@ or not os.path.exists(os.path.abspath(self.dirPicker.currentText())) ) ) - or (self.filterCheckBox.isChecked() and self.filterEdit.text() == "") + or ( + self.filterCheckBox.isChecked() + and self.filterComboBox.currentText() == "" + ) + or (self.projectButton.isChecked() and not self.__project.isOpen()) ): self.findButton.setEnabled(False) else: @@ -472,6 +520,20 @@ """ return txt.rstrip("\n\r") + def __buildReFileFilter(self, fileFilter): + """ + Private method to convert a file filter expression into a valid re search + pattern. + + @param fileFilter file filter expression + @type str + @return re search pattern with dot, question mark and star converted + @rtype str + """ + return "^{0}$".format( + fileFilter.strip().replace(".", r"\.").replace("*", ".*").replace("?", ".") + ) + @pyqtSlot() def __stopSearch(self): """ @@ -493,10 +555,9 @@ self.__cancelSearch = False if self.filterCheckBox.isChecked(): - fileFilter = self.filterEdit.text() + fileFilter = self.filterComboBox.currentData() fileFilterList = [ - "^{0}$".format(filter.replace(".", r"\.").replace("*", ".*")) - for filter in fileFilter.split(";") + self.__buildReFileFilter(filter) for filter in fileFilter.split(";") ] filterRe = re.compile("|".join(fileFilterList)) @@ -529,9 +590,7 @@ if itm.checkState() == Qt.CheckState.Checked: filters.extend( [ - "^{0}$".format( - assoc.replace(".", r"\.").replace("*", ".*") - ) + self.__buildReFileFilter(assoc) for assoc in self.__project.getFiletypeAssociations( itm.data(Qt.ItemDataRole.UserRole) ) @@ -545,9 +604,7 @@ if fileType == "SOURCES": filters.extend( [ - "^{0}$".format( - assoc.replace(".", r"\.").replace("*", ".*") - ) + self.__buildReFileFilter(assoc) for assoc in Preferences.getEditorLexerAssocs() if assoc not in self.__project.getFileCategoryExtension( @@ -558,9 +615,7 @@ else: filters.extend( [ - "^{0}$".format( - ext.replace(".", r"\.").replace("*", ".*") - ) + self.__buildReFileFilter(ext) for ext in self.__project.getFileCategoryExtension( # __IGNORE_WARNING__ fileType