--- a/PipxInterface/PipxWidget.py Wed Jun 26 18:40:48 2024 +0200 +++ b/PipxInterface/PipxWidget.py Thu Jun 27 15:42:50 2024 +0200 @@ -7,10 +7,13 @@ Module implementing the pipx management widget. """ +import os + from PyQt6.QtCore import Qt, pyqtSlot from PyQt6.QtWidgets import QDialog, QMenu, QTreeWidgetItem, QWidget from eric7.EricGui import EricPixmapCache +from eric7.EricWidgets import EricFileDialog, EricMessageBox from .Pipx import Pipx from .PipxAppStartDialog import PipxAppStartDialog @@ -55,6 +58,13 @@ # TODO: set the various icons self.pipxMenuButton.setIcon(EricPixmapCache.getIcon("superMenu")) self.refreshButton.setIcon(EricPixmapCache.getIcon("reload")) + self.installButton.setIcon(EricPixmapCache.getIcon("plus")) + self.upgradeButton.setIcon(EricPixmapCache.getIcon("upgrade")) + self.uninstallButton.setIcon(EricPixmapCache.getIcon("minus")) + + self.installButton.clicked.connect(self.__installPackages) + self.upgradeButton.clicked.connect(self.__upgradePackages) + self.uninstallButton.clicked.connect(self.__uninstallPackages) self.pipxMenuButton.setAutoRaise(True) self.pipxMenuButton.setShowMenuInside(True) @@ -73,6 +83,7 @@ self.interpretersPathEdit.setText(pipxPaths["pythonPath"]) self.__populatePackages() + self.on_packagesList_itemSelectionChanged() ####################################################################### ## Menu related methods below @@ -154,10 +165,11 @@ """ Private slot to set the action enabled status. """ - hasPackagesSelected = bool(self.__selectedPackages()) - self.__reinstallPackagesAct.setEnabled(hasPackagesSelected) - self.__upgradePackagesAct.setEnabled(hasPackagesSelected) - self.__uninstallPackagesAct.setEnabled(hasPackagesSelected) + selectedPackages = self.__selectedPackages() + + self.__reinstallPackagesAct.setEnabled(len(selectedPackages) == 1) + self.__upgradePackagesAct.setEnabled(bool(selectedPackages)) + self.__uninstallPackagesAct.setEnabled(len(selectedPackages) == 1) @pyqtSlot() def __installPackages(self): @@ -183,13 +195,12 @@ """ 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( + self.__pipx.installAllPackages( specFile, interpreterVersion=pyVersion, fetchMissingInterpreter=fetchMissing, @@ -203,8 +214,51 @@ """ Private slot to create a spec metadata file needed by 'pipx install-all'. """ - # TODO: not implemented yet - pass + specFile, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( + self, + self.tr("Create Spec Metadata File"), + "", + self.tr("JSON Files (*.json);;All Files (*)"), + self.tr("JSON Files (*.json)"), + EricFileDialog.DontConfirmOverwrite, + ) + if specFile: + ext = os.path.splitext(specFile)[1] + if not ext: + ex = selectedFilter.split("(*")[1].split(")")[0] + if ex: + specFile += ex + + if os.path.exists(specFile): + ok = EricMessageBox.yesNo( + self, + self.tr("Create Spec Metadata File"), + self.tr( + "<p>The file <b>{0}</b> exists already. Overwrite it?</p>" + ).format(specFile), + ) + if not ok: + return + + ok, message = self.__pipx.createSpecMetadataFile(specFile=specFile) + if ok: + EricMessageBox.information( + self, + self.tr("Create Spec Metadata File"), + self.tr( + "<p>The spec metadata file <b>{0}</b> was created" + " successfully.</p>" + ).format(specFile), + ) + else: + EricMessageBox.critical( + self, + self.tr("Create Spec Metadata File"), + self.tr( + "<p>The spec metadata file <b>{0}</b> could not be created.</p>" + "<p>Reason: {1}</p>" + ).format(specFile, message), + ) @pyqtSlot() def __reinstallPackages(self): @@ -336,6 +390,16 @@ dlg = PipxAppStartDialog(app, self.__plugin, self) dlg.show() + @pyqtSlot() + def on_packagesList_itemSelectionChanged(self): + """ + Private slot to handle a change of selected packages and apps. + """ + selectedPackages = self.__selectedPackages() + + self.upgradeButton.setEnabled(bool(selectedPackages)) + self.uninstallButton.setEnabled(len(selectedPackages) == 1) + def __selectedPackages(self): """ Private method to determine the list of selected packages.