PipInterface: continued with the pip interface widget. pypi

Fri, 22 Feb 2019 19:34:44 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Fri, 22 Feb 2019 19:34:44 +0100
branch
pypi
changeset 6798
3985c1a67fa2
parent 6795
6e2ed2aac325
child 6799
6947cb9d4ce8

PipInterface: continued with the pip interface widget.

PipInterface/Pip.py file | annotate | diff | comparison | revisions
PipInterface/PipFreezeDialog.py file | annotate | diff | comparison | revisions
PipInterface/PipFreezeDialog.ui file | annotate | diff | comparison | revisions
PipInterface/PipPackageDetailsDialog.py file | annotate | diff | comparison | revisions
PipInterface/PipPackagesWidget.py file | annotate | diff | comparison | revisions
PipInterface/PipPackagesWidget.ui file | annotate | diff | comparison | revisions
Plugins/PluginPipInterface.py file | annotate | diff | comparison | revisions
Preferences/__init__.py file | annotate | diff | comparison | revisions
eric6.e4p file | annotate | diff | comparison | revisions
--- a/PipInterface/Pip.py	Thu Feb 21 19:55:35 2019 +0100
+++ b/PipInterface/Pip.py	Fri Feb 22 19:34:44 2019 +0100
@@ -17,19 +17,25 @@
 import sys
 import json
 
-from PyQt5.QtCore import pyqtSlot, QObject, QProcess
-from PyQt5.QtWidgets import QMenu, QInputDialog, QDialog
+from PyQt5.QtCore import pyqtSlot, QObject, QProcess, QUrl, QCoreApplication
+from PyQt5.QtWidgets import QDialog
+from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, \
+    QNetworkReply
 
 from E5Gui import E5MessageBox
-from E5Gui.E5Action import E5Action
 from E5Gui.E5Application import e5App
 
+from E5Network.E5NetworkProxyFactory import proxyAuthenticationRequired
+try:
+    from E5Network.E5SslErrorHandler import E5SslErrorHandler
+    SSL_AVAILABLE = True
+except ImportError:
+    SSL_AVAILABLE = False
+
 from .PipDialog import PipDialog
 
 import Preferences
 import Globals
-##
-##import UI.PixmapCache
 
 
 class Pip(QObject):
