Sun, 29 Sep 2024 11:34:16 +0200
Prepared a new release with updated Spanish translations.
# -*- coding: utf-8 -*- # Copyright (c) 2024 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing the pipx Interface plug-in. """ import importlib.util import os import sysconfig from PyQt6.QtCore import QCoreApplication, QObject, Qt, QTranslator, pyqtSignal from PyQt6.QtGui import QKeySequence from eric7 import Globals, Preferences from eric7.EricGui import EricPixmapCache from eric7.EricGui.EricAction import EricAction from eric7.EricWidgets.EricApplication import ericApp from eric7.SystemUtilities import OSUtilities try: from eric7.UI.UserInterface import UserInterfaceSide _Side = UserInterfaceSide.Right except ImportError: # backward compatibility for eric < 24.2 from eric7.UI.UserInterface import UserInterface _Side = UserInterface.RightSide # Start-Of-Header __header__ = { "name": "pipx Interface", "author": "Detlev Offenbach <detlev@die-offenbachs.de>", "autoactivate": True, "deactivateable": True, "version": "10.5.1", "className": "PluginPipxInterface", "packageName": "PipxInterface", "shortDescription": "Graphical interface to the 'pipx' command.", "longDescription": ( "Plugin implementing widgets and dialogues to interact with the various pipx" " commands and to start pipx managed applications from within the eric-ide." ), "needsRestart": False, "hasCompiledForms": True, "pyqtApi": 2, } # End-Of-Header error = "" # noqa: U200 pipxInterfacePluginObject = None def exeDisplayData(): """ Module function to support the display of some executable info. @return dictionary containing the data to query the presence of the executable @rtype dict """ pipx = os.path.join(sysconfig.get_path("scripts"), "pipx") if OSUtilities.isWindowsPlatform(): pipx += ".exe" data = { "programEntry": True, "header": QCoreApplication.translate( "PluginPipxInterface", "PyPI Application Management" ), "exe": pipx, "versionCommand": "--version", "versionStartsWith": "", "versionRe": None, "versionPosition": -1, "version": "", "versionCleanup": None, "exeModule": None, } return data def createPipxPage(_configDlg): """ Module function to create the pipx configuration page. @param _configDlg reference to the configuration dialog (unused) @type ConfigurationWidget @return reference to the configuration page @rtype PipxPage """ from PipxInterface.ConfigurationPage.PipxPage import PipxPage # noqa: I102 global pipxInterfacePluginObject page = PipxPage(pipxInterfacePluginObject) return page def getConfigData(): """ Module function returning data as required by the configuration dialog. @return dictionary containing the relevant data @rtype dict """ return { "pipxPage": [ QCoreApplication.translate( "PluginPipxInterface", "Python Application Management" ), os.path.join("PipxInterface", "icons", "pipx22"), createPipxPage, None, None, ], } def prepareUninstall(): """ Module function to prepare for an un-installation. """ Preferences.getSettings().remove(PluginPipxInterface.PreferencesKey) class PluginPipxInterface(QObject): """ Class documentation goes here. @signal preferencesChanged() emitted to signal a change of preferences. This signal is simply relayed from the main UI. """ PreferencesKey = "Pipx" preferencesChanged = pyqtSignal() def __init__(self, ui): """ Constructor @param ui reference to the user interface object @type UI.UserInterface """ super().__init__(ui) self.__ui = ui self.__initialize() self.__defaults = { "RecentAppWorkdirs": [], "MaxRecentAppWorkdirs": 20, "IncludeOutdatedDependencies": True, "AutoCheckOutdated": False, "PeriodicOutdatedCheckInterval": 1, # interval in hours, 0 = disable; 1 h <= value <= 24 h } self.__translator = None self.__loadTranslator() def __initialize(self): """ Private slot to (re)initialize the plugin. """ self.__widget = None def activate(self): """ Public method to activate this plug-in. @return tuple of None and activation status @rtype bool """ from PipxInterface.PipxWidget import PipxWidget # noqa: I102 global error, pipxInterfacePluginObject error = "" # clear previous error pipxInterfacePluginObject = self self.__widget = PipxWidget(self, fromEric=True) iconName = "pipx96" if self.__ui.getLayoutType() == "Sidebars" else "pipx22" self.__ui.addSideWidget( _Side, self.__widget, EricPixmapCache.getIcon(os.path.join("PipxInterface", "icons", iconName)), self.tr("PyPI Application Management"), ) self.__activateAct = EricAction( self.tr("PyPI Application Management"), self.tr("PyPI Application Management"), QKeySequence(self.tr("Ctrl+Alt+Shift+A")), 0, self, "pipx_interface_activate", ) self.__activateAct.setStatusTip( self.tr("Switch the input focus to the PyPI Application Management window.") ) self.__activateAct.setWhatsThis( self.tr( """<b>Activate PyPI Application Management</b>""" """<p>This switches the input focus to the PyPI Application""" """ Management window.</p>""" ) ) self.__activateAct.triggered.connect(self.__activateWidget) self.__ui.addEricActions([self.__activateAct], "ui") menu = self.__ui.getMenu("subwindow") menu.addAction(self.__activateAct) ericApp().getObject("PluginManager").shutdown.connect(self.__widget.shutdown) self.__ui.preferencesChanged.connect(self.preferencesChanged) return None, True def deactivate(self): """ Public method to deactivate this plug-in. """ self.__ui.preferencesChanged.disconnect(self.preferencesChanged) ericApp().getObject("PluginManager").shutdown.disconnect(self.__widget.shutdown) menu = self.__ui.getMenu("subwindow") menu.removeAction(self.__activateAct) self.__ui.removeEricActions([self.__activateAct], "ui") self.__ui.removeSideWidget(self.__widget) self.__initialize() def __loadTranslator(self): """ Private method to load the translation file. """ if self.__ui is not None: loc = self.__ui.getLocale() if loc and loc != "C": locale_dir = os.path.join( os.path.dirname(__file__), "PipxInterface", "i18n" ) translation = "pipx_{0}".format(loc) translator = QTranslator(None) loaded = translator.load(translation, locale_dir) if loaded: self.__translator = translator ericApp().installTranslator(self.__translator) else: print( "Warning: translation file '{0}' could not be" " loaded.".format(translation) ) print("Using default.") def __activateWidget(self): """ Private slot to handle the activation of the pipx interface. """ uiLayoutType = self.__ui.getLayoutType() if uiLayoutType == "Toolboxes": self.__ui.rToolboxDock.show() self.__ui.rToolbox.setCurrentWidget(self.__widget) elif uiLayoutType == "Sidebars": try: self.__ui.activateLeftRightSidebarWidget(self.__widget) except AttributeError: self.__activateLeftRightSidebarWidget(self.__widget) else: self.__widget.show() self.__widget.setFocus(Qt.FocusReason.ActiveWindowFocusReason) def setOutdatedIndicator(self, outdated): """ Public method to set or clear the outdated indication of the pipx icon. @param outdated flag indicating outdated packages or dependencies @type bool """ uiLayoutType = self.__ui.getLayoutType() if uiLayoutType == "Toolboxes": iconName = "pipxOutdated22" if outdated else "pipx22" index = self.__ui.rToolbox.indexOf(self.__widget) self.__ui.rToolbox.setItemIcon( index, EricPixmapCache.getIcon( os.path.join("PipxInterface", "icons", iconName) ), ) elif uiLayoutType == "Sidebars": iconName = "pipxOutdated96" if outdated else "pipx96" try: self.__ui.setLeftRightSidebarWidgetIcon( self.__widget, EricPixmapCache.getIcon( os.path.join("PipxInterface", "icons", iconName) ), ) except AttributeError: self.__setLeftRightSidebarWidgetIcon( self.__widget, EricPixmapCache.getIcon( os.path.join("PipxInterface", "icons", iconName) ), ) def getPreferences(self, key): """ Public method to retrieve the various settings values. @param key the key of the value to get @type str @return the requested setting value @rtype Any """ if key in ("RecentAppWorkdirs",): return Globals.toList( Preferences.Prefs.settings.value( self.PreferencesKey + "/" + key, self.__defaults[key] ) ) elif key in ("MaxRecentAppWorkdirs", "PeriodicOutdatedCheckInterval"): return int( Preferences.Prefs.settings.value( self.PreferencesKey + "/" + key, self.__defaults[key] ) ) elif key in ("IncludeOutdatedDependencies", "AutoCheckOutdated"): return Globals.toBool( Preferences.Prefs.settings.value( self.PreferencesKey + "/" + key, self.__defaults[key] ) ) else: return Preferences.Prefs.settings.value( self.PreferencesKey + "/" + key, self.__defaults[key] ) return None def setPreferences(self, key, value): """ Public method to store the various settings values. @param key the key of the setting to be set @type str @param value the value to be set @type Any """ Preferences.Prefs.settings.setValue(self.PreferencesKey + "/" + key, value) ############################################################################ ## Methods for backward compatibility with eric-ide < 24.9 ############################################################################ def __activateLeftRightSidebarWidget(self, widget): """ Private method to activate the given widget in the left or right sidebar. @param widget reference to the widget to be activated @type QWidget """ # This is for backward compatibility with eric-ide < 24.9. sidebar = ( self.__ui.leftSidebar if Preferences.getUI("CombinedLeftRightSidebar") else self.__ui.rightSidebar ) sidebar.show() sidebar.setCurrentWidget(widget) def __setLeftRightSidebarWidgetIcon(self, widget, icon): """ Private method to set the icon of the given widget in the left or right sidebar. @param widget reference to the widget to set the icon for @type QWidget @param icon icon to be set @type QIcon """ sidebar = ( self.__ui.leftSidebar if Preferences.getUI("CombinedLeftRightSidebar") else self.__ui.rightSidebar ) index = sidebar.indexOf(widget) sidebar.setTabIcon(index, icon) def installDependencies(pipInstall): """ Function to install dependencies of this plug-in. @param pipInstall function to be called with a list of package names. @type function """ packagesToInstall = [] if importlib.util.find_spec("pipx") is None: packagesToInstall.append("pipx>=1.5.0") if importlib.util.find_spec("psutil") is None: packagesToInstall.append("psutil") if packagesToInstall: pipInstall(packagesToInstall) # # eflag: noqa = M801, U200