--- a/PipxInterface/PipxWidget.py Wed Jun 26 11:57:04 2024 +0200 +++ b/PipxInterface/PipxWidget.py Wed Jun 26 18:40:48 2024 +0200 @@ -8,7 +8,7 @@ """ from PyQt6.QtCore import Qt, pyqtSlot -from PyQt6.QtWidgets import QTreeWidgetItem, QWidget +from PyQt6.QtWidgets import QDialog, QMenu, QTreeWidgetItem, QWidget from eric7.EricGui import EricPixmapCache @@ -56,10 +56,14 @@ self.pipxMenuButton.setIcon(EricPixmapCache.getIcon("superMenu")) self.refreshButton.setIcon(EricPixmapCache.getIcon("reload")) + self.pipxMenuButton.setAutoRaise(True) + self.pipxMenuButton.setShowMenuInside(True) + self.packagesList.header().setSortIndicator( PipxWidget.PackageColumn, Qt.SortOrder.AscendingOrder ) + self.__initPipxMenu() self.__showPipxVersion() pipxPaths = self.__pipx.getPipxStrPaths() @@ -70,6 +74,198 @@ self.__populatePackages() + ####################################################################### + ## Menu related methods below + ####################################################################### + + def __initPipxMenu(self): + """ + Private method to create the super menu and attach it to the super + menu button. + """ + ################################################################### + ## Menu with install related actions + ################################################################### + + self.__installSubmenu = QMenu(self.tr("Install")) + self.__installPackagesAct = self.__installSubmenu.addAction( + self.tr("Install Packages"), self.__installPackages + ) + self.__installAllPackagesAct = self.__installSubmenu.addAction( + self.tr("Install All Packages"), self.__installAllPackages + ) + self.__installSubmenu.addSeparator() + self.__reinstallPackagesAct = self.__installSubmenu.addAction( + self.tr("Re-Install Selected Packages"), self.__reinstallPackages + ) + self.__reinstallAllPackagesAct = self.__installSubmenu.addAction( + self.tr("Re-Install All Packages"), self.__reinstallAllPackages + ) + self.__installSubmenu.addSeparator() + self.__createSpecMetadataAct = self.__installSubmenu.addAction( + self.tr("Create Spec Metadata File"), self.__createSpecMetadataFile + ) + + ################################################################### + ## Menu with upgrade related actions + ################################################################### + + self.__upgradeSubmenu = QMenu(self.tr("Upgrade")) + self.__upgradePackagesAct = self.__upgradeSubmenu.addAction( + self.tr("Upgrade Selected Packages"), self.__upgradePackages + ) + self.__upgradeAllPackagesAct = self.__upgradeSubmenu.addAction( + self.tr("Upgrade All Packages"), self.__upgradeAllPackages + ) + self.__upgradeSubmenu.addSeparator() + self.__upgradeSharedLibsAct = self.__upgradeSubmenu.addAction( + self.tr("Upgrade Shared Libraries"), self.__upgradeSharedLibs + ) + + ################################################################### + ## Menu with upgrade related actions + ################################################################### + + self.__uninstallSubmenu = QMenu(self.tr("Uninstall")) + self.__uninstallPackagesAct = self.__uninstallSubmenu.addAction( + self.tr("Uninstall Selected Packages"), self.__uninstallPackages + ) + self.__uninstallAllPackagesAct = self.__uninstallSubmenu.addAction( + self.tr("Uninstall All Packages"), self.__uninstallAllPackages + ) + + ################################################################### + ## Main menu + ################################################################### + + self.__pipxMenu = QMenu() + self.__installSubmenuAct = self.__pipxMenu.addMenu(self.__installSubmenu) + self.__pipxMenu.addSeparator() + self.__upgradeSubmenuAct = self.__pipxMenu.addMenu(self.__upgradeSubmenu) + self.__pipxMenu.addSeparator() + self.__uninstallSubmenuAct = self.__pipxMenu.addMenu(self.__uninstallSubmenu) + + self.__pipxMenu.aboutToShow.connect(self.__aboutToShowPipxMenu) + + self.pipxMenuButton.setMenu(self.__pipxMenu) + + @pyqtSlot() + def __aboutToShowPipxMenu(self): + """ + Private slot to set the action enabled status. + """ + hasPackagesSelected = bool(self.__selectedPackages()) + self.__reinstallPackagesAct.setEnabled(hasPackagesSelected) + self.__upgradePackagesAct.setEnabled(hasPackagesSelected) + self.__uninstallPackagesAct.setEnabled(hasPackagesSelected) + + @pyqtSlot() + def __installPackages(self): + """ + Private slot to install packages to be given by the user. + """ + from .PipxPackagesInputDialog import PipxPackagesInputDialog + + dlg = PipxPackagesInputDialog(self.tr("Install Packages")) + if dlg.exec() == QDialog.DialogCode.Accepted: + packages, pyVersion, fetchMissing, force, systemSitePackages = dlg.getData() + self.__pipx.installPackages( + packages, + interpreterVersion=pyVersion, + fetchMissingInterpreter=fetchMissing, + forceVenvModification=force, + systemSitePackages=systemSitePackages, + ) + self.on_refreshButton_clicked() + + @pyqtSlot() + def __installAllPackages(self): + """ + Private slot to install all packages listed in a specification file. + """ + # TODO: not implemented yet + from .PipxSpecInputDialog import PipxSpecInputDialog + + dlg = PipxSpecInputDialog(self.tr("Install All Packages")) + if dlg.exec() == QDialog.DialogCode.Accepted: + specFile, pyVersion, fetchMissing, force, systemSitePackages = dlg.getData() + self.__pipx.installPackages( + specFile, + interpreterVersion=pyVersion, + fetchMissingInterpreter=fetchMissing, + forceVenvModification=force, + systemSitePackages=systemSitePackages, + ) + self.on_refreshButton_clicked() + + @pyqtSlot() + def __createSpecMetadataFile(self): + """ + Private slot to create a spec metadata file needed by 'pipx install-all'. + """ + # TODO: not implemented yet + pass + + @pyqtSlot() + def __reinstallPackages(self): + """ + Private slot to force a re-installation of the selected packages. + """ + # TODO: not implemented yet + pass + + @pyqtSlot() + def __reinstallAllPackages(self): + """ + Private slot to force a re-installation of all packages. + """ + # TODO: not implemented yet + pass + + @pyqtSlot() + def __upgradePackages(self): + """ + Private slot to upgrade the selected packages. + """ + # TODO: not implemented yet + pass + + @pyqtSlot() + def __upgradeAllPackages(self): + """ + Private slot to upgrade all packages. + """ + # TODO: not implemented yet + pass + + @pyqtSlot() + def __upgradeSharedLibs(self): + """ + Private slot to upgrade the shared libraries. + """ + # TODO: not implemented yet + pass + + @pyqtSlot() + def __uninstallPackages(self): + """ + Private slot to uninstall the selected packages. + """ + # TODO: not implemented yet + pass + + @pyqtSlot() + def __uninstallAllPackages(self): + """ + Private slot to uninstall all packages. + """ + # TODO: not implemented yet + pass + + ####################################################################### + ## Main widget related methods below + ####################################################################### + def __showPipxVersion(self): """ Private method to show the pipx version in the widget header. @@ -139,3 +335,19 @@ app = item.data(0, PipxWidget.AppPathRole) dlg = PipxAppStartDialog(app, self.__plugin, self) dlg.show() + + def __selectedPackages(self): + """ + Private method to determine the list of selected packages. + + @return list of selected packages + @rtype list of QTreeWidgetItem + """ + packages = [] + + for row in range(self.packagesList.topLevelItemCount()): + itm = self.packagesList.topLevelItem(row) + if itm.isSelected(): + packages.append(itm.text(PipxWidget.PackageColumn)) + + return packages