@@ -48,413 +54,16 @@
         @type QObject
         """
         super(Pip, self).__init__(parent)
-##        
-##        self.__virtualenvManager = e5App().getObject("VirtualEnvManager")
-##        self.__project = e5App().getObject("Project")
-##        
-##        self.__menus = {}   # dictionary with references to menus
-##        
-##        self.__plugin.currentEnvironmentChanged.connect(
-##            self.__handleTearOffMenu)
-    
-##    def initActions(self):
-##        """
-##        Public method to define the actions.
-##        """
-##        self.actions = []
-##    
-##        self.selectEnvironmentAct = E5Action(
-##            self.tr('Virtual Environment for pip'),
-##            self.tr('&Virtual Environment for pip'),
-##            0, 0,
-##            self, 'pip_select_environment')
-##        self.selectEnvironmentAct.setStatusTip(self.tr(
-##            'Selects the virtual environment to be used for pip'))
-##        self.selectEnvironmentAct.setWhatsThis(self.tr(
-##            """<b>Virtual Environment for pip</b>"""
-##            """<p>This selects the virtual environment to be used for pip."""
-##            """</p>"""
-##        ))
-##        self.selectEnvironmentAct.triggered.connect(self.__selectPipVirtualenv)
-##        self.actions.append(self.selectEnvironmentAct)
-##        
-##        ##############################################
-##        ## Actions for listing packages
-##        ##############################################
-##        
-##        self.listPackagesAct = E5Action(
-##            self.tr('List Installed Packages'),
-##            self.tr('&List Installed Packages...'),
-##            0, 0,
-##            self, 'pip_list_packages')
-##        self.listPackagesAct.setStatusTip(self.tr(
-##            'List all installed packages with versions'))
-##        self.listPackagesAct.setWhatsThis(self.tr(
-##            """<b>List Installed Packages</b>"""
-##            """<p>This lists all the installed packages together"""
-##            """ with their versions.</p>"""
-##        ))
-##        self.listPackagesAct.triggered.connect(self.__listPackages)
-##        self.actions.append(self.listPackagesAct)
-##        
-##        self.listUptodatePackagesAct = E5Action(
-##            self.tr('List Up-to-date Packages'),
-##            self.tr('List Up-to-&date Packages...'),
-##            0, 0,
-##            self, 'pip_list_uptodate_packages')
-##        self.listUptodatePackagesAct.setStatusTip(self.tr(
-##            'List all installed, up-to-date packages with versions'))
-##        self.listUptodatePackagesAct.setWhatsThis(self.tr(
-##            """<b>List Up-to-date Packages</b>"""
-##            """<p>This lists all the installed, up-to-date packages together"""
-##            """ with their versions.</p>"""
-##        ))
-##        self.listUptodatePackagesAct.triggered.connect(
-##            self.__listUptodatePackages)
-##        self.actions.append(self.listUptodatePackagesAct)
-##        
-##        self.listOutdatedPackagesAct = E5Action(
-##            self.tr('List Outdated Packages'),
-##            self.tr('List &Outdated Packages...'),
-##            0, 0,
-##            self, 'pip_list_outdated_packages')
-##        self.listOutdatedPackagesAct.setStatusTip(self.tr(
-##            'List all installed, outdated packages with versions'))
-##        self.listOutdatedPackagesAct.setWhatsThis(self.tr(
-##            """<b>List Up-to-date Packages</b>"""
-##            """<p>This lists all the installed, outdated packages together"""
-##            """ with their current and latest versions.</p>"""
-##        ))
-##        self.listOutdatedPackagesAct.triggered.connect(
-##            self.__listOutdatedPackages)
-##        self.actions.append(self.listOutdatedPackagesAct)
-##        
-##        ##############################################
-##        ## Actions for installing packages
-##        ##############################################
-##        
-##        self.installPackagesAct = E5Action(
-##            self.tr('Install Packages'),
-##            self.tr('&Install Packages'),
-##            0, 0,
-##            self, 'pip_install_packages')
-##        self.installPackagesAct.setStatusTip(self.tr(
-##            'Install packages according to user input'))
-##        self.installPackagesAct.setWhatsThis(self.tr(
-##            """<b>Install Packages</b>"""
-##            """<p>This installs packages according to user input.</p>"""
-##        ))
-##        self.installPackagesAct.triggered.connect(self.__installPackages)
-##        self.actions.append(self.installPackagesAct)
-##        
-##        self.installLocalPackageAct = E5Action(
-##            self.tr('Install Local Package'),
-##            self.tr('Install Local Package'),
-##            0, 0,
-##            self, 'pip_install_local_package')
-##        self.installLocalPackageAct.setStatusTip(self.tr(
-##            'Install a package from local storage'))
-##        self.installLocalPackageAct.setWhatsThis(self.tr(
-##            """<b>Install Local Package</b>"""
-##            """<p>This installs a package available on local storage.</p>"""
-##        ))
-##        self.installLocalPackageAct.triggered.connect(
-##            self.__installLocalPackage)
-##        self.actions.append(self.installLocalPackageAct)
-##        
-##        self.installRequirementsAct = E5Action(
-##            self.tr('Install Requirements'),
-##            self.tr('Install Requirements'),
-##            0, 0,
-##            self, 'pip_install_requirements')
-##        self.installRequirementsAct.setStatusTip(self.tr(
-##            'Install packages according to a requirements file'))
-##        self.installRequirementsAct.setWhatsThis(self.tr(
-##            """<b>Install Requirements</b>"""
-##            """<p>This installs packages according to a requirements"""
-##            """ file.</p>"""
-##        ))
-##        self.installRequirementsAct.triggered.connect(
-##            self.__installRequirements)
-##        self.actions.append(self.installRequirementsAct)
-##        
-##        self.installPipAct = E5Action(
-##            self.tr('Install Pip'),
-##            self.tr('Install Pip'),
-##            0, 0,
-##            self, 'pip_install_pip')
-##        self.installPipAct.setStatusTip(self.tr(
-##            'Install the pip package itself'))
-##        self.installPipAct.setWhatsThis(self.tr(
-##            """<b>Install Pip</b>"""
-##            """<p>This installs the pip package itself.</p>"""
-##        ))
-##        self.installPipAct.triggered.connect(self.__installPip)
-##        self.actions.append(self.installPipAct)
-##        
-##        self.repairPipAct = E5Action(
-##            self.tr('Repair Pip'),
-##            self.tr('Repair Pip'),
-##            0, 0,
-##            self, 'pip_repair_pip')
-##        self.repairPipAct.setStatusTip(self.tr(
-##            'Repair the pip package'))
-##        self.repairPipAct.setWhatsThis(self.tr(
-##            """<b>Repair Pip</b>"""
-##            """<p>This repairs the pip package by re-installing it.</p>"""
-##        ))
-##        self.repairPipAct.triggered.connect(self.__repairPip)
-##        self.actions.append(self.repairPipAct)
-##        
-##        self.upgradePipAct = E5Action(
-##            self.tr('Upgrade Pip'),
-##            self.tr('Upgrade &Pip'),
-##            0, 0,
-##            self, 'pip_upgrade_pip')
-##        self.upgradePipAct.setStatusTip(self.tr(
-##            'Upgrade the pip package itself'))
-##        self.upgradePipAct.setWhatsThis(self.tr(
-##            """<b>Upgrade Pip</b>"""
-##            """<p>This upgrades the pip package itself.</p>"""
-##        ))
-##        self.upgradePipAct.triggered.connect(self.upgradePip)
-##        self.actions.append(self.upgradePipAct)
-##        
-##        self.upgradePackagesAct = E5Action(
-##            self.tr('Upgrade Packages'),
-##            self.tr('&Upgrade Packages'),
-##            0, 0,
-##            self, 'pip_upgrade_packages')
-##        self.upgradePackagesAct.setStatusTip(self.tr(
-##            'Upgrade packages according to user input'))
-##        self.upgradePackagesAct.setWhatsThis(self.tr(
-##            """<b>Upgrade Packages</b>"""
-##            """<p>This upgrades packages according to user input.</p>"""
-##        ))
-##        self.upgradePackagesAct.triggered.connect(self.__upgradePackages)
-##        self.actions.append(self.upgradePackagesAct)
-##        
-##        ##############################################
-##        ## Actions for uninstalling packages
-##        ##############################################
-##        
-##        self.uninstallPackagesAct = E5Action(
-##            self.tr('Uninstall Packages'),
-##            self.tr('Uninstall Packages'),
-##            0, 0,
-##            self, 'pip_uninstall_packages')
-##        self.uninstallPackagesAct.setStatusTip(self.tr(
-##            'Uninstall packages according to user input'))
-##        self.uninstallPackagesAct.setWhatsThis(self.tr(
-##            """<b>Uninstall Packages</b>"""
-##            """<p>This uninstalls packages according to user input.</p>"""
-##        ))
-##        self.uninstallPackagesAct.triggered.connect(self.__uninstallPackages)
-##        self.actions.append(self.uninstallPackagesAct)
-##        
-##        self.uninstallRequirementsAct = E5Action(
-##            self.tr('Uninstall Requirements'),
-##            self.tr('Uninstall Requirements'),
-##            0, 0,
-##            self, 'pip_uninstall_requirements')
-##        self.uninstallRequirementsAct.setStatusTip(self.tr(
-##            'Uninstall packages according to a requirements file'))
-##        self.uninstallRequirementsAct.setWhatsThis(self.tr(
-##            """<b>Uninstall Requirements</b>"""
-##            """<p>This uninstalls packages according to a requirements"""
-##            """ file.</p>"""
-##        ))
-##        self.uninstallRequirementsAct.triggered.connect(
-##            self.__uninstallRequirements)
-##        self.actions.append(self.uninstallRequirementsAct)
-##        
-##        ##############################################
-##        ## Actions for generating requirements files
-##        ##############################################
-##        
-##        self.generateRequirementsAct = E5Action(
-##            self.tr('Generate Requirements'),
-##            self.tr('&Generate Requirements...'),
-##            0, 0,
-##            self, 'pip_generate_requirements')
-##        self.generateRequirementsAct.setStatusTip(self.tr(
-##            'Generate the contents of a requirements file'))
-##        self.generateRequirementsAct.setWhatsThis(self.tr(
-##            """<b>Generate Requirements</b>"""
-##            """<p>This generates the contents of a requirements file.</p>"""
-##        ))
-##        self.generateRequirementsAct.triggered.connect(
-##            self.__generateRequirements)
-##        self.actions.append(self.generateRequirementsAct)
-##        
-##        ##############################################
-##        ## Actions for generating requirements files
-##        ##############################################
-##        
-##        self.searchPyPIAct = E5Action(
-##            self.tr('Search PyPI'),
-##            self.tr('&Search PyPI...'),
-##            0, 0,
-##            self, 'pip_search_pypi')
-##        self.searchPyPIAct.setStatusTip(self.tr(
-##            'Open a dialog to search the Python Package Index'))
-##        self.searchPyPIAct.setWhatsThis(self.tr(
-##            """<b>Search PyPI</b>"""
-##            """<p>This opens a dialog to search the Python Package"""
-##            """ Index.</p>"""
-##        ))
-##        self.searchPyPIAct.triggered.connect(self.__searchPyPI)
-##        self.actions.append(self.searchPyPIAct)
-##        
-##        ##############################################
-##        ## Actions for editing configuration files
-##        ##############################################
-##        
-##        self.editUserConfigAct = E5Action(
-##            self.tr('Edit User Configuration'),
-##            self.tr('Edit User Configuration...'),
-##            0, 0,
-##            self, 'pip_edit_user_config')
-##        self.editUserConfigAct.setStatusTip(self.tr(
-##            'Open the per user configuration file in an editor'))
-##        self.editUserConfigAct.setWhatsThis(self.tr(
-##            """<b>Edit User Configuration</b>"""
-##            """<p>This opens the per user configuration file in an editor."""
-##            """</p>"""
-##        ))
-##        self.editUserConfigAct.triggered.connect(self.__editUserConfiguration)
-##        self.actions.append(self.editUserConfigAct)
-##        
-##        self.editVirtualenvConfigAct = E5Action(
-##            self.tr('Edit Current Virtualenv Configuration'),
-##            self.tr('Edit Current Virtualenv Configuration...'),
-##            0, 0,
-##            self, 'pip_edit_virtualenv_config')
-##        self.editVirtualenvConfigAct.setStatusTip(self.tr(
-##            'Open the current virtualenv configuration file in an editor'))
-##        self.editVirtualenvConfigAct.setWhatsThis(self.tr(
-##            """<b>Edit Current Virtualenv Configuration</b>"""
-##            """<p>This opens the current virtualenv configuration file in"""
-##            """ an editor. </p>"""
-##        ))
-##        self.editVirtualenvConfigAct.triggered.connect(
-##            self.__editVirtualenvConfiguration)
-##        self.actions.append(self.editVirtualenvConfigAct)
-##        
-##        self.pipConfigAct = E5Action(
-##            self.tr('Configure'),
-##            self.tr('Configure...'),
-##            0, 0, self, 'pip_configure')
-##        self.pipConfigAct.setStatusTip(self.tr(
-##            'Show the configuration dialog with the Python Package Management'
-##            ' page selected'
-##        ))
-##        self.pipConfigAct.setWhatsThis(self.tr(
-##            """<b>Configure</b>"""
-##            """<p>Show the configuration dialog with the Python Package"""
-##            """ Management page selected.</p>"""
-##        ))
-##        self.pipConfigAct.triggered.connect(self.__pipConfigure)
-##        self.actions.append(self.pipConfigAct)
-##    
-##    def initMenu(self):
-##        """
-##        Public slot to initialize the menu.
-##        
-##        @return the menu generated
-##        @rtype QMenu
-##        """
-##        self.__menus = {}   # clear menus references
-##        
-##        menu = QMenu()
-##        menu.setTearOffEnabled(True)
-##        menu.setIcon(UI.PixmapCache.getIcon("pypi.png"))
-##        
-##        menu.addAction(self.selectEnvironmentAct)
-##        menu.addSeparator()
-##        menu.addAction(self.listPackagesAct)
-##        menu.addAction(self.listUptodatePackagesAct)
-##        menu.addAction(self.listOutdatedPackagesAct)
-##        menu.addSeparator()
-##        menu.addAction(self.installPipAct)
-##        menu.addSeparator()
-##        menu.addAction(self.installPackagesAct)
-##        menu.addAction(self.installLocalPackageAct)
-##        menu.addAction(self.installRequirementsAct)
-##        menu.addSeparator()
-##        menu.addAction(self.upgradePipAct)
-##        menu.addAction(self.upgradePackagesAct)
-##        menu.addSeparator()
-##        menu.addAction(self.uninstallPackagesAct)
-##        menu.addAction(self.uninstallRequirementsAct)
-##        menu.addSeparator()
-##        menu.addAction(self.generateRequirementsAct)
-##        menu.addSeparator()
-##        menu.addAction(self.searchPyPIAct)
-##        menu.addSeparator()
-##        menu.addAction(self.repairPipAct)
-##        menu.addSeparator()
-##        menu.addAction(self.editUserConfigAct)
-##        menu.addAction(self.editVirtualenvConfigAct)
-##        menu.addSeparator()
-##        menu.addAction(self.pipConfigAct)
-##        
-##        self.__menus["main"] = menu
-##        
-##        menu.aboutToShow.connect(self.__aboutToShowMenu)
-##        
-##        return menu
-##    
-##    def __aboutToShowMenu(self):
-##        """
-##        Private slot to set the action enabled status.
-##        """
-##        enable = bool(Preferences.getPip("CurrentEnvironment"))
-##        for act in self.actions:
-##            if act not in [self.selectEnvironmentAct,
-##                           self.installPipAct,
-##                           self.editUserConfigAct,
-##                           self.editVirtualenvConfigAct,
-##                           self.pipConfigAct]:
-##                act.setEnabled(enable)
-##    
-##    def getMenu(self, name):
-##        """
-##        Public method to get a reference to the requested menu.
-##        
-##        @param name name of the menu
-##        @type str
-##        @return reference to the menu or None, if no
-##            menu with the given name exists
-##        @rtype QMenu or None
-##        """
-##        if name in self.__menus:
-##            return self.__menus[name]
-##        else:
-##            return None
-##    
-##    def getMenuNames(self):
-##        """
-##        Public method to get the names of all menus.
-##        
-##        @return menu names
-##        @rtype list of str
-##        """
-##        return list(self.__menus.keys())
-##    
-##    def __handleTearOffMenu(self, venvName):
-##        """
-##        Private slot to handle a change of the selected virtual environment.
-##        
-##        @param venvName logical name of the virtual environment
-##        @type str
-##        """
-##        if self.__menus["main"].isTearOffMenuVisible():
-##            # determine, if torn off menu needs to be refreshed
-##            enabled = self.listPackagesAct.isEnabled()
-##            if ((bool(venvName) and not enabled) or
-##                    (not bool(venvName) and enabled)):
-##                self.__menus["main"].hideTearOffMenu()
+        
+        # attributes for the network objects
+        self.__networkManager = QNetworkAccessManager(self)
+        self.__networkManager.proxyAuthenticationRequired.connect(
+            proxyAuthenticationRequired)
+        if SSL_AVAILABLE:
+            self.__sslErrorHandler = E5SslErrorHandler(self)
+            self.__networkManager.sslErrors.connect(
+                self.__sslErrorHandler.sslErrorsReply)
+        self.__replies = []
     
     ##########################################################################
     ## Methods below implement some utility functions
