diff -r d792e054cde2 -r 91fa67e8ebbc CondaInterface/CondaPackagesWidget.py --- a/CondaInterface/CondaPackagesWidget.py Thu Feb 07 18:54:38 2019 +0100 +++ b/CondaInterface/CondaPackagesWidget.py Sat Feb 09 16:43:49 2019 +0100 @@ -14,18 +14,26 @@ from PyQt5.QtWidgets import QWidget, QToolButton, QMenu, QTreeWidgetItem, \ QApplication +from E5Gui import E5MessageBox + from .Ui_CondaPackagesWidget import Ui_CondaPackagesWidget import UI.PixmapCache +import CondaInterface + class CondaPackagesWidget(QWidget, Ui_CondaPackagesWidget): """ Class implementing the conda packages management widget. """ + # Role definition of packages list PackageVersionRole = Qt.UserRole + 1 PackageBuildRole = Qt.UserRole + 2 + # Role definitions of search results list + PackageDetailedDataRole = Qt.UserRole + 1 + def __init__(self, conda, parent=None): """ Constructor @@ -50,10 +58,21 @@ self.condaMenuButton.setAutoRaise(True) self.condaMenuButton.setShowMenuInside(True) + self.searchToggleButton.setIcon(UI.PixmapCache.getIcon("find.png")) + + if CondaInterface.condaVersion() >= (4, 4, 0): + self.searchOptionsWidget.hide() + else: + self.platformComboBox.addItems(sorted([ + "", "win-32", "win-64", "osx-64", "linux-32", "linux-64", + ])) + self.__initCondaMenu() self.__populateEnvironments() self.__updateActionButtons() + self.searchWidget.hide() + self.__conda.condaEnvironmentCreated.connect( self.on_refreshButton_clicked) self.__conda.condaEnvironmentRemoved.connect( @@ -164,10 +183,12 @@ )) self.packagesList.sortItems(0, Qt.AscendingOrder) + self.packagesList.resizeColumnToContents(0) self.packagesList.setUpdatesEnabled(True) QApplication.restoreOverrideCursor() self.__updateActionButtons() + self.__updateSearchActionButtons() @pyqtSlot() def on_packagesList_itemSelectionChanged(self): @@ -234,3 +255,173 @@ ok = self.__conda.uninstallPackages(packages, prefix=prefix) if ok: self.on_refreshButton_clicked() + + ####################################################################### + ## Search widget related methods below + ####################################################################### + + def __updateSearchActionButtons(self): + """ + Private method to update the action button states of the search widget. + """ + enable = len(self.searchResultList.selectedItems()) == 1 + self.installButton.setEnabled( + enable and self.environmentsComboBox.currentIndex() > 0) + self.showDetailsButton.setEnabled( + enable and bool(self.searchResultList.selectedItems()[0].parent())) + + def __doSearch(self): + """ + Private method to search for packages. + """ + self.searchResultList.clear() + pattern = self.searchEdit.text() + if pattern: + QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) + QApplication.processEvents() + + prefix = self.environmentsComboBox.itemData( + self.environmentsComboBox.currentIndex()) + ok, result = self.__conda.searchPackages( + pattern, + fullNameOnly=self.fullNameButton.isChecked(), + packageSpec=self.packageSpecButton.isChecked(), + platform=self.platformComboBox.currentText(), + prefix=prefix, + ) + + if result: + if ok: + self.searchResultList.setUpdatesEnabled(False) + for package in result: + itm = QTreeWidgetItem(self.searchResultList, [package]) + itm.setExpanded(False) + for detail in result[package]: + version = detail["version"] + build = detail["build"] + if "subdir" in detail: + platform = detail["subdir"] + elif "platform" in detail: + platform = detail["platform"] + else: + platform = "" + citm = QTreeWidgetItem( + itm, ["", version, build, platform]) + citm.setData(0, self.PackageDetailedDataRole, + detail) + + self.searchResultList.sortItems(0, Qt.AscendingOrder) + self.searchResultList.resizeColumnToContents(0) + self.searchResultList.setUpdatesEnabled(True) + else: + QApplication.restoreOverrideCursor() + try: + message = result["message"] + except KeyError: + message = result["error"] + E5MessageBox.warning( + self, + self.tr("Conda Search Package Error"), + message) + QApplication.restoreOverrideCursor() + + def __showDetails(self, item): + """ + Private method to show a dialog with details about a package item. + + @param item reference to the package item + @type QTreeWidgetItem + """ + details = item.data(0, self.PackageDetailedDataRole) + if details: + from .CondaPackageDetailsWidget import CondaPackageDetailsDialog + dlg = CondaPackageDetailsDialog(details, self) + dlg.show() + + @pyqtSlot(str) + def on_searchEdit_textChanged(self, txt): + """ + Private slot handling changes of the entered search specification. + + @param txt current search entry + @type str + """ + self.searchButton.setEnabled(bool(txt)) + + @pyqtSlot() + def on_searchEdit_returnPressed(self): + """ + Private slot handling the user pressing the Return button in the + search edit. + """ + self.__doSearch() + + @pyqtSlot() + def on_searchButton_clicked(self): + """ + Private slot handling the press of the search button. + """ + self.__doSearch() + + @pyqtSlot() + def on_installButton_clicked(self): + """ + Slot documentation goes here. + """ + # TODO: not implemented yet + raise NotImplementedError + + @pyqtSlot() + def on_showDetailsButton_clicked(self): + """ + Private slot handling the 'Show Details' button. + """ + item = self.searchResultList.selectedItems()[0] + self.__showDetails(item) + + @pyqtSlot() + def on_searchResultList_itemSelectionChanged(self): + """ + Private slot handling a change of selected search results. + """ + self.__updateSearchActionButtons() + + @pyqtSlot(QTreeWidgetItem) + def on_searchResultList_itemExpanded(self, item): + """ + Private slot handling the expansion of an item. + + @param item reference to the expanded item + @type QTreeWidgetItem + """ + for col in range(1, self.searchResultList.columnCount()): + self.searchResultList.resizeColumnToContents(col) + + @pyqtSlot(QTreeWidgetItem, int) + def on_searchResultList_itemDoubleClicked(self, item, column): + """ + Private slot handling a double click of an item. + + @param item reference to the item that was double clicked + @type QTreeWidgetItem + @param column column of the double click + @type int + """ + if item.parent() is not None: + self.__showDetails(item) + + @pyqtSlot(bool) + def on_searchToggleButton_toggled(self, checked): + """ + Private slot to togle the search widget. + + @param checked state of the search widget button + @type bool + """ + self.searchWidget.setVisible(checked) + + if checked: + self.searchEdit.setFocus(Qt.OtherFocusReason) + self.searchEdit.selectAll() + + self.__updateSearchActionButtons()