--- a/src/eric7/PipInterface/PipPackagesWidget.py Sun Feb 09 15:47:57 2025 +0100 +++ b/src/eric7/PipInterface/PipPackagesWidget.py Sat Mar 01 15:52:40 2025 +0100 @@ -13,7 +13,7 @@ from packaging.specifiers import InvalidSpecifier, SpecifierSet from PyQt6.QtCore import Qt, QUrl, QUrlQuery, pyqtSlot -from PyQt6.QtGui import QDesktopServices, QIcon +from PyQt6.QtGui import QBrush, QDesktopServices, QIcon from PyQt6.QtWidgets import ( QDialog, QHeaderView, @@ -415,6 +415,8 @@ if self.__packageDetailsDialog is not None: self.__packageDetailsDialog.close() + self.packageSearchEdit.clear() + if self.viewToggleButton.isChecked(): self.__refreshDependencyTree() else: @@ -1222,7 +1224,7 @@ ericApp().getObject("UserInterface").showPreferences("pipPage") except KeyError: # we were called from outside the eric IDE - from eric7.Preferences.ConfigurationDialog import ( # noqa: I101 + from eric7.Preferences.ConfigurationDialog import ( # noqa: I-101 ConfigurationDialog, ConfigurationMode, ) @@ -1530,6 +1532,11 @@ self.__updateDepActionButtons() + self.packageSearchEdit.setEnabled( + bool(self.dependenciesList.topLevelItemCount()) + ) + self.on_packageSearchEdit_textChanged(self.packageSearchEdit.text()) + def __addDependency(self, dependency, parent): """ Private method to add a dependency branch to a given parent. @@ -1736,6 +1743,69 @@ ) self.on_refreshDependenciesButton_clicked() + @pyqtSlot(str) + def on_packageSearchEdit_textChanged(self, package): + """ + Private slot to search packages in the dependencies tree. + + @param package package text to search for + @type str + """ + self.__resetPackageSearchHighlights() + + foundItems = ( + self.dependenciesList.findItems( + package, + Qt.MatchFlag.MatchContains + | Qt.MatchFlag.MatchRecursive + | Qt.MatchFlag.MatchWrap, + ) + if package + else [] + ) + self.__setPackageSearchHighlights(foundItems) + + def __resetPackageSearchHighlights(self, parent=None): + """ + Private method to reset the package search markers. + + @param parent reference to the parent item (defaults to None) + @type QTreeWidgetItem (optional) + """ + if parent is None: + for index in range(self.dependenciesList.topLevelItemCount()): + itm = self.dependenciesList.topLevelItem(index) + self.__resetPackageSearchHighlight(itm) + else: + for index in range(parent.childCount()): + itm = parent.child(index) + self.__resetPackageSearchHighlight(itm) + + def __resetPackageSearchHighlight(self, packageItem): + """ + Private method to reset the package search marker of an individual item. + + @param packageItem reference to the package item + @type QTreeWidgetItem + """ + for column in range(self.dependenciesList.columnCount()): + packageItem.setBackground(column, QBrush()) + if packageItem.childCount(): + self.__resetPackageSearchHighlights(parent=packageItem) + + def __setPackageSearchHighlights(self, packageItems): + """ + Private method to highlight the given package items. + + @param packageItems list of package dependency items to be highlighted + @type list of QTreeWidgetItem + """ + for packageItem in packageItems: + for column in range(self.dependenciesList.columnCount()): + packageItem.setBackground( + column, QBrush(Preferences.getPip("DependencyHighlightColor")) + ) + ################################################################## ## Interface to show the licenses dialog below ################################################################## @@ -1766,7 +1836,7 @@ """ Private slot to create a "Software Bill Of Material" file. """ - import CycloneDXInterface # __IGNORE_WARNING_I102__ + import CycloneDXInterface # __IGNORE_WARNING_I-102__ venvName = self.environmentsComboBox.currentText() if venvName == self.__pip.getProjectEnvironmentString(): @@ -1791,3 +1861,5 @@ self.__updateVulnerabilityData(clearFirst=True) else: self.__clearVulnerabilityInfo() + + self.on_packageSearchEdit_textChanged(self.packageSearchEdit.text())