@@ -501,9 +110,9 @@
         
         return False, self.tr("python could not be started.")
     
-    def __getUserConfig(self):
+    def getUserConfig(self):
         """
-        Private method to get the name of the user configuration file.
+        Public method to get the name of the user configuration file.
         
         @return path of the user configuration file
         @rtype str
@@ -528,33 +137,28 @@
         
         return config
     
-    def __getVirtualenvConfig(self):
+    def getVirtualenvConfig(self, venvName):
         """
-        Private method to get the name of the virtualenv configuration file.
+        Public method to get the name of the virtualenv configuration file.
         
+        @param venvName name of the environment to get config file path for
+        @type str
         @return path of the virtualenv configuration file
         @rtype str
         """
         # Unix, OS X:   $VIRTUAL_ENV/pip.conf
         # Windows:      %VIRTUAL_ENV%\pip.ini
         
-        # TODO: modify to use venvName
         if Globals.isWindowsPlatform():
             pip = "pip.ini"
         else:
             pip = "pip.conf"
-        try:
-            venvDirectory = os.environ["VIRTUAL_ENV"]
-        except KeyError:
-            venvName = Preferences.getPip("CurrentEnvironment")
-            if not venvName:
-                self.__selectPipVirtualenv()
-                venvName = Preferences.getPip("CurrentEnvironment")
-            venvManager = e5App().getObject("VirtualEnvManager")
-            if venvManager.isGlobalEnvironment(venvName):
-                venvDirectory = self.__getUserConfig()
-            else:
-                venvDirectory = venvManager.getVirtualenvDirectory(venvName)
+        
+        venvManager = e5App().getObject("VirtualEnvManager")
+        if venvManager.isGlobalEnvironment(venvName):
+            venvDirectory = self.__getUserConfig()
+        else:
+            venvDirectory = venvManager.getVirtualenvDirectory(venvName)
         
         if venvDirectory:
             config = os.path.join(venvDirectory, pip)
@@ -563,15 +167,6 @@
         
         return config
     
-##    def getDefaultEnvironmentString(self):
-##        """
-##        Public method to get the string for the default environment.
-##        
-##        @return string for the default environment
-##        @rtype str
-##        """
-##        return self.tr("<standard>")
-##    
     def getProjectEnvironmentString(self):
         """
         Public method to get the string for the project environment.
@@ -593,16 +188,12 @@
         @return interpreter path
         @rtype str
         """
-##        if venvName == self.getDefaultEnvironmentString():
-##            venvName = Preferences.getPip("CurrentEnvironment")
         if venvName == self.getProjectEnvironmentString():
             venvName = \
                 e5App().getObject("Project").getDebugProperty("VIRTUALENV")
             if not venvName:
                 # fall back to interpreter used to run eric6
                 return sys.executable
-##                # fall back to standard if not defined
-##                venvName = Preferences.getPip("CurrentEnvironment")
         
         interpreter = \
             e5App().getObject("VirtualEnvManager").getVirtualenvInterpreter(
@@ -626,137 +217,6 @@
         return sorted(
             e5App().getObject("VirtualEnvManager").getVirtualenvNames())
     
-    ##########################################################################
-    ## Methods below implement the individual menu entries
-    ##########################################################################
-    
-##    def __selectPipVirtualenv(self):
-##        """
-##        Private method to select the virtual environment to be used.
-##        """
-##        environments = self.getVirtualenvNames()
-##        if environments:
-##            currentEnvironment = Preferences.getPip("CurrentEnvironment")
-##            try:
-##                index = environments.index(currentEnvironment)
-##            except ValueError:
-##                index = 0
-##            environment, ok = QInputDialog.getItem(
-##                None,
-##                self.tr("Virtual Environment for pip"),
-##                self.tr("Select the virtual environment to be used:"),
-##                environments, index, False)
-##            
-##            if ok and environment:
-##                Preferences.getPip("CurrentEnvironment", environment)
-##        else:
-##            E5MessageBox.warning(
-##                None,
-##                self.tr("Virtual Environment for pip"),
-##                self.tr("""No virtual environments have been configured yet."""
-##                        """ Please use the Virtualenv Manager to do that."""))
-##    
-##    def __listPackages(self):
-##        """
-##        Private slot to list all installed packages.
-##        """
-##        from .PipListDialog import PipListDialog
-##        self.__listDialog = PipListDialog(
-##            self, "list", Preferences.getPip("PipSearchIndex"),
-##            self.tr("Installed Packages"))
-##        self.__listDialog.show()
-##        self.__listDialog.start()
-##    
-##    def __listUptodatePackages(self):
-##        """
-##        Private slot to list all installed, up-to-date packages.
-##        """
-##        from .PipListDialog import PipListDialog
-##        self.__listUptodateDialog = PipListDialog(
-##            self, "uptodate", Preferences.getPip("PipSearchIndex"),
-##            self.tr("Up-to-date Packages"))
-##        self.__listUptodateDialog.show()
-##        self.__listUptodateDialog.start()
-##    
-##    def __listOutdatedPackages(self):
-##        """
-##        Private slot to list all installed, up-to-date packages.
-##        """
-##        from .PipListDialog import PipListDialog
-##        self.__listOutdatedDialog = PipListDialog(
-##            self, "outdated", Preferences.getPip("PipSearchIndex"),
-##            self.tr("Outdated Packages"))
-##        self.__listOutdatedDialog.show()
-##        self.__listOutdatedDialog.start()
-##    
-##    def __editUserConfiguration(self):
-##        """
-##        Private slot to edit the user configuration.
-##        """
-##        self.__editConfiguration()
-##    
-##    def __editVirtualenvConfiguration(self):
-##        """
-##        Private slot to edit the current virtualenv configuration.
-##        """
-##        self.__editConfiguration(virtualenv=True)
-##    
-##    def __editConfiguration(self, virtualenv=False):
-##        """
-##        Private method to edit a configuration.
-##        
-##        @param virtualenv flag indicating to edit the current virtualenv
-##            configuration file
-##        @type bool
-##        """
-##        from QScintilla.MiniEditor import MiniEditor
-##        if virtualenv:
-##            cfgFile = self.__getVirtualenvConfig()
-##            if not cfgFile:
-##                return
-##        else:
-##            cfgFile = self.__getUserConfig()
-##        cfgDir = os.path.dirname(cfgFile)
-##        if not cfgDir:
-##            E5MessageBox.critical(
-##                None,
-##                self.tr("Edit Configuration"),
-##                self.tr("""No valid configuration path determined."""
-##                        """ Is a virtual environment selected? Aborting"""))
-##            return
-##        
-##        try:
-##            if not os.path.isdir(cfgDir):
-##                os.makedirs(cfgDir)
-##        except OSError:
-##            E5MessageBox.critical(
-##                None,
-##                self.tr("Edit Configuration"),
-##                self.tr("""No valid configuration path determined."""
-##                        """ Is a virtual environment selected? Aborting"""))
-##            return
-##        
-##        if not os.path.exists(cfgFile):
-##            try:
-##                f = open(cfgFile, "w")
-##                f.write("[global]\n")
-##                f.close()
-##            except (IOError, OSError):
-##                # ignore these
-##                pass
-##        
-##        # check, if the destination is writeable
-##        if not os.access(cfgFile, os.W_OK):
-##            E5MessageBox.critical(
-##                None,
-##                self.tr("Edit Configuration"),
-##                self.tr("""No valid configuartion path determined."""
-##                        """ Is a virtual environment selected? Aborting"""))
-##            return
-##        
-##        self.__editor = MiniEditor(cfgFile, "Properties")
-##        self.__editor.show()
-##    
     def installPip(self, venvName, userSite=False):
         """
         Public method to install pip.
@@ -791,50 +251,6 @@
         if res:
             dia.exec_()
     
-##    @pyqtSlot()
-##    def upgradePip(self, venvName="", userSite=False):
-##        """
-##        Public method to upgrade pip itself.
-##        
-##        @param venvName name of the virtual environment to be used
-##        @type str
-##        @param userSite flag indicating an install to the user install
-##            directory
-##        @type bool
-##        @return flag indicating a successful execution
-##        @rtype bool
-##        """
-##        # Upgrading pip needs to be treated specially because
-##        # it must be done using the python executable
-##        
-##        if not venvName:
-##            from .PipSelectionDialog import PipSelectionDialog
-##            dlg = PipSelectionDialog(self)
-##            if dlg.exec_() != QDialog.Accepted:
-##                return
-##            
-##            venvName, userSite = dlg.getData()
-##        
-##        interpreter = self.getVirtualenvInterpreter(venvName)
-##        if not interpreter:
-##            return
-##        
-##        if Preferences.getPip("PipSearchIndex"):
-##            indexUrl = Preferences.getPip("PipSearchIndex") + "/simple"
-##            args = ["-m", "pip", "install", "--index-url", indexUrl,
-##                    "--upgrade"]
-##        else:
-##            args = ["-m", "pip", "install", "--upgrade"]
-##        if userSite:
-##            args.append("--user")
-##        args.append("pip")
-##        
-##        dia = PipDialog(self.tr('Upgrade PIP'))
-##        res = dia.startProcess(interpreter, args)
-##        if res:
-##            dia.exec_()
-##        return res
-##    
     @pyqtSlot()
     def repairPip(self, venvName):
         """
@@ -842,8 +258,6 @@
         
         @param venvName name of the environment to install pip into
         @type str
-        @return flag indicating a successful execution
-        @rtype bool
         """
         interpreter = self.getVirtualenvInterpreter(venvName)
         if not interpreter:
@@ -873,14 +287,15 @@
         @rtype bool
         """
         pyqtPackages = [p for p in packages
-                        if p.lower() in ["pyqt5", "qscintilla", "sip"]]
+                        if p.lower() in ["pyqt5", "pyqt5-sip", "pyqtwebengine",
+                                         "qscintilla", "sip"]]
         
         if bool(pyqtPackages):
             abort = not E5MessageBox.yesNo(
                 None,
                 self.tr("Upgrade Packages"),
                 self.tr(
-                    """You are trying to upgrade PyQt packages. This will"""
+                    """You are trying to upgrade PyQt packages. This might"""
                     """ not work for the current instance of Python ({0})."""
                     """ Do you want to continue?""").format(sys.executable),
                 icon=E5MessageBox.Critical)
@@ -889,7 +304,7 @@
         
         return abort
     
-    def upgradePackages(self, packages, venvName="", userSite=False):
+    def upgradePackages(self, packages, venvName, userSite=False):
         """
         Public method to upgrade the given list of packages.
         
@@ -907,10 +322,11 @@
             return False
         
         if not venvName:
-            venvName = Preferences.getPip("CurrentEnvironment")
+            return False
+        
         interpreter = self.getVirtualenvInterpreter(venvName)
         if not interpreter:
-            return
+            return False
         
         if Preferences.getPip("PipSearchIndex"):
             indexUrl = Preferences.getPip("PipSearchIndex") + "/simple"
@@ -927,19 +343,7 @@
             dia.exec_()
         return res
     
-    def __upgradePackages(self):
-        """
-        Private slot to upgrade packages to be given by the user.
-        """
-        from .PipPackagesInputDialog import PipPackagesInputDialog
-        dlg = PipPackagesInputDialog(self, self.tr("Upgrade Packages"))
-        if dlg.exec_() == QDialog.Accepted:
-            venvName, packages, user = dlg.getData()
-            if packages:
-                self.upgradePackages(packages, venvName=venvName,
-                                     userSite=user)
-    
-    def installPackages(self, packages, venvName="", userSite=False):
+    def installPackages(self, packages, venvName, userSite=False):
         """
         Public method to install the given list of packages.
         
@@ -951,62 +355,40 @@
             directory
         @type bool
         """
-        if not venvName:
-            venvName = Preferences.getPip("CurrentEnvironment")
-        interpreter = self.getVirtualenvInterpreter(venvName)
-        if not interpreter:
-            return
+        if venvName:
+            interpreter = self.getVirtualenvInterpreter(venvName)
+            if not interpreter:
+                return
+            
+            if Preferences.getPip("PipSearchIndex"):
+                indexUrl = Preferences.getPip("PipSearchIndex") + "/simple"
+                args = ["-m", "pip", "install", "--index-url", indexUrl]
+            else:
+                args = ["-m", "pip", "install"]
+            if userSite:
+                args.append("--user")
+            args += packages
+            dia = PipDialog(self.tr('Install Packages'))
+            res = dia.startProcess(interpreter, args)
+            if res:
+                dia.exec_()
+    
+    def installRequirements(self, venvName):
+        """
+        Public method to install packages as given in a requirements file.
         
-        if Preferences.getPip("PipSearchIndex"):
-            indexUrl = Preferences.getPip("PipSearchIndex") + "/simple"
-            args = ["-m", "pip", "install", "--index-url", indexUrl]
-        else:
-            args = ["-m", "pip", "install"]
-        if userSite:
-            args.append("--user")
-        args += packages
-        dia = PipDialog(self.tr('Install Packages'))
-        res = dia.startProcess(interpreter, args)
-        if res:
-            dia.exec_()
-##    
-##    def __installPackages(self):
-##        """
-##        Private slot to install packages to be given by the user.
-##        """
-##        from .PipPackagesInputDialog import PipPackagesInputDialog
-##        dlg = PipPackagesInputDialog(
-##            self, self.tr("Install Packages"))
-##        if dlg.exec_() == QDialog.Accepted:
-##            venvName, packages, user = dlg.getData()
-##            if packages:
-##                self.installPackages(packages, venvName=venvName,
-##                                     userSite=user)
-##    
-##    def __installLocalPackage(self):
-##        """
-##        Private slot to install a package available on local storage.
-##        """
-##        from .PipFileSelectionDialog import PipFileSelectionDialog
-##        dlg = PipFileSelectionDialog(self, "package")
-##        if dlg.exec_() == QDialog.Accepted:
-##            venvName, package, user = dlg.getData()
-##            if package and os.path.exists(package):
-##                self.installPackages([package], venvName=venvName,
-##                                     userSite=user)
-    
-    def __installRequirements(self):
-        """
-        Private slot to install packages as given in a requirements file.
+        @param venvName name of the virtual environment to be used
+        @type str
         """
         from .PipFileSelectionDialog import PipFileSelectionDialog
         dlg = PipFileSelectionDialog(self, "requirements")
         if dlg.exec_() == QDialog.Accepted:
-            venvName, requirements, user = dlg.getData()
+            requirements, user = dlg.getData()
             if requirements and os.path.exists(requirements):
                 interpreter = self.getVirtualenvInterpreter(venvName)
                 if not interpreter:
                     return
+                
                 if Preferences.getPip("PipSearchIndex"):
                     indexUrl = Preferences.getPip("PipSearchIndex") + \
                         "/simple"
@@ -1021,7 +403,7 @@
                 if res:
                     dia.exec_()
     
-    def uninstallPackages(self, packages, venvName=""):
+    def uninstallPackages(self, packages, venvName):
         """
         Public method to uninstall the given list of packages.
         
@@ -1033,7 +415,7 @@
         @rtype bool
         """
         res = False
-        if packages:
+        if packages and venvName:
             from UI.DeleteFilesConfirmationDialog import \
                 DeleteFilesConfirmationDialog
             dlg = DeleteFilesConfirmationDialog(
@@ -1043,8 +425,6 @@
                     "Do you really want to uninstall these packages?"),
                 packages)
             if dlg.exec_() == QDialog.Accepted:
-                if not venvName:
-                    venvName = Preferences.getPip("CurrentEnvironment")
                 interpreter = self.getVirtualenvInterpreter(venvName)
                 if not interpreter:
                     return
@@ -1055,80 +435,48 @@
                     dia.exec_()
         return res
     
-##    def __uninstallPackages(self):
-##        """
-##        Private slot to uninstall packages to be given by the user.
-##        """
-##        from .PipPackagesInputDialog import PipPackagesInputDialog
-##        dlg = PipPackagesInputDialog(
-##            self, self.tr("Uninstall Packages"), install=False)
-##        if dlg.exec_() == QDialog.Accepted:
-##            venvName, packages, _user = dlg.getData()
-##            if packages:
-##                self.uninstallPackages(packages, venvName=venvName)
-##    
-    def __uninstallRequirements(self):
+    def uninstallRequirements(self, venvName):
         """
-        Private slot to uninstall packages as given in a requirements file.
+        Public method to uninstall packages as given in a requirements file.
+        
+        @param venvName name of the virtual environment to be used
+        @type str
         """
-        from .PipFileSelectionDialog import PipFileSelectionDialog
-        dlg = PipFileSelectionDialog(self, "requirements",
-                                     install=False)
-        if dlg.exec_() == QDialog.Accepted:
-            venvName, requirements, _user = dlg.getData()
-            if requirements and os.path.exists(requirements):
-                try:
-                    f = open(requirements, "r")
-                    reqs = f.read().splitlines()
-                    f.close()
-                except (OSError, IOError):
-                    return
-                
-                from UI.DeleteFilesConfirmationDialog import \
-                    DeleteFilesConfirmationDialog
-                dlg = DeleteFilesConfirmationDialog(
-                    self.parent(),
-                    self.tr("Uninstall Packages"),
-                    self.tr(
-                        "Do you really want to uninstall these packages?"),
-                    reqs)
-                if dlg.exec_() == QDialog.Accepted:
-                    if not venvName:
-                        venvName = Preferences.getPip("CurrentEnvironment")
-                    interpreter = self.getVirtualenvInterpreter(venvName)
-                    if not interpreter:
+        if venvName:
+            from .PipFileSelectionDialog import PipFileSelectionDialog
+            dlg = PipFileSelectionDialog(self, "requirements",
+                                         install=False)
+            if dlg.exec_() == QDialog.Accepted:
+                requirements, _user = dlg.getData()
+                if requirements and os.path.exists(requirements):
+                    try:
+                        f = open(requirements, "r")
+                        reqs = f.read().splitlines()
+                        f.close()
+                    except (OSError, IOError):
                         return
-                    args = ["-m", "pip", "uninstall", "--requirement",
-                            requirements]
-                    dia = PipDialog(
-                        self.tr('Uninstall Packages from Requirements'))
-                    res = dia.startProcess(interpreter, args)
-                    if res:
-                        dia.exec_()
+                    
+                    from UI.DeleteFilesConfirmationDialog import \
+                        DeleteFilesConfirmationDialog
+                    dlg = DeleteFilesConfirmationDialog(
+                        self.parent(),
+                        self.tr("Uninstall Packages"),
+                        self.tr(
+                            "Do you really want to uninstall these packages?"),
+                        reqs)
+                    if dlg.exec_() == QDialog.Accepted:
+                        interpreter = self.getVirtualenvInterpreter(venvName)
+                        if not interpreter:
+                            return
+                        
+                        args = ["-m", "pip", "uninstall", "--requirement",
+                                requirements]
+                        dia = PipDialog(
+                            self.tr('Uninstall Packages from Requirements'))
+                        res = dia.startProcess(interpreter, args)
+                        if res:
+                            dia.exec_()
     
-##    def __generateRequirements(self):
-##        """
-##        Private slot to generate the contents for a requirements file.
-##        """
-##        from .PipFreezeDialog import PipFreezeDialog
-##        self.__freezeDialog = PipFreezeDialog(self)
-##        self.__freezeDialog.show()
-##        self.__freezeDialog.start()
-##    
-##    def __searchPyPI(self):
-##        """
-##        Private slot to search the Python Package Index.
-##        """
-##        from .PipSearchDialog import PipSearchDialog
-##        
-##        if Preferences.getPip("PipSearchIndex"):
-##            indexUrl = Preferences.getPip("PipSearchIndex") + "/pypi"
-##        else:
-##            indexUrl = DefaultIndexUrlXml
-##        
-##        self.__searchDialog = PipSearchDialog(self, indexUrl)
-##        self.__searchDialog.show()
-##    
     def getIndexUrl(self):
         """
         Public method to get the index URL for PyPI.
@@ -1271,9 +619,36 @@
                                 ))
            
         return packages
-## 
-##    def __pipConfigure(self):
-##        """
-##        Private slot to open the configuration page.
-##        """
-##        e5App().getObject("UserInterface").showPreferences("pipPage")
+    
+    def getPackageDetails(self, name, version):
+        """
+        Public method to get package details using the PyPI JSON interface.
+        
+        @param name package name
+        @type str
+        @param version package version
+        @type str
+        @return dictionary containing PyPI package data
+        @rtype dict
+        """
+        result = {}
+        
+        if name and version:
+            url = "https://pypi.org/pypi/{0}/{1}/json".format(name, version)
+            request = QNetworkRequest(QUrl(url))
+            reply = self.__networkManager.get(request)
+            while not reply.isFinished():
+                QCoreApplication.processEvents()
+            
+            reply.deleteLater()
+            if reply.error() == QNetworkReply.NoError:
+                data = str(reply.readAll(),
+                           Preferences.getSystem("IOEncoding"),
+                           'replace')
+                try:
+                    result = json.loads(data)
+                except Exception:
+                    # ignore JSON exceptions
+                    pass
+        
+        return result
--- a/PipInterface/PipFreezeDialog.py	Thu Feb 21 19:55:35 2019 +0100
+++ b/PipInterface/PipFreezeDialog.py	Fri Feb 22 19:34:44 2019 +0100
@@ -54,12 +54,6 @@
         
         self.__pip = pip
         
-        self.venvComboBox.addItem(pip.getDefaultEnvironmentString())
-        projectVenv = self.__pip.getProjectEnvironmentString()
-        if projectVenv:
-            self.venvComboBox.addItem(projectVenv)
-        self.venvComboBox.addItems(pip.getVirtualenvNames())
-        
         self.__requirementsEdited = False
         self.__requirementsAvailable = False
         
@@ -75,16 +69,6 @@
         QApplication.restoreOverrideCursor()
         e.accept()
     
-    @pyqtSlot(str)
-    def on_venvComboBox_activated(self, txt):
-        """
-        Private slot handling the selection of a virtual environment.
-        
-        @param txt virtual environment
-        @type str
-        """
-        self.__refresh()
-    
     @pyqtSlot(bool)
     def on_localCheckBox_clicked(self, checked):
         """
@@ -140,14 +124,16 @@
         if ok:
             self.start()
     
-    def start(self):
+    def start(self, venvName):
         """
         Public method to start the command.
+        
+        @param venvName name of the environment to act upon
+        @type str
         """
         self.requirementsEdit.clear()
         self.__requirementsAvailable = False
         
-        venvName = self.venvComboBox.currentText()
         interpreter = self.__pip.getVirtualenvInterpreter(venvName)
         if not interpreter:
             return
--- a/PipInterface/PipFreezeDialog.ui	Thu Feb 21 19:55:35 2019 +0100
+++ b/PipInterface/PipFreezeDialog.ui	Fri Feb 22 19:34:44 2019 +0100
@@ -21,30 +21,6 @@
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
-    <layout class="QHBoxLayout" name="horizontalLayout_2">
-     <item>
-      <widget class="QLabel" name="label_2">
-       <property name="text">
-        <string>Virtual Environment:</string>
-       </property>
-      </widget>
-     </item>
-     <item>
-      <widget class="QComboBox" name="venvComboBox">
-       <property name="sizePolicy">
-        <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
-         <horstretch>0</horstretch>
-         <verstretch>0</verstretch>
-        </sizepolicy>
-       </property>
-       <property name="toolTip">
-        <string>Select the virtual environment to be used</string>
-       </property>
-      </widget>
-     </item>
-    </layout>
-   </item>
-   <item>
     <widget class="QCheckBox" name="localCheckBox">
      <property name="toolTip">
       <string>Select to show requirements for locally-installed packages only</string>
@@ -183,7 +159,6 @@
   </customwidget>
  </customwidgets>
  <tabstops>
-  <tabstop>venvComboBox</tabstop>
   <tabstop>localCheckBox</tabstop>
   <tabstop>requirementsFilePicker</tabstop>
   <tabstop>requirementsEdit</tabstop>
--- a/PipInterface/PipPackageDetailsDialog.py	Thu Feb 21 19:55:35 2019 +0100
+++ b/PipInterface/PipPackageDetailsDialog.py	Fri Feb 22 19:34:44 2019 +0100
@@ -24,14 +24,12 @@
     """
     Class implementing a dialog to show details about a package.
     """
-    def __init__(self, detailsData, downloadsData, parent=None):
+    def __init__(self, detailsData, parent=None):
         """
         Constructor
         
         @param detailsData package details
         @type dict
-        @param downloadsData downloads information
-        @type dict
         @param parent reference to the parent widget
         @type QWidget
         """
@@ -51,9 +49,9 @@
             "bdist_dumb": self.tr("Archive"),
         }
         
-        self.__populateDetails(detailsData)
-        self.__populateDownloadUrls(downloadsData)
-        self.__populateRequiresProvides(detailsData)
+        self.__populateDetails(detailsData["info"])
+        self.__populateDownloadUrls(detailsData["urls"])
+        self.__populateRequiresProvides(detailsData["info"])
     
     def __populateDetails(self, detailsData):
         """
@@ -147,17 +145,17 @@
         """
         populatedItems = 0
         
-        if "requires" in detailsData:
+        if "requires" in detailsData and detailsData["requires"]:
             self.requiredPackagesList.addItems(detailsData["requires"])
             populatedItems += len(detailsData["requires"])
-        if "requires_dist" in detailsData:
+        if "requires_dist" in detailsData and detailsData["requires_dist"]:
             self.requiredDistributionsList.addItems(
                 detailsData["requires_dist"])
             populatedItems += len(detailsData["requires_dist"])
-        if "provides" in detailsData:
+        if "provides" in detailsData and detailsData["provides"]:
             self.providedPackagesList.addItems(detailsData["provides"])
             populatedItems += len(detailsData["provides"])
-        if "provides_dist" in detailsData:
+        if "provides_dist" in detailsData and detailsData["provides_dist"]:
             self.providedDistributionsList.addItems(
                 detailsData["provides_dist"])
             populatedItems += len(detailsData["provides_dist"])
--- a/PipInterface/PipPackagesWidget.py	Thu Feb 21 19:55:35 2019 +0100
+++ b/PipInterface/PipPackagesWidget.py	Fri Feb 22 19:34:44 2019 +0100
@@ -29,6 +29,8 @@
 from .Pip import Pip
 
 
+# TODO: use icons for action buttons
+# TODO: show package details for installed packages
 class PipPackagesWidget(QWidget, Ui_PipPackagesWidget):
     """
     Class implementing the pip packages management widget.
@@ -111,8 +113,8 @@
         self.statusLabel.hide()
         self.searchWidget.hide()
         
-        self.__detailsData = {}
-        self.__query = []
+        self.__queryName = []
+        self.__querySummary = []
         
         self.__packageDetailsDialog = None
     
@@ -471,7 +473,8 @@
         Private method to update the state of the search button.
         """
         self.searchButton.setEnabled(
-            bool(self.searchEdit.text()) and
+            (bool(self.searchEditName.text()) or
+             bool(self.searchEditSummary.text())) and
             self.__isPipAvailable()
         )
     
@@ -486,14 +489,14 @@
         self.searchWidget.setVisible(checked)
         
         if checked:
-            self.searchEdit.setFocus(Qt.OtherFocusReason)
-            self.searchEdit.selectAll()
+            self.searchEditName.setFocus(Qt.OtherFocusReason)
+            self.searchEditName.selectAll()
             
             self.__updateSearchActionButtons()
             self.__updateSearchButton()
     
     @pyqtSlot(str)
-    def on_searchEdit_textChanged(self, txt):
+    def on_searchEditName_textChanged(self, txt):
         """
         Private slot handling a change of the search term.
         
@@ -503,7 +506,24 @@
         self.__updateSearchButton()
     
     @pyqtSlot()
-    def on_searchEdit_returnPressed(self):
+    def on_searchEditName_returnPressed(self):
+        """
+        Private slot initiating a search via a press of the Return key.
+        """
+        self.__search()
+    
+    @pyqtSlot(str)
+    def on_searchEditSummary_textChanged(self, txt):
+        """
+        Private slot handling a change of the search term.
+        
+        @param txt search term
+        @type str
+        """
+        self.__updateSearchButton()
+    
+    @pyqtSlot()
+    def on_searchEditSummary_returnPressed(self):
         """
         Private slot initiating a search via a press of the Return key.
         """
@@ -534,11 +554,19 @@
         QApplication.setOverrideCursor(Qt.WaitCursor)
         QApplication.processEvents(QEventLoop.ExcludeUserInputEvents)
         
-        self.__query = [term for term in self.searchEdit.text().strip().split()
-                        if term not in self.SearchStopwords]
+        self.__queryName = [
+            term for term in self.searchEditName.text().strip().split()
+            if term not in self.SearchStopwords
+        ]
+        self.__querySummary = [
+            term for term in self.searchEditSummary.text().strip().split()
+            if term not in self.SearchStopwords
+        ]
         self.__client.call(
             "search",
-            ({"name": self.__query, "summary": self.__query}, "or"),
+            ({"name": self.__queryName,
+              "summary": self.__querySummary},
+             self.searchTermCombineComboBox.currentText()),
             self.__processSearchResult,
             self.__searchError
         )
@@ -616,7 +644,7 @@
         self.__updateSearchActionButtons()
         self.__updateSearchButton()
         
-        self.searchEdit.setFocus(Qt.OtherFocusReason)
+        self.searchEditName.setFocus(Qt.OtherFocusReason)
     
     def __searchError(self, errorCode, errorString):
         """
@@ -682,12 +710,13 @@
         @rtype int
         """
         score = 0
-        for queryTerm in self.__query:
+        for queryTerm in self.__queryName:
             if queryTerm.lower() in name.lower():
                 score += 4
                 if queryTerm.lower() == name.lower():
                     score += 4
             
+        for queryTerm in self.__querySummary:
             if queryTerm.lower() in summary.lower():
                 if QRegExp(r'\b{0}\b'.format(QRegExp.escape(queryTerm)),
                            Qt.CaseInsensitive).indexIn(summary) != -1:
@@ -758,8 +787,6 @@
         QApplication.setOverrideCursor(Qt.WaitCursor)
         QApplication.processEvents(QEventLoop.ExcludeUserInputEvents)
         
-        self.__detailsData = {}
-        
         if not item:
             item = self.searchResultList.selectedItems()[0]
         
@@ -777,86 +804,28 @@
                 0, False)
             if not ok:
                 return
-        
         packageName = item.text(0)
-        self.__client.call(
-            "release_data",
-            (packageName, packageVersion),
-            lambda d: self.__getPackageDownloadsData(packageName,
-                                                     packageVersion,
-                                                     d),
-            lambda c, s: self.__detailsError(packageName, c, s)
-        )
-    
-    def __getPackageDownloadsData(self, packageName, packageVersion, data):
-        """
-        Private method to store the details data and get downloads
-        information.
+        packageData = self.__pip.getPackageDetails(packageName, packageVersion)
         
-        @param packageName name of the package
-        @type str
-        @param packageVersion version info
-        @type str
-        @param data result data with package details in the first
-            element
-        @type tuple
-        """
-        if data and data[0]:
-            self.__detailsData = data[0]
-            self.__client.call(
-                "release_urls",
-                (packageName, packageVersion),
-                self.__displayPackageDetails,
-                lambda c, s: self.__detailsError(packageName, c, s)
-            )
+        QApplication.restoreOverrideCursor()
+        if packageData:
+            from .PipPackageDetailsDialog import PipPackageDetailsDialog
+            
+            self.showDetailsButton.setEnabled(True)
+            
+            if self.__packageDetailsDialog is not None:
+                self.__packageDetailsDialog.close()
+            
+            self.__packageDetailsDialog = \
+                PipPackageDetailsDialog(packageData, self)
+            self.__packageDetailsDialog.show()
         else:
-            QApplication.restoreOverrideCursor()
             E5MessageBox.warning(
                 self,
                 self.tr("Search PyPI"),
                 self.tr("""<p>No package details info for <b>{0}</b>"""
                         """ available.</p>""").format(packageName))
     
-    def __displayPackageDetails(self, data):
-        """
-        Private method to display the returned package details.
-        
-        @param data result data with downloads information in the first element
-        @type tuple
-        """
-        from .PipPackageDetailsDialog import PipPackageDetailsDialog
-        
-        QApplication.restoreOverrideCursor()
-        self.showDetailsButton.setEnabled(True)
-        
-        if self.__packageDetailsDialog is not None:
-            self.__packageDetailsDialog.close()
-        
-        self.__packageDetailsDialog = \
-            PipPackageDetailsDialog(self.__detailsData, data[0], self)
-        self.__packageDetailsDialog.show()
-    
-    def __detailsError(self, packageName, errorCode, errorString):
-        """
-        Private method handling a details error.
-        
-        @param packageName name of the package
-        @type str
-        @param errorCode code of the error
-        @type int
-        @param errorString error message
-        @type str
-        """
-        QApplication.restoreOverrideCursor()
-        self.showDetailsButton.setEnabled(True)
-        E5MessageBox.warning(
-            self,
-            self.tr("Search PyPI"),
-            self.tr("""<p>Package details info for <b>{0}</b> could not be"""
-                    """ retrieved.</p><p>Reason: {1}</p>""")
-            .format(packageName, errorString)
-        )
-    
     #######################################################################
     ## Menu related methods below
     #######################################################################
@@ -993,27 +962,32 @@
     @pyqtSlot()
     def __installRequirements(self):
         """
-        
+        Private slot to install packages as given in a requirements file.
         """
-        # TODO: call pip.installRequirements()
+        venvName = self.environmentsComboBox.currentText()
+        if venvName:
+            self.__pip.installRequirements(venvName)
     
     @pyqtSlot()
     def __uninstallRequirements(self):
         """
-        
+        Private slot to uninstall packages as given in a requirements file.
         """
-        # TODO: call pip.uninstallRequirements()
+        venvName = self.environmentsComboBox.currentText()
+        if venvName:
+            self.__pip.uninstallRequirements(venvName)
     
     @pyqtSlot()
     def __generateRequirements(self):
         """
         Private slot to generate the contents for a requirements file.
         """
-        # TODO: modify to get selected environment
-        from .PipFreezeDialog import PipFreezeDialog
-        self.__freezeDialog = PipFreezeDialog(self)
-        self.__freezeDialog.show()
-        self.__freezeDialog.start()
+        venvName = self.environmentsComboBox.currentText()
+        if venvName:
+            from .PipFreezeDialog import PipFreezeDialog
+            self.__freezeDialog = PipFreezeDialog(self.__pip, self)
+            self.__freezeDialog.show()
+            self.__freezeDialog.start(venvName)
     
     @pyqtSlot()
     def __editUserConfiguration(self):
@@ -1025,34 +999,33 @@
     @pyqtSlot()
     def __editVirtualenvConfiguration(self):
         """
-        Private slot to edit the current virtualenv configuration.
+        Private slot to edit the configuration of the selected environment.
         """
-        # TODO: modify to get selected environment
-        self.__editConfiguration(virtualenv=True)
+        venvName = self.environmentsComboBox.currentText()
+        if venvName:
+            self.__editConfiguration(venvName=venvName)
     
-    def __editConfiguration(self, virtualenv=False):
+    def __editConfiguration(self, venvName=""):
         """
         Private method to edit a configuration.
         
-        @param virtualenv flag indicating to edit the current virtualenv
-            configuration file
-        @type bool
+        @param venvName name of the environment to act upon
+        @type str
         """
-        # TODO: modify to use venvName
         from QScintilla.MiniEditor import MiniEditor
-        if virtualenv:
-            cfgFile = self.__getVirtualenvConfig()
+        if venvName:
+            cfgFile = self.__pip.getVirtualenvConfig(venvName)
             if not cfgFile:
                 return
         else:
-            cfgFile = self.__getUserConfig()
+            cfgFile = self.__pip.getUserConfig()
         cfgDir = os.path.dirname(cfgFile)
         if not cfgDir:
             E5MessageBox.critical(
                 None,
                 self.tr("Edit Configuration"),
                 self.tr("""No valid configuration path determined."""
-                        """ Is a virtual environment selected? Aborting"""))
+                        """ Aborting"""))
             return
         
         try:
@@ -1063,7 +1036,7 @@
                 None,
                 self.tr("Edit Configuration"),
                 self.tr("""No valid configuration path determined."""
-                        """ Is a virtual environment selected? Aborting"""))
+                        """ Aborting"""))
             return
         
         if not os.path.exists(cfgFile):
@@ -1081,7 +1054,7 @@
                 None,
                 self.tr("Edit Configuration"),
                 self.tr("""No valid configuartion path determined."""
-                        """ Is a virtual environment selected? Aborting"""))
+                        """ Aborting"""))
             return
         
         self.__editor = MiniEditor(cfgFile, "Properties")
--- a/PipInterface/PipPackagesWidget.ui	Thu Feb 21 19:55:35 2019 +0100
+++ b/PipInterface/PipPackagesWidget.ui	Fri Feb 22 19:34:44 2019 +0100
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>500</width>
-    <height>600</height>
+    <height>700</height>
    </rect>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout_5">
@@ -313,18 +313,42 @@
        <number>0</number>
       </property>
       <item>
-       <layout class="QHBoxLayout" name="horizontalLayout_4">
-        <item>
-         <widget class="QLineEdit" name="searchEdit">
+       <layout class="QGridLayout" name="gridLayout">
+        <item row="0" column="0">
+         <widget class="QLabel" name="label">
+          <property name="text">
+           <string>Name:</string>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="1">
+         <widget class="QLineEdit" name="searchEditName">
           <property name="toolTip">
-           <string>Enter the search term</string>
+           <string>Enter the search term for the package name</string>
           </property>
           <property name="placeholderText">
            <string>Enter search term</string>
           </property>
          </widget>
         </item>
-        <item>
+        <item row="0" column="2" rowspan="2">
+         <widget class="QComboBox" name="searchTermCombineComboBox">
+          <property name="toolTip">
+           <string>Select the search term combination operation</string>
+          </property>
+          <item>
+           <property name="text">
+            <string notr="true">and</string>
+           </property>
+          </item>
+          <item>
+           <property name="text">
+            <string notr="true">or</string>
+           </property>
+          </item>
+         </widget>
+        </item>
+        <item row="0" column="3" rowspan="2">
          <widget class="QPushButton" name="searchButton">
           <property name="enabled">
            <bool>false</bool>
@@ -337,6 +361,23 @@
           </property>
          </widget>
         </item>
+        <item row="1" column="0">
+         <widget class="QLabel" name="label_2">
+          <property name="text">
+           <string>Summary:</string>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="1">
+         <widget class="QLineEdit" name="searchEditSummary">
+          <property name="toolTip">
+           <string>Enter the search term for the package summary</string>
+          </property>
+          <property name="placeholderText">
+           <string>Enter search term</string>
+          </property>
+         </widget>
+        </item>
        </layout>
       </item>
       <item>
@@ -469,16 +510,25 @@
  <tabstops>
   <tabstop>environmentsComboBox</tabstop>
   <tabstop>pipMenuButton</tabstop>
+  <tabstop>localCheckBox</tabstop>
+  <tabstop>notRequiredCheckBox</tabstop>
+  <tabstop>userCheckBox</tabstop>
   <tabstop>packagesList</tabstop>
+  <tabstop>verboseCheckBox</tabstop>
+  <tabstop>installedFilesCheckBox</tabstop>
+  <tabstop>infoWidget</tabstop>
   <tabstop>refreshButton</tabstop>
   <tabstop>upgradeButton</tabstop>
   <tabstop>upgradeAllButton</tabstop>
   <tabstop>uninstallButton</tabstop>
   <tabstop>searchToggleButton</tabstop>
-  <tabstop>searchEdit</tabstop>
+  <tabstop>searchEditName</tabstop>
+  <tabstop>searchTermCombineComboBox</tabstop>
+  <tabstop>searchEditSummary</tabstop>
   <tabstop>searchButton</tabstop>
   <tabstop>searchResultList</tabstop>
   <tabstop>installButton</tabstop>
+  <tabstop>installUserSiteButton</tabstop>
   <tabstop>showDetailsButton</tabstop>
  </tabstops>
  <resources/>
--- a/Plugins/PluginPipInterface.py	Thu Feb 21 19:55:35 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,235 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
-#
-
-"""
-Module implementing the pip interface plug-in.
-"""
-
-from __future__ import unicode_literals
-
-
-from PyQt5.QtCore import pyqtSignal, QObject, QCoreApplication
-
-from E5Gui.E5Application import e5App
-
-import Preferences
-import UI.Info
-
-# Start-Of-Header
-name = "pip Interface Plug-in"
-author = "Detlev Offenbach <detlev@die-offenbachs.de>"
-autoactivate = True
-deactivateable = True
-version = UI.Info.VersionOnly
-className = "PipInterfacePlugin"
-packageName = "__core__"
-shortDescription = "Plug-in implementing a simple GUI for the pip command."
-longDescription = (
-    """Plug-in implementing a simple GUI for the pip command."""
-)
-needsRestart = False
-pyqtApi = 2
-python2Compatible = True
-# End-Of-Header
-
-error = ""
-
-pipPluginObject = None
-
-
-##def exeDisplayDataList():
-##    """
-##    Module function to support the display of some executable info.
-##    
-##    @return list of dictionaries containing the data to query the presence of
-##        the executable
-##    """
-##    global pipPluginObject
-##    
-##    dataList = []
-##    data = {
-##        "programEntry": True,
-##        "header": QCoreApplication.translate(
-##            "PipInterfacePlugin", "Package Management - pip"),
-##        "exe": "dummyExe",
-##        "versionCommand": "--version",
-##        "versionStartsWith": "pip",
-##        "versionPosition": 1,
-##        "version": "",
-##        "versionCleanup": None,
-##        "exeModule": ["-m", "pip"],
-##    }
-##    virtualenvManager = e5App().getObject("VirtualEnvManager")
-##    for venvName in virtualenvManager.getVirtualenvNames():
-##        interpreter = virtualenvManager.getVirtualenvInterpreter(venvName)
-##        data["exe"] = interpreter
-##        dataList.append(data.copy())
-##    return dataList
-##
-##
-##def createPipPage(configDlg):
-##    """
-##    Module function to create the pip configuration page.
-##    
-##    @param configDlg reference to the configuration dialog
-##    @return reference to the configuration page
-##    """
-##    global pipPluginObject
-##    from UiExtensionPlugins.PipInterface.ConfigurationPage.PipPage import \
-##        PipPage
-##    page = PipPage(pipPluginObject)
-##    return page
-##    
-##
-##def getConfigData():
-##    """
-##    Module function returning data as required by the configuration dialog.
-##    
-##    @return dictionary containing the relevant data
-##    """
-##    return {
-##        "pipPage": [
-##            QCoreApplication.translate(
-##                "PipInterfacePlugin", "Python Package Management"),
-##            "pypi.png",
-##            createPipPage, None, None
-##        ],
-##    }
-##
-##
-##def prepareUninstall():
-##    """
-##    Module function to prepare for an un-installation.
-##    """
-##    Preferences.Prefs.settings.remove(PipInterfacePlugin.PreferencesKey)
-
-
-class PipInterfacePlugin(QObject):
-    """
-    Class implementing the pip interface plug-in.
-    
-    @signal currentEnvironmentChanged(str) emitted to signal a change of the
-        currently selected virtual environment
-    """
-    PreferencesKey = "PipPlugin"
-    
-    currentEnvironmentChanged = pyqtSignal(str)
-    
-    def __init__(self, ui):
-        """
-        Constructor
-        
-        @param ui reference to the user interface object (UI.UserInterface)
-        """
-        super(PipInterfacePlugin, self).__init__(ui)
-        self.__ui = ui
-        self.__initialize()
-        
-        self.__defaults = {
-            "CurrentEnvironment": "",
-            "PipSearchIndex": "",           # used by the search command
-        }
-    
-    def __initialize(self):
-        """
-        Private slot to (re)initialize the plugin.
-        """
-        self.__object = None
-        
-        self.__mainAct = None
-        self.__mainMenu = None
-    
-    def activate(self):
-        """
-        Public method to activate this plugin.
-        
-        @return tuple of None and activation status
-        @rtype tuple of (None, bool)
-        """
-        global error
-        error = ""     # clear previous error
-        
-        global pipPluginObject
-        pipPluginObject = self
-        
-        from UiExtensionPlugins.PipInterface.Pip import Pip
-        self.__object = Pip(self, self.__ui)
-        self.__object.initActions()
-        e5App().registerPluginObject("PipGui", self.__object)
-        
-        menu = self.__ui.getMenu("extras")
-        self.__mainMenu = self.__object.initMenu()
-        self.__mainAct = menu.addMenu(self.__mainMenu)
-        
-        return None, True
-    
-    def deactivate(self):
-        """
-        Public method to deactivate this plugin.
-        """
-        e5App().unregisterPluginObject("PipGui")
-        
-        menu = self.__ui.getMenu("extras")
-        menu.removeAction(self.__mainAct)
-        self.__mainAct = None
-        
-        self.__initialize()
-##    
-##    def getPreferences(self, key):
-##        """
-##        Public method to retrieve the various pip related settings.
-##        
-##        @param key the key of the value to get
-##        @type str
-##        @return the requested setting
-##        @rtype any
-##        """
-##        return Preferences.Prefs.settings.value(
-##            self.PreferencesKey + "/" + key, self.__defaults[key])
-##    
-##    def setPreferences(self, key, value):
-##        """
-##        Public method to store the various pip related settings.
-##        
-##        @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)
-##        
-##        if key == "CurrentEnvironment":
-##            self.currentEnvironmentChanged.emit(value)
-    
-    def getMenu(self, name):
-        """
-        Public method to get a reference to the requested menu.
-        
-        @param name name of the menu
-        @type str
-        @return reference to the menu or None, if no
-            menu with the given name exists
-        @rtype  QMenu or None
-        """
-        if self.__object is not None:
-            return self.__object.getMenu(name)
-        else:
-            return None
-    
-    def getMenuNames(self):
-        """
-        Public method to get the names of all menus.
-        
-        @return menu names
-        @rtype list of str
-        """
-        if self.__object is not None:
-            return list(self.__menus.keys())
-        else:
-            return []
-
-#
-# eflag: noqa = M801
--- a/Preferences/__init__.py	Thu Feb 21 19:55:35 2019 +0100
+++ b/Preferences/__init__.py	Fri Feb 22 19:34:44 2019 +0100
@@ -1591,7 +1591,6 @@
     
     # defaults for pip
     pipDefaults = {
-        "CurrentEnvironment": "",
         "PipSearchIndex": "",           # used by the search command
     }
 
--- a/eric6.e4p	Thu Feb 21 19:55:35 2019 +0100
+++ b/eric6.e4p	Fri Feb 22 19:34:44 2019 +0100
@@ -527,7 +527,6 @@
     <Source>Plugins/PluginCodeStyleChecker.py</Source>
     <Source>Plugins/PluginEricapi.py</Source>
     <Source>Plugins/PluginEricdoc.py</Source>
-    <Source>Plugins/PluginPipInterface.py</Source>
     <Source>Plugins/PluginSyntaxChecker.py</Source>
     <Source>Plugins/PluginTabnanny.py</Source>
     <Source>Plugins/PluginTranslator.py</Source>
@@ -2256,14 +2255,14 @@
   </Resources>
   <Others>
     <Other>.hgignore</Other>
-    <Other>APIs/Python/zope-2.10.7.api</Other>
-    <Other>APIs/Python/zope-2.11.2.api</Other>
-    <Other>APIs/Python/zope-3.3.1.api</Other>
     <Other>APIs/Python3/PyQt4.bas</Other>
     <Other>APIs/Python3/PyQt5.bas</Other>
     <Other>APIs/Python3/QScintilla2.bas</Other>
     <Other>APIs/Python3/eric6.api</Other>
     <Other>APIs/Python3/eric6.bas</Other>
+    <Other>APIs/Python/zope-2.10.7.api</Other>
+    <Other>APIs/Python/zope-2.11.2.api</Other>
+    <Other>APIs/Python/zope-3.3.1.api</Other>
     <Other>APIs/QSS/qss.api</Other>
     <Other>APIs/Ruby/Ruby-1.8.7.api</Other>
     <Other>APIs/Ruby/Ruby-1.8.7.bas</Other>

eric ide

mercurial