Sat, 23 Feb 2019 15:46:15 +0100
Merged with the pypi branch.
--- a/Documentation/Source/eric6.Plugins.UiExtensionPlugins.PipInterface.ConfigurationPage.PipPage.html Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -<!DOCTYPE html> -<html><head> -<title>eric6.Plugins.UiExtensionPlugins.PipInterface.ConfigurationPage.PipPage</title> -<meta charset="UTF-8"> -<style> -body { - background: #EDECE6; - margin: 0em 1em 10em 1em; - color: black; -} - -h1 { color: white; background: #85774A; } -h2 { color: white; background: #85774A; } -h3 { color: white; background: #9D936E; } -h4 { color: white; background: #9D936E; } - -a { color: #BA6D36; } - -</style> -</head> -<body><a NAME="top" ID="top"></a> -<h1>eric6.Plugins.UiExtensionPlugins.PipInterface.ConfigurationPage.PipPage</h1> -<p> -Package implementing the pip configuration page. -</p> -<h3>Global Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Classes</h3> -<table> -<tr> -<td><a href="#PipPage">PipPage</a></td> -<td>Class implementing the pip configuration page.</td> -</tr> -</table> -<h3>Functions</h3> -<table> -<tr><td>None</td></tr> -</table> -<hr /><hr /> -<a NAME="PipPage" ID="PipPage"></a> -<h2>PipPage</h2> -<p> - Class implementing the pip configuration page. -</p> -<h3>Derived from</h3> -ConfigurationPageBase, Ui_PipPage -<h3>Class Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Class Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Methods</h3> -<table> -<tr> -<td><a href="#PipPage.__init__">PipPage</a></td> -<td>Constructor</td> -</tr><tr> -<td><a href="#PipPage.save">save</a></td> -<td>Public slot to save the pip configuration.</td> -</tr> -</table> -<h3>Static Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<a NAME="PipPage.__init__" ID="PipPage.__init__"></a> -<h4>PipPage (Constructor)</h4> -<b>PipPage</b>(<i>plugin</i>) -<p> - Constructor -</p><dl> -<dt><i>plugin</i> (PipInterfacePlugin)</dt> -<dd> -reference to the plugin object -</dd> -</dl><a NAME="PipPage.save" ID="PipPage.save"></a> -<h4>PipPage.save</h4> -<b>save</b>(<i></i>) -<p> - Public slot to save the pip configuration. -</p> -<div align="right"><a href="#top">Up</a></div> -<hr /> -</body></html> \ No newline at end of file
--- a/Documentation/Source/eric6.Plugins.UiExtensionPlugins.PipInterface.Pip.html Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,608 +0,0 @@ -<!DOCTYPE html> -<html><head> -<title>eric6.Plugins.UiExtensionPlugins.PipInterface.Pip</title> -<meta charset="UTF-8"> -<style> -body { - background: #EDECE6; - margin: 0em 1em 10em 1em; - color: black; -} - -h1 { color: white; background: #85774A; } -h2 { color: white; background: #85774A; } -h3 { color: white; background: #9D936E; } -h4 { color: white; background: #9D936E; } - -a { color: #BA6D36; } - -</style> -</head> -<body><a NAME="top" ID="top"></a> -<h1>eric6.Plugins.UiExtensionPlugins.PipInterface.Pip</h1> -<p> -Package implementing the pip GUI logic. -</p> -<h3>Global Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Classes</h3> -<table> -<tr> -<td><a href="#Pip">Pip</a></td> -<td>Class implementing the pip GUI logic.</td> -</tr> -</table> -<h3>Functions</h3> -<table> -<tr><td>None</td></tr> -</table> -<hr /><hr /> -<a NAME="Pip" ID="Pip"></a> -<h2>Pip</h2> -<p> - Class implementing the pip GUI logic. -</p> -<h3>Derived from</h3> -QObject -<h3>Class Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Class Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Methods</h3> -<table> -<tr> -<td><a href="#Pip.__init__">Pip</a></td> -<td>Constructor</td> -</tr><tr> -<td><a href="#Pip.__aboutToShowMenu">__aboutToShowMenu</a></td> -<td>Private slot to set the action enabled status.</td> -</tr><tr> -<td><a href="#Pip.__checkUpgradePyQt">__checkUpgradePyQt</a></td> -<td>Private method to check, if an upgrade of PyQt packages is attempted.</td> -</tr><tr> -<td><a href="#Pip.__editConfiguration">__editConfiguration</a></td> -<td>Private method to edit a configuration.</td> -</tr><tr> -<td><a href="#Pip.__editUserConfiguration">__editUserConfiguration</a></td> -<td>Private slot to edit the user configuration.</td> -</tr><tr> -<td><a href="#Pip.__editVirtualenvConfiguration">__editVirtualenvConfiguration</a></td> -<td>Private slot to edit the current virtualenv configuration.</td> -</tr><tr> -<td><a href="#Pip.__generateRequirements">__generateRequirements</a></td> -<td>Private slot to generate the contents for a requirements file.</td> -</tr><tr> -<td><a href="#Pip.__getUserConfig">__getUserConfig</a></td> -<td>Private method to get the name of the user configuration file.</td> -</tr><tr> -<td><a href="#Pip.__getVirtualenvConfig">__getVirtualenvConfig</a></td> -<td>Private method to get the name of the virtualenv configuration file.</td> -</tr><tr> -<td><a href="#Pip.__handleTearOffMenu">__handleTearOffMenu</a></td> -<td>Private slot to handle a change of the selected virtual environment.</td> -</tr><tr> -<td><a href="#Pip.__installLocalPackage">__installLocalPackage</a></td> -<td>Private slot to install a package available on local storage.</td> -</tr><tr> -<td><a href="#Pip.__installPackages">__installPackages</a></td> -<td>Private slot to install packages to be given by the user.</td> -</tr><tr> -<td><a href="#Pip.__installPip">__installPip</a></td> -<td>Private slot to install pip.</td> -</tr><tr> -<td><a href="#Pip.__installRequirements">__installRequirements</a></td> -<td>Private slot to install packages as given in a requirements file.</td> -</tr><tr> -<td><a href="#Pip.__listOutdatedPackages">__listOutdatedPackages</a></td> -<td>Private slot to list all installed, up-to-date packages.</td> -</tr><tr> -<td><a href="#Pip.__listPackages">__listPackages</a></td> -<td>Private slot to list all installed packages.</td> -</tr><tr> -<td><a href="#Pip.__listUptodatePackages">__listUptodatePackages</a></td> -<td>Private slot to list all installed, up-to-date packages.</td> -</tr><tr> -<td><a href="#Pip.__pipConfigure">__pipConfigure</a></td> -<td>Private slot to open the configuration page.</td> -</tr><tr> -<td><a href="#Pip.__repairPip">__repairPip</a></td> -<td>Private method to repair the pip installation.</td> -</tr><tr> -<td><a href="#Pip.__searchPyPI">__searchPyPI</a></td> -<td>Private slot to search the Python Package Index.</td> -</tr><tr> -<td><a href="#Pip.__selectPipVirtualenv">__selectPipVirtualenv</a></td> -<td>Private method to select the virtual environment to be used.</td> -</tr><tr> -<td><a href="#Pip.__uninstallPackages">__uninstallPackages</a></td> -<td>Private slot to uninstall packages to be given by the user.</td> -</tr><tr> -<td><a href="#Pip.__uninstallRequirements">__uninstallRequirements</a></td> -<td>Private slot to uninstall packages as given in a requirements file.</td> -</tr><tr> -<td><a href="#Pip.__upgradePackages">__upgradePackages</a></td> -<td>Private slot to upgrade packages to be given by the user.</td> -</tr><tr> -<td><a href="#Pip.getDefaultEnvironmentString">getDefaultEnvironmentString</a></td> -<td>Public method to get the string for the default environment.</td> -</tr><tr> -<td><a href="#Pip.getMenu">getMenu</a></td> -<td>Public method to get a reference to the requested menu.</td> -</tr><tr> -<td><a href="#Pip.getMenuNames">getMenuNames</a></td> -<td>Public method to get the names of all menus.</td> -</tr><tr> -<td><a href="#Pip.getProjectEnvironmentString">getProjectEnvironmentString</a></td> -<td>Public method to get the string for the project environment.</td> -</tr><tr> -<td><a href="#Pip.getVirtualenvInterpreter">getVirtualenvInterpreter</a></td> -<td>Public method to get the interpreter for a virtual environment.</td> -</tr><tr> -<td><a href="#Pip.getVirtualenvNames">getVirtualenvNames</a></td> -<td>Public method to get a sorted list of virtual environment names.</td> -</tr><tr> -<td><a href="#Pip.initActions">initActions</a></td> -<td>Public method to define the actions.</td> -</tr><tr> -<td><a href="#Pip.initMenu">initMenu</a></td> -<td>Public slot to initialize the menu.</td> -</tr><tr> -<td><a href="#Pip.installPackages">installPackages</a></td> -<td>Public method to install the given list of packages.</td> -</tr><tr> -<td><a href="#Pip.runProcess">runProcess</a></td> -<td>Public method to execute the current pip with the given arguments.</td> -</tr><tr> -<td><a href="#Pip.uninstallPackages">uninstallPackages</a></td> -<td>Public method to uninstall the given list of packages.</td> -</tr><tr> -<td><a href="#Pip.upgradePackages">upgradePackages</a></td> -<td>Public method to upgrade the given list of packages.</td> -</tr><tr> -<td><a href="#Pip.upgradePip">upgradePip</a></td> -<td>Public method to upgrade pip itself.</td> -</tr> -</table> -<h3>Static Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<a NAME="Pip.__init__" ID="Pip.__init__"></a> -<h4>Pip (Constructor)</h4> -<b>Pip</b>(<i>plugin, parent=None</i>) -<p> - Constructor -</p><dl> -<dt><i>plugin</i> (PipInterfacePlugin)</dt> -<dd> -reference to the plugin object -</dd><dt><i>parent</i> (QObject)</dt> -<dd> -parent -</dd> -</dl><a NAME="Pip.__aboutToShowMenu" ID="Pip.__aboutToShowMenu"></a> -<h4>Pip.__aboutToShowMenu</h4> -<b>__aboutToShowMenu</b>(<i></i>) -<p> - Private slot to set the action enabled status. -</p><a NAME="Pip.__checkUpgradePyQt" ID="Pip.__checkUpgradePyQt"></a> -<h4>Pip.__checkUpgradePyQt</h4> -<b>__checkUpgradePyQt</b>(<i>packages</i>) -<p> - Private method to check, if an upgrade of PyQt packages is attempted. -</p><dl> -<dt><i>packages</i> (list of str)</dt> -<dd> -list of packages to upgrade -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -flag indicating to abort the upgrade attempt -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -bool -</dd> -</dl><a NAME="Pip.__editConfiguration" ID="Pip.__editConfiguration"></a> -<h4>Pip.__editConfiguration</h4> -<b>__editConfiguration</b>(<i>virtualenv=False</i>) -<p> - Private method to edit a configuration. -</p><dl> -<dt><i>virtualenv</i> (bool)</dt> -<dd> -flag indicating to edit the current virtualenv - configuration file -</dd> -</dl><a NAME="Pip.__editUserConfiguration" ID="Pip.__editUserConfiguration"></a> -<h4>Pip.__editUserConfiguration</h4> -<b>__editUserConfiguration</b>(<i></i>) -<p> - Private slot to edit the user configuration. -</p><a NAME="Pip.__editVirtualenvConfiguration" ID="Pip.__editVirtualenvConfiguration"></a> -<h4>Pip.__editVirtualenvConfiguration</h4> -<b>__editVirtualenvConfiguration</b>(<i></i>) -<p> - Private slot to edit the current virtualenv configuration. -</p><a NAME="Pip.__generateRequirements" ID="Pip.__generateRequirements"></a> -<h4>Pip.__generateRequirements</h4> -<b>__generateRequirements</b>(<i></i>) -<p> - Private slot to generate the contents for a requirements file. -</p><a NAME="Pip.__getUserConfig" ID="Pip.__getUserConfig"></a> -<h4>Pip.__getUserConfig</h4> -<b>__getUserConfig</b>(<i></i>) -<p> - Private method to get the name of the user configuration file. -</p><dl> -<dt>Returns:</dt> -<dd> -path of the user configuration file -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -str -</dd> -</dl><a NAME="Pip.__getVirtualenvConfig" ID="Pip.__getVirtualenvConfig"></a> -<h4>Pip.__getVirtualenvConfig</h4> -<b>__getVirtualenvConfig</b>(<i></i>) -<p> - Private method to get the name of the virtualenv configuration file. -</p><dl> -<dt>Returns:</dt> -<dd> -path of the virtualenv configuration file -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -str -</dd> -</dl><a NAME="Pip.__handleTearOffMenu" ID="Pip.__handleTearOffMenu"></a> -<h4>Pip.__handleTearOffMenu</h4> -<b>__handleTearOffMenu</b>(<i>venvName</i>) -<p> - Private slot to handle a change of the selected virtual environment. -</p><dl> -<dt><i>venvName</i> (str)</dt> -<dd> -logical name of the virtual environment -</dd> -</dl><a NAME="Pip.__installLocalPackage" ID="Pip.__installLocalPackage"></a> -<h4>Pip.__installLocalPackage</h4> -<b>__installLocalPackage</b>(<i></i>) -<p> - Private slot to install a package available on local storage. -</p><a NAME="Pip.__installPackages" ID="Pip.__installPackages"></a> -<h4>Pip.__installPackages</h4> -<b>__installPackages</b>(<i></i>) -<p> - Private slot to install packages to be given by the user. -</p><a NAME="Pip.__installPip" ID="Pip.__installPip"></a> -<h4>Pip.__installPip</h4> -<b>__installPip</b>(<i>userSite=False</i>) -<p> - Private slot to install pip. -</p><dl> -<dt><i>userSite</i> (bool)</dt> -<dd> -flag indicating an install to the user install - directory -</dd> -</dl><a NAME="Pip.__installRequirements" ID="Pip.__installRequirements"></a> -<h4>Pip.__installRequirements</h4> -<b>__installRequirements</b>(<i></i>) -<p> - Private slot to install packages as given in a requirements file. -</p><a NAME="Pip.__listOutdatedPackages" ID="Pip.__listOutdatedPackages"></a> -<h4>Pip.__listOutdatedPackages</h4> -<b>__listOutdatedPackages</b>(<i></i>) -<p> - Private slot to list all installed, up-to-date packages. -</p><a NAME="Pip.__listPackages" ID="Pip.__listPackages"></a> -<h4>Pip.__listPackages</h4> -<b>__listPackages</b>(<i></i>) -<p> - Private slot to list all installed packages. -</p><a NAME="Pip.__listUptodatePackages" ID="Pip.__listUptodatePackages"></a> -<h4>Pip.__listUptodatePackages</h4> -<b>__listUptodatePackages</b>(<i></i>) -<p> - Private slot to list all installed, up-to-date packages. -</p><a NAME="Pip.__pipConfigure" ID="Pip.__pipConfigure"></a> -<h4>Pip.__pipConfigure</h4> -<b>__pipConfigure</b>(<i></i>) -<p> - Private slot to open the configuration page. -</p><a NAME="Pip.__repairPip" ID="Pip.__repairPip"></a> -<h4>Pip.__repairPip</h4> -<b>__repairPip</b>(<i></i>) -<p> - Private method to repair the pip installation. -</p><dl> -<dt>Returns:</dt> -<dd> -flag indicating a successful execution -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -bool -</dd> -</dl><a NAME="Pip.__searchPyPI" ID="Pip.__searchPyPI"></a> -<h4>Pip.__searchPyPI</h4> -<b>__searchPyPI</b>(<i></i>) -<p> - Private slot to search the Python Package Index. -</p><a NAME="Pip.__selectPipVirtualenv" ID="Pip.__selectPipVirtualenv"></a> -<h4>Pip.__selectPipVirtualenv</h4> -<b>__selectPipVirtualenv</b>(<i></i>) -<p> - Private method to select the virtual environment to be used. -</p><a NAME="Pip.__uninstallPackages" ID="Pip.__uninstallPackages"></a> -<h4>Pip.__uninstallPackages</h4> -<b>__uninstallPackages</b>(<i></i>) -<p> - Private slot to uninstall packages to be given by the user. -</p><a NAME="Pip.__uninstallRequirements" ID="Pip.__uninstallRequirements"></a> -<h4>Pip.__uninstallRequirements</h4> -<b>__uninstallRequirements</b>(<i></i>) -<p> - Private slot to uninstall packages as given in a requirements file. -</p><a NAME="Pip.__upgradePackages" ID="Pip.__upgradePackages"></a> -<h4>Pip.__upgradePackages</h4> -<b>__upgradePackages</b>(<i></i>) -<p> - Private slot to upgrade packages to be given by the user. -</p><a NAME="Pip.getDefaultEnvironmentString" ID="Pip.getDefaultEnvironmentString"></a> -<h4>Pip.getDefaultEnvironmentString</h4> -<b>getDefaultEnvironmentString</b>(<i></i>) -<p> - Public method to get the string for the default environment. -</p><dl> -<dt>Returns:</dt> -<dd> -string for the default environment -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -str -</dd> -</dl><a NAME="Pip.getMenu" ID="Pip.getMenu"></a> -<h4>Pip.getMenu</h4> -<b>getMenu</b>(<i>name</i>) -<p> - Public method to get a reference to the requested menu. -</p><dl> -<dt><i>name</i> (str)</dt> -<dd> -name of the menu -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -reference to the menu or None, if no - menu with the given name exists -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -QMenu or None -</dd> -</dl><a NAME="Pip.getMenuNames" ID="Pip.getMenuNames"></a> -<h4>Pip.getMenuNames</h4> -<b>getMenuNames</b>(<i></i>) -<p> - Public method to get the names of all menus. -</p><dl> -<dt>Returns:</dt> -<dd> -menu names -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -list of str -</dd> -</dl><a NAME="Pip.getProjectEnvironmentString" ID="Pip.getProjectEnvironmentString"></a> -<h4>Pip.getProjectEnvironmentString</h4> -<b>getProjectEnvironmentString</b>(<i></i>) -<p> - Public method to get the string for the project environment. -</p><dl> -<dt>Returns:</dt> -<dd> -string for the project environment -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -str -</dd> -</dl><a NAME="Pip.getVirtualenvInterpreter" ID="Pip.getVirtualenvInterpreter"></a> -<h4>Pip.getVirtualenvInterpreter</h4> -<b>getVirtualenvInterpreter</b>(<i>venvName</i>) -<p> - Public method to get the interpreter for a virtual environment. -</p><dl> -<dt><i>venvName</i> (str)</dt> -<dd> -logical name for the virtual environment -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -interpreter path -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -str -</dd> -</dl><a NAME="Pip.getVirtualenvNames" ID="Pip.getVirtualenvNames"></a> -<h4>Pip.getVirtualenvNames</h4> -<b>getVirtualenvNames</b>(<i></i>) -<p> - Public method to get a sorted list of virtual environment names. -</p><dl> -<dt>Returns:</dt> -<dd> -sorted list of virtual environment names -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -list of str -</dd> -</dl><a NAME="Pip.initActions" ID="Pip.initActions"></a> -<h4>Pip.initActions</h4> -<b>initActions</b>(<i></i>) -<p> - Public method to define the actions. -</p><a NAME="Pip.initMenu" ID="Pip.initMenu"></a> -<h4>Pip.initMenu</h4> -<b>initMenu</b>(<i></i>) -<p> - Public slot to initialize the menu. -</p><dl> -<dt>Returns:</dt> -<dd> -the menu generated -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -QMenu -</dd> -</dl><a NAME="Pip.installPackages" ID="Pip.installPackages"></a> -<h4>Pip.installPackages</h4> -<b>installPackages</b>(<i>packages, venvName="", userSite=False</i>) -<p> - Public method to install the given list of packages. -</p><dl> -<dt><i>packages</i> (list of str)</dt> -<dd> -list of packages to install -</dd><dt><i>venvName</i> (str)</dt> -<dd> -name of the virtual environment to be used -</dd><dt><i>userSite</i> (bool)</dt> -<dd> -flag indicating an install to the user install - directory -</dd> -</dl><a NAME="Pip.runProcess" ID="Pip.runProcess"></a> -<h4>Pip.runProcess</h4> -<b>runProcess</b>(<i>args, interpreter</i>) -<p> - Public method to execute the current pip with the given arguments. -</p><p> - The selected pip executable is called with the given arguments and - waited for its end. -</p><dl> -<dt><i>args</i> (list of str)</dt> -<dd> -list of command line arguments -</dd><dt><i>interpreter</i> (str)</dt> -<dd> -path of the Python interpreter to be used -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -tuple containing a flag indicating success and the output - of the process -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -tuple of (bool, str) -</dd> -</dl><a NAME="Pip.uninstallPackages" ID="Pip.uninstallPackages"></a> -<h4>Pip.uninstallPackages</h4> -<b>uninstallPackages</b>(<i>packages, venvName=""</i>) -<p> - Public method to uninstall the given list of packages. -</p><dl> -<dt><i>packages</i> (list of str)</dt> -<dd> -list of packages to uninstall -</dd><dt><i>venvName</i> (str)</dt> -<dd> -name of the virtual environment to be used -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -flag indicating a successful execution -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -bool -</dd> -</dl><a NAME="Pip.upgradePackages" ID="Pip.upgradePackages"></a> -<h4>Pip.upgradePackages</h4> -<b>upgradePackages</b>(<i>packages, venvName="", userSite=False</i>) -<p> - Public method to upgrade the given list of packages. -</p><dl> -<dt><i>packages</i> (list of str)</dt> -<dd> -list of packages to upgrade -</dd><dt><i>venvName</i> (str)</dt> -<dd> -name of the virtual environment to be used -</dd><dt><i>userSite</i> (bool)</dt> -<dd> -flag indicating an install to the user install - directory -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -flag indicating a successful execution -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -bool -</dd> -</dl><a NAME="Pip.upgradePip" ID="Pip.upgradePip"></a> -<h4>Pip.upgradePip</h4> -<b>upgradePip</b>(<i>venvName="", userSite=False</i>) -<p> - Public method to upgrade pip itself. -</p><dl> -<dt><i>venvName</i> (str)</dt> -<dd> -name of the virtual environment to be used -</dd><dt><i>userSite</i> (bool)</dt> -<dd> -flag indicating an install to the user install - directory -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -flag indicating a successful execution -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -bool -</dd> -</dl> -<div align="right"><a href="#top">Up</a></div> -<hr /> -</body></html> \ No newline at end of file
--- a/Documentation/Source/eric6.Plugins.UiExtensionPlugins.PipInterface.PipDialog.html Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,224 +0,0 @@ -<!DOCTYPE html> -<html><head> -<title>eric6.Plugins.UiExtensionPlugins.PipInterface.PipDialog</title> -<meta charset="UTF-8"> -<style> -body { - background: #EDECE6; - margin: 0em 1em 10em 1em; - color: black; -} - -h1 { color: white; background: #85774A; } -h2 { color: white; background: #85774A; } -h3 { color: white; background: #9D936E; } -h4 { color: white; background: #9D936E; } - -a { color: #BA6D36; } - -</style> -</head> -<body><a NAME="top" ID="top"></a> -<h1>eric6.Plugins.UiExtensionPlugins.PipInterface.PipDialog</h1> -<p> -Module implementing a dialog showing the output of a pip command. -</p> -<h3>Global Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Classes</h3> -<table> -<tr> -<td><a href="#PipDialog">PipDialog</a></td> -<td>Class implementing a dialog showing the output of a 'python -m pip' command.</td> -</tr> -</table> -<h3>Functions</h3> -<table> -<tr><td>None</td></tr> -</table> -<hr /><hr /> -<a NAME="PipDialog" ID="PipDialog"></a> -<h2>PipDialog</h2> -<p> - Class implementing a dialog showing the output of a 'python -m pip' - command. -</p> -<h3>Derived from</h3> -QDialog, Ui_PipDialog -<h3>Class Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Class Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Methods</h3> -<table> -<tr> -<td><a href="#PipDialog.__init__">PipDialog</a></td> -<td>Constructor</td> -</tr><tr> -<td><a href="#PipDialog.__addOutput">__addOutput</a></td> -<td>Private method to add some text to the output pane.</td> -</tr><tr> -<td><a href="#PipDialog.__finish">__finish</a></td> -<td>Private slot called when the process finished or the user pressed the button.</td> -</tr><tr> -<td><a href="#PipDialog.__procFinished">__procFinished</a></td> -<td>Private slot connected to the finished signal.</td> -</tr><tr> -<td><a href="#PipDialog.__readStderr">__readStderr</a></td> -<td>Private slot to handle the readyReadStandardError signal.</td> -</tr><tr> -<td><a href="#PipDialog.__readStdout">__readStdout</a></td> -<td>Private slot to handle the readyReadStandardOutput signal.</td> -</tr><tr> -<td><a href="#PipDialog.closeEvent">closeEvent</a></td> -<td>Protected slot implementing a close event handler.</td> -</tr><tr> -<td><a href="#PipDialog.on_buttonBox_clicked">on_buttonBox_clicked</a></td> -<td>Private slot called by a button of the button box clicked.</td> -</tr><tr> -<td><a href="#PipDialog.startProcess">startProcess</a></td> -<td>Public slot used to start the process.</td> -</tr><tr> -<td><a href="#PipDialog.startProcesses">startProcesses</a></td> -<td>Public method to issue a list of commands to be executed.</td> -</tr> -</table> -<h3>Static Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<a NAME="PipDialog.__init__" ID="PipDialog.__init__"></a> -<h4>PipDialog (Constructor)</h4> -<b>PipDialog</b>(<i>text, parent=None</i>) -<p> - Constructor -</p><dl> -<dt><i>text</i> (str)</dt> -<dd> -text to be shown by the label -</dd><dt><i>parent</i> (QWidget)</dt> -<dd> -reference to the parent widget -</dd> -</dl><a NAME="PipDialog.__addOutput" ID="PipDialog.__addOutput"></a> -<h4>PipDialog.__addOutput</h4> -<b>__addOutput</b>(<i>txt</i>) -<p> - Private method to add some text to the output pane. -</p><dl> -<dt><i>txt</i> (str)</dt> -<dd> -text to be added -</dd> -</dl><a NAME="PipDialog.__finish" ID="PipDialog.__finish"></a> -<h4>PipDialog.__finish</h4> -<b>__finish</b>(<i></i>) -<p> - Private slot called when the process finished or the user pressed - the button. -</p><a NAME="PipDialog.__procFinished" ID="PipDialog.__procFinished"></a> -<h4>PipDialog.__procFinished</h4> -<b>__procFinished</b>(<i>exitCode, exitStatus</i>) -<p> - Private slot connected to the finished signal. -</p><dl> -<dt><i>exitCode</i> (int)</dt> -<dd> -exit code of the process -</dd><dt><i>exitStatus</i> (QProcess.ExitStatus)</dt> -<dd> -exit status of the process -</dd> -</dl><a NAME="PipDialog.__readStderr" ID="PipDialog.__readStderr"></a> -<h4>PipDialog.__readStderr</h4> -<b>__readStderr</b>(<i></i>) -<p> - Private slot to handle the readyReadStandardError signal. -</p><p> - It reads the error output of the process and inserts it into the - error pane. -</p><a NAME="PipDialog.__readStdout" ID="PipDialog.__readStdout"></a> -<h4>PipDialog.__readStdout</h4> -<b>__readStdout</b>(<i></i>) -<p> - Private slot to handle the readyReadStandardOutput signal. -</p><p> - It reads the output of the process, formats it and inserts it into - the contents pane. -</p><a NAME="PipDialog.closeEvent" ID="PipDialog.closeEvent"></a> -<h4>PipDialog.closeEvent</h4> -<b>closeEvent</b>(<i>e</i>) -<p> - Protected slot implementing a close event handler. -</p><dl> -<dt><i>e</i> (QCloseEvent)</dt> -<dd> -close event -</dd> -</dl><a NAME="PipDialog.on_buttonBox_clicked" ID="PipDialog.on_buttonBox_clicked"></a> -<h4>PipDialog.on_buttonBox_clicked</h4> -<b>on_buttonBox_clicked</b>(<i>button</i>) -<p> - Private slot called by a button of the button box clicked. -</p><dl> -<dt><i>button</i> (QAbstractButton)</dt> -<dd> -button that was clicked -</dd> -</dl><a NAME="PipDialog.startProcess" ID="PipDialog.startProcess"></a> -<h4>PipDialog.startProcess</h4> -<b>startProcess</b>(<i>cmd, args, showArgs=True</i>) -<p> - Public slot used to start the process. -</p><dl> -<dt><i>cmd</i> (str)</dt> -<dd> -name of the pip executable to be used -</dd><dt><i>args</i> (list of str)</dt> -<dd> -list of arguments for the process -</dd><dt><i>showArgs=</i> (bool)</dt> -<dd> -flag indicating to show the arguments -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -flag indicating a successful start of the process -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -bool -</dd> -</dl><a NAME="PipDialog.startProcesses" ID="PipDialog.startProcesses"></a> -<h4>PipDialog.startProcesses</h4> -<b>startProcesses</b>(<i>processParams</i>) -<p> - Public method to issue a list of commands to be executed. -</p><dl> -<dt><i>processParams</i> (list of tuples of (str, list of str))</dt> -<dd> -list of tuples containing the command - and arguments -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -flag indicating a successful start of the first process -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -bool -</dd> -</dl> -<div align="right"><a href="#top">Up</a></div> -<hr /> -</body></html> \ No newline at end of file
--- a/Documentation/Source/eric6.Plugins.UiExtensionPlugins.PipInterface.PipFileSelectionDialog.html Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +0,0 @@ -<!DOCTYPE html> -<html><head> -<title>eric6.Plugins.UiExtensionPlugins.PipInterface.PipFileSelectionDialog</title> -<meta charset="UTF-8"> -<style> -body { - background: #EDECE6; - margin: 0em 1em 10em 1em; - color: black; -} - -h1 { color: white; background: #85774A; } -h2 { color: white; background: #85774A; } -h3 { color: white; background: #9D936E; } -h4 { color: white; background: #9D936E; } - -a { color: #BA6D36; } - -</style> -</head> -<body><a NAME="top" ID="top"></a> -<h1>eric6.Plugins.UiExtensionPlugins.PipInterface.PipFileSelectionDialog</h1> -<p> -Module implementing a dialog to enter a file to be processed. -</p> -<h3>Global Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Classes</h3> -<table> -<tr> -<td><a href="#PipFileSelectionDialog">PipFileSelectionDialog</a></td> -<td>Class implementing a dialog to enter a file to be processed.</td> -</tr> -</table> -<h3>Functions</h3> -<table> -<tr><td>None</td></tr> -</table> -<hr /><hr /> -<a NAME="PipFileSelectionDialog" ID="PipFileSelectionDialog"></a> -<h2>PipFileSelectionDialog</h2> -<p> - Class implementing a dialog to enter a file to be processed. -</p> -<h3>Derived from</h3> -QDialog, Ui_PipFileSelectionDialog -<h3>Class Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Class Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Methods</h3> -<table> -<tr> -<td><a href="#PipFileSelectionDialog.__init__">PipFileSelectionDialog</a></td> -<td>Constructor</td> -</tr><tr> -<td><a href="#PipFileSelectionDialog.getData">getData</a></td> -<td>Public method to get the entered data.</td> -</tr><tr> -<td><a href="#PipFileSelectionDialog.on_filePicker_textChanged">on_filePicker_textChanged</a></td> -<td>Private slot to handle entering the name of a file.</td> -</tr> -</table> -<h3>Static Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<a NAME="PipFileSelectionDialog.__init__" ID="PipFileSelectionDialog.__init__"></a> -<h4>PipFileSelectionDialog (Constructor)</h4> -<b>PipFileSelectionDialog</b>(<i>pip, mode, install=True, parent=None</i>) -<p> - Constructor -</p><dl> -<dt><i>pip</i> (Pip)</dt> -<dd> -reference to the pip object -</dd><dt><i>mode</i> (str)</dt> -<dd> -mode of the dialog -</dd><dt><i>install</i> (bool)</dt> -<dd> -flag indicating an install action -</dd><dt><i>parent</i> (QWidget)</dt> -<dd> -reference to the parent widget -</dd> -</dl><a NAME="PipFileSelectionDialog.getData" ID="PipFileSelectionDialog.getData"></a> -<h4>PipFileSelectionDialog.getData</h4> -<b>getData</b>(<i></i>) -<p> - Public method to get the entered data. -</p><dl> -<dt>Returns:</dt> -<dd> -tuple with the environment name, the name of the - selected file and a flag indicating to install to the - user install directory -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -tuple of (str, str, bool) -</dd> -</dl><a NAME="PipFileSelectionDialog.on_filePicker_textChanged" ID="PipFileSelectionDialog.on_filePicker_textChanged"></a> -<h4>PipFileSelectionDialog.on_filePicker_textChanged</h4> -<b>on_filePicker_textChanged</b>(<i>txt</i>) -<p> - Private slot to handle entering the name of a file. -</p><dl> -<dt><i>txt</i> (str)</dt> -<dd> -name of the file -</dd> -</dl> -<div align="right"><a href="#top">Up</a></div> -<hr /> -</body></html> \ No newline at end of file
--- a/Documentation/Source/eric6.Plugins.UiExtensionPlugins.PipInterface.PipFreezeDialog.html Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,245 +0,0 @@ -<!DOCTYPE html> -<html><head> -<title>eric6.Plugins.UiExtensionPlugins.PipInterface.PipFreezeDialog</title> -<meta charset="UTF-8"> -<style> -body { - background: #EDECE6; - margin: 0em 1em 10em 1em; - color: black; -} - -h1 { color: white; background: #85774A; } -h2 { color: white; background: #85774A; } -h3 { color: white; background: #9D936E; } -h4 { color: white; background: #9D936E; } - -a { color: #BA6D36; } - -</style> -</head> -<body><a NAME="top" ID="top"></a> -<h1>eric6.Plugins.UiExtensionPlugins.PipInterface.PipFreezeDialog</h1> -<p> -Module implementing a dialog to generate a requirements file. -</p> -<h3>Global Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Classes</h3> -<table> -<tr> -<td><a href="#PipFreezeDialog">PipFreezeDialog</a></td> -<td>Class implementing a dialog to generate a requirements file.</td> -</tr> -</table> -<h3>Functions</h3> -<table> -<tr><td>None</td></tr> -</table> -<hr /><hr /> -<a NAME="PipFreezeDialog" ID="PipFreezeDialog"></a> -<h2>PipFreezeDialog</h2> -<p> - Class implementing a dialog to generate a requirements file. -</p> -<h3>Derived from</h3> -QDialog, Ui_PipFreezeDialog -<h3>Class Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Class Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Methods</h3> -<table> -<tr> -<td><a href="#PipFreezeDialog.__init__">PipFreezeDialog</a></td> -<td>Constructor</td> -</tr><tr> -<td><a href="#PipFreezeDialog.__refresh">__refresh</a></td> -<td>Private slot to refresh the displayed list.</td> -</tr><tr> -<td><a href="#PipFreezeDialog.__updateButtons">__updateButtons</a></td> -<td>Private method to set the state of the various buttons.</td> -</tr><tr> -<td><a href="#PipFreezeDialog.__writeToFile">__writeToFile</a></td> -<td>Private method to write the requirements text to a file.</td> -</tr><tr> -<td><a href="#PipFreezeDialog.closeEvent">closeEvent</a></td> -<td>Protected slot implementing a close event handler.</td> -</tr><tr> -<td><a href="#PipFreezeDialog.on_buttonBox_clicked">on_buttonBox_clicked</a></td> -<td>Private slot called by a button of the button box clicked.</td> -</tr><tr> -<td><a href="#PipFreezeDialog.on_copyButton_clicked">on_copyButton_clicked</a></td> -<td>Private slot to copy the requirements text to the clipboard.</td> -</tr><tr> -<td><a href="#PipFreezeDialog.on_insertButton_clicked">on_insertButton_clicked</a></td> -<td>Private slot to insert the requirements text at the cursor position of the current editor.</td> -</tr><tr> -<td><a href="#PipFreezeDialog.on_localCheckBox_clicked">on_localCheckBox_clicked</a></td> -<td>Private slot handling the switching of the local mode.</td> -</tr><tr> -<td><a href="#PipFreezeDialog.on_replaceAllButton_clicked">on_replaceAllButton_clicked</a></td> -<td>Private slot to replace the text of the current editor with the requirements text.</td> -</tr><tr> -<td><a href="#PipFreezeDialog.on_replaceSelectionButton_clicked">on_replaceSelectionButton_clicked</a></td> -<td>Private slot to replace the selected text of the current editor with the requirements text.</td> -</tr><tr> -<td><a href="#PipFreezeDialog.on_requirementsEdit_textChanged">on_requirementsEdit_textChanged</a></td> -<td>Private slot handling changes of the requirements text.</td> -</tr><tr> -<td><a href="#PipFreezeDialog.on_requirementsFilePicker_textChanged">on_requirementsFilePicker_textChanged</a></td> -<td>Private slot handling a change of the requirements file name.</td> -</tr><tr> -<td><a href="#PipFreezeDialog.on_saveButton_clicked">on_saveButton_clicked</a></td> -<td>Private slot to save the requirements text to the requirements file.</td> -</tr><tr> -<td><a href="#PipFreezeDialog.on_saveToButton_clicked">on_saveToButton_clicked</a></td> -<td>Private slot to write the requirements text to a new file.</td> -</tr><tr> -<td><a href="#PipFreezeDialog.on_venvComboBox_activated">on_venvComboBox_activated</a></td> -<td>Private slot handling the selection of a virtual environment.</td> -</tr><tr> -<td><a href="#PipFreezeDialog.start">start</a></td> -<td>Public method to start the command.</td> -</tr> -</table> -<h3>Static Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<a NAME="PipFreezeDialog.__init__" ID="PipFreezeDialog.__init__"></a> -<h4>PipFreezeDialog (Constructor)</h4> -<b>PipFreezeDialog</b>(<i>pip, parent=None</i>) -<p> - Constructor -</p><dl> -<dt><i>pip</i> (Pip)</dt> -<dd> -reference to the master object -</dd><dt><i>parent</i> (QWidget)</dt> -<dd> -reference to the parent widget -</dd> -</dl><a NAME="PipFreezeDialog.__refresh" ID="PipFreezeDialog.__refresh"></a> -<h4>PipFreezeDialog.__refresh</h4> -<b>__refresh</b>(<i></i>) -<p> - Private slot to refresh the displayed list. -</p><a NAME="PipFreezeDialog.__updateButtons" ID="PipFreezeDialog.__updateButtons"></a> -<h4>PipFreezeDialog.__updateButtons</h4> -<b>__updateButtons</b>(<i></i>) -<p> - Private method to set the state of the various buttons. -</p><a NAME="PipFreezeDialog.__writeToFile" ID="PipFreezeDialog.__writeToFile"></a> -<h4>PipFreezeDialog.__writeToFile</h4> -<b>__writeToFile</b>(<i>fileName</i>) -<p> - Private method to write the requirements text to a file. -</p><dl> -<dt><i>fileName</i> (str)</dt> -<dd> -name of the file to write to -</dd> -</dl><a NAME="PipFreezeDialog.closeEvent" ID="PipFreezeDialog.closeEvent"></a> -<h4>PipFreezeDialog.closeEvent</h4> -<b>closeEvent</b>(<i>e</i>) -<p> - Protected slot implementing a close event handler. -</p><dl> -<dt><i>e</i> (QCloseEvent)</dt> -<dd> -close event -</dd> -</dl><a NAME="PipFreezeDialog.on_buttonBox_clicked" ID="PipFreezeDialog.on_buttonBox_clicked"></a> -<h4>PipFreezeDialog.on_buttonBox_clicked</h4> -<b>on_buttonBox_clicked</b>(<i>button</i>) -<p> - Private slot called by a button of the button box clicked. -</p><dl> -<dt><i>button</i> (QAbstractButton)</dt> -<dd> -button that was clicked -</dd> -</dl><a NAME="PipFreezeDialog.on_copyButton_clicked" ID="PipFreezeDialog.on_copyButton_clicked"></a> -<h4>PipFreezeDialog.on_copyButton_clicked</h4> -<b>on_copyButton_clicked</b>(<i></i>) -<p> - Private slot to copy the requirements text to the clipboard. -</p><a NAME="PipFreezeDialog.on_insertButton_clicked" ID="PipFreezeDialog.on_insertButton_clicked"></a> -<h4>PipFreezeDialog.on_insertButton_clicked</h4> -<b>on_insertButton_clicked</b>(<i></i>) -<p> - Private slot to insert the requirements text at the cursor position - of the current editor. -</p><a NAME="PipFreezeDialog.on_localCheckBox_clicked" ID="PipFreezeDialog.on_localCheckBox_clicked"></a> -<h4>PipFreezeDialog.on_localCheckBox_clicked</h4> -<b>on_localCheckBox_clicked</b>(<i>checked</i>) -<p> - Private slot handling the switching of the local mode. -</p><dl> -<dt><i>checked</i> (bool)</dt> -<dd> -state of the local check box -</dd> -</dl><a NAME="PipFreezeDialog.on_replaceAllButton_clicked" ID="PipFreezeDialog.on_replaceAllButton_clicked"></a> -<h4>PipFreezeDialog.on_replaceAllButton_clicked</h4> -<b>on_replaceAllButton_clicked</b>(<i></i>) -<p> - Private slot to replace the text of the current editor with the - requirements text. -</p><a NAME="PipFreezeDialog.on_replaceSelectionButton_clicked" ID="PipFreezeDialog.on_replaceSelectionButton_clicked"></a> -<h4>PipFreezeDialog.on_replaceSelectionButton_clicked</h4> -<b>on_replaceSelectionButton_clicked</b>(<i></i>) -<p> - Private slot to replace the selected text of the current editor - with the requirements text. -</p><a NAME="PipFreezeDialog.on_requirementsEdit_textChanged" ID="PipFreezeDialog.on_requirementsEdit_textChanged"></a> -<h4>PipFreezeDialog.on_requirementsEdit_textChanged</h4> -<b>on_requirementsEdit_textChanged</b>(<i></i>) -<p> - Private slot handling changes of the requirements text. -</p><a NAME="PipFreezeDialog.on_requirementsFilePicker_textChanged" ID="PipFreezeDialog.on_requirementsFilePicker_textChanged"></a> -<h4>PipFreezeDialog.on_requirementsFilePicker_textChanged</h4> -<b>on_requirementsFilePicker_textChanged</b>(<i>txt</i>) -<p> - Private slot handling a change of the requirements file name. -</p><dl> -<dt><i>txt</i> (str)</dt> -<dd> -name of the requirements file -</dd> -</dl><a NAME="PipFreezeDialog.on_saveButton_clicked" ID="PipFreezeDialog.on_saveButton_clicked"></a> -<h4>PipFreezeDialog.on_saveButton_clicked</h4> -<b>on_saveButton_clicked</b>(<i></i>) -<p> - Private slot to save the requirements text to the requirements file. -</p><a NAME="PipFreezeDialog.on_saveToButton_clicked" ID="PipFreezeDialog.on_saveToButton_clicked"></a> -<h4>PipFreezeDialog.on_saveToButton_clicked</h4> -<b>on_saveToButton_clicked</b>(<i></i>) -<p> - Private slot to write the requirements text to a new file. -</p><a NAME="PipFreezeDialog.on_venvComboBox_activated" ID="PipFreezeDialog.on_venvComboBox_activated"></a> -<h4>PipFreezeDialog.on_venvComboBox_activated</h4> -<b>on_venvComboBox_activated</b>(<i>txt</i>) -<p> - Private slot handling the selection of a virtual environment. -</p><dl> -<dt><i>txt</i> (str)</dt> -<dd> -virtual environment -</dd> -</dl><a NAME="PipFreezeDialog.start" ID="PipFreezeDialog.start"></a> -<h4>PipFreezeDialog.start</h4> -<b>start</b>(<i></i>) -<p> - Public method to start the command. -</p> -<div align="right"><a href="#top">Up</a></div> -<hr /> -</body></html> \ No newline at end of file
--- a/Documentation/Source/eric6.Plugins.UiExtensionPlugins.PipInterface.PipListDialog.html Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,331 +0,0 @@ -<!DOCTYPE html> -<html><head> -<title>eric6.Plugins.UiExtensionPlugins.PipInterface.PipListDialog</title> -<meta charset="UTF-8"> -<style> -body { - background: #EDECE6; - margin: 0em 1em 10em 1em; - color: black; -} - -h1 { color: white; background: #85774A; } -h2 { color: white; background: #85774A; } -h3 { color: white; background: #9D936E; } -h4 { color: white; background: #9D936E; } - -a { color: #BA6D36; } - -</style> -</head> -<body><a NAME="top" ID="top"></a> -<h1>eric6.Plugins.UiExtensionPlugins.PipInterface.PipListDialog</h1> -<p> -Module implementing a dialog to list installed packages. -</p> -<h3>Global Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Classes</h3> -<table> -<tr> -<td><a href="#PipListDialog">PipListDialog</a></td> -<td>Class implementing a dialog to list installed packages.</td> -</tr> -</table> -<h3>Functions</h3> -<table> -<tr><td>None</td></tr> -</table> -<hr /><hr /> -<a NAME="PipListDialog" ID="PipListDialog"></a> -<h2>PipListDialog</h2> -<p> - Class implementing a dialog to list installed packages. -</p> -<h3>Derived from</h3> -QDialog, Ui_PipListDialog -<h3>Class Attributes</h3> -<table> -<tr><td>CommandArguments</td></tr><tr><td>ShowProcessClassifiersMode</td></tr><tr><td>ShowProcessEntryPointsMode</td></tr><tr><td>ShowProcessFilesListMode</td></tr><tr><td>ShowProcessGeneralMode</td></tr> -</table> -<h3>Class Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Methods</h3> -<table> -<tr> -<td><a href="#PipListDialog.__init__">PipListDialog</a></td> -<td>Constructor</td> -</tr><tr> -<td><a href="#PipListDialog.__executeUpgradePackages">__executeUpgradePackages</a></td> -<td>Private method to execute the pip upgrade command.</td> -</tr><tr> -<td><a href="#PipListDialog.__finish">__finish</a></td> -<td>Private slot called when the process finished or the user pressed the cancel button.</td> -</tr><tr> -<td><a href="#PipListDialog.__procFinished">__procFinished</a></td> -<td>Private slot connected to the finished signal.</td> -</tr><tr> -<td><a href="#PipListDialog.__processOutput">__processOutput</a></td> -<td>Private method to process the captured output.</td> -</tr><tr> -<td><a href="#PipListDialog.__readStderr">__readStderr</a></td> -<td>Private slot to handle the readyReadStandardError signal.</td> -</tr><tr> -<td><a href="#PipListDialog.__readStdout">__readStdout</a></td> -<td>Private slot to handle the readyReadStandardOutput signal.</td> -</tr><tr> -<td><a href="#PipListDialog.__refresh">__refresh</a></td> -<td>Private slot to refresh the displayed list.</td> -</tr><tr> -<td><a href="#PipListDialog.__stopProcess">__stopProcess</a></td> -<td>Private slot to stop the running process.</td> -</tr><tr> -<td><a href="#PipListDialog.__uninstallPackages">__uninstallPackages</a></td> -<td>Private slot to uninstall the selected packages.</td> -</tr><tr> -<td><a href="#PipListDialog.__upgradeAllPackages">__upgradeAllPackages</a></td> -<td>Private slot to upgrade all listed packages.</td> -</tr><tr> -<td><a href="#PipListDialog.__upgradePackages">__upgradePackages</a></td> -<td>Private slot to upgrade the selected packages.</td> -</tr><tr> -<td><a href="#PipListDialog.__upgradePip">__upgradePip</a></td> -<td>Private slot to upgrade pip itself.</td> -</tr><tr> -<td><a href="#PipListDialog.closeEvent">closeEvent</a></td> -<td>Protected slot implementing a close event handler.</td> -</tr><tr> -<td><a href="#PipListDialog.on_buttonBox_clicked">on_buttonBox_clicked</a></td> -<td>Private slot called by a button of the button box clicked.</td> -</tr><tr> -<td><a href="#PipListDialog.on_installedFilesCheckBox_clicked">on_installedFilesCheckBox_clicked</a></td> -<td>Private slot to handle a change of the installed files information checkbox.</td> -</tr><tr> -<td><a href="#PipListDialog.on_localCheckBox_clicked">on_localCheckBox_clicked</a></td> -<td>Private slot handling the switching of the local mode.</td> -</tr><tr> -<td><a href="#PipListDialog.on_notRequiredCheckBox_clicked">on_notRequiredCheckBox_clicked</a></td> -<td>Private slot handling the switching of the 'not required' mode.</td> -</tr><tr> -<td><a href="#PipListDialog.on_packageList_itemSelectionChanged">on_packageList_itemSelectionChanged</a></td> -<td>Private slot handling the selection of a package.</td> -</tr><tr> -<td><a href="#PipListDialog.on_userCheckBox_clicked">on_userCheckBox_clicked</a></td> -<td>Private slot handling the switching of the 'user-site' mode.</td> -</tr><tr> -<td><a href="#PipListDialog.on_venvComboBox_activated">on_venvComboBox_activated</a></td> -<td>Private slot handling the selection of a virtual environment.</td> -</tr><tr> -<td><a href="#PipListDialog.on_verboseCheckBox_clicked">on_verboseCheckBox_clicked</a></td> -<td>Private slot to handle a change of the verbose package information checkbox.</td> -</tr><tr> -<td><a href="#PipListDialog.start">start</a></td> -<td>Public method to start the command.</td> -</tr> -</table> -<h3>Static Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<a NAME="PipListDialog.__init__" ID="PipListDialog.__init__"></a> -<h4>PipListDialog (Constructor)</h4> -<b>PipListDialog</b>(<i>pip, mode, indexUrl, title, parent=None</i>) -<p> - Constructor -</p><dl> -<dt><i>pip</i> (Pip)</dt> -<dd> -reference to the master object -</dd><dt><i>mode</i> (str)</dt> -<dd> -list command mode (one of 'list', 'uptodate', 'outdated') -</dd><dt><i>indexUrl</i> (str)</dt> -<dd> -URL of the pypi index -</dd><dt><i>title</i> (str)</dt> -<dd> -title of the dialog -</dd><dt><i>parent</i> (QWidget)</dt> -<dd> -reference to the parent widget -</dd> -</dl><a NAME="PipListDialog.__executeUpgradePackages" ID="PipListDialog.__executeUpgradePackages"></a> -<h4>PipListDialog.__executeUpgradePackages</h4> -<b>__executeUpgradePackages</b>(<i>packages</i>) -<p> - Private method to execute the pip upgrade command. -</p><dl> -<dt><i>packages</i> (list of str)</dt> -<dd> -list of package names to be upgraded -</dd> -</dl><a NAME="PipListDialog.__finish" ID="PipListDialog.__finish"></a> -<h4>PipListDialog.__finish</h4> -<b>__finish</b>(<i></i>) -<p> - Private slot called when the process finished or the user pressed - the cancel button. -</p><a NAME="PipListDialog.__procFinished" ID="PipListDialog.__procFinished"></a> -<h4>PipListDialog.__procFinished</h4> -<b>__procFinished</b>(<i>exitCode, exitStatus</i>) -<p> - Private slot connected to the finished signal. -</p><dl> -<dt><i>exitCode</i> (int)</dt> -<dd> -exit code of the process -</dd><dt><i>exitStatus</i> (QProcess.ExitStatus)</dt> -<dd> -exit status of the process -</dd> -</dl><a NAME="PipListDialog.__processOutput" ID="PipListDialog.__processOutput"></a> -<h4>PipListDialog.__processOutput</h4> -<b>__processOutput</b>(<i></i>) -<p> - Private method to process the captured output. -</p><a NAME="PipListDialog.__readStderr" ID="PipListDialog.__readStderr"></a> -<h4>PipListDialog.__readStderr</h4> -<b>__readStderr</b>(<i></i>) -<p> - Private slot to handle the readyReadStandardError signal. -</p><p> - It reads the error output of the process and inserts it into the - error pane. -</p><a NAME="PipListDialog.__readStdout" ID="PipListDialog.__readStdout"></a> -<h4>PipListDialog.__readStdout</h4> -<b>__readStdout</b>(<i></i>) -<p> - Private slot to handle the readyReadStandardOutput signal. -</p><p> - It reads the output of the process, formats it and inserts it into - the contents pane. -</p><a NAME="PipListDialog.__refresh" ID="PipListDialog.__refresh"></a> -<h4>PipListDialog.__refresh</h4> -<b>__refresh</b>(<i></i>) -<p> - Private slot to refresh the displayed list. -</p><a NAME="PipListDialog.__stopProcess" ID="PipListDialog.__stopProcess"></a> -<h4>PipListDialog.__stopProcess</h4> -<b>__stopProcess</b>(<i></i>) -<p> - Private slot to stop the running process. -</p><a NAME="PipListDialog.__uninstallPackages" ID="PipListDialog.__uninstallPackages"></a> -<h4>PipListDialog.__uninstallPackages</h4> -<b>__uninstallPackages</b>(<i></i>) -<p> - Private slot to uninstall the selected packages. -</p><a NAME="PipListDialog.__upgradeAllPackages" ID="PipListDialog.__upgradeAllPackages"></a> -<h4>PipListDialog.__upgradeAllPackages</h4> -<b>__upgradeAllPackages</b>(<i></i>) -<p> - Private slot to upgrade all listed packages. -</p><a NAME="PipListDialog.__upgradePackages" ID="PipListDialog.__upgradePackages"></a> -<h4>PipListDialog.__upgradePackages</h4> -<b>__upgradePackages</b>(<i></i>) -<p> - Private slot to upgrade the selected packages. -</p><a NAME="PipListDialog.__upgradePip" ID="PipListDialog.__upgradePip"></a> -<h4>PipListDialog.__upgradePip</h4> -<b>__upgradePip</b>(<i></i>) -<p> - Private slot to upgrade pip itself. -</p><a NAME="PipListDialog.closeEvent" ID="PipListDialog.closeEvent"></a> -<h4>PipListDialog.closeEvent</h4> -<b>closeEvent</b>(<i>e</i>) -<p> - Protected slot implementing a close event handler. -</p><dl> -<dt><i>e</i> (QCloseEvent)</dt> -<dd> -close event -</dd> -</dl><a NAME="PipListDialog.on_buttonBox_clicked" ID="PipListDialog.on_buttonBox_clicked"></a> -<h4>PipListDialog.on_buttonBox_clicked</h4> -<b>on_buttonBox_clicked</b>(<i>button</i>) -<p> - Private slot called by a button of the button box clicked. -</p><dl> -<dt><i>button</i> (QAbstractButton)</dt> -<dd> -button that was clicked -</dd> -</dl><a NAME="PipListDialog.on_installedFilesCheckBox_clicked" ID="PipListDialog.on_installedFilesCheckBox_clicked"></a> -<h4>PipListDialog.on_installedFilesCheckBox_clicked</h4> -<b>on_installedFilesCheckBox_clicked</b>(<i>checked</i>) -<p> - Private slot to handle a change of the installed files information - checkbox. -</p><dl> -<dt><i>checked</i> (bool)</dt> -<dd> -state of the checkbox -</dd> -</dl><a NAME="PipListDialog.on_localCheckBox_clicked" ID="PipListDialog.on_localCheckBox_clicked"></a> -<h4>PipListDialog.on_localCheckBox_clicked</h4> -<b>on_localCheckBox_clicked</b>(<i>checked</i>) -<p> - Private slot handling the switching of the local mode. -</p><dl> -<dt><i>checked</i> (bool)</dt> -<dd> -state of the local check box -</dd> -</dl><a NAME="PipListDialog.on_notRequiredCheckBox_clicked" ID="PipListDialog.on_notRequiredCheckBox_clicked"></a> -<h4>PipListDialog.on_notRequiredCheckBox_clicked</h4> -<b>on_notRequiredCheckBox_clicked</b>(<i>checked</i>) -<p> - Private slot handling the switching of the 'not required' mode. -</p><dl> -<dt><i>checked</i> (bool)</dt> -<dd> -state of the 'not required' check box -</dd> -</dl><a NAME="PipListDialog.on_packageList_itemSelectionChanged" ID="PipListDialog.on_packageList_itemSelectionChanged"></a> -<h4>PipListDialog.on_packageList_itemSelectionChanged</h4> -<b>on_packageList_itemSelectionChanged</b>(<i></i>) -<p> - Private slot handling the selection of a package. -</p><a NAME="PipListDialog.on_userCheckBox_clicked" ID="PipListDialog.on_userCheckBox_clicked"></a> -<h4>PipListDialog.on_userCheckBox_clicked</h4> -<b>on_userCheckBox_clicked</b>(<i>checked</i>) -<p> - Private slot handling the switching of the 'user-site' mode. -</p><dl> -<dt><i>checked</i> (bool)</dt> -<dd> -state of the 'user-site' check box -</dd> -</dl><a NAME="PipListDialog.on_venvComboBox_activated" ID="PipListDialog.on_venvComboBox_activated"></a> -<h4>PipListDialog.on_venvComboBox_activated</h4> -<b>on_venvComboBox_activated</b>(<i>txt</i>) -<p> - Private slot handling the selection of a virtual environment. -</p><dl> -<dt><i>txt</i> (str)</dt> -<dd> -virtual environment -</dd> -</dl><a NAME="PipListDialog.on_verboseCheckBox_clicked" ID="PipListDialog.on_verboseCheckBox_clicked"></a> -<h4>PipListDialog.on_verboseCheckBox_clicked</h4> -<b>on_verboseCheckBox_clicked</b>(<i>checked</i>) -<p> - Private slot to handle a change of the verbose package information - checkbox. -</p><dl> -<dt><i>checked</i> (bool)</dt> -<dd> -state of the checkbox -</dd> -</dl><a NAME="PipListDialog.start" ID="PipListDialog.start"></a> -<h4>PipListDialog.start</h4> -<b>start</b>(<i></i>) -<p> - Public method to start the command. -</p> -<div align="right"><a href="#top">Up</a></div> -<hr /> -</body></html> \ No newline at end of file
--- a/Documentation/Source/eric6.Plugins.UiExtensionPlugins.PipInterface.PipPackageDetailsDialog.html Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,198 +0,0 @@ -<!DOCTYPE html> -<html><head> -<title>eric6.Plugins.UiExtensionPlugins.PipInterface.PipPackageDetailsDialog</title> -<meta charset="UTF-8"> -<style> -body { - background: #EDECE6; - margin: 0em 1em 10em 1em; - color: black; -} - -h1 { color: white; background: #85774A; } -h2 { color: white; background: #85774A; } -h3 { color: white; background: #9D936E; } -h4 { color: white; background: #9D936E; } - -a { color: #BA6D36; } - -</style> -</head> -<body><a NAME="top" ID="top"></a> -<h1>eric6.Plugins.UiExtensionPlugins.PipInterface.PipPackageDetailsDialog</h1> -<p> -Module implementing a dialog to show details about a package. -</p> -<h3>Global Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Classes</h3> -<table> -<tr> -<td><a href="#PipPackageDetailsDialog">PipPackageDetailsDialog</a></td> -<td>Class implementing a dialog to show details about a package.</td> -</tr> -</table> -<h3>Functions</h3> -<table> -<tr><td>None</td></tr> -</table> -<hr /><hr /> -<a NAME="PipPackageDetailsDialog" ID="PipPackageDetailsDialog"></a> -<h2>PipPackageDetailsDialog</h2> -<p> - Class implementing a dialog to show details about a package. -</p> -<h3>Derived from</h3> -QDialog, Ui_PipPackageDetailsDialog -<h3>Class Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Class Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Methods</h3> -<table> -<tr> -<td><a href="#PipPackageDetailsDialog.__init__">PipPackageDetailsDialog</a></td> -<td>Constructor</td> -</tr><tr> -<td><a href="#PipPackageDetailsDialog.__formatSize">__formatSize</a></td> -<td>Private slot to format the size.</td> -</tr><tr> -<td><a href="#PipPackageDetailsDialog.__formatUploadDate">__formatUploadDate</a></td> -<td>Private method to format the upload date.</td> -</tr><tr> -<td><a href="#PipPackageDetailsDialog.__populateDetails">__populateDetails</a></td> -<td>Private method to populate the details tab.</td> -</tr><tr> -<td><a href="#PipPackageDetailsDialog.__populateDownloadUrls">__populateDownloadUrls</a></td> -<td>Private method to populate the download URLs tab.</td> -</tr><tr> -<td><a href="#PipPackageDetailsDialog.__populateRequiresProvides">__populateRequiresProvides</a></td> -<td>Private method to populate the requires/provides tab.</td> -</tr><tr> -<td><a href="#PipPackageDetailsDialog.__sanitize">__sanitize</a></td> -<td>Private method to clean-up the given text.</td> -</tr> -</table> -<h3>Static Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<a NAME="PipPackageDetailsDialog.__init__" ID="PipPackageDetailsDialog.__init__"></a> -<h4>PipPackageDetailsDialog (Constructor)</h4> -<b>PipPackageDetailsDialog</b>(<i>detailsData, downloadsData, parent=None</i>) -<p> - Constructor -</p><dl> -<dt><i>detailsData</i> (dict)</dt> -<dd> -package details -</dd><dt><i>downloadsData</i> (dict)</dt> -<dd> -downloads information -</dd><dt><i>parent</i> (QWidget)</dt> -<dd> -reference to the parent widget -</dd> -</dl><a NAME="PipPackageDetailsDialog.__formatSize" ID="PipPackageDetailsDialog.__formatSize"></a> -<h4>PipPackageDetailsDialog.__formatSize</h4> -<b>__formatSize</b>(<i>size</i>) -<p> - Private slot to format the size. -</p><dl> -<dt><i>size</i> (int)</dt> -<dd> -size to be formatted -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -formatted size -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -str -</dd> -</dl><a NAME="PipPackageDetailsDialog.__formatUploadDate" ID="PipPackageDetailsDialog.__formatUploadDate"></a> -<h4>PipPackageDetailsDialog.__formatUploadDate</h4> -<b>__formatUploadDate</b>(<i>datetime</i>) -<p> - Private method to format the upload date. -</p><dl> -<dt><i>datetime</i> (xmlrpc.DateTime or str)</dt> -<dd> -upload date and time -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -formatted date string -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -str -</dd> -</dl><a NAME="PipPackageDetailsDialog.__populateDetails" ID="PipPackageDetailsDialog.__populateDetails"></a> -<h4>PipPackageDetailsDialog.__populateDetails</h4> -<b>__populateDetails</b>(<i>detailsData</i>) -<p> - Private method to populate the details tab. -</p><dl> -<dt><i>detailsData</i> (dict)</dt> -<dd> -package details -</dd> -</dl><a NAME="PipPackageDetailsDialog.__populateDownloadUrls" ID="PipPackageDetailsDialog.__populateDownloadUrls"></a> -<h4>PipPackageDetailsDialog.__populateDownloadUrls</h4> -<b>__populateDownloadUrls</b>(<i>downloadsData</i>) -<p> - Private method to populate the download URLs tab. -</p><dl> -<dt><i>downloadsData</i> (dict)</dt> -<dd> -downloads information -</dd> -</dl><a NAME="PipPackageDetailsDialog.__populateRequiresProvides" ID="PipPackageDetailsDialog.__populateRequiresProvides"></a> -<h4>PipPackageDetailsDialog.__populateRequiresProvides</h4> -<b>__populateRequiresProvides</b>(<i>detailsData</i>) -<p> - Private method to populate the requires/provides tab. -</p><dl> -<dt><i>detailsData</i> (dict)</dt> -<dd> -package details -</dd> -</dl><a NAME="PipPackageDetailsDialog.__sanitize" ID="PipPackageDetailsDialog.__sanitize"></a> -<h4>PipPackageDetailsDialog.__sanitize</h4> -<b>__sanitize</b>(<i>text, forUrl=False</i>) -<p> - Private method to clean-up the given text. -</p><dl> -<dt><i>text</i> (str)</dt> -<dd> -raw text -</dd><dt><i>forUrl</i> (bool)</dt> -<dd> -flag indicating to sanitize an URL text -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -processed text -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -str -</dd> -</dl> -<div align="right"><a href="#top">Up</a></div> -<hr /> -</body></html> \ No newline at end of file
--- a/Documentation/Source/eric6.Plugins.UiExtensionPlugins.PipInterface.PipPackagesInputDialog.html Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +0,0 @@ -<!DOCTYPE html> -<html><head> -<title>eric6.Plugins.UiExtensionPlugins.PipInterface.PipPackagesInputDialog</title> -<meta charset="UTF-8"> -<style> -body { - background: #EDECE6; - margin: 0em 1em 10em 1em; - color: black; -} - -h1 { color: white; background: #85774A; } -h2 { color: white; background: #85774A; } -h3 { color: white; background: #9D936E; } -h4 { color: white; background: #9D936E; } - -a { color: #BA6D36; } - -</style> -</head> -<body><a NAME="top" ID="top"></a> -<h1>eric6.Plugins.UiExtensionPlugins.PipInterface.PipPackagesInputDialog</h1> -<p> -Module implementing a dialog to enter package specifications. -</p> -<h3>Global Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Classes</h3> -<table> -<tr> -<td><a href="#PipPackagesInputDialog">PipPackagesInputDialog</a></td> -<td>Class implementing a dialog to enter package specifications.</td> -</tr> -</table> -<h3>Functions</h3> -<table> -<tr><td>None</td></tr> -</table> -<hr /><hr /> -<a NAME="PipPackagesInputDialog" ID="PipPackagesInputDialog"></a> -<h2>PipPackagesInputDialog</h2> -<p> - Class implementing a dialog to enter package specifications. -</p> -<h3>Derived from</h3> -QDialog, Ui_PipPackagesInputDialog -<h3>Class Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Class Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Methods</h3> -<table> -<tr> -<td><a href="#PipPackagesInputDialog.__init__">PipPackagesInputDialog</a></td> -<td>Constructor</td> -</tr><tr> -<td><a href="#PipPackagesInputDialog.getData">getData</a></td> -<td>Public method to get the entered data.</td> -</tr><tr> -<td><a href="#PipPackagesInputDialog.on_packagesEdit_textChanged">on_packagesEdit_textChanged</a></td> -<td>Private slot handling entering package names.</td> -</tr> -</table> -<h3>Static Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<a NAME="PipPackagesInputDialog.__init__" ID="PipPackagesInputDialog.__init__"></a> -<h4>PipPackagesInputDialog (Constructor)</h4> -<b>PipPackagesInputDialog</b>(<i>pip, title, install=True, parent=None</i>) -<p> - Constructor -</p><dl> -<dt><i>pip</i> (Pip)</dt> -<dd> -reference to the pip object -</dd><dt><i>title</i> (str)</dt> -<dd> -dialog title -</dd><dt><i>install</i> (bool)</dt> -<dd> -flag indicating an install action -</dd><dt><i>parent</i> (QWidget)</dt> -<dd> -reference to the parent widget -</dd> -</dl><a NAME="PipPackagesInputDialog.getData" ID="PipPackagesInputDialog.getData"></a> -<h4>PipPackagesInputDialog.getData</h4> -<b>getData</b>(<i></i>) -<p> - Public method to get the entered data. -</p><dl> -<dt>Returns:</dt> -<dd> -tuple with the environment name, the list of package - specifications and a flag indicating to install to the user - install directory -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -tuple of (str, list of str, bool) -</dd> -</dl><a NAME="PipPackagesInputDialog.on_packagesEdit_textChanged" ID="PipPackagesInputDialog.on_packagesEdit_textChanged"></a> -<h4>PipPackagesInputDialog.on_packagesEdit_textChanged</h4> -<b>on_packagesEdit_textChanged</b>(<i>txt</i>) -<p> - Private slot handling entering package names. -</p><dl> -<dt><i>txt</i> (str)</dt> -<dd> -name of the requirements file -</dd> -</dl> -<div align="right"><a href="#top">Up</a></div> -<hr /> -</body></html> \ No newline at end of file
--- a/Documentation/Source/eric6.Plugins.UiExtensionPlugins.PipInterface.PipSearchDialog.html Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,321 +0,0 @@ -<!DOCTYPE html> -<html><head> -<title>eric6.Plugins.UiExtensionPlugins.PipInterface.PipSearchDialog</title> -<meta charset="UTF-8"> -<style> -body { - background: #EDECE6; - margin: 0em 1em 10em 1em; - color: black; -} - -h1 { color: white; background: #85774A; } -h2 { color: white; background: #85774A; } -h3 { color: white; background: #9D936E; } -h4 { color: white; background: #9D936E; } - -a { color: #BA6D36; } - -</style> -</head> -<body><a NAME="top" ID="top"></a> -<h1>eric6.Plugins.UiExtensionPlugins.PipInterface.PipSearchDialog</h1> -<p> -Module implementing a dialog to search PyPI. -</p> -<h3>Global Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Classes</h3> -<table> -<tr> -<td><a href="#PipSearchDialog">PipSearchDialog</a></td> -<td>Class implementing a dialog to search PyPI.</td> -</tr> -</table> -<h3>Functions</h3> -<table> -<tr><td>None</td></tr> -</table> -<hr /><hr /> -<a NAME="PipSearchDialog" ID="PipSearchDialog"></a> -<h2>PipSearchDialog</h2> -<p> - Class implementing a dialog to search PyPI. -</p> -<h3>Derived from</h3> -QDialog, Ui_PipSearchDialog -<h3>Class Attributes</h3> -<table> -<tr><td>Stopwords</td></tr><tr><td>VersionRole</td></tr> -</table> -<h3>Class Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Methods</h3> -<table> -<tr> -<td><a href="#PipSearchDialog.__init__">PipSearchDialog</a></td> -<td>Constructor</td> -</tr><tr> -<td><a href="#PipSearchDialog.__detailsError">__detailsError</a></td> -<td>Private method handling a details error.</td> -</tr><tr> -<td><a href="#PipSearchDialog.__displayPackageDetails">__displayPackageDetails</a></td> -<td>Private method to display the returned package details.</td> -</tr><tr> -<td><a href="#PipSearchDialog.__finish">__finish</a></td> -<td>Private slot performing the finishing actions.</td> -</tr><tr> -<td><a href="#PipSearchDialog.__getPackageDownloadsData">__getPackageDownloadsData</a></td> -<td>Private method to store the details data and get downloads information.</td> -</tr><tr> -<td><a href="#PipSearchDialog.__install">__install</a></td> -<td>Private slot to install the selected packages.</td> -</tr><tr> -<td><a href="#PipSearchDialog.__processSearchResult">__processSearchResult</a></td> -<td>Private method to process the search result data from PyPI.</td> -</tr><tr> -<td><a href="#PipSearchDialog.__score">__score</a></td> -<td>Private method to calculate some score for a search result.</td> -</tr><tr> -<td><a href="#PipSearchDialog.__search">__search</a></td> -<td>Private method to perform the search.</td> -</tr><tr> -<td><a href="#PipSearchDialog.__searchError">__searchError</a></td> -<td>Private method handling a search error.</td> -</tr><tr> -<td><a href="#PipSearchDialog.__showDetails">__showDetails</a></td> -<td>Private slot to show details about the selected package.</td> -</tr><tr> -<td><a href="#PipSearchDialog.__transformHits">__transformHits</a></td> -<td>Private method to convert the list returned from pypi into a packages list.</td> -</tr><tr> -<td><a href="#PipSearchDialog.closeEvent">closeEvent</a></td> -<td>Protected slot implementing a close event handler.</td> -</tr><tr> -<td><a href="#PipSearchDialog.on_buttonBox_clicked">on_buttonBox_clicked</a></td> -<td>Private slot called by a button of the button box clicked.</td> -</tr><tr> -<td><a href="#PipSearchDialog.on_resultList_itemActivated">on_resultList_itemActivated</a></td> -<td>Private slot reacting on an item activation.</td> -</tr><tr> -<td><a href="#PipSearchDialog.on_resultList_itemSelectionChanged">on_resultList_itemSelectionChanged</a></td> -<td>Private slot handling changes of the selection.</td> -</tr><tr> -<td><a href="#PipSearchDialog.on_searchButton_clicked">on_searchButton_clicked</a></td> -<td>Private slot handling a press of the search button.</td> -</tr><tr> -<td><a href="#PipSearchDialog.on_searchEdit_textChanged">on_searchEdit_textChanged</a></td> -<td>Private slot handling a change of the search term.</td> -</tr> -</table> -<h3>Static Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<a NAME="PipSearchDialog.__init__" ID="PipSearchDialog.__init__"></a> -<h4>PipSearchDialog (Constructor)</h4> -<b>PipSearchDialog</b>(<i>pip, indexUrl, parent=None</i>) -<p> - Constructor -</p><dl> -<dt><i>pip</i> (Pip)</dt> -<dd> -reference to the master object -</dd><dt><i>indexUrl</i> (str)</dt> -<dd> -URL of XML RPC interface to the pypi index -</dd><dt><i>parent</i> (QWidget)</dt> -<dd> -reference to the parent widget -</dd> -</dl><a NAME="PipSearchDialog.__detailsError" ID="PipSearchDialog.__detailsError"></a> -<h4>PipSearchDialog.__detailsError</h4> -<b>__detailsError</b>(<i>errorCode, errorString</i>) -<p> - Private method handling a details error. -</p><dl> -<dt><i>errorCode</i> (int)</dt> -<dd> -code of the error -</dd><dt><i>errorString</i> (str)</dt> -<dd> -error message -</dd> -</dl><a NAME="PipSearchDialog.__displayPackageDetails" ID="PipSearchDialog.__displayPackageDetails"></a> -<h4>PipSearchDialog.__displayPackageDetails</h4> -<b>__displayPackageDetails</b>(<i>data</i>) -<p> - Private method to display the returned package details. -</p><dl> -<dt><i>data</i> (tuple)</dt> -<dd> -result data with downloads information in the first element -</dd> -</dl><a NAME="PipSearchDialog.__finish" ID="PipSearchDialog.__finish"></a> -<h4>PipSearchDialog.__finish</h4> -<b>__finish</b>(<i></i>) -<p> - Private slot performing the finishing actions. -</p><a NAME="PipSearchDialog.__getPackageDownloadsData" ID="PipSearchDialog.__getPackageDownloadsData"></a> -<h4>PipSearchDialog.__getPackageDownloadsData</h4> -<b>__getPackageDownloadsData</b>(<i>packageVersion, data</i>) -<p> - Private method to store the details data and get downloads - information. -</p><dl> -<dt><i>packageVersion</i> (str)</dt> -<dd> -version info -</dd><dt><i>data</i> (tuple)</dt> -<dd> -result data with package details in the first - element -</dd> -</dl><a NAME="PipSearchDialog.__install" ID="PipSearchDialog.__install"></a> -<h4>PipSearchDialog.__install</h4> -<b>__install</b>(<i>userSite=False</i>) -<p> - Private slot to install the selected packages. -</p><dl> -<dt><i>userSite</i> (bool)</dt> -<dd> -flag indicating to install to the user directory -</dd> -</dl><a NAME="PipSearchDialog.__processSearchResult" ID="PipSearchDialog.__processSearchResult"></a> -<h4>PipSearchDialog.__processSearchResult</h4> -<b>__processSearchResult</b>(<i>data</i>) -<p> - Private method to process the search result data from PyPI. -</p><dl> -<dt><i>data</i> (tuple)</dt> -<dd> -result data with hits in the first element -</dd> -</dl><a NAME="PipSearchDialog.__score" ID="PipSearchDialog.__score"></a> -<h4>PipSearchDialog.__score</h4> -<b>__score</b>(<i>name, summary</i>) -<p> - Private method to calculate some score for a search result. -</p><dl> -<dt><i>name</i> (str)</dt> -<dd> -name of the returned package -</dd><dt><i>summary</i> (str)</dt> -<dd> -summary text for the package -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -score value -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -int -</dd> -</dl><a NAME="PipSearchDialog.__search" ID="PipSearchDialog.__search"></a> -<h4>PipSearchDialog.__search</h4> -<b>__search</b>(<i></i>) -<p> - Private method to perform the search. -</p><a NAME="PipSearchDialog.__searchError" ID="PipSearchDialog.__searchError"></a> -<h4>PipSearchDialog.__searchError</h4> -<b>__searchError</b>(<i>errorCode, errorString</i>) -<p> - Private method handling a search error. -</p><dl> -<dt><i>errorCode</i> (int)</dt> -<dd> -code of the error -</dd><dt><i>errorString</i> (str)</dt> -<dd> -error message -</dd> -</dl><a NAME="PipSearchDialog.__showDetails" ID="PipSearchDialog.__showDetails"></a> -<h4>PipSearchDialog.__showDetails</h4> -<b>__showDetails</b>(<i></i>) -<p> - Private slot to show details about the selected package. -</p><a NAME="PipSearchDialog.__transformHits" ID="PipSearchDialog.__transformHits"></a> -<h4>PipSearchDialog.__transformHits</h4> -<b>__transformHits</b>(<i>hits</i>) -<p> - Private method to convert the list returned from pypi into a - packages list. -</p><dl> -<dt><i>hits</i> (list of dict)</dt> -<dd> -list returned from pypi -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -list of packages -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -list of dict -</dd> -</dl><a NAME="PipSearchDialog.closeEvent" ID="PipSearchDialog.closeEvent"></a> -<h4>PipSearchDialog.closeEvent</h4> -<b>closeEvent</b>(<i>e</i>) -<p> - Protected slot implementing a close event handler. -</p><dl> -<dt><i>e</i> (QCloseEvent)</dt> -<dd> -close event -</dd> -</dl><a NAME="PipSearchDialog.on_buttonBox_clicked" ID="PipSearchDialog.on_buttonBox_clicked"></a> -<h4>PipSearchDialog.on_buttonBox_clicked</h4> -<b>on_buttonBox_clicked</b>(<i>button</i>) -<p> - Private slot called by a button of the button box clicked. -</p><dl> -<dt><i>button</i> (QAbstractButton)</dt> -<dd> -button that was clicked -</dd> -</dl><a NAME="PipSearchDialog.on_resultList_itemActivated" ID="PipSearchDialog.on_resultList_itemActivated"></a> -<h4>PipSearchDialog.on_resultList_itemActivated</h4> -<b>on_resultList_itemActivated</b>(<i>item, column</i>) -<p> - Private slot reacting on an item activation. -</p><dl> -<dt><i>item</i> (QTreeWidgetItem)</dt> -<dd> -reference to the activated item -</dd><dt><i>column</i> (int)</dt> -<dd> -activated column -</dd> -</dl><a NAME="PipSearchDialog.on_resultList_itemSelectionChanged" ID="PipSearchDialog.on_resultList_itemSelectionChanged"></a> -<h4>PipSearchDialog.on_resultList_itemSelectionChanged</h4> -<b>on_resultList_itemSelectionChanged</b>(<i></i>) -<p> - Private slot handling changes of the selection. -</p><a NAME="PipSearchDialog.on_searchButton_clicked" ID="PipSearchDialog.on_searchButton_clicked"></a> -<h4>PipSearchDialog.on_searchButton_clicked</h4> -<b>on_searchButton_clicked</b>(<i></i>) -<p> - Private slot handling a press of the search button. -</p><a NAME="PipSearchDialog.on_searchEdit_textChanged" ID="PipSearchDialog.on_searchEdit_textChanged"></a> -<h4>PipSearchDialog.on_searchEdit_textChanged</h4> -<b>on_searchEdit_textChanged</b>(<i>txt</i>) -<p> - Private slot handling a change of the search term. -</p><dl> -<dt><i>txt</i> (str)</dt> -<dd> -search term -</dd> -</dl> -<div align="right"><a href="#top">Up</a></div> -<hr /> -</body></html> \ No newline at end of file
--- a/Documentation/Source/eric6.Plugins.UiExtensionPlugins.PipInterface.PipSelectionDialog.html Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -<!DOCTYPE html> -<html><head> -<title>eric6.Plugins.UiExtensionPlugins.PipInterface.PipSelectionDialog</title> -<meta charset="UTF-8"> -<style> -body { - background: #EDECE6; - margin: 0em 1em 10em 1em; - color: black; -} - -h1 { color: white; background: #85774A; } -h2 { color: white; background: #85774A; } -h3 { color: white; background: #9D936E; } -h4 { color: white; background: #9D936E; } - -a { color: #BA6D36; } - -</style> -</head> -<body><a NAME="top" ID="top"></a> -<h1>eric6.Plugins.UiExtensionPlugins.PipInterface.PipSelectionDialog</h1> -<p> -Module implementing a dialog to select the pip executable to be used. -</p> -<h3>Global Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Classes</h3> -<table> -<tr> -<td><a href="#PipSelectionDialog">PipSelectionDialog</a></td> -<td>Class implementing a dialog to select the pip executable to be used.</td> -</tr> -</table> -<h3>Functions</h3> -<table> -<tr><td>None</td></tr> -</table> -<hr /><hr /> -<a NAME="PipSelectionDialog" ID="PipSelectionDialog"></a> -<h2>PipSelectionDialog</h2> -<p> - Class implementing a dialog to select the pip executable to be used. -</p> -<h3>Derived from</h3> -QDialog, Ui_PipSelectionDialog -<h3>Class Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Class Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Methods</h3> -<table> -<tr> -<td><a href="#PipSelectionDialog.__init__">PipSelectionDialog</a></td> -<td>Constructor</td> -</tr><tr> -<td><a href="#PipSelectionDialog.getData">getData</a></td> -<td>Public method to get the entered data.</td> -</tr> -</table> -<h3>Static Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<a NAME="PipSelectionDialog.__init__" ID="PipSelectionDialog.__init__"></a> -<h4>PipSelectionDialog (Constructor)</h4> -<b>PipSelectionDialog</b>(<i>pip, parent=None</i>) -<p> - Constructor -</p><dl> -<dt><i>pip</i> (Pip)</dt> -<dd> -reference to the pip object -</dd><dt><i>parent</i> (QWidget)</dt> -<dd> -reference to the parent widget -</dd> -</dl><a NAME="PipSelectionDialog.getData" ID="PipSelectionDialog.getData"></a> -<h4>PipSelectionDialog.getData</h4> -<b>getData</b>(<i></i>) -<p> - Public method to get the entered data. -</p><dl> -<dt>Returns:</dt> -<dd> -tuple with the environment name and a flag indicating to - install to the user install directory -</dd> -</dl><dl> -<dt>Return Type:</dt> -<dd> -tuple of (str, bool) -</dd> -</dl> -<div align="right"><a href="#top">Up</a></div> -<hr /> -</body></html> \ No newline at end of file
--- a/Documentation/Source/index-eric6.Plugins.UiExtensionPlugins.PipInterface.ConfigurationPage.html Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -<!DOCTYPE html> -<html><head> -<title>eric6.Plugins.UiExtensionPlugins.PipInterface.ConfigurationPage</title> -<meta charset="UTF-8"> -<style> -body { - background: #EDECE6; - margin: 0em 1em 10em 1em; - color: black; -} - -h1 { color: white; background: #85774A; } -h2 { color: white; background: #85774A; } -h3 { color: white; background: #9D936E; } -h4 { color: white; background: #9D936E; } - -a { color: #BA6D36; } - -</style> -</head> -<body> -<h1>eric6.Plugins.UiExtensionPlugins.PipInterface.ConfigurationPage</h1> -<p> -Package implementing the configuration page. -</p> - - -<h3>Modules</h3> -<table> -<tr> -<td><a href="eric6.Plugins.UiExtensionPlugins.PipInterface.ConfigurationPage.PipPage.html">PipPage</a></td> -<td>Package implementing the pip configuration page.</td> -</tr> -</table> -</body></html> \ No newline at end of file
--- a/Documentation/Source/index-eric6.Plugins.UiExtensionPlugins.PipInterface.html Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -<!DOCTYPE html> -<html><head> -<title>eric6.Plugins.UiExtensionPlugins.PipInterface</title> -<meta charset="UTF-8"> -<style> -body { - background: #EDECE6; - margin: 0em 1em 10em 1em; - color: black; -} - -h1 { color: white; background: #85774A; } -h2 { color: white; background: #85774A; } -h3 { color: white; background: #9D936E; } -h4 { color: white; background: #9D936E; } - -a { color: #BA6D36; } - -</style> -</head> -<body> -<h1>eric6.Plugins.UiExtensionPlugins.PipInterface</h1> -<p> -Package implementing the various pip dialogs and data. -</p> - -<h3>Packages</h3> -<table> -<tr> -<td><a href="index-eric6.Plugins.UiExtensionPlugins.PipInterface.ConfigurationPage.html">ConfigurationPage</a></td> -<td>Package implementing the configuration page.</td> -</tr> -</table> - -<h3>Modules</h3> -<table> -<tr> -<td><a href="eric6.Plugins.UiExtensionPlugins.PipInterface.Pip.html">Pip</a></td> -<td>Package implementing the pip GUI logic.</td> -</tr><tr> -<td><a href="eric6.Plugins.UiExtensionPlugins.PipInterface.PipDialog.html">PipDialog</a></td> -<td>Module implementing a dialog showing the output of a pip command.</td> -</tr><tr> -<td><a href="eric6.Plugins.UiExtensionPlugins.PipInterface.PipFileSelectionDialog.html">PipFileSelectionDialog</a></td> -<td>Module implementing a dialog to enter a file to be processed.</td> -</tr><tr> -<td><a href="eric6.Plugins.UiExtensionPlugins.PipInterface.PipFreezeDialog.html">PipFreezeDialog</a></td> -<td>Module implementing a dialog to generate a requirements file.</td> -</tr><tr> -<td><a href="eric6.Plugins.UiExtensionPlugins.PipInterface.PipListDialog.html">PipListDialog</a></td> -<td>Module implementing a dialog to list installed packages.</td> -</tr><tr> -<td><a href="eric6.Plugins.UiExtensionPlugins.PipInterface.PipPackageDetailsDialog.html">PipPackageDetailsDialog</a></td> -<td>Module implementing a dialog to show details about a package.</td> -</tr><tr> -<td><a href="eric6.Plugins.UiExtensionPlugins.PipInterface.PipPackagesInputDialog.html">PipPackagesInputDialog</a></td> -<td>Module implementing a dialog to enter package specifications.</td> -</tr><tr> -<td><a href="eric6.Plugins.UiExtensionPlugins.PipInterface.PipSearchDialog.html">PipSearchDialog</a></td> -<td>Module implementing a dialog to search PyPI.</td> -</tr><tr> -<td><a href="eric6.Plugins.UiExtensionPlugins.PipInterface.PipSelectionDialog.html">PipSelectionDialog</a></td> -<td>Module implementing a dialog to select the pip executable to be used.</td> -</tr> -</table> -</body></html> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PipInterface/Pip.py Sat Feb 23 15:46:15 2019 +0100 @@ -0,0 +1,654 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Package implementing the pip GUI logic. +""" + +from __future__ import unicode_literals +try: + str = unicode # __IGNORE_EXCEPTION__ +except NameError: + pass + +import os +import sys +import json + +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.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 + + +class Pip(QObject): + """ + Class implementing the pip GUI logic. + """ + DefaultPyPiUrl = "https://pypi.org" + DefaultIndexUrlXml = DefaultPyPiUrl + "/pypi" + DefaultIndexUrlPip = DefaultPyPiUrl + "/simple" + + def __init__(self, parent=None): + """ + Constructor + + @param parent parent + @type QObject + """ + super(Pip, self).__init__(parent) + + # 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 + ########################################################################## + + def runProcess(self, args, interpreter): + """ + Public method to execute the current pip with the given arguments. + + The selected pip executable is called with the given arguments and + waited for its end. + + @param args list of command line arguments + @type list of str + @param interpreter path of the Python interpreter to be used + @type str + @return tuple containing a flag indicating success and the output + of the process + @rtype tuple of (bool, str) + """ + ioEncoding = Preferences.getSystem("IOEncoding") + + process = QProcess() + process.start(interpreter, args) + procStarted = process.waitForStarted() + if procStarted: + finished = process.waitForFinished(30000) + if finished: + if process.exitCode() == 0: + output = str(process.readAllStandardOutput(), ioEncoding, + 'replace') + return True, output + else: + return (False, + self.tr("python exited with an error ({0}).") + .format(process.exitCode())) + else: + process.terminate() + process.waitForFinished(2000) + process.kill() + process.waitForFinished(3000) + return False, self.tr("python did not finish within" + " 30 seconds.") + + return False, self.tr("python could not be started.") + + def getUserConfig(self): + """ + Public method to get the name of the user configuration file. + + @return path of the user configuration file + @rtype str + """ + # Unix: ~/.config/pip/pip.conf + # OS X: ~/Library/Application Support/pip/pip.conf + # Windows: %APPDATA%\pip\pip.ini + # Environment: $PIP_CONFIG_FILE + + try: + return os.environ["PIP_CONFIG_FILE"] + except KeyError: + pass + + if Globals.isWindowsPlatform(): + config = os.path.join(os.environ["APPDATA"], "pip", "pip.ini") + elif Globals.isMacPlatform(): + config = os.path.expanduser( + "~/Library/Application Support/pip/pip.conf") + else: + config = os.path.expanduser("~/.config/pip/pip.conf") + + return config + + def getVirtualenvConfig(self, venvName): + """ + 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 + + if Globals.isWindowsPlatform(): + pip = "pip.ini" + else: + pip = "pip.conf" + + venvManager = e5App().getObject("VirtualEnvManager") + if venvManager.isGlobalEnvironment(venvName): + venvDirectory = self.__getUserConfig() + else: + venvDirectory = venvManager.getVirtualenvDirectory(venvName) + + if venvDirectory: + config = os.path.join(venvDirectory, pip) + else: + config = "" + + return config + + def getProjectEnvironmentString(self): + """ + Public method to get the string for the project environment. + + @return string for the project environment + @rtype str + """ + if e5App().getObject("Project").isOpen(): + return self.tr("<project>") + else: + return "" + + def getVirtualenvInterpreter(self, venvName): + """ + Public method to get the interpreter for a virtual environment. + + @param venvName logical name for the virtual environment + @type str + @return interpreter path + @rtype str + """ + if venvName == self.getProjectEnvironmentString(): + venvName = \ + e5App().getObject("Project").getDebugProperty("VIRTUALENV") + if not venvName: + # fall back to interpreter used to run eric6 + return sys.executable + + interpreter = \ + e5App().getObject("VirtualEnvManager").getVirtualenvInterpreter( + venvName) + if not interpreter: + E5MessageBox.critical( + None, + self.tr("Interpreter for Virtual Environment"), + self.tr("""No interpreter configured for the selected""" + """ virtual environment.""")) + + return interpreter + + def getVirtualenvNames(self): + """ + Public method to get a sorted list of virtual environment names. + + @return sorted list of virtual environment names + @rtype list of str + """ + return sorted( + e5App().getObject("VirtualEnvManager").getVirtualenvNames()) + + def installPip(self, venvName, userSite=False): + """ + Public method to install pip. + + @param venvName name of the environment to install pip into + @type str + @param userSite flag indicating an install to the user install + directory + @type bool + """ + interpreter = self.getVirtualenvInterpreter(venvName) + if not interpreter: + return + + dia = PipDialog(self.tr('Install PIP')) + if userSite: + commands = [(interpreter, ["-m", "ensurepip", "--user"])] + else: + commands = [(interpreter, ["-m", "ensurepip"])] + 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") + commands.append((interpreter, args[:])) + + res = dia.startProcesses(commands) + if res: + dia.exec_() + + @pyqtSlot() + def repairPip(self, venvName): + """ + Public method to repair the pip installation. + + @param venvName name of the environment to install pip into + @type str + """ + interpreter = self.getVirtualenvInterpreter(venvName) + if not interpreter: + return + + # python -m pip install --ignore-installed pip + if Preferences.getPip("PipSearchIndex"): + indexUrl = Preferences.getPip("PipSearchIndex") + "/simple" + args = ["-m", "pip", "install", "--index-url", indexUrl, + "--ignore-installed"] + else: + args = ["-m", "pip", "install", "--ignore-installed"] + args.append("pip") + + dia = PipDialog(self.tr('Repair PIP')) + res = dia.startProcess(interpreter, args) + if res: + dia.exec_() + + def __checkUpgradePyQt(self, packages): + """ + Private method to check, if an upgrade of PyQt packages is attempted. + + @param packages list of packages to upgrade + @type list of str + @return flag indicating to abort the upgrade attempt + @rtype bool + """ + pyqtPackages = [p for p in packages + 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 might""" + """ not work for the current instance of Python ({0}).""" + """ Do you want to continue?""").format(sys.executable), + icon=E5MessageBox.Critical) + else: + abort = False + + return abort + + def upgradePackages(self, packages, venvName, userSite=False): + """ + Public method to upgrade the given list of packages. + + @param packages list of packages to upgrade + @type list of str + @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 + """ + if self.__checkUpgradePyQt(packages): + return False + + if not venvName: + return False + + interpreter = self.getVirtualenvInterpreter(venvName) + if not interpreter: + return False + + 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 += packages + dia = PipDialog(self.tr('Upgrade Packages')) + res = dia.startProcess(interpreter, args) + if res: + dia.exec_() + return res + + def installPackages(self, packages, venvName, userSite=False): + """ + Public method to install the given list of packages. + + @param packages list of packages to install + @type list of str + @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 + """ + 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. + + @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: + 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" + args = ["-m", "pip", "install", "--index-url", indexUrl] + else: + args = ["-m", "pip", "install"] + if user: + args.append("--user") + args += ["--requirement", requirements] + dia = PipDialog(self.tr('Install Packages from Requirements')) + res = dia.startProcess(interpreter, args) + if res: + dia.exec_() + + def uninstallPackages(self, packages, venvName): + """ + Public method to uninstall the given list of packages. + + @param packages list of packages to uninstall + @type list of str + @param venvName name of the virtual environment to be used + @type str + @return flag indicating a successful execution + @rtype bool + """ + res = False + if packages and venvName: + from UI.DeleteFilesConfirmationDialog import \ + DeleteFilesConfirmationDialog + dlg = DeleteFilesConfirmationDialog( + self.parent(), + self.tr("Uninstall Packages"), + self.tr( + "Do you really want to uninstall these packages?"), + packages) + if dlg.exec_() == QDialog.Accepted: + interpreter = self.getVirtualenvInterpreter(venvName) + if not interpreter: + return + args = ["-m", "pip", "uninstall", "--yes"] + packages + dia = PipDialog(self.tr('Uninstall Packages')) + res = dia.startProcess(interpreter, args) + if res: + dia.exec_() + return res + + def uninstallRequirements(self, venvName): + """ + Public method to uninstall packages as given in a requirements file. + + @param venvName name of the virtual environment to be used + @type str + """ + 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 + + 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 getIndexUrl(self): + """ + Public method to get the index URL for PyPI. + + @return index URL for PyPI + @rtype str + """ + if Preferences.getPip("PipSearchIndex"): + indexUrl = Preferences.getPip("PipSearchIndex") + "/simple" + else: + indexUrl = Pip.DefaultIndexUrlPip + + return indexUrl + + def getIndexUrlXml(self): + """ + Public method to get the index URL for XML RPC calls. + + @return index URL for XML RPC calls + @rtype str + """ + if Preferences.getPip("PipSearchIndex"): + indexUrl = Preferences.getPip("PipSearchIndex") + "/pypi" + else: + indexUrl = Pip.DefaultIndexUrlXml + + return indexUrl + + def getInstalledPackages(self, envName, localPackages=True, + notRequired=False, usersite=False): + """ + Public method to get the list of installed packages. + + @param envName name of the environment to get the packages for + @type str + @param localPackages flag indicating to get local packages only + @type bool + @param notRequired flag indicating to list packages that are not + dependencies of installed packages as well + @type bool + @param usersite flag indicating to only list packages installed + in user-site + @type bool + @return list of tuples containing the package name and version + @rtype list of tuple of (str, str) + """ + packages = [] + + if envName: + interpreter = self.getVirtualenvInterpreter(envName) + if interpreter: + args = [ + "-m", "pip", + "list", + "--format=json", + ] + if localPackages: + args.append("--local") + if notRequired: + args.append("--not-required") + if usersite: + args.append("--user") + + proc = QProcess() + proc.start(interpreter, args) + if proc.waitForStarted(15000): + if proc.waitForFinished(30000): + output = str(proc.readAllStandardOutput(), + Preferences.getSystem("IOEncoding"), + 'replace').strip() + try: + jsonList = json.loads(output) + except Exception: + jsonList = [] + + for package in jsonList: + if isinstance(package, dict): + packages.append(( + package["name"], + package["version"], + )) + + return packages + + def getOutdatedPackages(self, envName, localPackages=True, + notRequired=False, usersite=False): + """ + Public method to get the list of outdated packages. + + @param envName name of the environment to get the packages for + @type str + @param localPackages flag indicating to get local packages only + @type bool + @param notRequired flag indicating to list packages that are not + dependencies of installed packages as well + @type bool + @param usersite flag indicating to only list packages installed + in user-site + @type bool + @return list of tuples containing the package name, installed version + and available version + @rtype list of tuple of (str, str, str) + """ + packages = [] + + if envName: + interpreter = self.getVirtualenvInterpreter(envName) + if interpreter: + args = [ + "-m", "pip", + "list", + "--outdated", + "--format=json", + ] + if localPackages: + args.append("--local") + if notRequired: + args.append("--not-required") + if usersite: + args.append("--user") + + proc = QProcess() + proc.start(interpreter, args) + if proc.waitForStarted(15000): + if proc.waitForFinished(30000): + output = str(proc.readAllStandardOutput(), + Preferences.getSystem("IOEncoding"), + 'replace').strip() + try: + jsonList = json.loads(output) + except Exception: + jsonList = [] + + for package in jsonList: + if isinstance(package, dict): + packages.append(( + package["name"], + package["version"], + package["latest_version"], + )) + + return packages + + 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PipInterface/PipDialog.py Sat Feb 23 15:46:15 2019 +0100 @@ -0,0 +1,205 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a dialog showing the output of a pip command. +""" + +from __future__ import unicode_literals +try: + str = unicode # __IGNORE_EXCEPTION__ +except NameError: + pass + +from PyQt5.QtCore import pyqtSlot, Qt, QCoreApplication, QTimer, \ + QProcess +from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton + +from E5Gui import E5MessageBox + +from .Ui_PipDialog import Ui_PipDialog + +import Preferences + + +class PipDialog(QDialog, Ui_PipDialog): + """ + Class implementing a dialog showing the output of a 'python -m pip' + command. + """ + def __init__(self, text, parent=None): + """ + Constructor + + @param text text to be shown by the label + @type str + @param parent reference to the parent widget + @type QWidget + """ + super(PipDialog, self).__init__(parent) + self.setupUi(self) + + self.proc = None + self.__processQueue = [] + self.__ioEncoding = Preferences.getSystem("IOEncoding") + + self.outputGroup.setTitle(text) + + self.show() + QCoreApplication.processEvents() + + def closeEvent(self, e): + """ + Protected slot implementing a close event handler. + + @param e close event + @type QCloseEvent + """ + self.__processQueue = [] + + if self.proc is not None and \ + self.proc.state() != QProcess.NotRunning: + self.proc.terminate() + QTimer.singleShot(2000, self.proc.kill) + self.proc.waitForFinished(3000) + + self.proc = None + + e.accept() + + def __finish(self): + """ + Private slot called when the process finished or the user pressed + the button. + """ + if self.proc is not None and \ + self.proc.state() != QProcess.NotRunning: + self.proc.terminate() + QTimer.singleShot(2000, self.proc.kill) + self.proc.waitForFinished(3000) + + self.proc = None + + self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) + self.buttonBox.button(QDialogButtonBox.Close).setFocus( + Qt.OtherFocusReason) + + if self.__processQueue: + cmd, args = self.__processQueue.pop(0) + self.__addOutput("\n\n") + self.startProcess(cmd, args) + + @pyqtSlot(QAbstractButton) + def on_buttonBox_clicked(self, button): + """ + Private slot called by a button of the button box clicked. + + @param button button that was clicked + @type QAbstractButton + """ + if button == self.buttonBox.button(QDialogButtonBox.Close): + self.close() + + def __procFinished(self, exitCode, exitStatus): + """ + Private slot connected to the finished signal. + + @param exitCode exit code of the process + @type int + @param exitStatus exit status of the process + @type QProcess.ExitStatus + """ + self.__finish() + + def startProcess(self, cmd, args, showArgs=True): + """ + Public slot used to start the process. + + @param cmd name of the pip executable to be used + @type str + @param args list of arguments for the process + @type list of str + @keyparam showArgs flag indicating to show the arguments + @type bool + @return flag indicating a successful start of the process + @rtype bool + """ + if len(self.errors.toPlainText()) == 0: + self.errorGroup.hide() + + if showArgs: + self.resultbox.append(cmd + ' ' + ' '.join(args)) + self.resultbox.append('') + + self.proc = QProcess() + self.proc.finished.connect(self.__procFinished) + self.proc.readyReadStandardOutput.connect(self.__readStdout) + self.proc.readyReadStandardError.connect(self.__readStderr) + self.proc.start(cmd, args) + procStarted = self.proc.waitForStarted(5000) + if not procStarted: + self.buttonBox.setFocus() + E5MessageBox.critical( + self, + self.tr('Process Generation Error'), + self.tr( + 'The process {0} could not be started.' + ).format(cmd)) + return procStarted + + def startProcesses(self, processParams): + """ + Public method to issue a list of commands to be executed. + + @param processParams list of tuples containing the command + and arguments + @type list of tuples of (str, list of str) + @return flag indicating a successful start of the first process + @rtype bool + """ + if len(processParams) > 1: + for cmd, args in processParams[1:]: + self.__processQueue.append((cmd, args[:])) + cmd, args = processParams[0] + return self.startProcess(cmd, args) + + def __readStdout(self): + """ + Private slot to handle the readyReadStandardOutput signal. + + It reads the output of the process, formats it and inserts it into + the contents pane. + """ + if self.proc is not None: + txt = str(self.proc.readAllStandardOutput(), + self.__ioEncoding, 'replace') + self.__addOutput(txt) + + def __addOutput(self, txt): + """ + Private method to add some text to the output pane. + + @param txt text to be added + @type str + """ + self.resultbox.insertPlainText(txt) + self.resultbox.ensureCursorVisible() + QCoreApplication.processEvents() + + def __readStderr(self): + """ + Private slot to handle the readyReadStandardError signal. + + It reads the error output of the process and inserts it into the + error pane. + """ + if self.proc is not None: + s = str(self.proc.readAllStandardError(), + self.__ioEncoding, 'replace') + self.errorGroup.show() + self.errors.insertPlainText(s) + self.errors.ensureCursorVisible() + + QCoreApplication.processEvents()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PipInterface/PipDialog.ui Sat Feb 23 15:46:15 2019 +0100 @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PipDialog</class> + <widget class="QDialog" name="PipDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>500</height> + </rect> + </property> + <property name="windowTitle"> + <string>pip</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout"> + <item> + <widget class="QGroupBox" name="outputGroup"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>2</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Output</string> + </property> + <layout class="QVBoxLayout"> + <item> + <widget class="QTextEdit" name="resultbox"> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="acceptRichText"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="errorGroup"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Errors</string> + </property> + <layout class="QVBoxLayout"> + <item> + <widget class="QTextEdit" name="errors"> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="acceptRichText"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Close</set> + </property> + </widget> + </item> + </layout> + </widget> + <layoutdefault spacing="6" margin="11"/> + <pixmapfunction>qPixmapFromMimeSource</pixmapfunction> + <tabstops> + <tabstop>resultbox</tabstop> + <tabstop>errors</tabstop> + <tabstop>buttonBox</tabstop> + </tabstops> + <resources/> + <connections/> +</ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PipInterface/PipFileSelectionDialog.py Sat Feb 23 15:46:15 2019 +0100 @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> +# + + +""" +Module implementing a dialog to enter a file to be processed. +""" + +from __future__ import unicode_literals + +import os + +from PyQt5.QtCore import pyqtSlot +from PyQt5.QtWidgets import QDialog, QDialogButtonBox + +from E5Gui.E5PathPicker import E5PathPickerModes + +from .Ui_PipFileSelectionDialog import Ui_PipFileSelectionDialog + +import Utilities + + +class PipFileSelectionDialog(QDialog, Ui_PipFileSelectionDialog): + """ + Class implementing a dialog to enter a file to be processed. + """ + def __init__(self, pip, mode, install=True, parent=None): + """ + Constructor + + @param pip reference to the pip object + @type Pip + @param mode mode of the dialog + @type str + @param install flag indicating an install action + @type bool + @param parent reference to the parent widget + @type QWidget + """ + super(PipFileSelectionDialog, self).__init__(parent) + self.setupUi(self) + + if mode == "requirements": + self.fileLabel.setText(self.tr("Enter requirements file:")) + self.filePicker.setMode(E5PathPickerModes.OpenFileMode) + self.filePicker.setToolTip(self.tr( + "Press to select the requirements file through a file" + " selection dialog.")) + self.filePicker.setFilters( + self.tr("Text Files (*.txt);;All Files (*)")) + elif mode == "package": + self.fileLabel.setText(self.tr("Enter package file:")) + self.filePicker.setMode(E5PathPickerModes.OpenFileMode) + self.filePicker.setToolTip(self.tr( + "Press to select the package file through a file" + " selection dialog.")) + self.filePicker.setFilters( + self.tr("Python Wheel (*.whl);;" + "Archive Files (*.tar.gz *.zip);;" + "All Files (*)")) + else: + self.fileLabel.setText(self.tr("Enter file name:")) + self.filePicker.setMode(E5PathPickerModes.OpenFileMode) + self.filePicker.setToolTip(self.tr( + "Press to select a file through a file selection dialog.")) + self.filePicker.setFilters(self.tr("All Files (*)")) + self.filePicker.setDefaultDirectory(os.path.expanduser("~")) + + self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) + + self.userCheckBox.setVisible(install) + + msh = self.minimumSizeHint() + self.resize(max(self.width(), msh.width()), msh.height()) + + @pyqtSlot(str) + def on_filePicker_textChanged(self, txt): + """ + Private slot to handle entering the name of a file. + + @param txt name of the file + @type str + """ + self.buttonBox.button(QDialogButtonBox.Ok).setEnabled( + bool(txt) and + os.path.exists(Utilities.toNativeSeparators(txt)) + ) + + def getData(self): + """ + Public method to get the entered data. + + @return tuple with the name of the selected file and a flag indicating + to install to the user install directory + @rtype tuple of (str, bool) + """ + return ( + self.filePicker.text(), + self.userCheckBox.isChecked() + )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PipInterface/PipFileSelectionDialog.ui Sat Feb 23 15:46:15 2019 +0100 @@ -0,0 +1,99 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PipFileSelectionDialog</class> + <widget class="QDialog" name="PipFileSelectionDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>114</height> + </rect> + </property> + <property name="windowTitle"> + <string>Select File</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="fileLabel"> + <property name="text"> + <string>File Name:</string> + </property> + </widget> + </item> + <item> + <widget class="E5PathPicker" name="filePicker" native="true"> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="userCheckBox"> + <property name="toolTip"> + <string>Select to install to the Python user install directory</string> + </property> + <property name="text"> + <string>Install into User Directory</string> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>E5PathPicker</class> + <extends>QWidget</extends> + <header>E5Gui/E5PathPicker.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>PipFileSelectionDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>PipFileSelectionDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PipInterface/PipFreezeDialog.py Sat Feb 23 15:46:15 2019 +0100 @@ -0,0 +1,286 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a dialog to generate a requirements file. +""" + +from __future__ import unicode_literals +try: + str = unicode # __IGNORE_EXCEPTION__ +except NameError: + pass + +import os + +from PyQt5.QtCore import pyqtSlot, Qt +from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton, \ + QApplication + +from E5Gui import E5MessageBox, E5FileDialog +from E5Gui.E5PathPicker import E5PathPickerModes +from E5Gui.E5Application import e5App + +from .Ui_PipFreezeDialog import Ui_PipFreezeDialog + +import Utilities + + +class PipFreezeDialog(QDialog, Ui_PipFreezeDialog): + """ + Class implementing a dialog to generate a requirements file. + """ + def __init__(self, pip, parent=None): + """ + Constructor + + @param pip reference to the master object + @type Pip + @param parent reference to the parent widget + @type QWidget + """ + super(PipFreezeDialog, self).__init__(parent) + self.setupUi(self) + self.setWindowFlags(Qt.Window) + + self.__refreshButton = self.buttonBox.addButton( + self.tr("&Refresh"), QDialogButtonBox.ActionRole) + + self.requirementsFilePicker.setMode(E5PathPickerModes.SaveFileMode) + self.requirementsFilePicker.setFilters( + self.tr("Text Files (*.txt);;All Files (*)")) + + self.__pip = pip + + self.__requirementsEdited = False + self.__requirementsAvailable = False + + self.__updateButtons() + + def closeEvent(self, e): + """ + Protected slot implementing a close event handler. + + @param e close event + @type QCloseEvent + """ + QApplication.restoreOverrideCursor() + e.accept() + + @pyqtSlot(bool) + def on_localCheckBox_clicked(self, checked): + """ + Private slot handling the switching of the local mode. + + @param checked state of the local check box + @type bool + """ + self.__refresh() + + @pyqtSlot(str) + def on_requirementsFilePicker_textChanged(self, txt): + """ + Private slot handling a change of the requirements file name. + + @param txt name of the requirements file + @type str + """ + self.__updateButtons() + + @pyqtSlot() + def on_requirementsEdit_textChanged(self): + """ + Private slot handling changes of the requirements text. + """ + self.__requirementsEdited = True + + @pyqtSlot(QAbstractButton) + def on_buttonBox_clicked(self, button): + """ + Private slot called by a button of the button box clicked. + + @param button button that was clicked + @type QAbstractButton + """ + if button == self.buttonBox.button(QDialogButtonBox.Close): + self.close() + elif button == self.__refreshButton: + self.__refresh() + + def __refresh(self): + """ + Private slot to refresh the displayed list. + """ + if self.__requirementsEdited: + ok = E5MessageBox.yesNo( + self, + self.tr("Generate Requirements"), + self.tr("""The requirements were changed. Do you want""" + """ to overwrite these changes?""")) + else: + ok = True + if ok: + self.start() + + 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 + + interpreter = self.__pip.getVirtualenvInterpreter(venvName) + if not interpreter: + return + + args = ["-m", "pip", "freeze"] + if self.localCheckBox.isChecked(): + args.append("--local") + if self.requirementsFilePicker.text(): + fileName = Utilities.toNativeSeparators( + self.requirementsFilePicker.text()) + if os.path.exists(fileName): + args.append("--requirement") + args.append(fileName) + + QApplication.setOverrideCursor(Qt.WaitCursor) + success, output = self.__pip.runProcess(args, interpreter) + + if success: + self.requirementsEdit.setPlainText(output) + self.__requirementsAvailable = True + else: + self.requirementsEdit.setPlainText( + self.tr("No output generated by 'pip freeze'.")) + + QApplication.restoreOverrideCursor() + self.__updateButtons() + + self.__requirementsEdited = False + + def __updateButtons(self): + """ + Private method to set the state of the various buttons. + """ + self.saveButton.setEnabled( + self.__requirementsAvailable and + bool(self.requirementsFilePicker.text()) + ) + self.saveToButton.setEnabled(self.__requirementsAvailable) + self.copyButton.setEnabled(self.__requirementsAvailable) + + aw = e5App().getObject("ViewManager").activeWindow() + if aw and self.__requirementsAvailable: + self.insertButton.setEnabled(True) + self.replaceAllButton.setEnabled(True) + self.replaceSelectionButton.setEnabled( + aw.hasSelectedText()) + else: + self.insertButton.setEnabled(False) + self.replaceAllButton.setEnabled(False) + self.replaceSelectionButton.setEnabled(False) + + def __writeToFile(self, fileName): + """ + Private method to write the requirements text to a file. + + @param fileName name of the file to write to + @type str + """ + if os.path.exists(fileName): + ok = E5MessageBox.warning( + self, + self.tr("Generate Requirements"), + self.tr("""The file <b>{0}</b> already exists. Do you want""" + """ to overwrite it?""").format(fileName)) + if not ok: + return + + try: + f = open(fileName, "w") + f.write(self.requirementsEdit.toPlainText()) + f.close() + except (OSError, IOError) as err: + E5MessageBox.critical( + self, + self.tr("Generate Requirements"), + self.tr("""<p>The requirements could not be written""" + """ to <b>{0}</b>.</p><p>Reason: {1}</p>""") + .format(fileName, str(err))) + + @pyqtSlot() + def on_saveButton_clicked(self): + """ + Private slot to save the requirements text to the requirements file. + """ + fileName = self.requirementsFilePicker.text() + self.__writeToFile(fileName) + + @pyqtSlot() + def on_saveToButton_clicked(self): + """ + Private slot to write the requirements text to a new file. + """ + fileName, selectedFilter = E5FileDialog.getSaveFileNameAndFilter( + self, + self.tr("Generate Requirements"), + os.path.expanduser("~"), + self.tr("Text Files (*.txt);;All Files (*)"), + None, + E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite) + ) + if fileName: + ext = os.path.splitext(fileName)[1] + if not ext: + ex = selectedFilter.split("(*")[1].split(")")[0] + if ex: + fileName += ex + self.__writeToFile(fileName) + + @pyqtSlot() + def on_copyButton_clicked(self): + """ + Private slot to copy the requirements text to the clipboard. + """ + txt = self.requirementsEdit.toPlainText() + cb = QApplication.clipboard() + cb.setText(txt) + + @pyqtSlot() + def on_insertButton_clicked(self): + """ + Private slot to insert the requirements text at the cursor position + of the current editor. + """ + aw = e5App().getObject("ViewManager").activeWindow() + if aw: + aw.beginUndoAction() + aw.insert(self.requirementsEdit.toPlainText()) + aw.endUndoAction() + + @pyqtSlot() + def on_replaceSelectionButton_clicked(self): + """ + Private slot to replace the selected text of the current editor + with the requirements text. + """ + aw = e5App().getObject("ViewManager").activeWindow() + if aw: + aw.beginUndoAction() + aw.replaceSelectedText(self.requirementsEdit.toPlainText()) + aw.endUndoAction() + + @pyqtSlot() + def on_replaceAllButton_clicked(self): + """ + Private slot to replace the text of the current editor with the + requirements text. + """ + aw = e5App().getObject("ViewManager").activeWindow() + if aw: + aw.setText(self.requirementsEdit.toPlainText())
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PipInterface/PipFreezeDialog.ui Sat Feb 23 15:46:15 2019 +0100 @@ -0,0 +1,207 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PipFreezeDialog</class> + <widget class="QDialog" name="PipFreezeDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>550</height> + </rect> + </property> + <property name="windowTitle"> + <string>Generate Requirements</string> + </property> + <property name="toolTip"> + <string>Replace the current selection with the requirements text</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QCheckBox" name="localCheckBox"> + <property name="toolTip"> + <string>Select to show requirements for locally-installed packages only</string> + </property> + <property name="text"> + <string>Local packages only</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Requirements File:</string> + </property> + </widget> + </item> + <item> + <widget class="E5PathPicker" name="requirementsFilePicker" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="1"> + <widget class="QPushButton" name="saveButton"> + <property name="toolTip"> + <string>Press to save to the requirements file</string> + </property> + <property name="text"> + <string>Save</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QPushButton" name="saveToButton"> + <property name="toolTip"> + <string>Save to a new file</string> + </property> + <property name="text"> + <string>Save To</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QPushButton" name="copyButton"> + <property name="toolTip"> + <string>Copy the requirements text to the clipboard</string> + </property> + <property name="text"> + <string>Copy</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QPushButton" name="insertButton"> + <property name="toolTip"> + <string>Insert the requirements text at the cursor position</string> + </property> + <property name="text"> + <string>Insert</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QPushButton" name="replaceSelectionButton"> + <property name="text"> + <string>Replace Selection</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QPushButton" name="replaceAllButton"> + <property name="toolTip"> + <string>Replace all text with the requirements text</string> + </property> + <property name="text"> + <string>Replace All</string> + </property> + </widget> + </item> + <item row="6" column="1"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="0" rowspan="7"> + <widget class="QPlainTextEdit" name="requirementsEdit"> + <property name="tabChangesFocus"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Close</set> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>E5PathPicker</class> + <extends>QWidget</extends> + <header>E5Gui/E5PathPicker.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <tabstops> + <tabstop>localCheckBox</tabstop> + <tabstop>requirementsFilePicker</tabstop> + <tabstop>requirementsEdit</tabstop> + <tabstop>saveButton</tabstop> + <tabstop>saveToButton</tabstop> + <tabstop>copyButton</tabstop> + <tabstop>insertButton</tabstop> + <tabstop>replaceSelectionButton</tabstop> + <tabstop>replaceAllButton</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>PipFreezeDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>PipFreezeDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PipInterface/PipPackageDetailsDialog.py Sat Feb 23 15:46:15 2019 +0100 @@ -0,0 +1,227 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a dialog to show details about a package. +""" + +from __future__ import unicode_literals +try: + basestring # __IGNORE_WARNING__ +except NameError: + basestring = str + +from PyQt5.QtCore import Qt, QLocale +from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QTreeWidgetItem, \ + QLabel, QHeaderView + +from .Ui_PipPackageDetailsDialog import Ui_PipPackageDetailsDialog + + +class PipPackageDetailsDialog(QDialog, Ui_PipPackageDetailsDialog): + """ + Class implementing a dialog to show details about a package. + """ + def __init__(self, detailsData, parent=None): + """ + Constructor + + @param detailsData package details + @type dict + @param parent reference to the parent widget + @type QWidget + """ + super(PipPackageDetailsDialog, self).__init__(parent) + self.setupUi(self) + self.setWindowFlags(Qt.Window) + + self.__locale = QLocale() + self.__packageTypeMap = { + "sdist": self.tr("Source"), + "bdist_wheel": self.tr("Python Wheel"), + "bdist_egg": self.tr("Python Egg"), + "bdist_wininst": self.tr("MS Windows Installer"), + "bdist_msi": self.tr("MS Windows Installer"), + "bdist_rpm": self.tr("Unix Installer"), + "bdist_deb": self.tr("Unix Installer"), + "bdist_dumb": self.tr("Archive"), + } + + self.__populateDetails(detailsData["info"]) + self.__populateDownloadUrls(detailsData["urls"]) + self.__populateRequiresProvides(detailsData["info"]) + + def __populateDetails(self, detailsData): + """ + Private method to populate the details tab. + + @param detailsData package details + @type dict + """ + self.packageNameLabel.setText( + "<h1>{0} {1}</h1".format(self.__sanitize(detailsData["name"]), + self.__sanitize(detailsData["version"]))) + self.summaryLabel.setText( + self.__sanitize(detailsData["summary"][:240])) + self.descriptionEdit.setPlainText( + self.__sanitize(detailsData["description"])) + self.authorLabel.setText(self.__sanitize(detailsData["author"])) + self.authorEmailLabel.setText( + '<a href="mailto:{0}">{0}</a>'.format( + self.__sanitize(detailsData["author_email"]))) + self.licenseLabel.setText(self.__sanitize(detailsData["license"])) + self.platformLabel.setText(self.__sanitize(detailsData["platform"])) + self.homePageLabel.setText( + '<a href="{0}">{0}</a>'.format( + self.__sanitize(detailsData["home_page"], forUrl=True))) + self.packageUrlLabel.setText( + '<a href="{0}">{0}</a>'.format( + self.__sanitize(detailsData["package_url"], forUrl=True))) + self.releaseUrlLabel.setText( + '<a href="{0}">{0}</a>'.format( + self.__sanitize(detailsData["release_url"], forUrl=True))) + self.docsUrlLabel.setText( + '<a href="{0}">{0}</a>'.format( + self.__sanitize(detailsData["docs_url"], forUrl=True))) + self.downloadsDayLabel.setText(self.__locale.toString( + detailsData["downloads"]["last_day"])) + self.downloadsWeekLabel.setText(self.__locale.toString( + detailsData["downloads"]["last_week"])) + self.downloadsMonthLabel.setText(self.__locale.toString( + detailsData["downloads"]["last_month"])) + self.classifiersList.addItems(detailsData["classifiers"]) + + self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) + self.buttonBox.button(QDialogButtonBox.Close).setFocus( + Qt.OtherFocusReason) + + def __populateDownloadUrls(self, downloadsData): + """ + Private method to populate the download URLs tab. + + @param downloadsData downloads information + @type dict + """ + index = self.infoWidget.indexOf(self.urls) + if downloadsData: + self.infoWidget.setTabEnabled(index, True) + for download in downloadsData: + itm = QTreeWidgetItem(self.downloadUrlsList, [ + "", + self.__packageTypeMap[download["packagetype"]] + if download["packagetype"] in self.__packageTypeMap + else "", + download["python_version"] + if download["python_version"] != "source" + else "", + self.__locale.toString(download["downloads"]), + self.__formatUploadDate(download["upload_time"]), + self.__formatSize(download["size"]), + ]) + if download["has_sig"]: + pgpLink = ' (<a href="{0}">pgp</a>)'.format( + download["url"] + ".asc") + else: + pgpLink = "" + urlLabel = QLabel('<a href="{0}#md5={2}">{1}</a>{3}'.format( + download["url"], download["filename"], + download["md5_digest"], pgpLink)) + urlLabel.setTextInteractionFlags(Qt.LinksAccessibleByMouse) + urlLabel.setOpenExternalLinks(True) + self.downloadUrlsList.setItemWidget(itm, 0, urlLabel) + header = self.downloadUrlsList.header() + header.resizeSections(QHeaderView.ResizeToContents) + else: + self.infoWidget.setTabEnabled(index, False) + + def __populateRequiresProvides(self, detailsData): + """ + Private method to populate the requires/provides tab. + + @param detailsData package details + @type dict + """ + populatedItems = 0 + + if "requires" in detailsData and detailsData["requires"]: + self.requiredPackagesList.addItems(detailsData["requires"]) + populatedItems += len(detailsData["requires"]) + if "requires_dist" in detailsData and detailsData["requires_dist"]: + self.requiredDistributionsList.addItems( + detailsData["requires_dist"]) + populatedItems += len(detailsData["requires_dist"]) + if "provides" in detailsData and detailsData["provides"]: + self.providedPackagesList.addItems(detailsData["provides"]) + populatedItems += len(detailsData["provides"]) + if "provides_dist" in detailsData and detailsData["provides_dist"]: + self.providedDistributionsList.addItems( + detailsData["provides_dist"]) + populatedItems += len(detailsData["provides_dist"]) + + index = self.infoWidget.indexOf(self.requires) + self.infoWidget.setTabEnabled(index, populatedItems > 0) + + def __sanitize(self, text, forUrl=False): + """ + Private method to clean-up the given text. + + @param text raw text + @type str + @param forUrl flag indicating to sanitize an URL text + @type bool + @return processed text + @rtype str + """ + if text == "UNKNOWN": + text = "" + elif text == "any": + text = self.tr("any") + elif text is None: + text = "" + if forUrl: + if not isinstance(text, basestring) or \ + not text.startswith(("http://", "https://", "ftp://")): + # ignore if the schema is not one of the listed ones + text = "" + + return text + + def __formatUploadDate(self, datetime): + """ + Private method to format the upload date. + + @param datetime upload date and time + @type xmlrpc.DateTime or str + @return formatted date string + @rtype str + """ + if isinstance(datetime, str): + return datetime.split("T")[0] + else: + date = datetime.value.split("T")[0] + return "{0}-{1}-{2}".format(date[:4], date[4:6], date[6:]) + + def __formatSize(self, size): + """ + Private slot to format the size. + + @param size size to be formatted + @type int + @return formatted size + @rtype str + """ + unit = "" + if size < 1024: + unit = self.tr("B") + elif size < 1024 * 1024: + size /= 1024 + unit = self.tr("KB") + elif size < 1024 * 1024 * 1024: + size /= 1024 * 1024 + unit = self.tr("MB") + else: + size /= 1024 * 1024 * 1024 + unit = self.tr("GB") + return self.tr("{0:.1f} {1}", "value, unit").format(size, unit)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PipInterface/PipPackageDetailsDialog.ui Sat Feb 23 15:46:15 2019 +0100 @@ -0,0 +1,517 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PipPackageDetailsDialog</class> + <widget class="QDialog" name="PipPackageDetailsDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>800</width> + <height>700</height> + </rect> + </property> + <property name="windowTitle"> + <string>Package Details</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="packageNameLabel"/> + </item> + <item> + <widget class="QTabWidget" name="infoWidget"> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="details"> + <attribute name="title"> + <string>Details</string> + </attribute> + <attribute name="toolTip"> + <string>Lists package informations</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="1"> + <widget class="QLabel" name="summaryLabel"> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Description:</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLabel" name="authorEmailLabel"> + <property name="openExternalLinks"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QPlainTextEdit" name="descriptionEdit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>5</verstretch> + </sizepolicy> + </property> + <property name="tabChangesFocus"> + <bool>true</bool> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Author:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="authorLabel"/> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>Author Email:</string> + </property> + </widget> + </item> + <item row="7" column="1"> + <widget class="QLabel" name="packageUrlLabel"> + <property name="openExternalLinks"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_6"> + <property name="text"> + <string>License:</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLabel" name="licenseLabel"/> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Summary:</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="label_7"> + <property name="text"> + <string>Platform:</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QLabel" name="platformLabel"/> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="label_8"> + <property name="text"> + <string>Home Page:</string> + </property> + </widget> + </item> + <item row="6" column="1"> + <widget class="QLabel" name="homePageLabel"> + <property name="openExternalLinks"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="7" column="0"> + <widget class="QLabel" name="label_9"> + <property name="text"> + <string>Package URL:</string> + </property> + </widget> + </item> + <item row="8" column="0"> + <widget class="QLabel" name="label_10"> + <property name="text"> + <string>Release URL:</string> + </property> + </widget> + </item> + <item row="8" column="1"> + <widget class="QLabel" name="releaseUrlLabel"> + <property name="openExternalLinks"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="9" column="0"> + <widget class="QLabel" name="label_11"> + <property name="text"> + <string>Documentation URL:</string> + </property> + </widget> + </item> + <item row="9" column="1"> + <widget class="QLabel" name="docsUrlLabel"> + <property name="openExternalLinks"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="10" column="0"> + <widget class="QLabel" name="label_12"> + <property name="text"> + <string>Downloads:</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + </widget> + </item> + <item row="10" column="1"> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label_13"> + <property name="text"> + <string>Last Day:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="downloadsDayLabel"> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="2"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_14"> + <property name="text"> + <string>Last Week:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="downloadsWeekLabel"> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_15"> + <property name="text"> + <string>Last Month:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="downloadsMonthLabel"> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + </layout> + </item> + <item row="11" column="0"> + <widget class="QLabel" name="label_16"> + <property name="text"> + <string>Classifiers:</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + </widget> + </item> + <item row="11" column="1"> + <widget class="QListWidget" name="classifiersList"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::NoSelection</enum> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="urls"> + <attribute name="title"> + <string>Download URLs</string> + </attribute> + <attribute name="toolTip"> + <string>Lists the download URLs</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QTreeWidget" name="downloadUrlsList"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::NoSelection</enum> + </property> + <property name="rootIsDecorated"> + <bool>false</bool> + </property> + <property name="itemsExpandable"> + <bool>false</bool> + </property> + <attribute name="headerStretchLastSection"> + <bool>false</bool> + </attribute> + <column> + <property name="text"> + <string>File</string> + </property> + </column> + <column> + <property name="text"> + <string>Type</string> + </property> + </column> + <column> + <property name="text"> + <string>Py Version</string> + </property> + </column> + <column> + <property name="text"> + <string>Downloads</string> + </property> + </column> + <column> + <property name="text"> + <string>Uploaded on</string> + </property> + </column> + <column> + <property name="text"> + <string>Size</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="requires"> + <attribute name="title"> + <string>Requires/Provides</string> + </attribute> + <attribute name="toolTip"> + <string>Lists required and provided packages</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Requires</string> + </property> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="0" column="0"> + <widget class="QLabel" name="label_17"> + <property name="text"> + <string>Required Packages:</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QListWidget" name="requiredPackagesList"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::NoSelection</enum> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_18"> + <property name="text"> + <string>Required Distributions:</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QListWidget" name="requiredDistributionsList"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::NoSelection</enum> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>Provides</string> + </property> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0"> + <widget class="QLabel" name="label_20"> + <property name="text"> + <string>Provided Packages:</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QListWidget" name="providedPackagesList"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::NoSelection</enum> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_19"> + <property name="text"> + <string>Provided Distributions:</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QListWidget" name="providedDistributionsList"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::NoSelection</enum> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Close</set> + </property> + </widget> + </item> + </layout> + </widget> + <tabstops> + <tabstop>infoWidget</tabstop> + <tabstop>descriptionEdit</tabstop> + <tabstop>classifiersList</tabstop> + <tabstop>downloadUrlsList</tabstop> + <tabstop>requiredPackagesList</tabstop> + <tabstop>requiredDistributionsList</tabstop> + <tabstop>providedPackagesList</tabstop> + <tabstop>providedDistributionsList</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>PipPackageDetailsDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>PipPackageDetailsDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PipInterface/PipPackagesInputDialog.py Sat Feb 23 15:46:15 2019 +0100 @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a dialog to enter package specifications. +""" + +from __future__ import unicode_literals + +from PyQt5.QtCore import pyqtSlot +from PyQt5.QtWidgets import QDialog, QDialogButtonBox + +from .Ui_PipPackagesInputDialog import Ui_PipPackagesInputDialog + + +class PipPackagesInputDialog(QDialog, Ui_PipPackagesInputDialog): + """ + Class implementing a dialog to enter package specifications. + """ + def __init__(self, pip, title, install=True, parent=None): + """ + Constructor + + @param pip reference to the pip object + @type Pip + @param title dialog title + @type str + @param install flag indicating an install action + @type bool + @param parent reference to the parent widget + @type QWidget + """ + super(PipPackagesInputDialog, self).__init__(parent) + self.setupUi(self) + + self.setWindowTitle(title) + + self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) + + self.userCheckBox.setVisible(install) + + msh = self.minimumSizeHint() + self.resize(max(self.width(), msh.width()), msh.height()) + + @pyqtSlot(str) + def on_packagesEdit_textChanged(self, txt): + """ + Private slot handling entering package names. + + @param txt name of the requirements file + @type str + """ + self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(bool(txt)) + + def getData(self): + """ + Public method to get the entered data. + + @return tuple with the list of package specifications and a flag + indicating to install to the user install directory + @rtype tuple of (list of str, bool) + """ + packages = [p.strip() for p in self.packagesEdit.text().split()] + + return ( + packages, + self.userCheckBox.isChecked() + )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PipInterface/PipPackagesInputDialog.ui Sat Feb 23 15:46:15 2019 +0100 @@ -0,0 +1,87 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PipPackagesInputDialog</class> + <widget class="QDialog" name="PipPackagesInputDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>130</height> + </rect> + </property> + <property name="windowTitle"> + <string>Packages </string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Package Specifications (separated by whitespace):</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="packagesEdit"/> + </item> + <item> + <widget class="QCheckBox" name="userCheckBox"> + <property name="toolTip"> + <string>Select to install to the Python user install directory</string> + </property> + <property name="text"> + <string>Install into User Directory</string> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>PipPackagesInputDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>PipPackagesInputDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PipInterface/PipPackagesWidget.py Sat Feb 23 15:46:15 2019 +0100 @@ -0,0 +1,1129 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing the pip packages management widget. +""" + +from __future__ import unicode_literals + +import textwrap +import os + +from PyQt5.QtCore import pyqtSlot, Qt, QEventLoop, QRegExp +from PyQt5.QtGui import QCursor +from PyQt5.QtWidgets import QWidget, QToolButton, QApplication, QHeaderView, \ + QTreeWidgetItem, QInputDialog, QMenu, QDialog + +from E5Gui.E5Application import e5App +from E5Gui import E5MessageBox + +from E5Network.E5XmlRpcClient import E5XmlRpcClient + +from .Ui_PipPackagesWidget import Ui_PipPackagesWidget + +import UI.PixmapCache + +from .Pip import Pip + + +class PipPackagesWidget(QWidget, Ui_PipPackagesWidget): + """ + Class implementing the pip packages management widget. + """ + ShowProcessGeneralMode = 0 + ShowProcessClassifiersMode = 1 + ShowProcessEntryPointsMode = 2 + ShowProcessFilesListMode = 3 + + SearchStopwords = { + "a", "and", "are", "as", "at", "be", "but", "by", + "for", "if", "in", "into", "is", "it", + "no", "not", "of", "on", "or", "such", + "that", "the", "their", "then", "there", "these", + "they", "this", "to", "was", "will", + } + SearchVersionRole = Qt.UserRole + 1 + + def __init__(self, parent=None): + """ + Constructor + + @param parent reference to the parent widget + @type QWidget + """ + super(PipPackagesWidget, self).__init__(parent) + self.setupUi(self) + + self.pipMenuButton.setObjectName( + "navigation_supermenu_button") + self.pipMenuButton.setIcon(UI.PixmapCache.getIcon("superMenu")) + self.pipMenuButton.setToolTip(self.tr("pip Menu")) + self.pipMenuButton.setPopupMode(QToolButton.InstantPopup) + self.pipMenuButton.setToolButtonStyle(Qt.ToolButtonIconOnly) + self.pipMenuButton.setFocusPolicy(Qt.NoFocus) + self.pipMenuButton.setAutoRaise(True) + self.pipMenuButton.setShowMenuInside(True) + + self.refreshButton.setIcon(UI.PixmapCache.getIcon("reload")) + self.upgradeButton.setIcon(UI.PixmapCache.getIcon("1uparrow")) + self.upgradeAllButton.setIcon(UI.PixmapCache.getIcon("2uparrow")) + self.uninstallButton.setIcon(UI.PixmapCache.getIcon("minus")) + self.showPackageDetailsButton.setIcon(UI.PixmapCache.getIcon("info")) + self.searchToggleButton.setIcon(UI.PixmapCache.getIcon("find")) + self.searchButton.setIcon(UI.PixmapCache.getIcon("findNext")) + self.installButton.setIcon(UI.PixmapCache.getIcon("plus")) + self.installUserSiteButton.setIcon(UI.PixmapCache.getIcon("addUser")) + self.showDetailsButton.setIcon(UI.PixmapCache.getIcon("info")) + + self.__pip = Pip(self) + self.__client = E5XmlRpcClient(self.__pip.getIndexUrlXml(), self) + + self.packagesList.header().setSortIndicator(0, Qt.AscendingOrder) + + self.__infoLabels = { + "name": self.tr("Name:"), + "version": self.tr("Version:"), + "location": self.tr("Location:"), + "requires": self.tr("Requires:"), + "summary": self.tr("Summary:"), + "home-page": self.tr("Homepage:"), + "author": self.tr("Author:"), + "author-email": self.tr("Author Email:"), + "license": self.tr("License:"), + "metadata-version": self.tr("Metadata Version:"), + "installer": self.tr("Installer:"), + "classifiers": self.tr("Classifiers:"), + "entry-points": self.tr("Entry Points:"), + "files": self.tr("Files:"), + } + self.infoWidget.setHeaderLabels(["Key", "Value"]) + + venvManager = e5App().getObject("VirtualEnvManager") + venvManager.virtualEnvironmentAdded.connect( + self.on_refreshButton_clicked) + venvManager.virtualEnvironmentRemoved.connect( + self.on_refreshButton_clicked) + + project = e5App().getObject("Project") + project.projectOpened.connect( + self.on_refreshButton_clicked) + project.projectClosed.connect( + self.on_refreshButton_clicked) + + self.__initPipMenu() + self.__populateEnvironments() + self.__updateActionButtons() + + self.statusLabel.hide() + self.searchWidget.hide() + + self.__queryName = [] + self.__querySummary = [] + + self.__packageDetailsDialog = None + + def __populateEnvironments(self): + """ + Private method to get a list of environments and populate the selector. + """ + self.environmentsComboBox.addItem("") + projectVenv = self.__pip.getProjectEnvironmentString() + if projectVenv: + self.environmentsComboBox.addItem(projectVenv) + self.environmentsComboBox.addItems(self.__pip.getVirtualenvNames()) + + def __isPipAvailable(self): + """ + Private method to check, if the pip package is available for the + selected environment. + + @return flag indicating availability + @rtype bool + """ + available = False + + venvName = self.environmentsComboBox.currentText() + if venvName: + available = len(self.packagesList.findItems( + "pip", Qt.MatchExactly | Qt.MatchCaseSensitive)) == 1 + + return available + + ####################################################################### + ## Slots handling widget signals below + ####################################################################### + + def __selectedUpdateableItems(self): + """ + Private method to get a list of selected items that can be updated. + + @return list of selected items that can be updated + @rtype list of QTreeWidgetItem + """ + return [ + itm for itm in self.packagesList.selectedItems() + if bool(itm.text(2)) + ] + + def __allUpdateableItems(self): + """ + Private method to get a list of all items that can be updated. + + @return list of all items that can be updated + @rtype list of QTreeWidgetItem + """ + updateableItems = [] + for index in range(self.packagesList.topLevelItemCount()): + itm = self.packagesList.topLevelItem(index) + if itm.text(2): + updateableItems.append(itm) + + return updateableItems + + def __updateActionButtons(self): + """ + Private method to set the state of the action buttons. + """ + if self.__isPipAvailable(): + self.upgradeButton.setEnabled( + bool(self.__selectedUpdateableItems())) + self.uninstallButton.setEnabled( + bool(self.packagesList.selectedItems())) + self.upgradeAllButton.setEnabled( + bool(self.__allUpdateableItems())) + self.showPackageDetailsButton.setEnabled( + len(self.packagesList.selectedItems()) == 1) + else: + self.upgradeButton.setEnabled(False) + self.uninstallButton.setEnabled(False) + self.upgradeAllButton.setEnabled(False) + self.showPackageDetailsButton.setEnabled(False) + + def __refreshPackagesList(self): + """ + Private method to referesh the packages list. + """ + self.packagesList.clear() + venvName = self.environmentsComboBox.currentText() + if venvName: + interpreter = self.__pip.getVirtualenvInterpreter(venvName) + if interpreter: + QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) + self.statusLabel.show() + self.statusLabel.setText( + self.tr("Getting installed packages...")) + QApplication.processEvents() + + # 1. populate with installed packages + self.packagesList.setUpdatesEnabled(False) + installedPackages = self.__pip.getInstalledPackages( + venvName, + localPackages=self.localCheckBox.isChecked(), + notRequired=self.notRequiredCheckBox.isChecked(), + usersite=self.userCheckBox.isChecked(), + ) + for package, version in installedPackages: + QTreeWidgetItem(self.packagesList, [package, version]) + self.packagesList.setUpdatesEnabled(True) + self.statusLabel.setText( + self.tr("Getting outdated packages...")) + QApplication.processEvents() + + # 2. update with update information + self.packagesList.setUpdatesEnabled(False) + outdatedPackages = self.__pip.getOutdatedPackages( + venvName, + localPackages=self.localCheckBox.isChecked(), + notRequired=self.notRequiredCheckBox.isChecked(), + usersite=self.userCheckBox.isChecked(), + ) + for package, _version, latest in outdatedPackages: + items = self.packagesList.findItems( + package, Qt.MatchExactly | Qt.MatchCaseSensitive) + if items: + itm = items[0] + itm.setText(2, latest) + + self.packagesList.sortItems(0, Qt.AscendingOrder) + for col in range(self.packagesList.columnCount()): + self.packagesList.resizeColumnToContents(col) + self.packagesList.setUpdatesEnabled(True) + QApplication.restoreOverrideCursor() + self.statusLabel.hide() + + self.__updateActionButtons() + self.__updateSearchActionButtons() + self.__updateSearchButton() + + @pyqtSlot(int) + def on_environmentsComboBox_currentIndexChanged(self, index): + """ + Private slot handling the selection of a conda environment. + + @param index index of the selected conda environment + @type int + """ + self.__refreshPackagesList() + + @pyqtSlot(bool) + def on_localCheckBox_clicked(self, checked): + """ + Private slot handling the switching of the local mode. + + @param checked state of the local check box + @type bool + """ + self.__refreshPackagesList() + + @pyqtSlot(bool) + def on_notRequiredCheckBox_clicked(self, checked): + """ + Private slot handling the switching of the 'not required' mode. + + @param checked state of the 'not required' check box + @type bool + """ + self.__refreshPackagesList() + + @pyqtSlot(bool) + def on_userCheckBox_clicked(self, checked): + """ + Private slot handling the switching of the 'user-site' mode. + + @param checked state of the 'user-site' check box + @type bool + """ + self.__refreshPackagesList() + + @pyqtSlot() + def on_packagesList_itemSelectionChanged(self): + """ + Private slot handling the selection of a package. + """ + self.infoWidget.clear() + + if len(self.packagesList.selectedItems()) == 1: + itm = self.packagesList.selectedItems()[0] + + environment = self.environmentsComboBox.currentText() + interpreter = self.__pip.getVirtualenvInterpreter(environment) + if not interpreter: + return + + QApplication.setOverrideCursor(Qt.WaitCursor) + + args = ["-m", "pip", "show"] + if self.verboseCheckBox.isChecked(): + args.append("--verbose") + if self.installedFilesCheckBox.isChecked(): + args.append("--files") + args.append(itm.text(0)) + success, output = self.__pip.runProcess(args, interpreter) + + if success and output: + mode = self.ShowProcessGeneralMode + for line in output.splitlines(): + line = line.rstrip() + if line != "---": + if mode != self.ShowProcessGeneralMode: + if line[0] == " ": + QTreeWidgetItem( + self.infoWidget, + [" ", line.strip()]) + else: + mode = self.ShowProcessGeneralMode + if mode == self.ShowProcessGeneralMode: + try: + label, info = line.split(": ", 1) + except ValueError: + label = line[:-1] + info = "" + label = label.lower() + if label in self.__infoLabels: + QTreeWidgetItem( + self.infoWidget, + [self.__infoLabels[label], info]) + if label == "files": + mode = self.ShowProcessFilesListMode + elif label == "classifiers": + mode = self.ShowProcessClassifiersMode + elif label == "entry-points": + mode = self.ShowProcessEntryPointsMode + self.infoWidget.scrollToTop() + + header = self.infoWidget.header() + header.setStretchLastSection(False) + header.resizeSections(QHeaderView.ResizeToContents) + if header.sectionSize(0) + header.sectionSize(1) < header.width(): + header.setStretchLastSection(True) + + QApplication.restoreOverrideCursor() + + self.__updateActionButtons() + + @pyqtSlot(QTreeWidgetItem, int) + def on_packagesList_itemActivated(self, item, column): + """ + Private slot reacting on a package item activation. + + @param item reference to the activated item + @type QTreeWidgetItem + @param column activated column + @type int + """ + packageName = item.text(0) + if column == 1: + # show details for installed version + packageVersion = item.text(1) + else: + # show details for available version or installed one + if item.text(2): + packageVersion = item.text(2) + else: + packageVersion = item.text(1) + + self.__showPackageDetails(packageName, packageVersion) + + @pyqtSlot(bool) + def on_verboseCheckBox_clicked(self, checked): + """ + Private slot to handle a change of the verbose package information + checkbox. + + @param checked state of the checkbox + @type bool + """ + self.on_packagesList_itemSelectionChanged() + + @pyqtSlot(bool) + def on_installedFilesCheckBox_clicked(self, checked): + """ + Private slot to handle a change of the installed files information + checkbox. + + @param checked state of the checkbox + @type bool + """ + self.on_packagesList_itemSelectionChanged() + + @pyqtSlot() + def on_refreshButton_clicked(self): + """ + Private slot to refresh the display. + """ + currentEnvironment = self.environmentsComboBox.currentText() + self.environmentsComboBox.clear() + self.packagesList.clear() + + QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) + QApplication.processEvents() + + self.__populateEnvironments() + + index = self.environmentsComboBox.findText( + currentEnvironment, Qt.MatchExactly | Qt.MatchCaseSensitive) + if index != -1: + self.environmentsComboBox.setCurrentIndex(index) + + QApplication.restoreOverrideCursor() + self.__updateActionButtons() + + @pyqtSlot() + def on_upgradeButton_clicked(self): + """ + Private slot to upgrade selected packages of the selected environment. + """ + packages = [itm.text(0) for itm in self.__selectedUpdateableItems()] + if packages: + ok = self.__executeUpgradePackages(packages) + if ok: + self.on_refreshButton_clicked() + + @pyqtSlot() + def on_upgradeAllButton_clicked(self): + """ + Private slot to upgrade all packages of the selected environment. + """ + packages = [itm.text(0) for itm in self.__allUpdateableItems()] + if packages: + ok = self.__executeUpgradePackages(packages) + if ok: + self.on_refreshButton_clicked() + + @pyqtSlot() + def on_uninstallButton_clicked(self): + """ + Private slot to remove selected packages of the selected environment. + """ + packages = [itm.text(0) for itm in self.packagesList.selectedItems()] + if packages: + ok = self.__pip.uninstallPackages( + packages, + venvName=self.environmentsComboBox.currentText()) + if ok: + self.on_refreshButton_clicked() + + def __executeUpgradePackages(self, packages): + """ + Private method to execute the pip upgrade command. + + @param packages list of package names to be upgraded + @type list of str + @return flag indicating success + @rtype bool + """ + ok = self.__pip.upgradePackages( + packages, venvName=self.environmentsComboBox.currentText(), + userSite=self.userCheckBox.isChecked()) + return ok + + @pyqtSlot() + def on_showPackageDetailsButton_clicked(self): + """ + Private slot to show information for the selected package. + """ + item = self.packagesList.selectedItems()[0] + if item: + packageName = item.text(0) + # show details for available version or installed one + if item.text(2): + packageVersion = item.text(2) + else: + packageVersion = item.text(1) + + self.__showPackageDetails(packageName, packageVersion) + + ####################################################################### + ## Search widget related methods below + ####################################################################### + + def __updateSearchActionButtons(self): + """ + Private method to update the action button states of the search widget. + """ + installEnable = ( + len(self.searchResultList.selectedItems()) > 0 and + self.environmentsComboBox.currentIndex() > 0 and + self.__isPipAvailable() + ) + self.installButton.setEnabled(installEnable) + self.installUserSiteButton.setEnabled(installEnable) + + self.showDetailsButton.setEnabled( + len(self.searchResultList.selectedItems()) == 1 and + self.__isPipAvailable() + ) + + def __updateSearchButton(self): + """ + Private method to update the state of the search button. + """ + self.searchButton.setEnabled( + (bool(self.searchEditName.text()) or + bool(self.searchEditSummary.text())) and + self.__isPipAvailable() + ) + + @pyqtSlot(bool) + def on_searchToggleButton_toggled(self, checked): + """ + Private slot to togle the search widget. + + @param checked state of the search widget button + @type bool + """ + self.searchWidget.setVisible(checked) + + if checked: + self.searchEditName.setFocus(Qt.OtherFocusReason) + self.searchEditName.selectAll() + + self.__updateSearchActionButtons() + self.__updateSearchButton() + + @pyqtSlot(str) + def on_searchEditName_textChanged(self, txt): + """ + Private slot handling a change of the search term. + + @param txt search term + @type str + """ + self.__updateSearchButton() + + @pyqtSlot() + 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. + """ + self.__search() + + @pyqtSlot() + def on_searchButton_clicked(self): + """ + Private slot handling a press of the search button. + """ + self.__search() + + @pyqtSlot() + def on_searchResultList_itemSelectionChanged(self): + """ + Private slot handling changes of the search result selection. + """ + self.__updateSearchActionButtons() + + def __search(self): + """ + Private method to perform the search. + """ + self.searchResultList.clear() + self.searchInfoLabel.clear() + + self.searchButton.setEnabled(False) + QApplication.setOverrideCursor(Qt.WaitCursor) + QApplication.processEvents(QEventLoop.ExcludeUserInputEvents) + + 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.__queryName, + "summary": self.__querySummary}, + self.searchTermCombineComboBox.currentText()), + self.__processSearchResult, + self.__searchError + ) + + def __processSearchResult(self, data): + """ + Private method to process the search result data from PyPI. + + @param data result data with hits in the first element + @type tuple + """ + if data: + packages = self.__transformHits(data[0]) + if packages: + self.searchInfoLabel.setText( + self.tr("%n package(s) found.", "", len(packages))) + wrapper = textwrap.TextWrapper(width=80) + count = 0 + total = 0 + for package in packages: + itm = QTreeWidgetItem( + self.searchResultList, [ + package['name'].strip(), + "{0:4d}".format(package['score']), + "\n".join([ + wrapper.fill(line) for line in + package['summary'].strip().splitlines() + ]) + ]) + itm.setData(0, self.SearchVersionRole, package['version']) + count += 1 + total += 1 + if count == 100: + count = 0 + QApplication.processEvents() + else: + QApplication.restoreOverrideCursor() + E5MessageBox.warning( + self, + self.tr("Search PyPI"), + self.tr("""<p>The package search did not return""" + """ anything.</p>""")) + self.searchInfoLabel.setText( + self.tr("""<p>The package search did not return""" + """ anything.</p>""")) + else: + QApplication.restoreOverrideCursor() + E5MessageBox.warning( + self, + self.tr("Search PyPI"), + self.tr("""<p>The package search did not return anything.""" + """</p>""")) + self.searchInfoLabel.setText( + self.tr("""<p>The package search did not return anything.""" + """</p>""")) + + header = self.searchResultList.header() + self.searchResultList.sortItems(1, Qt.DescendingOrder) + header.setStretchLastSection(False) + header.resizeSections(QHeaderView.ResizeToContents) + headerSize = 0 + for col in range(header.count()): + headerSize += header.sectionSize(col) + if headerSize < header.width(): + header.setStretchLastSection(True) + + self.__finishSearch() + + def __finishSearch(self): + """ + Private slot performing the search finishing actions. + """ + QApplication.restoreOverrideCursor() + + self.__updateSearchActionButtons() + self.__updateSearchButton() + + self.searchEditName.setFocus(Qt.OtherFocusReason) + + def __searchError(self, errorCode, errorString): + """ + Private method handling a search error. + + @param errorCode code of the error + @type int + @param errorString error message + @type str + """ + self.__finish() + E5MessageBox.warning( + self, + self.tr("Search PyPI"), + self.tr("""<p>The package search failed.</p><p>Reason: {0}</p>""") + .format(errorString)) + self.searchInfoLabel.setText(self.tr("Error: {0}").format(errorString)) + + def __transformHits(self, hits): + """ + Private method to convert the list returned from pypi into a + packages list. + + @param hits list returned from pypi + @type list of dict + @return list of packages + @rtype list of dict + """ + # we only include the record with the highest score + packages = {} + for hit in hits: + name = hit['name'].strip() + summary = (hit['summary'] or "").strip() + version = hit['version'].strip() + score = self.__score(name, summary) + # cleanup the summary + if summary in ["UNKNOWN", "."]: + summary = "" + + if name not in packages: + packages[name] = { + 'name': name, + 'summary': summary, + 'version': [version.strip()], + 'score': score} + else: + if score > packages[name]['score']: + packages[name]['score'] = score + packages[name]['summary'] = summary + packages[name]['version'].append(version.strip()) + + return list(packages.values()) + + def __score(self, name, summary): + """ + Private method to calculate some score for a search result. + + @param name name of the returned package + @type str + @param summary summary text for the package + @type str + @return score value + @rtype int + """ + score = 0 + 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: + # word match gets even higher score + score += 2 + else: + score += 1 + + return score + + @pyqtSlot() + def on_installButton_clicked(self): + """ + Private slot to handle pressing the Install button.. + """ + self.__install() + + @pyqtSlot() + def on_installUserSiteButton_clicked(self): + """ + Private slot to handle pressing the Install to User-Site button.. + """ + self.__install(userSite=True) + + def __install(self, userSite=False): + """ + Private slot to install the selected packages. + + @param userSite flag indicating to install to the user directory + @type bool + """ + venvName = self.environmentsComboBox.currentText() + if venvName: + packages = [] + for itm in self.searchResultList.selectedItems(): + packages.append(itm.text(0).strip()) + if packages: + self.__pip.installPackages(packages, venvName=venvName, + userSite=userSite) + + @pyqtSlot() + def on_showDetailsButton_clicked(self): + """ + Private slot to handle pressing the Show Details button. + """ + self.__showSearchedDetails() + + @pyqtSlot(QTreeWidgetItem, int) + def on_searchResultList_itemActivated(self, item, column): + """ + Private slot reacting on an search result item activation. + + @param item reference to the activated item + @type QTreeWidgetItem + @param column activated column + @type int + """ + self.__showDetails(item) + + def __showSearchedDetails(self, item=None): + """ + Private slot to show details about the selected search result package. + + @param item reference to the search result item to show details for + @type QTreeWidgetItem + """ + self.showDetailsButton.setEnabled(False) + + if not item: + item = self.searchResultList.selectedItems()[0] + + packageVersions = item.data(0, self.SearchVersionRole) + if len(packageVersions) == 1: + packageVersion = packageVersions[0] + elif len(packageVersions) == 0: + packageVersion = "" + else: + packageVersion, ok = QInputDialog.getItem( + self, + self.tr("Show Package Details"), + self.tr("Select the package version:"), + packageVersions, + 0, False) + if not ok: + return + packageName = item.text(0) + + self.__showPackageDetails(packageName, packageVersion) + + def __showPackageDetails(self, packageName, packageVersion): + """ + Private method to populate the package details dialog. + + @param packageName name of the package to show details for + @type str + @param packageVersion version of the package + @type str + """ + QApplication.setOverrideCursor(Qt.WaitCursor) + QApplication.processEvents(QEventLoop.ExcludeUserInputEvents) + + packageData = self.__pip.getPackageDetails(packageName, packageVersion) + + 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: + E5MessageBox.warning( + self, + self.tr("Search PyPI"), + self.tr("""<p>No package details info for <b>{0}</b>""" + """ available.</p>""").format(packageName)) + + ####################################################################### + ## Menu related methods below + ####################################################################### + + def __initPipMenu(self): + """ + Private method to create the super menu and attach it to the super + menu button. + """ + self.__pipMenu = QMenu() + self.__installPipAct = self.__pipMenu.addAction( + self.tr("Install Pip"), + self.__installPip) + self.__installPipUserAct = self.__pipMenu.addAction( + self.tr("Install Pip to User-Site"), + self.__installPipUser) + self.__repairPipAct = self.__pipMenu.addAction( + self.tr("Repair Pip"), + self.__repairPip) + self.__pipMenu.addSeparator() + self.__installPackagesAct = self.__pipMenu.addAction( + self.tr("Install Packages"), + self.__installPackages) + self.__installLocalPackageAct = self.__pipMenu.addAction( + self.tr("Install Local Package"), + self.__installLocalPackage) + self.__pipMenu.addSeparator() + self.__installRequirementsAct = self.__pipMenu.addAction( + self.tr("Install Requirements"), + self.__installRequirements) + self.__uninstallRequirementsAct = self.__pipMenu.addAction( + self.tr("Uninstall Requirements"), + self.__uninstallRequirements) + self.__generateRequirementsAct = self.__pipMenu.addAction( + self.tr("Generate Requirements..."), + self.__generateRequirements) + self.__pipMenu.addSeparator() + # editUserConfigAct + self.__pipMenu.addAction( + self.tr("Edit User Configuration..."), + self.__editUserConfiguration) + self.__editVirtualenvConfigAct = self.__pipMenu.addAction( + self.tr("Edit Current Virtualenv Configuration..."), + self.__editVirtualenvConfiguration) + self.__pipMenu.addSeparator() + # pipConfigAct + self.__pipMenu.addAction( + self.tr("Configure..."), + self.__pipConfigure) + + self.__pipMenu.aboutToShow.connect(self.__aboutToShowPipMenu) + + self.pipMenuButton.setMenu(self.__pipMenu) + + def __aboutToShowPipMenu(self): + """ + Private slot to set the action enabled status. + """ + enable = bool(self.environmentsComboBox.currentText()) + enablePip = self.__isPipAvailable() + + self.__installPipAct.setEnabled(not enablePip) + self.__installPipUserAct.setEnabled(not enablePip) + self.__repairPipAct.setEnabled(enablePip) + + self.__installPackagesAct.setEnabled(enablePip) + self.__installLocalPackageAct.setEnabled(enablePip) + + self.__installRequirementsAct.setEnabled(enablePip) + self.__uninstallRequirementsAct.setEnabled(enablePip) + self.__generateRequirementsAct.setEnabled(enablePip) + + self.__editVirtualenvConfigAct.setEnabled(enable) + + @pyqtSlot() + def __installPip(self): + """ + Private slot to install pip into the selected environment. + """ + venvName = self.environmentsComboBox.currentText() + if venvName: + self.__pip.installPip(venvName) + + @pyqtSlot() + def __installPipUser(self): + """ + Private slot to install pip into the user site for the selected + environment. + """ + venvName = self.environmentsComboBox.currentText() + if venvName: + self.__pip.installPip(venvName, userSite=True) + + @pyqtSlot() + def __repairPip(self): + """ + Private slot to repair the pip installation of the selected + environment. + """ + venvName = self.environmentsComboBox.currentText() + if venvName: + self.__pip.repairPip(venvName) + + @pyqtSlot() + def __installPackages(self): + """ + Private slot to install packages to be given by the user. + """ + venvName = self.environmentsComboBox.currentText() + if venvName: + from .PipPackagesInputDialog import PipPackagesInputDialog + dlg = PipPackagesInputDialog(self, self.tr("Install Packages")) + if dlg.exec_() == QDialog.Accepted: + packages, user = dlg.getData() + if packages: + self.__pip.installPackages(packages, venvName=venvName, + userSite=user) + + @pyqtSlot() + def __installLocalPackage(self): + """ + Private slot to install a package available on local storage. + """ + venvName = self.environmentsComboBox.currentText() + if venvName: + from .PipFileSelectionDialog import PipFileSelectionDialog + dlg = PipFileSelectionDialog(self, "package") + if dlg.exec_() == QDialog.Accepted: + package, user = dlg.getData() + if package and os.path.exists(package): + self.__pip.installPackages([package], venvName=venvName, + userSite=user) + + @pyqtSlot() + def __installRequirements(self): + """ + Private slot to install packages as given in a requirements file. + """ + 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. + """ + venvName = self.environmentsComboBox.currentText() + if venvName: + self.__pip.uninstallRequirements(venvName) + + @pyqtSlot() + def __generateRequirements(self): + """ + Private slot to generate the contents for a requirements file. + """ + 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): + """ + Private slot to edit the user configuration. + """ + self.__editConfiguration() + + @pyqtSlot() + def __editVirtualenvConfiguration(self): + """ + Private slot to edit the configuration of the selected environment. + """ + venvName = self.environmentsComboBox.currentText() + if venvName: + self.__editConfiguration(venvName=venvName) + + def __editConfiguration(self, venvName=""): + """ + Private method to edit a configuration. + + @param venvName name of the environment to act upon + @type str + """ + from QScintilla.MiniEditor import MiniEditor + if venvName: + cfgFile = self.__pip.getVirtualenvConfig(venvName) + if not cfgFile: + return + else: + 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.""" + """ 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.""" + """ 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.""" + """ Aborting""")) + return + + self.__editor = MiniEditor(cfgFile, "Properties") + self.__editor.show() + + def __pipConfigure(self): + """ + Private slot to open the configuration page. + """ + e5App().getObject("UserInterface").showPreferences("pipPage")
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PipInterface/PipPackagesWidget.ui Sat Feb 23 15:46:15 2019 +0100 @@ -0,0 +1,520 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PipPackagesWidget</class> + <widget class="QWidget" name="PipPackagesWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>503</width> + <height>700</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <widget class="QWidget" name="baseWidget" native="true"> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QComboBox" name="environmentsComboBox"/> + </item> + <item> + <widget class="E5ToolButton" name="pipMenuButton"/> + </item> + </layout> + </item> + <item> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <widget class="QCheckBox" name="localCheckBox"> + <property name="toolTip"> + <string>Select to show only locally-installed packages</string> + </property> + <property name="text"> + <string>Local packages only</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QCheckBox" name="notRequiredCheckBox"> + <property name="toolTip"> + <string>Select to list packages that are not dependencies of installed packages</string> + </property> + <property name="text"> + <string>Not required Packages</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QCheckBox" name="userCheckBox"> + <property name="toolTip"> + <string>Select to show only packages installed to the user-site</string> + </property> + <property name="text"> + <string>User-Site only</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="statusLabel"/> + </item> + <item> + <widget class="QSplitter" name="splitter"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <widget class="QTreeWidget" name="packagesList"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>3</verstretch> + </sizepolicy> + </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::ExtendedSelection</enum> + </property> + <property name="rootIsDecorated"> + <bool>false</bool> + </property> + <property name="itemsExpandable"> + <bool>false</bool> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + <attribute name="headerDefaultSectionSize"> + <number>150</number> + </attribute> + <column> + <property name="text"> + <string>Package</string> + </property> + </column> + <column> + <property name="text"> + <string>Installed Version</string> + </property> + </column> + <column> + <property name="text"> + <string>Available Version</string> + </property> + </column> + </widget> + <widget class="QWidget" name="widget" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_7"> + <item> + <widget class="QCheckBox" name="verboseCheckBox"> + <property name="toolTip"> + <string>Select to show verbose package information</string> + </property> + <property name="text"> + <string>Verbose Package Information</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="installedFilesCheckBox"> + <property name="toolTip"> + <string>Select to show information about installed files</string> + </property> + <property name="text"> + <string>Installed Files Information</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QTreeWidget" name="infoWidget"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="rootIsDecorated"> + <bool>false</bool> + </property> + <property name="itemsExpandable"> + <bool>false</bool> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + <property name="columnCount"> + <number>2</number> + </property> + <attribute name="headerVisible"> + <bool>false</bool> + </attribute> + <attribute name="headerStretchLastSection"> + <bool>false</bool> + </attribute> + <column> + <property name="text"> + <string notr="true">1</string> + </property> + </column> + <column> + <property name="text"> + <string notr="true">2</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QToolButton" name="refreshButton"> + <property name="toolTip"> + <string>Press to refresh the lists</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="upgradeButton"> + <property name="toolTip"> + <string>Press to upgrade the selected packages</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="upgradeAllButton"> + <property name="toolTip"> + <string>Press to upgrade all listed packages</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="uninstallButton"> + <property name="toolTip"> + <string>Press to uninstall the selected package</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="showPackageDetailsButton"> + <property name="toolTip"> + <string>Press to show details for the selected entry</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QToolButton" name="searchToggleButton"> + <property name="toolTip"> + <string>Toggle to show or hide the search window</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QWidget" name="searchWidget" native="true"> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <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 for the package name</string> + </property> + <property name="placeholderText"> + <string>Enter search term</string> + </property> + </widget> + </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="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> + <item row="0" column="3" rowspan="2"> + <widget class="QToolButton" name="searchButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="toolTip"> + <string>Press to start the search</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QWidget" name="searchOptionsWidget" native="true"> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + </layout> + </widget> + </item> + <item> + <widget class="QTreeWidget" name="searchResultList"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::ExtendedSelection</enum> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + <column> + <property name="text"> + <string>Package</string> + </property> + </column> + <column> + <property name="text"> + <string>Score</string> + </property> + </column> + <column> + <property name="text"> + <string>Description</string> + </property> + </column> + </widget> + </item> + <item> + <widget class="QLabel" name="searchInfoLabel"/> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QToolButton" name="installButton"> + <property name="toolTip"> + <string>Press to install the selected package</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="installUserSiteButton"> + <property name="toolTip"> + <string>Press to install the selected package to the user site</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="showDetailsButton"> + <property name="toolTip"> + <string>Press to show details for the selected entry</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>E5ToolButton</class> + <extends>QToolButton</extends> + <header>E5Gui/E5ToolButton.h</header> + </customwidget> + </customwidgets> + <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>showPackageDetailsButton</tabstop> + <tabstop>searchToggleButton</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/> + <connections/> +</ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PipInterface/__init__.py Sat Feb 23 15:46:15 2019 +0100 @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Package implementing the various pip dialogs and data. +"""
--- a/Plugins/PluginPipInterface.py Sat Feb 23 13:05:18 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/Plugins/UiExtensionPlugins/PipInterface/ConfigurationPage/PipPage.py Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Package implementing the pip configuration page. -""" - -from __future__ import unicode_literals - -from Preferences.ConfigurationPages.ConfigurationPageBase import \ - ConfigurationPageBase -from .Ui_PipPage import Ui_PipPage - -from .. import DefaultPyPiUrl - - -class PipPage(ConfigurationPageBase, Ui_PipPage): - """ - Class implementing the pip configuration page. - """ - def __init__(self, plugin): - """ - Constructor - - @param plugin reference to the plugin object - @type PipInterfacePlugin - """ - super(PipPage, self).__init__() - self.setupUi(self) - self.setObjectName("PipPage") - - self.__plugin = plugin - - self.indexLabel.setText(self.tr( - '<b>Note:</b> Leave empty to use the default index URL (' - '<a href="{0}">{0}</a>).') - .format(DefaultPyPiUrl)) - - # set initial values - self.indexEdit.setText(self.__plugin.getPreferences("PipSearchIndex")) - - def save(self): - """ - Public slot to save the pip configuration. - """ - self.__plugin.setPreferences( - "PipSearchIndex", self.indexEdit.text().strip())
--- a/Plugins/UiExtensionPlugins/PipInterface/ConfigurationPage/PipPage.ui Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>PipPage</class> - <widget class="QWidget" name="PipPage"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>602</width> - <height>389</height> - </rect> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <widget class="QLabel" name="headerLabel"> - <property name="text"> - <string><b>Configure pip</b></string> - </property> - </widget> - </item> - <item> - <widget class="Line" name="line9_3"> - <property name="frameShape"> - <enum>QFrame::HLine</enum> - </property> - <property name="frameShadow"> - <enum>QFrame::Sunken</enum> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item> - <widget class="QGroupBox" name="groupBox_2"> - <property name="title"> - <string>Index URL</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QLineEdit" name="indexEdit"> - <property name="toolTip"> - <string>Enter the URL of the package index or leave empty to use the default</string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="indexLabel"> - <property name="text"> - <string/> - </property> - <property name="openExternalLinks"> - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>234</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - <tabstops> - <tabstop>indexEdit</tabstop> - </tabstops> - <resources/> - <connections/> -</ui>
--- a/Plugins/UiExtensionPlugins/PipInterface/ConfigurationPage/__init__.py Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Package implementing the configuration page. -"""
--- a/Plugins/UiExtensionPlugins/PipInterface/Pip.py Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1144 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Package implementing the pip GUI logic. -""" - -from __future__ import unicode_literals -try: - str = unicode # __IGNORE_EXCEPTION__ -except NameError: - pass - -import os -import sys - -from PyQt5.QtCore import pyqtSlot, QObject, QProcess -from PyQt5.QtWidgets import QMenu, QInputDialog, QDialog - -from E5Gui import E5MessageBox -from E5Gui.E5Action import E5Action -from E5Gui.E5Application import e5App - -from .PipDialog import PipDialog -from . import DefaultIndexUrlXml - -import Preferences -import Globals - -import UI.PixmapCache - - -class Pip(QObject): - """ - Class implementing the pip GUI logic. - """ - def __init__(self, plugin, parent=None): - """ - Constructor - - @param plugin reference to the plugin object - @type PipInterfacePlugin - @param parent parent - @type QObject - """ - super(Pip, self).__init__(parent) - - self.__plugin = plugin - self.__ui = 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(self.tr('P&ython Package Management'), self.__ui) - 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(self.__plugin.getPreferences("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() - - ########################################################################## - ## Methods below implement some utility functions - ########################################################################## - - def runProcess(self, args, interpreter): - """ - Public method to execute the current pip with the given arguments. - - The selected pip executable is called with the given arguments and - waited for its end. - - @param args list of command line arguments - @type list of str - @param interpreter path of the Python interpreter to be used - @type str - @return tuple containing a flag indicating success and the output - of the process - @rtype tuple of (bool, str) - """ - ioEncoding = Preferences.getSystem("IOEncoding") - - process = QProcess() - process.start(interpreter, args) - procStarted = process.waitForStarted() - if procStarted: - finished = process.waitForFinished(30000) - if finished: - if process.exitCode() == 0: - output = str(process.readAllStandardOutput(), ioEncoding, - 'replace') - return True, output - else: - return (False, - self.tr("python exited with an error ({0}).") - .format(process.exitCode())) - else: - process.terminate() - process.waitForFinished(2000) - process.kill() - process.waitForFinished(3000) - return False, self.tr("python did not finish within" - " 30 seconds.") - - return False, self.tr("python could not be started.") - - def __getUserConfig(self): - """ - Private method to get the name of the user configuration file. - - @return path of the user configuration file - @rtype str - """ - # Unix: ~/.config/pip/pip.conf - # OS X: ~/Library/Application Support/pip/pip.conf - # Windows: %APPDATA%\pip\pip.ini - # Environment: $PIP_CONFIG_FILE - - try: - return os.environ["PIP_CONFIG_FILE"] - except KeyError: - pass - - if Globals.isWindowsPlatform(): - config = os.path.join(os.environ["APPDATA"], "pip", "pip.ini") - elif Globals.isMacPlatform(): - config = os.path.expanduser( - "~/Library/Application Support/pip/pip.conf") - else: - config = os.path.expanduser("~/.config/pip/pip.conf") - - return config - - def __getVirtualenvConfig(self): - """ - Private method to get the name of the virtualenv configuration file. - - @return path of the virtualenv configuration file - @rtype str - """ - # Unix, OS X: $VIRTUAL_ENV/pip.conf - # Windows: %VIRTUAL_ENV%\pip.ini - - if Globals.isWindowsPlatform(): - pip = "pip.ini" - else: - pip = "pip.conf" - try: - venvDirectory = os.environ["VIRTUAL_ENV"] - except KeyError: - venvName = self.__plugin.getPreferences("CurrentEnvironment") - if not venvName: - self.__selectPipVirtualenv() - venvName = self.__plugin.getPreferences("CurrentEnvironment") - if self.__virtualenvManager.isGlobalEnvironment(venvName): - venvDirectory = self.__getUserConfig() - else: - venvDirectory = \ - self.__virtualenvManager.getVirtualenvDirectory(venvName) - - return os.path.join(venvDirectory, pip) - - 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. - - @return string for the project environment - @rtype str - """ - if self.__project.isOpen(): - return self.tr("<project>") - else: - return "" - - def getVirtualenvInterpreter(self, venvName): - """ - Public method to get the interpreter for a virtual environment. - - @param venvName logical name for the virtual environment - @type str - @return interpreter path - @rtype str - """ - if venvName == self.getDefaultEnvironmentString(): - venvName = self.__plugin.getPreferences("CurrentEnvironment") - elif venvName == self.getProjectEnvironmentString(): - venvName = self.__project.getDebugProperty("VIRTUALENV") - if not venvName: - # fall back to standard if not defined - venvName = self.__plugin.getPreferences("CurrentEnvironment") - - interpreter = self.__virtualenvManager.getVirtualenvInterpreter( - venvName) - if not interpreter: - E5MessageBox.critical( - None, - self.tr("Interpreter for Virtual Environment"), - self.tr("""No interpreter configured for the selected""" - """ virtual environment.""")) - - return interpreter - - def getVirtualenvNames(self): - """ - Public method to get a sorted list of virtual environment names. - - @return sorted list of virtual environment names - @rtype list of str - """ - return sorted(self.__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 = self.__plugin.getPreferences( - "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: - self.__plugin.setPreferences("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", self.__plugin.getPreferences("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", self.__plugin.getPreferences("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", self.__plugin.getPreferences("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() - 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, userSite=False): - """ - Private slot to install pip. - - @param userSite flag indicating an install to the user install - directory - @type bool - """ - 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 - - dia = PipDialog(self.tr('Install PIP')) - if userSite: - commands = [(interpreter, ["-m", "ensurepip", "--user"])] - else: - commands = [(interpreter, ["-m", "ensurepip"])] - if self.__plugin.getPreferences("PipSearchIndex"): - indexUrl = \ - self.__plugin.getPreferences("PipSearchIndex") + "/simple" - args = ["-m", "pip", "install", "--index-url", indexUrl, - "--upgrade"] - else: - args = ["-m", "pip", "install", "--upgrade"] - if userSite: - args.append("--user") - args.append("pip") - commands.append((interpreter, args[:])) - - res = dia.startProcesses(commands) - 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 self.__plugin.getPreferences("PipSearchIndex"): - indexUrl = \ - self.__plugin.getPreferences("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): - """ - Private method to repair the pip installation. - - @return flag indicating a successful execution - @rtype bool - """ - from .PipSelectionDialog import PipSelectionDialog - dlg = PipSelectionDialog(self) - if dlg.exec_() != QDialog.Accepted: - return False - - venvName, userSite = dlg.getData() - interpreter = self.getVirtualenvInterpreter(venvName) - if not interpreter: - return - - # python -m pip install --ignore-installed pip - if self.__plugin.getPreferences("PipSearchIndex"): - indexUrl = \ - self.__plugin.getPreferences("PipSearchIndex") + "/simple" - args = ["-m", "pip", "install", "--index-url", indexUrl, - "--ignore-installed"] - else: - args = ["-m", "pip", "install", "--ignore-installed"] - if userSite: - args.append("--user") - args.append("pip") - - dia = PipDialog(self.tr('Repair PIP')) - res = dia.startProcess(interpreter, args) - if res: - dia.exec_() - - def __checkUpgradePyQt(self, packages): - """ - Private method to check, if an upgrade of PyQt packages is attempted. - - @param packages list of packages to upgrade - @type list of str - @return flag indicating to abort the upgrade attempt - @rtype bool - """ - pyqtPackages = [p for p in packages - if p.lower() in ["pyqt5", "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""" - """ not work for the current instance of Python ({0}).""" - """ Do you want to continue?""").format(sys.executable), - icon=E5MessageBox.Critical) - else: - abort = False - - return abort - - def upgradePackages(self, packages, venvName="", userSite=False): - """ - Public method to upgrade the given list of packages. - - @param packages list of packages to upgrade - @type list of str - @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 - """ - if self.__checkUpgradePyQt(packages): - return False - - if not venvName: - venvName = self.__plugin.getPreferences("CurrentEnvironment") - interpreter = self.getVirtualenvInterpreter(venvName) - if not interpreter: - return - - if self.__plugin.getPreferences("PipSearchIndex"): - indexUrl = \ - self.__plugin.getPreferences("PipSearchIndex") + "/simple" - args = ["-m", "pip", "install", "--index-url", indexUrl, - "--upgrade"] - else: - args = ["-m", "pip", "install", "--upgrade"] - if userSite: - args.append("--user") - args += packages - dia = PipDialog(self.tr('Upgrade Packages')) - res = dia.startProcess(interpreter, args) - if res: - 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): - """ - Public method to install the given list of packages. - - @param packages list of packages to install - @type list of str - @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 - """ - if not venvName: - venvName = self.__plugin.getPreferences("CurrentEnvironment") - interpreter = self.getVirtualenvInterpreter(venvName) - if not interpreter: - return - - if self.__plugin.getPreferences("PipSearchIndex"): - indexUrl = \ - self.__plugin.getPreferences("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. - """ - from .PipFileSelectionDialog import PipFileSelectionDialog - dlg = PipFileSelectionDialog(self, "requirements") - if dlg.exec_() == QDialog.Accepted: - venvName, requirements, user = dlg.getData() - if requirements and os.path.exists(requirements): - interpreter = self.getVirtualenvInterpreter(venvName) - if not interpreter: - return - if self.__plugin.getPreferences("PipSearchIndex"): - indexUrl = \ - self.__plugin.getPreferences("PipSearchIndex") + \ - "/simple" - args = ["-m", "pip", "install", "--index-url", indexUrl] - else: - args = ["-m", "pip", "install"] - if user: - args.append("--user") - args += ["--requirement", requirements] - dia = PipDialog(self.tr('Install Packages from Requirements')) - res = dia.startProcess(interpreter, args) - if res: - dia.exec_() - - def uninstallPackages(self, packages, venvName=""): - """ - Public method to uninstall the given list of packages. - - @param packages list of packages to uninstall - @type list of str - @param venvName name of the virtual environment to be used - @type str - @return flag indicating a successful execution - @rtype bool - """ - res = False - if packages: - from UI.DeleteFilesConfirmationDialog import \ - DeleteFilesConfirmationDialog - dlg = DeleteFilesConfirmationDialog( - self.parent(), - self.tr("Uninstall Packages"), - self.tr( - "Do you really want to uninstall these packages?"), - packages) - if dlg.exec_() == QDialog.Accepted: - if not venvName: - venvName = self.__plugin.getPreferences( - "CurrentEnvironment") - interpreter = self.getVirtualenvInterpreter(venvName) - if not interpreter: - return - args = ["-m", "pip", "uninstall", "--yes"] + packages - dia = PipDialog(self.tr('Uninstall Packages')) - res = dia.startProcess(interpreter, args) - if res: - 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): - """ - Private slot to uninstall packages as given in a requirements file. - """ - 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 = self.__plugin.getPreferences( - "CurrentEnvironment") - 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 self.__plugin.getPreferences("PipSearchIndex"): - indexUrl = self.__plugin.getPreferences("PipSearchIndex") + "/pypi" - else: - indexUrl = DefaultIndexUrlXml - - self.__searchDialog = PipSearchDialog(self, indexUrl) - self.__searchDialog.show() - - def __pipConfigure(self): - """ - Private slot to open the configuration page. - """ - e5App().getObject("UserInterface").showPreferences("pipPage")
--- a/Plugins/UiExtensionPlugins/PipInterface/PipDialog.py Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,205 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Module implementing a dialog showing the output of a pip command. -""" - -from __future__ import unicode_literals -try: - str = unicode # __IGNORE_EXCEPTION__ -except NameError: - pass - -from PyQt5.QtCore import pyqtSlot, Qt, QCoreApplication, QTimer, \ - QProcess -from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton - -from E5Gui import E5MessageBox - -from .Ui_PipDialog import Ui_PipDialog - -import Preferences - - -class PipDialog(QDialog, Ui_PipDialog): - """ - Class implementing a dialog showing the output of a 'python -m pip' - command. - """ - def __init__(self, text, parent=None): - """ - Constructor - - @param text text to be shown by the label - @type str - @param parent reference to the parent widget - @type QWidget - """ - super(PipDialog, self).__init__(parent) - self.setupUi(self) - - self.proc = None - self.__processQueue = [] - self.__ioEncoding = Preferences.getSystem("IOEncoding") - - self.outputGroup.setTitle(text) - - self.show() - QCoreApplication.processEvents() - - def closeEvent(self, e): - """ - Protected slot implementing a close event handler. - - @param e close event - @type QCloseEvent - """ - self.__processQueue = [] - - if self.proc is not None and \ - self.proc.state() != QProcess.NotRunning: - self.proc.terminate() - QTimer.singleShot(2000, self.proc.kill) - self.proc.waitForFinished(3000) - - self.proc = None - - e.accept() - - def __finish(self): - """ - Private slot called when the process finished or the user pressed - the button. - """ - if self.proc is not None and \ - self.proc.state() != QProcess.NotRunning: - self.proc.terminate() - QTimer.singleShot(2000, self.proc.kill) - self.proc.waitForFinished(3000) - - self.proc = None - - self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) - self.buttonBox.button(QDialogButtonBox.Close).setFocus( - Qt.OtherFocusReason) - - if self.__processQueue: - cmd, args = self.__processQueue.pop(0) - self.__addOutput("\n\n") - self.startProcess(cmd, args) - - @pyqtSlot(QAbstractButton) - def on_buttonBox_clicked(self, button): - """ - Private slot called by a button of the button box clicked. - - @param button button that was clicked - @type QAbstractButton - """ - if button == self.buttonBox.button(QDialogButtonBox.Close): - self.close() - - def __procFinished(self, exitCode, exitStatus): - """ - Private slot connected to the finished signal. - - @param exitCode exit code of the process - @type int - @param exitStatus exit status of the process - @type QProcess.ExitStatus - """ - self.__finish() - - def startProcess(self, cmd, args, showArgs=True): - """ - Public slot used to start the process. - - @param cmd name of the pip executable to be used - @type str - @param args list of arguments for the process - @type list of str - @keyparam showArgs flag indicating to show the arguments - @type bool - @return flag indicating a successful start of the process - @rtype bool - """ - if len(self.errors.toPlainText()) == 0: - self.errorGroup.hide() - - if showArgs: - self.resultbox.append(cmd + ' ' + ' '.join(args)) - self.resultbox.append('') - - self.proc = QProcess() - self.proc.finished.connect(self.__procFinished) - self.proc.readyReadStandardOutput.connect(self.__readStdout) - self.proc.readyReadStandardError.connect(self.__readStderr) - self.proc.start(cmd, args) - procStarted = self.proc.waitForStarted(5000) - if not procStarted: - self.buttonBox.setFocus() - E5MessageBox.critical( - self, - self.tr('Process Generation Error'), - self.tr( - 'The process {0} could not be started.' - ).format(cmd)) - return procStarted - - def startProcesses(self, processParams): - """ - Public method to issue a list of commands to be executed. - - @param processParams list of tuples containing the command - and arguments - @type list of tuples of (str, list of str) - @return flag indicating a successful start of the first process - @rtype bool - """ - if len(processParams) > 1: - for cmd, args in processParams[1:]: - self.__processQueue.append((cmd, args[:])) - cmd, args = processParams[0] - return self.startProcess(cmd, args) - - def __readStdout(self): - """ - Private slot to handle the readyReadStandardOutput signal. - - It reads the output of the process, formats it and inserts it into - the contents pane. - """ - if self.proc is not None: - txt = str(self.proc.readAllStandardOutput(), - self.__ioEncoding, 'replace') - self.__addOutput(txt) - - def __addOutput(self, txt): - """ - Private method to add some text to the output pane. - - @param txt text to be added - @type str - """ - self.resultbox.insertPlainText(txt) - self.resultbox.ensureCursorVisible() - QCoreApplication.processEvents() - - def __readStderr(self): - """ - Private slot to handle the readyReadStandardError signal. - - It reads the error output of the process and inserts it into the - error pane. - """ - if self.proc is not None: - s = str(self.proc.readAllStandardError(), - self.__ioEncoding, 'replace') - self.errorGroup.show() - self.errors.insertPlainText(s) - self.errors.ensureCursorVisible() - - QCoreApplication.processEvents()
--- a/Plugins/UiExtensionPlugins/PipInterface/PipDialog.ui Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>PipDialog</class> - <widget class="QDialog" name="PipDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>600</width> - <height>500</height> - </rect> - </property> - <property name="windowTitle"> - <string>pip</string> - </property> - <property name="sizeGripEnabled"> - <bool>true</bool> - </property> - <layout class="QVBoxLayout"> - <item> - <widget class="QGroupBox" name="outputGroup"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>2</verstretch> - </sizepolicy> - </property> - <property name="title"> - <string>Output</string> - </property> - <layout class="QVBoxLayout"> - <item> - <widget class="QTextEdit" name="resultbox"> - <property name="readOnly"> - <bool>true</bool> - </property> - <property name="acceptRichText"> - <bool>false</bool> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="errorGroup"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="title"> - <string>Errors</string> - </property> - <layout class="QVBoxLayout"> - <item> - <widget class="QTextEdit" name="errors"> - <property name="readOnly"> - <bool>true</bool> - </property> - <property name="acceptRichText"> - <bool>false</bool> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Close</set> - </property> - </widget> - </item> - </layout> - </widget> - <layoutdefault spacing="6" margin="11"/> - <pixmapfunction>qPixmapFromMimeSource</pixmapfunction> - <tabstops> - <tabstop>resultbox</tabstop> - <tabstop>errors</tabstop> - <tabstop>buttonBox</tabstop> - </tabstops> - <resources/> - <connections/> -</ui>
--- a/Plugins/UiExtensionPlugins/PipInterface/PipFileSelectionDialog.py Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> -# - - -""" -Module implementing a dialog to enter a file to be processed. -""" - -from __future__ import unicode_literals - -import os - -from PyQt5.QtCore import pyqtSlot -from PyQt5.QtWidgets import QDialog, QDialogButtonBox - -from E5Gui.E5PathPicker import E5PathPickerModes - -from .Ui_PipFileSelectionDialog import Ui_PipFileSelectionDialog - -import Utilities - - -class PipFileSelectionDialog(QDialog, Ui_PipFileSelectionDialog): - """ - Class implementing a dialog to enter a file to be processed. - """ - def __init__(self, pip, mode, install=True, parent=None): - """ - Constructor - - @param pip reference to the pip object - @type Pip - @param mode mode of the dialog - @type str - @param install flag indicating an install action - @type bool - @param parent reference to the parent widget - @type QWidget - """ - super(PipFileSelectionDialog, self).__init__(parent) - self.setupUi(self) - - if mode == "requirements": - self.fileLabel.setText(self.tr("Enter requirements file:")) - self.filePicker.setMode(E5PathPickerModes.OpenFileMode) - self.filePicker.setToolTip(self.tr( - "Press to select the requirements file through a file" - " selection dialog.")) - self.filePicker.setFilters( - self.tr("Text Files (*.txt);;All Files (*)")) - elif mode == "package": - self.fileLabel.setText(self.tr("Enter package file:")) - self.filePicker.setMode(E5PathPickerModes.OpenFileMode) - self.filePicker.setToolTip(self.tr( - "Press to select the package file through a file" - " selection dialog.")) - self.filePicker.setFilters( - self.tr("Python Wheel (*.whl);;" - "Archive Files (*.tar.gz *.zip);;" - "All Files (*)")) - else: - self.fileLabel.setText(self.tr("Enter file name:")) - self.filePicker.setMode(E5PathPickerModes.OpenFileMode) - self.filePicker.setToolTip(self.tr( - "Press to select a file through a file selection dialog.")) - self.filePicker.setFilters(self.tr("All Files (*)")) - self.filePicker.setDefaultDirectory(os.path.expanduser("~")) - - self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) - - self.venvComboBox.addItem(pip.getDefaultEnvironmentString()) - projectVenv = pip.getProjectEnvironmentString() - if projectVenv: - self.venvComboBox.addItem(projectVenv) - self.venvComboBox.addItems(pip.getVirtualenvNames()) - - self.userCheckBox.setVisible(install) - - msh = self.minimumSizeHint() - self.resize(max(self.width(), msh.width()), msh.height()) - - @pyqtSlot(str) - def on_filePicker_textChanged(self, txt): - """ - Private slot to handle entering the name of a file. - - @param txt name of the file - @type str - """ - self.buttonBox.button(QDialogButtonBox.Ok).setEnabled( - bool(txt) and - os.path.exists(Utilities.toNativeSeparators(txt)) - ) - - def getData(self): - """ - Public method to get the entered data. - - @return tuple with the environment name, the name of the - selected file and a flag indicating to install to the - user install directory - @rtype tuple of (str, str, bool) - """ - return ( - self.venvComboBox.currentText(), - self.filePicker.text(), - self.userCheckBox.isChecked() - )
--- a/Plugins/UiExtensionPlugins/PipInterface/PipFileSelectionDialog.ui Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>PipFileSelectionDialog</class> - <widget class="QDialog" name="PipFileSelectionDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>600</width> - <height>170</height> - </rect> - </property> - <property name="windowTitle"> - <string>Select File</string> - </property> - <property name="sizeGripEnabled"> - <bool>true</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Virtual Environment:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="venvComboBox"> - <property name="toolTip"> - <string>Select the virtual environment to be used</string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="fileLabel"> - <property name="text"> - <string>File Name:</string> - </property> - </widget> - </item> - <item> - <widget class="E5PathPicker" name="filePicker" native="true"> - <property name="focusPolicy"> - <enum>Qt::StrongFocus</enum> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="userCheckBox"> - <property name="toolTip"> - <string>Select to install to the Python user install directory</string> - </property> - <property name="text"> - <string>Install into User Directory</string> - </property> - </widget> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>E5PathPicker</class> - <extends>QWidget</extends> - <header>E5Gui/E5PathPicker.h</header> - <container>1</container> - </customwidget> - </customwidgets> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>PipFileSelectionDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>PipFileSelectionDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui>
--- a/Plugins/UiExtensionPlugins/PipInterface/PipFreezeDialog.py Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,300 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Module implementing a dialog to generate a requirements file. -""" - -from __future__ import unicode_literals -try: - str = unicode # __IGNORE_EXCEPTION__ -except NameError: - pass - -import os - -from PyQt5.QtCore import pyqtSlot, Qt -from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton, \ - QApplication - -from E5Gui import E5MessageBox, E5FileDialog -from E5Gui.E5PathPicker import E5PathPickerModes -from E5Gui.E5Application import e5App - -from .Ui_PipFreezeDialog import Ui_PipFreezeDialog - -import Utilities - - -class PipFreezeDialog(QDialog, Ui_PipFreezeDialog): - """ - Class implementing a dialog to generate a requirements file. - """ - def __init__(self, pip, parent=None): - """ - Constructor - - @param pip reference to the master object - @type Pip - @param parent reference to the parent widget - @type QWidget - """ - super(PipFreezeDialog, self).__init__(parent) - self.setupUi(self) - self.setWindowFlags(Qt.Window) - - self.__refreshButton = self.buttonBox.addButton( - self.tr("&Refresh"), QDialogButtonBox.ActionRole) - - self.requirementsFilePicker.setMode(E5PathPickerModes.SaveFileMode) - self.requirementsFilePicker.setFilters( - self.tr("Text Files (*.txt);;All Files (*)")) - - 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 - - self.__updateButtons() - - def closeEvent(self, e): - """ - Protected slot implementing a close event handler. - - @param e close event - @type QCloseEvent - """ - 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): - """ - Private slot handling the switching of the local mode. - - @param checked state of the local check box - @type bool - """ - self.__refresh() - - @pyqtSlot(str) - def on_requirementsFilePicker_textChanged(self, txt): - """ - Private slot handling a change of the requirements file name. - - @param txt name of the requirements file - @type str - """ - self.__updateButtons() - - @pyqtSlot() - def on_requirementsEdit_textChanged(self): - """ - Private slot handling changes of the requirements text. - """ - self.__requirementsEdited = True - - @pyqtSlot(QAbstractButton) - def on_buttonBox_clicked(self, button): - """ - Private slot called by a button of the button box clicked. - - @param button button that was clicked - @type QAbstractButton - """ - if button == self.buttonBox.button(QDialogButtonBox.Close): - self.close() - elif button == self.__refreshButton: - self.__refresh() - - def __refresh(self): - """ - Private slot to refresh the displayed list. - """ - if self.__requirementsEdited: - ok = E5MessageBox.yesNo( - self, - self.tr("Generate Requirements"), - self.tr("""The requirements were changed. Do you want""" - """ to overwrite these changes?""")) - else: - ok = True - if ok: - self.start() - - def start(self): - """ - Public method to start the command. - """ - self.requirementsEdit.clear() - self.__requirementsAvailable = False - - venvName = self.venvComboBox.currentText() - interpreter = self.__pip.getVirtualenvInterpreter(venvName) - if not interpreter: - return - - args = ["-m", "pip", "freeze"] - if self.localCheckBox.isChecked(): - args.append("--local") - if self.requirementsFilePicker.text(): - fileName = Utilities.toNativeSeparators( - self.requirementsFilePicker.text()) - if os.path.exists(fileName): - args.append("--requirement") - args.append(fileName) - - QApplication.setOverrideCursor(Qt.WaitCursor) - success, output = self.__pip.runProcess(args, interpreter) - - if success: - self.requirementsEdit.setPlainText(output) - self.__requirementsAvailable = True - else: - self.requirementsEdit.setPlainText( - self.tr("No output generated by 'pip freeze'.")) - - QApplication.restoreOverrideCursor() - self.__updateButtons() - - self.__requirementsEdited = False - - def __updateButtons(self): - """ - Private method to set the state of the various buttons. - """ - self.saveButton.setEnabled( - self.__requirementsAvailable and - bool(self.requirementsFilePicker.text()) - ) - self.saveToButton.setEnabled(self.__requirementsAvailable) - self.copyButton.setEnabled(self.__requirementsAvailable) - - aw = e5App().getObject("ViewManager").activeWindow() - if aw and self.__requirementsAvailable: - self.insertButton.setEnabled(True) - self.replaceAllButton.setEnabled(True) - self.replaceSelectionButton.setEnabled( - aw.hasSelectedText()) - else: - self.insertButton.setEnabled(False) - self.replaceAllButton.setEnabled(False) - self.replaceSelectionButton.setEnabled(False) - - def __writeToFile(self, fileName): - """ - Private method to write the requirements text to a file. - - @param fileName name of the file to write to - @type str - """ - if os.path.exists(fileName): - ok = E5MessageBox.warning( - self, - self.tr("Generate Requirements"), - self.tr("""The file <b>{0}</b> already exists. Do you want""" - """ to overwrite it?""").format(fileName)) - if not ok: - return - - try: - f = open(fileName, "w") - f.write(self.requirementsEdit.toPlainText()) - f.close() - except (OSError, IOError) as err: - E5MessageBox.critical( - self, - self.tr("Generate Requirements"), - self.tr("""<p>The requirements could not be written""" - """ to <b>{0}</b>.</p><p>Reason: {1}</p>""") - .format(fileName, str(err))) - - @pyqtSlot() - def on_saveButton_clicked(self): - """ - Private slot to save the requirements text to the requirements file. - """ - fileName = self.requirementsFilePicker.text() - self.__writeToFile(fileName) - - @pyqtSlot() - def on_saveToButton_clicked(self): - """ - Private slot to write the requirements text to a new file. - """ - fileName, selectedFilter = E5FileDialog.getSaveFileNameAndFilter( - self, - self.tr("Generate Requirements"), - os.path.expanduser("~"), - self.tr("Text Files (*.txt);;All Files (*)"), - None, - E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite) - ) - if fileName: - ext = os.path.splitext(fileName)[1] - if not ext: - ex = selectedFilter.split("(*")[1].split(")")[0] - if ex: - fileName += ex - self.__writeToFile(fileName) - - @pyqtSlot() - def on_copyButton_clicked(self): - """ - Private slot to copy the requirements text to the clipboard. - """ - txt = self.requirementsEdit.toPlainText() - cb = QApplication.clipboard() - cb.setText(txt) - - @pyqtSlot() - def on_insertButton_clicked(self): - """ - Private slot to insert the requirements text at the cursor position - of the current editor. - """ - aw = e5App().getObject("ViewManager").activeWindow() - if aw: - aw.beginUndoAction() - aw.insert(self.requirementsEdit.toPlainText()) - aw.endUndoAction() - - @pyqtSlot() - def on_replaceSelectionButton_clicked(self): - """ - Private slot to replace the selected text of the current editor - with the requirements text. - """ - aw = e5App().getObject("ViewManager").activeWindow() - if aw: - aw.beginUndoAction() - aw.replaceSelectedText(self.requirementsEdit.toPlainText()) - aw.endUndoAction() - - @pyqtSlot() - def on_replaceAllButton_clicked(self): - """ - Private slot to replace the text of the current editor with the - requirements text. - """ - aw = e5App().getObject("ViewManager").activeWindow() - if aw: - aw.setText(self.requirementsEdit.toPlainText())
--- a/Plugins/UiExtensionPlugins/PipInterface/PipFreezeDialog.ui Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,232 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>PipFreezeDialog</class> - <widget class="QDialog" name="PipFreezeDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>600</width> - <height>550</height> - </rect> - </property> - <property name="windowTitle"> - <string>Generate Requirements</string> - </property> - <property name="toolTip"> - <string>Replace the current selection with the requirements text</string> - </property> - <property name="sizeGripEnabled"> - <bool>true</bool> - </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> - </property> - <property name="text"> - <string>Local packages only</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Requirements File:</string> - </property> - </widget> - </item> - <item> - <widget class="E5PathPicker" name="requirementsFilePicker" native="true"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="focusPolicy"> - <enum>Qt::StrongFocus</enum> - </property> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="1"> - <widget class="QPushButton" name="saveButton"> - <property name="toolTip"> - <string>Press to save to the requirements file</string> - </property> - <property name="text"> - <string>Save</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QPushButton" name="saveToButton"> - <property name="toolTip"> - <string>Save to a new file</string> - </property> - <property name="text"> - <string>Save To</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QPushButton" name="copyButton"> - <property name="toolTip"> - <string>Copy the requirements text to the clipboard</string> - </property> - <property name="text"> - <string>Copy</string> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QPushButton" name="insertButton"> - <property name="toolTip"> - <string>Insert the requirements text at the cursor position</string> - </property> - <property name="text"> - <string>Insert</string> - </property> - </widget> - </item> - <item row="4" column="1"> - <widget class="QPushButton" name="replaceSelectionButton"> - <property name="text"> - <string>Replace Selection</string> - </property> - </widget> - </item> - <item row="5" column="1"> - <widget class="QPushButton" name="replaceAllButton"> - <property name="toolTip"> - <string>Replace all text with the requirements text</string> - </property> - <property name="text"> - <string>Replace All</string> - </property> - </widget> - </item> - <item row="6" column="1"> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="0" rowspan="7"> - <widget class="QPlainTextEdit" name="requirementsEdit"> - <property name="tabChangesFocus"> - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Close</set> - </property> - </widget> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>E5PathPicker</class> - <extends>QWidget</extends> - <header>E5Gui/E5PathPicker.h</header> - <container>1</container> - </customwidget> - </customwidgets> - <tabstops> - <tabstop>venvComboBox</tabstop> - <tabstop>localCheckBox</tabstop> - <tabstop>requirementsFilePicker</tabstop> - <tabstop>requirementsEdit</tabstop> - <tabstop>saveButton</tabstop> - <tabstop>saveToButton</tabstop> - <tabstop>copyButton</tabstop> - <tabstop>insertButton</tabstop> - <tabstop>replaceSelectionButton</tabstop> - <tabstop>replaceAllButton</tabstop> - </tabstops> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>PipFreezeDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>PipFreezeDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui>
--- a/Plugins/UiExtensionPlugins/PipInterface/PipListDialog.py Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,551 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Module implementing a dialog to list installed packages. -""" - -from __future__ import unicode_literals -try: - str = unicode # __IGNORE_EXCEPTION__ -except NameError: - pass - -import json - -from PyQt5.QtCore import pyqtSlot, Qt, QProcess, QTimer -from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton, \ - QApplication, QTreeWidgetItem, QHeaderView - -from E5Gui import E5MessageBox - -from .Ui_PipListDialog import Ui_PipListDialog - -import Preferences - - -class PipListDialog(QDialog, Ui_PipListDialog): - """ - Class implementing a dialog to list installed packages. - """ - CommandArguments = { - "list": ["list", "--format=json"], - "uptodate": ["list", "--uptodate", "--format=json"], - "outdated": ["list", "--outdated", "--format=json"], - } - - ShowProcessGeneralMode = 0 - ShowProcessClassifiersMode = 1 - ShowProcessEntryPointsMode = 2 - ShowProcessFilesListMode = 3 - - def __init__(self, pip, mode, indexUrl, title, parent=None): - """ - Constructor - - @param pip reference to the master object - @type Pip - @param mode list command mode (one of 'list', 'uptodate', 'outdated') - @type str - @param indexUrl URL of the pypi index - @type str - @param title title of the dialog - @type str - @param parent reference to the parent widget - @type QWidget - """ - assert mode in PipListDialog.CommandArguments - - super(PipListDialog, self).__init__(parent) - self.setupUi(self) - self.setWindowFlags(Qt.Window) - - self.setWindowTitle(title) - - self.__refreshButton = self.buttonBox.addButton( - self.tr("&Refresh"), QDialogButtonBox.ActionRole) - self.__refreshButton.setEnabled(False) - if mode == "outdated": - self.__upgradeButton = self.buttonBox.addButton( - self.tr("Up&grade"), QDialogButtonBox.ActionRole) - self.__upgradeButton.setEnabled(False) - self.__upgradeAllButton = self.buttonBox.addButton( - self.tr("Upgrade &All"), QDialogButtonBox.ActionRole) - self.__upgradeAllButton.setEnabled(False) - else: - self.__upgradeButton = None - self.__upgradeAllButton = None - self.__uninstallButton = self.buttonBox.addButton( - self.tr("&Uninstall"), QDialogButtonBox.ActionRole) - self.__uninstallButton.setEnabled(False) - - self.__pip = pip - self.__mode = mode - self.__ioEncoding = Preferences.getSystem("IOEncoding") - self.__indexUrl = indexUrl - self.__errors = "" - self.__output = [] - - self.__nothingStrings = { - "list": self.tr("Nothing to show"), - "uptodate": self.tr("All packages outdated"), - "outdated": self.tr("All packages up-to-date"), - } - - self.venvComboBox.addItem(self.__pip.getDefaultEnvironmentString()) - projectVenv = self.__pip.getProjectEnvironmentString() - if projectVenv: - self.venvComboBox.addItem(projectVenv) - self.venvComboBox.addItems(self.__pip.getVirtualenvNames()) - - if mode == "list": - self.infoLabel.setText(self.tr("Installed Packages:")) - self.packageList.setHeaderLabels([ - self.tr("Package"), - self.tr("Version"), - ]) - elif mode == "uptodate": - self.infoLabel.setText(self.tr("Up-to-date Packages:")) - self.packageList.setHeaderLabels([ - self.tr("Package"), - self.tr("Version"), - ]) - elif mode == "outdated": - self.infoLabel.setText(self.tr("Outdated Packages:")) - self.packageList.setHeaderLabels([ - self.tr("Package"), - self.tr("Current Version"), - self.tr("Latest Version"), - self.tr("Package Type"), - ]) - - self.packageList.header().setSortIndicator(0, Qt.AscendingOrder) - - self.__infoLabels = { - "name": self.tr("Name:"), - "version": self.tr("Version:"), - "location": self.tr("Location:"), - "requires": self.tr("Requires:"), - "summary": self.tr("Summary:"), - "home-page": self.tr("Homepage:"), - "author": self.tr("Author:"), - "author-email": self.tr("Author Email:"), - "license": self.tr("License:"), - "metadata-version": self.tr("Metadata Version:"), - "installer": self.tr("Installer:"), - "classifiers": self.tr("Classifiers:"), - "entry-points": self.tr("Entry Points:"), - "files": self.tr("Files:"), - } - self.infoWidget.setHeaderLabels(["Key", "Value"]) - - self.process = QProcess() - self.process.finished.connect(self.__procFinished) - self.process.readyReadStandardOutput.connect(self.__readStdout) - self.process.readyReadStandardError.connect(self.__readStderr) - - self.show() - QApplication.processEvents() - - def __stopProcess(self): - """ - Private slot to stop the running process. - """ - if self.process.state() != QProcess.NotRunning: - self.process.terminate() - QTimer.singleShot(2000, self.process.kill) - self.process.waitForFinished(3000) - - QApplication.restoreOverrideCursor() - - def closeEvent(self, e): - """ - Protected slot implementing a close event handler. - - @param e close event - @type QCloseEvent - """ - self.__stopProcess() - e.accept() - - def __finish(self): - """ - Private slot called when the process finished or the user pressed - the cancel button. - """ - self.__stopProcess() - - self.__processOutput() - - self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) - self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) - self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) - self.buttonBox.button(QDialogButtonBox.Close).setFocus( - Qt.OtherFocusReason) - self.__refreshButton.setEnabled(True) - - if self.packageList.topLevelItemCount() == 0: - QTreeWidgetItem(self.packageList, - [self.__nothingStrings[self.__mode]]) - if self.__errors and not self.__errors.startswith("DEPRECATION"): - E5MessageBox.critical( - self, - self.windowTitle(), - self.tr("""<p>The command failed.</p>""" - """<p>Reason: {0}</p>""").format( - self.__errors.replace("\r\n", "<br/>") - .replace("\n", "<br/>").replace("\r", "<br/>") - .replace(" ", " "))) - if self.__upgradeAllButton is not None: - self.__upgradeAllButton.setEnabled(False) - else: - if self.__upgradeAllButton is not None: - self.__upgradeAllButton.setEnabled(True) - - self.packageList.sortItems( - 0, - self.packageList.header().sortIndicatorOrder()) - self.packageList.header().resizeSections( - QHeaderView.ResizeToContents) - self.packageList.header().setStretchLastSection(True) - - @pyqtSlot(QAbstractButton) - def on_buttonBox_clicked(self, button): - """ - Private slot called by a button of the button box clicked. - - @param button button that was clicked - @type QAbstractButton - """ - if button == self.buttonBox.button(QDialogButtonBox.Close): - self.close() - elif button == self.buttonBox.button(QDialogButtonBox.Cancel): - self.__finish() - elif button == self.__refreshButton: - self.__refresh() - elif button == self.__upgradeButton: - self.__upgradePackages() - elif button == self.__upgradeAllButton: - self.__upgradeAllPackages() - elif button == self.__uninstallButton: - self.__uninstallPackages() - - def __procFinished(self, exitCode, exitStatus): - """ - Private slot connected to the finished signal. - - @param exitCode exit code of the process - @type int - @param exitStatus exit status of the process - @type QProcess.ExitStatus - """ - self.__finish() - - def __refresh(self): - """ - Private slot to refresh the displayed list. - """ - self.__stopProcess() - self.start() - - def start(self): - """ - Public method to start the command. - """ - self.packageList.clear() - self.__errors = "" - self.__output = [] - - self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) - self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True) - self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) - self.__refreshButton.setEnabled(False) - if self.__upgradeAllButton is not None: - self.__upgradeAllButton.setEnabled(False) - QApplication.processEvents() - - QApplication.setOverrideCursor(Qt.WaitCursor) - QApplication.processEvents() - - venvName = self.venvComboBox.currentText() - interpreter = self.__pip.getVirtualenvInterpreter(venvName) - if not interpreter: - return - - args = ["-m", "pip"] + PipListDialog.CommandArguments[self.__mode] - if self.localCheckBox.isChecked(): - args.append("--local") - if self.notRequiredCheckBox.isChecked(): - args.append("--not-required") - if self.userCheckBox.isChecked(): - args.append("--user") - - if self.__indexUrl: - args.append("--index-url") - args.append(self.__indexUrl + "/simple") - - self.process.start(interpreter, args) - procStarted = self.process.waitForStarted(5000) - if not procStarted: - self.buttonBox.setFocus() - self.__stopProcess() - E5MessageBox.critical( - self, - self.tr('Process Generation Error'), - self.tr( - 'The process {0} could not be started.' - ).format(interpreter)) - self.__finish() - - def __processOutput(self): - """ - Private method to process the captured output. - """ - if self.__output: - try: - packageData = json.loads("\n".join(self.__output)) - for package in packageData: - data = [ - package["name"], - package["version"], - ] - if self.__mode == "outdated": - data.extend([ - package["latest_version"], - package["latest_filetype"], - ]) - QTreeWidgetItem(self.packageList, data) - except ValueError as err: - self.__errors += str(err) + "\n" - self.__errors += "received output:\n" - self.__errors += "\n".join(self.__output) - - def __readStdout(self): - """ - Private slot to handle the readyReadStandardOutput signal. - - It reads the output of the process, formats it and inserts it into - the contents pane. - """ - self.process.setReadChannel(QProcess.StandardOutput) - - while self.process.canReadLine(): - line = str(self.process.readLine(), self.__ioEncoding, - 'replace').strip() - self.__output.append(line) - - def __readStderr(self): - """ - Private slot to handle the readyReadStandardError signal. - - It reads the error output of the process and inserts it into the - error pane. - """ - self.__errors += str(self.process.readAllStandardError(), - self.__ioEncoding, 'replace') - - @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): - """ - Private slot handling the switching of the local mode. - - @param checked state of the local check box - @type bool - """ - self.__refresh() - - @pyqtSlot(bool) - def on_notRequiredCheckBox_clicked(self, checked): - """ - Private slot handling the switching of the 'not required' mode. - - @param checked state of the 'not required' check box - @type bool - """ - self.__refresh() - - @pyqtSlot(bool) - def on_userCheckBox_clicked(self, checked): - """ - Private slot handling the switching of the 'user-site' mode. - - @param checked state of the 'user-site' check box - @type bool - """ - self.__refresh() - - @pyqtSlot() - def on_packageList_itemSelectionChanged(self): - """ - Private slot handling the selection of a package. - """ - self.infoWidget.clear() - - if len(self.packageList.selectedItems()) == 1: - itm = self.packageList.selectedItems()[0] - - environment = self.venvComboBox.currentText() - interpreter = self.__pip.getVirtualenvInterpreter(environment) - if not interpreter: - return - - QApplication.setOverrideCursor(Qt.WaitCursor) - - args = ["-m", "pip", "show"] - if self.verboseCheckBox.isChecked(): - args.append("--verbose") - if self.installedFilesCheckBox.isChecked(): - args.append("--files") - args.append(itm.text(0)) - success, output = self.__pip.runProcess(args, interpreter) - - if success and output: - mode = PipListDialog.ShowProcessGeneralMode - for line in output.splitlines(): - line = line.rstrip() - if line != "---": - if mode != PipListDialog.ShowProcessGeneralMode: - if line[0] == " ": - QTreeWidgetItem( - self.infoWidget, - [" ", line.strip()]) - else: - mode = PipListDialog.ShowProcessGeneralMode - if mode == PipListDialog.ShowProcessGeneralMode: - try: - label, info = line.split(": ", 1) - except ValueError: - label = line[:-1] - info = "" - label = label.lower() - if label in self.__infoLabels: - QTreeWidgetItem( - self.infoWidget, - [self.__infoLabels[label], info]) - if label == "files": - mode = PipListDialog.ShowProcessFilesListMode - elif label == "classifiers": - mode = PipListDialog.ShowProcessClassifiersMode - elif label == "entry-points": - mode = PipListDialog.ShowProcessEntryPointsMode - self.infoWidget.scrollToTop() - - header = self.infoWidget.header() - header.setStretchLastSection(False) - header.resizeSections(QHeaderView.ResizeToContents) - if header.sectionSize(0) + header.sectionSize(1) < header.width(): - header.setStretchLastSection(True) - - QApplication.restoreOverrideCursor() - - enable = (len(self.packageList.selectedItems()) > 1 or - (len(self.packageList.selectedItems()) == 1 and - self.packageList.selectedItems()[0].text(0) not in - self.__nothingStrings.values())) - self.__upgradeButton and self.__upgradeButton.setEnabled(enable) - self.__uninstallButton.setEnabled(enable) - - @pyqtSlot(bool) - def on_verboseCheckBox_clicked(self, checked): - """ - Private slot to handle a change of the verbose package information - checkbox. - - @param checked state of the checkbox - @type bool - """ - self.on_packageList_itemSelectionChanged() - - @pyqtSlot(bool) - def on_installedFilesCheckBox_clicked(self, checked): - """ - Private slot to handle a change of the installed files information - checkbox. - - @param checked state of the checkbox - @type bool - """ - self.on_packageList_itemSelectionChanged() - - def __upgradePackages(self): - """ - Private slot to upgrade the selected packages. - """ - packages = [] - for itm in self.packageList.selectedItems(): - packages.append(itm.text(0)) - - if packages: - if "pip" in packages: - self.__upgradePip() - else: - self.__executeUpgradePackages(packages) - - def __upgradeAllPackages(self): - """ - Private slot to upgrade all listed packages. - """ - packages = [] - for index in range(self.packageList.topLevelItemCount()): - itm = self.packageList.topLevelItem(index) - packages.append(itm.text(0)) - - if packages: - if "pip" in packages: - self.__upgradePip() - else: - self.__executeUpgradePackages(packages) - - def __upgradePip(self): - """ - Private slot to upgrade pip itself. - """ - res = self.__pip.upgradePip( - venvName=self.venvComboBox.currentText(), - userSite=self.userCheckBox.isChecked()) - if res: - self.__refresh() - - def __executeUpgradePackages(self, packages): - """ - Private method to execute the pip upgrade command. - - @param packages list of package names to be upgraded - @type list of str - """ - res = self.__pip.upgradePackages( - packages, venvName=self.venvComboBox.currentText(), - userSite=self.userCheckBox.isChecked()) - if res: - self.activateWindow() - self.raise_() - self.__refresh() - - def __uninstallPackages(self): - """ - Private slot to uninstall the selected packages. - """ - packages = [] - for itm in self.packageList.selectedItems(): - packages.append(itm.text(0)) - - if packages: - res = self.__pip.uninstallPackages( - packages, - venvName=self.venvComboBox.currentText()) - if res: - self.activateWindow() - self.raise_() - self.__refresh()
--- a/Plugins/UiExtensionPlugins/PipInterface/PipListDialog.ui Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,253 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>PipListDialog</class> - <widget class="QDialog" name="PipListDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>600</width> - <height>650</height> - </rect> - </property> - <property name="windowTitle"> - <string>Package List</string> - </property> - <property name="sizeGripEnabled"> - <bool>true</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <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> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="infoLabel"> - <property name="text"> - <string notr="true">TextLabel</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="2"> - <widget class="QCheckBox" name="localCheckBox"> - <property name="toolTip"> - <string>Select to show only locally-installed packages</string> - </property> - <property name="text"> - <string>Local packages only</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="0" column="3"> - <widget class="QCheckBox" name="notRequiredCheckBox"> - <property name="toolTip"> - <string>Select to list packages that are not dependencies of installed packages</string> - </property> - <property name="text"> - <string>Not required Packages</string> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QCheckBox" name="userCheckBox"> - <property name="toolTip"> - <string>Select to show only packages installed to the user-site</string> - </property> - <property name="text"> - <string>User-Site only</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QSplitter" name="splitter"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="childrenCollapsible"> - <bool>false</bool> - </property> - <widget class="QTreeWidget" name="packageList"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>3</verstretch> - </sizepolicy> - </property> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="selectionMode"> - <enum>QAbstractItemView::ExtendedSelection</enum> - </property> - <property name="rootIsDecorated"> - <bool>false</bool> - </property> - <property name="itemsExpandable"> - <bool>false</bool> - </property> - <property name="sortingEnabled"> - <bool>true</bool> - </property> - <column> - <property name="text"> - <string notr="true">1</string> - </property> - </column> - </widget> - <widget class="QWidget" name="widget" native="true"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QCheckBox" name="verboseCheckBox"> - <property name="toolTip"> - <string>Select to show verbose package information</string> - </property> - <property name="text"> - <string>Verbose Package Information</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="installedFilesCheckBox"> - <property name="toolTip"> - <string>Select to show information about installed files</string> - </property> - <property name="text"> - <string>Installed Files Information</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QTreeWidget" name="infoWidget"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="rootIsDecorated"> - <bool>false</bool> - </property> - <property name="itemsExpandable"> - <bool>false</bool> - </property> - <property name="allColumnsShowFocus"> - <bool>true</bool> - </property> - <property name="wordWrap"> - <bool>true</bool> - </property> - <property name="columnCount"> - <number>2</number> - </property> - <attribute name="headerVisible"> - <bool>false</bool> - </attribute> - <attribute name="headerStretchLastSection"> - <bool>false</bool> - </attribute> - <column> - <property name="text"> - <string notr="true">1</string> - </property> - </column> - <column> - <property name="text"> - <string notr="true">2</string> - </property> - </column> - </widget> - </item> - </layout> - </widget> - </widget> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Close</set> - </property> - </widget> - </item> - </layout> - </widget> - <tabstops> - <tabstop>venvComboBox</tabstop> - <tabstop>localCheckBox</tabstop> - <tabstop>notRequiredCheckBox</tabstop> - <tabstop>userCheckBox</tabstop> - <tabstop>packageList</tabstop> - <tabstop>verboseCheckBox</tabstop> - <tabstop>installedFilesCheckBox</tabstop> - <tabstop>infoWidget</tabstop> - </tabstops> - <resources/> - <connections/> -</ui>
--- a/Plugins/UiExtensionPlugins/PipInterface/PipPackageDetailsDialog.py Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,229 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Module implementing a dialog to show details about a package. -""" - -from __future__ import unicode_literals -try: - basestring # __IGNORE_WARNING__ -except NameError: - basestring = str - -from PyQt5.QtCore import Qt, QLocale -from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QTreeWidgetItem, \ - QLabel, QHeaderView - -from .Ui_PipPackageDetailsDialog import Ui_PipPackageDetailsDialog - - -class PipPackageDetailsDialog(QDialog, Ui_PipPackageDetailsDialog): - """ - Class implementing a dialog to show details about a package. - """ - def __init__(self, detailsData, downloadsData, parent=None): - """ - Constructor - - @param detailsData package details - @type dict - @param downloadsData downloads information - @type dict - @param parent reference to the parent widget - @type QWidget - """ - super(PipPackageDetailsDialog, self).__init__(parent) - self.setupUi(self) - self.setWindowFlags(Qt.Window) - - self.__locale = QLocale() - self.__packageTypeMap = { - "sdist": self.tr("Source"), - "bdist_wheel": self.tr("Python Wheel"), - "bdist_egg": self.tr("Python Egg"), - "bdist_wininst": self.tr("MS Windows Installer"), - "bdist_msi": self.tr("MS Windows Installer"), - "bdist_rpm": self.tr("Unix Installer"), - "bdist_deb": self.tr("Unix Installer"), - "bdist_dumb": self.tr("Archive"), - } - - self.__populateDetails(detailsData) - self.__populateDownloadUrls(downloadsData) - self.__populateRequiresProvides(detailsData) - - def __populateDetails(self, detailsData): - """ - Private method to populate the details tab. - - @param detailsData package details - @type dict - """ - self.packageNameLabel.setText( - "<h1>{0} {1}</h1".format(self.__sanitize(detailsData["name"]), - self.__sanitize(detailsData["version"]))) - self.summaryLabel.setText( - self.__sanitize(detailsData["summary"][:240])) - self.descriptionEdit.setPlainText( - self.__sanitize(detailsData["description"])) - self.authorLabel.setText(self.__sanitize(detailsData["author"])) - self.authorEmailLabel.setText( - '<a href="mailto:{0}">{0}</a>'.format( - self.__sanitize(detailsData["author_email"]))) - self.licenseLabel.setText(self.__sanitize(detailsData["license"])) - self.platformLabel.setText(self.__sanitize(detailsData["platform"])) - self.homePageLabel.setText( - '<a href="{0}">{0}</a>'.format( - self.__sanitize(detailsData["home_page"], forUrl=True))) - self.packageUrlLabel.setText( - '<a href="{0}">{0}</a>'.format( - self.__sanitize(detailsData["package_url"], forUrl=True))) - self.releaseUrlLabel.setText( - '<a href="{0}">{0}</a>'.format( - self.__sanitize(detailsData["release_url"], forUrl=True))) - self.docsUrlLabel.setText( - '<a href="{0}">{0}</a>'.format( - self.__sanitize(detailsData["docs_url"], forUrl=True))) - self.downloadsDayLabel.setText(self.__locale.toString( - detailsData["downloads"]["last_day"])) - self.downloadsWeekLabel.setText(self.__locale.toString( - detailsData["downloads"]["last_week"])) - self.downloadsMonthLabel.setText(self.__locale.toString( - detailsData["downloads"]["last_month"])) - self.classifiersList.addItems(detailsData["classifiers"]) - - self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) - self.buttonBox.button(QDialogButtonBox.Close).setFocus( - Qt.OtherFocusReason) - - def __populateDownloadUrls(self, downloadsData): - """ - Private method to populate the download URLs tab. - - @param downloadsData downloads information - @type dict - """ - index = self.infoWidget.indexOf(self.urls) - if downloadsData: - self.infoWidget.setTabEnabled(index, True) - for download in downloadsData: - itm = QTreeWidgetItem(self.downloadUrlsList, [ - "", - self.__packageTypeMap[download["packagetype"]] - if download["packagetype"] in self.__packageTypeMap - else "", - download["python_version"] - if download["python_version"] != "source" - else "", - self.__locale.toString(download["downloads"]), - self.__formatUploadDate(download["upload_time"]), - self.__formatSize(download["size"]), - ]) - if download["has_sig"]: - pgpLink = ' (<a href="{0}">pgp</a>)'.format( - download["url"] + ".asc") - else: - pgpLink = "" - urlLabel = QLabel('<a href="{0}#md5={2}">{1}</a>{3}'.format( - download["url"], download["filename"], - download["md5_digest"], pgpLink)) - urlLabel.setTextInteractionFlags(Qt.LinksAccessibleByMouse) - urlLabel.setOpenExternalLinks(True) - self.downloadUrlsList.setItemWidget(itm, 0, urlLabel) - header = self.downloadUrlsList.header() - header.resizeSections(QHeaderView.ResizeToContents) - else: - self.infoWidget.setTabEnabled(index, False) - - def __populateRequiresProvides(self, detailsData): - """ - Private method to populate the requires/provides tab. - - @param detailsData package details - @type dict - """ - populatedItems = 0 - - if "requires" in detailsData: - self.requiredPackagesList.addItems(detailsData["requires"]) - populatedItems += len(detailsData["requires"]) - if "requires_dist" in detailsData: - self.requiredDistributionsList.addItems( - detailsData["requires_dist"]) - populatedItems += len(detailsData["requires_dist"]) - if "provides" in detailsData: - self.providedPackagesList.addItems(detailsData["provides"]) - populatedItems += len(detailsData["provides"]) - if "provides_dist" in detailsData: - self.providedDistributionsList.addItems( - detailsData["provides_dist"]) - populatedItems += len(detailsData["provides_dist"]) - - index = self.infoWidget.indexOf(self.requires) - self.infoWidget.setTabEnabled(index, populatedItems > 0) - - def __sanitize(self, text, forUrl=False): - """ - Private method to clean-up the given text. - - @param text raw text - @type str - @param forUrl flag indicating to sanitize an URL text - @type bool - @return processed text - @rtype str - """ - if text == "UNKNOWN": - text = "" - elif text == "any": - text = self.tr("any") - elif text is None: - text = "" - if forUrl: - if not isinstance(text, basestring) or \ - not text.startswith(("http://", "https://", "ftp://")): - # ignore if the schema is not one of the listed ones - text = "" - - return text - - def __formatUploadDate(self, datetime): - """ - Private method to format the upload date. - - @param datetime upload date and time - @type xmlrpc.DateTime or str - @return formatted date string - @rtype str - """ - if isinstance(datetime, str): - return datetime.split("T")[0] - else: - date = datetime.value.split("T")[0] - return "{0}-{1}-{2}".format(date[:4], date[4:6], date[6:]) - - def __formatSize(self, size): - """ - Private slot to format the size. - - @param size size to be formatted - @type int - @return formatted size - @rtype str - """ - unit = "" - if size < 1024: - unit = self.tr("B") - elif size < 1024 * 1024: - size /= 1024 - unit = self.tr("KB") - elif size < 1024 * 1024 * 1024: - size /= 1024 * 1024 - unit = self.tr("MB") - else: - size /= 1024 * 1024 * 1024 - unit = self.tr("GB") - return self.tr("{0:.1f} {1}", "value, unit").format(size, unit)
--- a/Plugins/UiExtensionPlugins/PipInterface/PipPackageDetailsDialog.ui Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,517 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>PipPackageDetailsDialog</class> - <widget class="QDialog" name="PipPackageDetailsDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>800</width> - <height>700</height> - </rect> - </property> - <property name="windowTitle"> - <string>Package Details</string> - </property> - <property name="sizeGripEnabled"> - <bool>true</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QLabel" name="packageNameLabel"/> - </item> - <item> - <widget class="QTabWidget" name="infoWidget"> - <property name="currentIndex"> - <number>0</number> - </property> - <widget class="QWidget" name="details"> - <attribute name="title"> - <string>Details</string> - </attribute> - <attribute name="toolTip"> - <string>Lists package informations</string> - </attribute> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="1"> - <widget class="QLabel" name="summaryLabel"> - <property name="wordWrap"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_3"> - <property name="text"> - <string>Description:</string> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QLabel" name="authorEmailLabel"> - <property name="openExternalLinks"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QPlainTextEdit" name="descriptionEdit"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>5</verstretch> - </sizepolicy> - </property> - <property name="tabChangesFocus"> - <bool>true</bool> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_4"> - <property name="text"> - <string>Author:</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QLabel" name="authorLabel"/> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_5"> - <property name="text"> - <string>Author Email:</string> - </property> - </widget> - </item> - <item row="7" column="1"> - <widget class="QLabel" name="packageUrlLabel"> - <property name="openExternalLinks"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="4" column="0"> - <widget class="QLabel" name="label_6"> - <property name="text"> - <string>License:</string> - </property> - </widget> - </item> - <item row="4" column="1"> - <widget class="QLabel" name="licenseLabel"/> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Summary:</string> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> - </property> - </widget> - </item> - <item row="5" column="0"> - <widget class="QLabel" name="label_7"> - <property name="text"> - <string>Platform:</string> - </property> - </widget> - </item> - <item row="5" column="1"> - <widget class="QLabel" name="platformLabel"/> - </item> - <item row="6" column="0"> - <widget class="QLabel" name="label_8"> - <property name="text"> - <string>Home Page:</string> - </property> - </widget> - </item> - <item row="6" column="1"> - <widget class="QLabel" name="homePageLabel"> - <property name="openExternalLinks"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="7" column="0"> - <widget class="QLabel" name="label_9"> - <property name="text"> - <string>Package URL:</string> - </property> - </widget> - </item> - <item row="8" column="0"> - <widget class="QLabel" name="label_10"> - <property name="text"> - <string>Release URL:</string> - </property> - </widget> - </item> - <item row="8" column="1"> - <widget class="QLabel" name="releaseUrlLabel"> - <property name="openExternalLinks"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="9" column="0"> - <widget class="QLabel" name="label_11"> - <property name="text"> - <string>Documentation URL:</string> - </property> - </widget> - </item> - <item row="9" column="1"> - <widget class="QLabel" name="docsUrlLabel"> - <property name="openExternalLinks"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="10" column="0"> - <widget class="QLabel" name="label_12"> - <property name="text"> - <string>Downloads:</string> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> - </property> - </widget> - </item> - <item row="10" column="1"> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="label_13"> - <property name="text"> - <string>Last Day:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLabel" name="downloadsDayLabel"> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="0" column="2"> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_14"> - <property name="text"> - <string>Last Week:</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLabel" name="downloadsWeekLabel"> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_15"> - <property name="text"> - <string>Last Month:</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QLabel" name="downloadsMonthLabel"> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - </layout> - </item> - <item row="11" column="0"> - <widget class="QLabel" name="label_16"> - <property name="text"> - <string>Classifiers:</string> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> - </property> - </widget> - </item> - <item row="11" column="1"> - <widget class="QListWidget" name="classifiersList"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="selectionMode"> - <enum>QAbstractItemView::NoSelection</enum> - </property> - <property name="sortingEnabled"> - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="QWidget" name="urls"> - <attribute name="title"> - <string>Download URLs</string> - </attribute> - <attribute name="toolTip"> - <string>Lists the download URLs</string> - </attribute> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <widget class="QTreeWidget" name="downloadUrlsList"> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="selectionMode"> - <enum>QAbstractItemView::NoSelection</enum> - </property> - <property name="rootIsDecorated"> - <bool>false</bool> - </property> - <property name="itemsExpandable"> - <bool>false</bool> - </property> - <attribute name="headerStretchLastSection"> - <bool>false</bool> - </attribute> - <column> - <property name="text"> - <string>File</string> - </property> - </column> - <column> - <property name="text"> - <string>Type</string> - </property> - </column> - <column> - <property name="text"> - <string>Py Version</string> - </property> - </column> - <column> - <property name="text"> - <string>Downloads</string> - </property> - </column> - <column> - <property name="text"> - <string>Uploaded on</string> - </property> - </column> - <column> - <property name="text"> - <string>Size</string> - </property> - </column> - </widget> - </item> - </layout> - </widget> - <widget class="QWidget" name="requires"> - <attribute name="title"> - <string>Requires/Provides</string> - </attribute> - <attribute name="toolTip"> - <string>Lists required and provided packages</string> - </attribute> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <item> - <widget class="QGroupBox" name="groupBox"> - <property name="title"> - <string>Requires</string> - </property> - <layout class="QGridLayout" name="gridLayout_4"> - <item row="0" column="0"> - <widget class="QLabel" name="label_17"> - <property name="text"> - <string>Required Packages:</string> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QListWidget" name="requiredPackagesList"> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="selectionMode"> - <enum>QAbstractItemView::NoSelection</enum> - </property> - <property name="sortingEnabled"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_18"> - <property name="text"> - <string>Required Distributions:</string> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QListWidget" name="requiredDistributionsList"> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="selectionMode"> - <enum>QAbstractItemView::NoSelection</enum> - </property> - <property name="sortingEnabled"> - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="groupBox_2"> - <property name="title"> - <string>Provides</string> - </property> - <layout class="QGridLayout" name="gridLayout_3"> - <item row="0" column="0"> - <widget class="QLabel" name="label_20"> - <property name="text"> - <string>Provided Packages:</string> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QListWidget" name="providedPackagesList"> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="selectionMode"> - <enum>QAbstractItemView::NoSelection</enum> - </property> - <property name="sortingEnabled"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_19"> - <property name="text"> - <string>Provided Distributions:</string> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QListWidget" name="providedDistributionsList"> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="selectionMode"> - <enum>QAbstractItemView::NoSelection</enum> - </property> - <property name="sortingEnabled"> - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - </widget> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Close</set> - </property> - </widget> - </item> - </layout> - </widget> - <tabstops> - <tabstop>infoWidget</tabstop> - <tabstop>descriptionEdit</tabstop> - <tabstop>classifiersList</tabstop> - <tabstop>downloadUrlsList</tabstop> - <tabstop>requiredPackagesList</tabstop> - <tabstop>requiredDistributionsList</tabstop> - <tabstop>providedPackagesList</tabstop> - <tabstop>providedDistributionsList</tabstop> - </tabstops> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>PipPackageDetailsDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>PipPackageDetailsDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui>
--- a/Plugins/UiExtensionPlugins/PipInterface/PipPackagesInputDialog.py Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Module implementing a dialog to enter package specifications. -""" - -from __future__ import unicode_literals - -from PyQt5.QtCore import pyqtSlot -from PyQt5.QtWidgets import QDialog, QDialogButtonBox - -from .Ui_PipPackagesInputDialog import Ui_PipPackagesInputDialog - - -class PipPackagesInputDialog(QDialog, Ui_PipPackagesInputDialog): - """ - Class implementing a dialog to enter package specifications. - """ - def __init__(self, pip, title, install=True, parent=None): - """ - Constructor - - @param pip reference to the pip object - @type Pip - @param title dialog title - @type str - @param install flag indicating an install action - @type bool - @param parent reference to the parent widget - @type QWidget - """ - super(PipPackagesInputDialog, self).__init__(parent) - self.setupUi(self) - - self.setWindowTitle(title) - - self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) - - self.venvComboBox.addItem(pip.getDefaultEnvironmentString()) - projectVenv = pip.getProjectEnvironmentString() - if projectVenv: - self.venvComboBox.addItem(projectVenv) - self.venvComboBox.addItems(pip.getVirtualenvNames()) - - self.userCheckBox.setVisible(install) - - msh = self.minimumSizeHint() - self.resize(max(self.width(), msh.width()), msh.height()) - - @pyqtSlot(str) - def on_packagesEdit_textChanged(self, txt): - """ - Private slot handling entering package names. - - @param txt name of the requirements file - @type str - """ - self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(bool(txt)) - - def getData(self): - """ - Public method to get the entered data. - - @return tuple with the environment name, the list of package - specifications and a flag indicating to install to the user - install directory - @rtype tuple of (str, list of str, bool) - """ - packages = [p.strip() for p in self.packagesEdit.text().split()] - - return ( - self.venvComboBox.currentText(), - packages, - self.userCheckBox.isChecked() - )
--- a/Plugins/UiExtensionPlugins/PipInterface/PipPackagesInputDialog.ui Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>PipPackagesInputDialog</class> - <widget class="QDialog" name="PipPackagesInputDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>600</width> - <height>186</height> - </rect> - </property> - <property name="windowTitle"> - <string>Packages </string> - </property> - <property name="sizeGripEnabled"> - <bool>true</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Virtual Environment:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="venvComboBox"> - <property name="toolTip"> - <string>Select the virtual environment to be used</string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>Package Specifications (separated by whitespace):</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="packagesEdit"/> - </item> - <item> - <widget class="QCheckBox" name="userCheckBox"> - <property name="toolTip"> - <string>Select to install to the Python user install directory</string> - </property> - <property name="text"> - <string>Install into User Directory</string> - </property> - </widget> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>PipPackagesInputDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>PipPackagesInputDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui>
--- a/Plugins/UiExtensionPlugins/PipInterface/PipSearchDialog.py Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,465 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Module implementing a dialog to search PyPI. -""" - -from __future__ import unicode_literals - -import textwrap - -from PyQt5.QtCore import pyqtSlot, Qt, QEventLoop, QRegExp -from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton, \ - QApplication, QTreeWidgetItem, QHeaderView, QInputDialog - -from E5Gui import E5MessageBox -try: - from E5Network.E5XmlRpcClient import E5XmlRpcClient -except ImportError: - from .E5XmlRpcClient import E5XmlRpcClient - -from .Ui_PipSearchDialog import Ui_PipSearchDialog - - -class PipSearchDialog(QDialog, Ui_PipSearchDialog): - """ - Class implementing a dialog to search PyPI. - """ - VersionRole = Qt.UserRole + 1 - - Stopwords = { - "a", "and", "are", "as", "at", "be", "but", "by", - "for", "if", "in", "into", "is", "it", - "no", "not", "of", "on", "or", "such", - "that", "the", "their", "then", "there", "these", - "they", "this", "to", "was", "will", - } - - def __init__(self, pip, indexUrl, parent=None): - """ - Constructor - - @param pip reference to the master object - @type Pip - @param indexUrl URL of XML RPC interface to the pypi index - @type str - @param parent reference to the parent widget - @type QWidget - """ - super(PipSearchDialog, self).__init__(parent) - self.setupUi(self) - self.setWindowFlags(Qt.Window) - - self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) - - self.__installButton = self.buttonBox.addButton( - self.tr("&Install"), QDialogButtonBox.ActionRole) - self.__installButton.setEnabled(False) - - self.__installUserButton = self.buttonBox.addButton( - self.tr("Install to &User-Site"), QDialogButtonBox.ActionRole) - self.__installUserButton.setEnabled(False) - - self.__showDetailsButton = self.buttonBox.addButton( - self.tr("&Show Details..."), QDialogButtonBox.ActionRole) - self.__showDetailsButton.setEnabled(False) - - self.__pip = pip - self.__client = E5XmlRpcClient(indexUrl, self) - - self.venvComboBox.addItem(self.__pip.getDefaultEnvironmentString()) - projectVenv = self.__pip.getProjectEnvironmentString() - if projectVenv: - self.venvComboBox.addItem(projectVenv) - self.venvComboBox.addItems(self.__pip.getVirtualenvNames()) - - self.searchEdit.setFocus(Qt.OtherFocusReason) - - self.__canceled = False - self.__detailsData = {} - self.__query = [] - - self.__packageDetailsDialog = None - - def closeEvent(self, e): - """ - Protected slot implementing a close event handler. - - @param e close event - @type QCloseEvent - """ - QApplication.restoreOverrideCursor() - - if self.__packageDetailsDialog is not None: - self.__packageDetailsDialog.close() - - e.accept() - - @pyqtSlot(str) - def on_searchEdit_textChanged(self, txt): - """ - Private slot handling a change of the search term. - - @param txt search term - @type str - """ - self.searchButton.setEnabled(bool(txt)) - - @pyqtSlot() - def on_searchButton_clicked(self): - """ - Private slot handling a press of the search button. - """ - self.__search() - - @pyqtSlot() - def on_resultList_itemSelectionChanged(self): - """ - Private slot handling changes of the selection. - """ - self.__installButton.setEnabled( - len(self.resultList.selectedItems()) > 0) - self.__installUserButton.setEnabled( - len(self.resultList.selectedItems()) > 0) - self.__showDetailsButton.setEnabled( - len(self.resultList.selectedItems()) == 1) - - @pyqtSlot(QAbstractButton) - def on_buttonBox_clicked(self, button): - """ - Private slot called by a button of the button box clicked. - - @param button button that was clicked - @type QAbstractButton - """ - if button == self.buttonBox.button(QDialogButtonBox.Close): - self.close() - elif button == self.buttonBox.button(QDialogButtonBox.Cancel): - self.__client.abort() - self.__canceled = True - elif button == self.__installButton: - self.__install() - elif button == self.__installUserButton: - self.__install(userSite=True) - elif button == self.__showDetailsButton: - self.__showDetails() - - def __search(self): - """ - Private method to perform the search. - """ - self.resultList.clear() - self.infoLabel.clear() - - self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) - self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True) - self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) - self.searchButton.setEnabled(False) - QApplication.processEvents(QEventLoop.ExcludeUserInputEvents) - - QApplication.setOverrideCursor(Qt.WaitCursor) - QApplication.processEvents(QEventLoop.ExcludeUserInputEvents) - - self.__canceled = False - - self.__query = [term for term in self.searchEdit.text().strip().split() - if term not in PipSearchDialog.Stopwords] - self.__client.call( - "search", - ({"name": self.__query, "summary": self.__query}, "or"), - self.__processSearchResult, - self.__searchError - ) - - def __processSearchResult(self, data): - """ - Private method to process the search result data from PyPI. - - @param data result data with hits in the first element - @type tuple - """ - if data: - packages = self.__transformHits(data[0]) - if packages: - self.infoLabel.setText(self.tr("%n package(s) found.", "", - len(packages))) - wrapper = textwrap.TextWrapper(width=80) - count = 0 - total = 0 - for package in packages: - if self.__canceled: - self.infoLabel.setText( - self.tr("Canceled - only {0} out of %n package(s)" - " shown", "", len(packages)).format(total)) - break - itm = QTreeWidgetItem( - self.resultList, [ - package['name'].strip(), - "{0:4d}".format(package['score']), - "\n".join([ - wrapper.fill(line) for line in - package['summary'].strip().splitlines() - ]) - ]) - itm.setData(0, self.VersionRole, package['version']) - count += 1 - total += 1 - if count == 100: - count = 0 - QApplication.processEvents() - else: - QApplication.restoreOverrideCursor() - E5MessageBox.warning( - self, - self.tr("Search PyPI"), - self.tr("""<p>The package search did not return""" - """ anything.</p>""")) - self.infoLabel.setText( - self.tr("""<p>The package search did not return""" - """ anything.</p>""")) - else: - QApplication.restoreOverrideCursor() - E5MessageBox.warning( - self, - self.tr("Search PyPI"), - self.tr("""<p>The package search did not return anything.""" - """</p>""")) - self.infoLabel.setText( - self.tr("""<p>The package search did not return anything.""" - """</p>""")) - - header = self.resultList.header() - self.resultList.sortItems(1, Qt.DescendingOrder) - header.setStretchLastSection(False) - header.resizeSections(QHeaderView.ResizeToContents) - headerSize = 0 - for col in range(header.count()): - headerSize += header.sectionSize(col) - if headerSize < header.width(): - header.setStretchLastSection(True) - - self.__finish() - - def __finish(self): - """ - Private slot performing the finishing actions. - """ - QApplication.restoreOverrideCursor() - self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) - self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) - self.searchButton.setEnabled(True) - self.searchButton.setDefault(True) - self.searchEdit.setFocus(Qt.OtherFocusReason) - - def __searchError(self, errorCode, errorString): - """ - Private method handling a search error. - - @param errorCode code of the error - @type int - @param errorString error message - @type str - """ - self.__finish() - E5MessageBox.warning( - self, - self.tr("Search PyPI"), - self.tr("""<p>The package search failed.</p><p>Reason: {0}</p>""") - .format(errorString)) - self.infoLabel.setText(self.tr("Error: {0}").format(errorString)) - - def __transformHits(self, hits): - """ - Private method to convert the list returned from pypi into a - packages list. - - @param hits list returned from pypi - @type list of dict - @return list of packages - @rtype list of dict - """ - # we only include the record with the highest score - packages = {} - for hit in hits: - name = hit['name'].strip() - summary = (hit['summary'] or "").strip() - version = hit['version'].strip() - score = self.__score(name, summary) - # cleanup the summary - if summary in ["UNKNOWN", "."]: - summary = "" - - if name not in packages: - packages[name] = { - 'name': name, - 'summary': summary, - 'version': [version.strip()], - 'score': score} - else: - if score > packages[name]['score']: - packages[name]['score'] = score - packages[name]['summary'] = summary - packages[name]['version'].append(version.strip()) - - return list(packages.values()) - - def __score(self, name, summary): - """ - Private method to calculate some score for a search result. - - @param name name of the returned package - @type str - @param summary summary text for the package - @type str - @return score value - @rtype int - """ - score = 0 - for queryTerm in self.__query: - if queryTerm.lower() in name.lower(): - score += 4 - if queryTerm.lower() == name.lower(): - score += 4 - - if queryTerm.lower() in summary.lower(): - if QRegExp(r'\b{0}\b'.format(QRegExp.escape(queryTerm)), - Qt.CaseInsensitive).indexIn(summary) != -1: - # word match gets even higher score - score += 2 - else: - score += 1 - - return score - - def __install(self, userSite=False): - """ - Private slot to install the selected packages. - - @param userSite flag indicating to install to the user directory - @type bool - """ - venvName = self.venvComboBox.currentText() - - packages = [] - for itm in self.resultList.selectedItems(): - packages.append(itm.text(0).strip()) - if packages: - self.__pip.installPackages(packages, venvName=venvName, - userSite=userSite) - - def __showDetails(self): - """ - Private slot to show details about the selected package. - """ - self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) - self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True) - self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) - self.__showDetailsButton.setEnabled(False) - QApplication.setOverrideCursor(Qt.WaitCursor) - QApplication.processEvents(QEventLoop.ExcludeUserInputEvents) - - self.__detailsData = {} - - itm = self.resultList.selectedItems()[0] - packageVersions = itm.data(0, self.VersionRole) - if len(packageVersions) == 1: - packageVersion = packageVersions[0] - elif len(packageVersions) == 0: - packageVersion = "" - else: - packageVersion, ok = QInputDialog.getItem( - self, - self.tr("Show Package Details"), - self.tr("Select the package version:"), - packageVersions, - 0, False) - if not ok: - return - - packageName = itm.text(0) - self.__client.call( - "release_data", - (packageName, packageVersion), - lambda d: self.__getPackageDownloadsData(packageVersion, d), - self.__detailsError - ) - - def __getPackageDownloadsData(self, packageVersion, data): - """ - Private method to store the details data and get downloads - information. - - @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] - itm = self.resultList.selectedItems()[0] - packageName = itm.text(0) - self.__client.call( - "release_urls", - (packageName, packageVersion), - self.__displayPackageDetails, - self.__detailsError - ) - else: - self.__finish() - E5MessageBox.warning( - self, - self.tr("Search PyPI"), - self.tr("""<p>No package details info available.</p>""")) - - 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 - - self.__finish() - 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, errorCode, errorString): - """ - Private method handling a details error. - - @param errorCode code of the error - @type int - @param errorString error message - @type str - """ - self.__finish() - self.__showDetailsButton.setEnabled(True) - E5MessageBox.warning( - self, - self.tr("Search PyPI"), - self.tr("""<p>Package details info could not be retrieved.</p>""" - """<p>Reason: {0}</p>""") - .format(errorString)) - - @pyqtSlot(QTreeWidgetItem, int) - def on_resultList_itemActivated(self, item, column): - """ - Private slot reacting on an item activation. - - @param item reference to the activated item - @type QTreeWidgetItem - @param column activated column - @type int - """ - self.__showDetails()
--- a/Plugins/UiExtensionPlugins/PipInterface/PipSearchDialog.ui Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,138 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>PipSearchDialog</class> - <widget class="QDialog" name="PipSearchDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>700</width> - <height>600</height> - </rect> - </property> - <property name="windowTitle"> - <string>Search PyPI</string> - </property> - <property name="sizeGripEnabled"> - <bool>true</bool> - </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> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Query:</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="searchEdit"> - <property name="toolTip"> - <string>Enter the search term</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="searchButton"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="toolTip"> - <string>Press to start the search</string> - </property> - <property name="text"> - <string>Search</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QTreeWidget" name="resultList"> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="selectionMode"> - <enum>QAbstractItemView::ExtendedSelection</enum> - </property> - <property name="rootIsDecorated"> - <bool>false</bool> - </property> - <property name="itemsExpandable"> - <bool>false</bool> - </property> - <property name="sortingEnabled"> - <bool>true</bool> - </property> - <property name="allColumnsShowFocus"> - <bool>true</bool> - </property> - <property name="wordWrap"> - <bool>true</bool> - </property> - <column> - <property name="text"> - <string>Package</string> - </property> - </column> - <column> - <property name="text"> - <string>Score</string> - </property> - </column> - <column> - <property name="text"> - <string>Description</string> - </property> - </column> - </widget> - </item> - <item> - <widget class="QLabel" name="infoLabel"/> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Close</set> - </property> - </widget> - </item> - </layout> - </widget> - <tabstops> - <tabstop>venvComboBox</tabstop> - <tabstop>searchEdit</tabstop> - <tabstop>searchButton</tabstop> - <tabstop>resultList</tabstop> - </tabstops> - <resources/> - <connections/> -</ui>
--- a/Plugins/UiExtensionPlugins/PipInterface/PipSelectionDialog.py Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2018 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Module implementing a dialog to select the pip executable to be used. -""" - -from __future__ import unicode_literals - -from PyQt5.QtWidgets import QDialog - -from .Ui_PipSelectionDialog import Ui_PipSelectionDialog - - -class PipSelectionDialog(QDialog, Ui_PipSelectionDialog): - """ - Class implementing a dialog to select the pip executable to be used. - """ - def __init__(self, pip, parent=None): - """ - Constructor - - @param pip reference to the pip object - @type Pip - @param parent reference to the parent widget - @type QWidget - """ - super(PipSelectionDialog, self).__init__(parent) - self.setupUi(self) - - self.venvComboBox.addItem(pip.getDefaultEnvironmentString()) - projectVenv = pip.getProjectEnvironmentString() - if projectVenv: - self.venvComboBox.addItem(projectVenv) - self.venvComboBox.addItems(pip.getVirtualenvNames()) - - msh = self.minimumSizeHint() - self.resize(max(self.width(), msh.width()), msh.height()) - - def getData(self): - """ - Public method to get the entered data. - - @return tuple with the environment name and a flag indicating to - install to the user install directory - @rtype tuple of (str, bool) - """ - return ( - self.venvComboBox.currentText(), - self.userCheckBox.isChecked(), - )
--- a/Plugins/UiExtensionPlugins/PipInterface/PipSelectionDialog.ui Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>PipSelectionDialog</class> - <widget class="QDialog" name="PipSelectionDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>600</width> - <height>130</height> - </rect> - </property> - <property name="windowTitle"> - <string>Select Virtual Environment</string> - </property> - <property name="sizeGripEnabled"> - <bool>true</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Virtual Environment:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="venvComboBox"> - <property name="toolTip"> - <string>Select the virtual environment to be used</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="userCheckBox"> - <property name="toolTip"> - <string>Select to install to the Python user install directory</string> - </property> - <property name="text"> - <string>Install into User Directory</string> - </property> - </widget> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>PipSelectionDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>PipSelectionDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui>
--- a/Plugins/UiExtensionPlugins/PipInterface/__init__.py Sat Feb 23 13:05:18 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Package implementing the various pip dialogs and data. -""" - -from __future__ import unicode_literals - -DefaultPyPiUrl = "https://pypi.org" -DefaultIndexUrlXml = DefaultPyPiUrl + "/pypi" -DefaultIndexUrlPip = DefaultPyPiUrl + "/simple"
--- a/Preferences/ConfigurationDialog.py Sat Feb 23 13:05:18 2019 +0100 +++ b/Preferences/ConfigurationDialog.py Sat Feb 23 15:46:15 2019 +0100 @@ -182,6 +182,9 @@ [self.tr("Notifications"), "preferences-notifications.png", "NotificationsPage", None, None], + "pipPage": + [self.tr("Python Package Management"), "pypi.png", + "PipPage", None, None], "pluginManagerPage": [self.tr("Plugin Manager"), "preferences-pluginmanager.png",
--- a/Preferences/ConfigurationPages/InterfacePage.py Sat Feb 23 13:05:18 2019 +0100 +++ b/Preferences/ConfigurationPages/InterfacePage.py Sat Feb 23 15:46:15 2019 +0100 @@ -102,6 +102,8 @@ # right side self.codeDocumentationViewerCheckBox.setChecked( Preferences.getUI("ShowCodeDocumentationViewer")) + self.pypiCheckBox.setChecked( + Preferences.getUI("ShowPyPIPackageManager")) self.condaCheckBox.setChecked( Preferences.getUI("ShowCondaPackageManager")) self.cooperationCheckBox.setChecked( @@ -202,6 +204,9 @@ "ShowCodeDocumentationViewer", self.codeDocumentationViewerCheckBox.isChecked()) Preferences.setUI( + "ShowPyPIPackageManager", + self.pypiCheckBox.isChecked()) + Preferences.setUI( "ShowCondaPackageManager", self.condaCheckBox.isChecked()) Preferences.setUI(
--- a/Preferences/ConfigurationPages/InterfacePage.ui Sat Feb 23 13:05:18 2019 +0100 +++ b/Preferences/ConfigurationPages/InterfacePage.ui Sat Feb 23 15:46:15 2019 +0100 @@ -516,7 +516,17 @@ </property> </widget> </item> - <item row="0" column="1"> + <item row="1" column="0"> + <widget class="QCheckBox" name="pypiCheckBox"> + <property name="toolTip"> + <string>Select to activate the PyPI package manager widget</string> + </property> + <property name="text"> + <string>PyPI Package Manager</string> + </property> + </widget> + </item> + <item row="1" column="1"> <widget class="QCheckBox" name="condaCheckBox"> <property name="toolTip"> <string>Select to activate the conda package manager widget</string> @@ -526,7 +536,7 @@ </property> </widget> </item> - <item row="1" column="0"> + <item row="2" column="0"> <widget class="QCheckBox" name="cooperationCheckBox"> <property name="toolTip"> <string>Select to activate the Cooperation widget</string> @@ -536,7 +546,7 @@ </property> </widget> </item> - <item row="1" column="1"> + <item row="2" column="1"> <widget class="QCheckBox" name="ircCheckBox"> <property name="toolTip"> <string>Select to activate the IRC widget</string> @@ -642,6 +652,7 @@ <tabstop>fileBrowserCheckBox</tabstop> <tabstop>symbolsCheckBox</tabstop> <tabstop>codeDocumentationViewerCheckBox</tabstop> + <tabstop>pypiCheckBox</tabstop> <tabstop>condaCheckBox</tabstop> <tabstop>cooperationCheckBox</tabstop> <tabstop>ircCheckBox</tabstop>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Preferences/ConfigurationPages/PipPage.py Sat Feb 23 15:46:15 2019 +0100 @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Package implementing the pip configuration page. +""" + +from __future__ import unicode_literals + +from .ConfigurationPageBase import ConfigurationPageBase +from .Ui_PipPage import Ui_PipPage + +from PipInterface import DefaultPyPiUrl + +import Preferences + + +class PipPage(ConfigurationPageBase, Ui_PipPage): + """ + Class implementing the pip configuration page. + """ + def __init__(self): + """ + Constructor + """ + super(PipPage, self).__init__() + self.setupUi(self) + self.setObjectName("PipPage") + + self.indexLabel.setText(self.tr( + '<b>Note:</b> Leave empty to use the default index URL (' + '<a href="{0}">{0}</a>).') + .format(DefaultPyPiUrl)) + + # set initial values + self.indexEdit.setText(Preferences.getPip("PipSearchIndex")) + + def save(self): + """ + Public slot to save the pip configuration. + """ + Preferences.setPip( + "PipSearchIndex", self.indexEdit.text().strip()) + + +def create(dlg): + """ + Module function to create the configuration page. + + @param dlg reference to the configuration dialog + @return reference to the instantiated page (ConfigurationPageBase) + """ + page = PipPage() + return page
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Preferences/ConfigurationPages/PipPage.ui Sat Feb 23 15:46:15 2019 +0100 @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PipPage</class> + <widget class="QWidget" name="PipPage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>602</width> + <height>389</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QLabel" name="headerLabel"> + <property name="text"> + <string><b>Configure pip</b></string> + </property> + </widget> + </item> + <item> + <widget class="Line" name="line9_3"> + <property name="frameShape"> + <enum>QFrame::HLine</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>Index URL</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLineEdit" name="indexEdit"> + <property name="toolTip"> + <string>Enter the URL of the package index or leave empty to use the default</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="indexLabel"> + <property name="text"> + <string/> + </property> + <property name="openExternalLinks"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>234</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <tabstops> + <tabstop>indexEdit</tabstop> + </tabstops> + <resources/> + <connections/> +</ui>
--- a/Preferences/ProgramsDialog.py Sat Feb 23 13:05:18 2019 +0100 +++ b/Preferences/ProgramsDialog.py Sat Feb 23 15:46:15 2019 +0100 @@ -224,8 +224,16 @@ self.__createProgramEntry( self.tr("conda Manager"), exe, '--version', 'conda', -1) - # 6. do the CORBA and Protobuf programs - # 6a. omniORB + # 6. do the pip program(s) + virtualenvManager = e5App().getObject("VirtualEnvManager") + for venvName in virtualenvManager.getVirtualenvNames(): + interpreter = virtualenvManager.getVirtualenvInterpreter(venvName) + self.__createProgramEntry( + self.tr("PyPI Package Management"), interpreter, '--version', + 'pip', 1, exeModule=["-m", "pip"]) + + # 7. do the CORBA and Protobuf programs + # 7a. omniORB exe = Preferences.getCorba("omniidl") if not exe: exe = "omniidl" @@ -233,7 +241,7 @@ exe += ".exe" self.__createProgramEntry( self.tr("CORBA IDL Compiler"), exe, '-V', 'omniidl', -1) - # 6b. protobuf + # 7b. protobuf exe = Preferences.getProtobuf("protoc") if not exe: exe = "protoc" @@ -241,7 +249,7 @@ exe += ".exe" self.__createProgramEntry( self.tr("Protobuf Compiler"), exe, '--version', 'libprotoc', -1) - # 6c. grpc + # 7c. grpc exe = Preferences.getProtobuf("grpcPython") if not exe: exe = sys.executable @@ -249,7 +257,7 @@ self.tr("gRPC Compiler"), exe, '--version', 'libprotoc', -1, exeModule=['-m', 'grpc_tools.protoc']) - # 7. do the spell checking entry + # 8. do the spell checking entry try: import enchant try: @@ -266,7 +274,7 @@ self.__createEntry( self.tr("Spell Checker - PyEnchant"), text, version) - # 8. do the pygments entry + # 9. do the pygments entry try: import pygments try: @@ -283,7 +291,7 @@ self.__createEntry( self.tr("Source Highlighter - Pygments"), text, version) - # 9. do the plugin related programs + # 10. do the plugin related programs pm = e5App().getObject("PluginManager") for info in pm.getPluginExeDisplayData(): if info["programEntry"]:
--- a/Preferences/__init__.py Sat Feb 23 13:05:18 2019 +0100 +++ b/Preferences/__init__.py Sat Feb 23 15:46:15 2019 +0100 @@ -171,6 +171,7 @@ "ShowFileBrowser": True, # left side "ShowSymbolsViewer": True, # left side "ShowCodeDocumentationViewer": True, # right side + "ShowPyPIPackageManager": True, # right side "ShowCondaPackageManager": True, # right side "ShowCooperation": True, # right side "ShowIrc": True, # right side @@ -1587,6 +1588,11 @@ condaDefaults = { "CondaExecutable": "", } + + # defaults for pip + pipDefaults = { + "PipSearchIndex": "", # used by the search command + } def readToolGroups(prefClass=Prefs): @@ -1990,10 +1996,10 @@ "LayoutShellEmbedded", "LayoutFileBrowserEmbedded", "CheckErrorLog", "NotificationsEnabled", "DynamicOnlineCheck", "OpenCrashSessionOnStartup", "CrashSessionEnabled", - "ShowCodeDocumentationViewer", "ShowCondaPackageManager", - "ShowCooperation", "ShowIrc", "ShowTemplateViewer", - "ShowFileBrowser", "ShowSymbolsViewer", "ShowNumbersViewer", - "UseNativeMenuBar"]: + "ShowCodeDocumentationViewer", "ShowPyPIPackageManager", + "ShowCondaPackageManager", "ShowCooperation", "ShowIrc", + "ShowTemplateViewer", "ShowFileBrowser", "ShowSymbolsViewer", + "ShowNumbersViewer", "UseNativeMenuBar"]: return toBool(prefClass.settings.value( "UI/" + key, prefClass.uiDefaults[key])) elif key in ["TabViewManagerFilenameLength", "CaptionFilenameLength", @@ -3775,6 +3781,30 @@ prefClass.settings.setValue("Conda/" + key, value) +def getPip(key, prefClass=Prefs): + """ + Module function to retrieve the pip related settings. + + @param key the key of the value to get + @param prefClass preferences class used as the storage area + @return the requested pip value + """ + return prefClass.settings.value( + "Pip/" + key, + prefClass.pipDefaults[key]) + + +def setPip(key, value, prefClass=Prefs): + """ + Module function to store the pip related settings. + + @param key the key of the setting to be set + @param value the value to be set + @param prefClass preferences class used as the storage area + """ + prefClass.settings.setValue("Pip/" + key, value) + + def getGeometry(key, prefClass=Prefs): """ Module function to retrieve the display geometry.
--- a/UI/UserInterface.py Sat Feb 23 13:05:18 2019 +0100 +++ b/UI/UserInterface.py Sat Feb 23 15:46:15 2019 +0100 @@ -253,6 +253,7 @@ # Generate an empty project object and multi project object from Project.Project import Project self.project = Project(self) + e5App().registerObject("Project", self.project) from MultiProject.MultiProject import MultiProject self.multiProject = MultiProject(self.project, self) @@ -578,7 +579,6 @@ e5App().registerObject("DebugServer", debugServer) e5App().registerObject("BackgroundService", self.backgroundService) e5App().registerObject("ViewManager", self.viewmanager) - e5App().registerObject("Project", self.project) e5App().registerObject("ProjectBrowser", self.projectBrowser) e5App().registerObject("MultiProject", self.multiProject) e5App().registerObject("TaskViewer", self.taskViewer) @@ -840,6 +840,15 @@ UI.PixmapCache.getIcon("debugViewer.png"), self.tr("Debug-Viewer")) + if Preferences.getUI("ShowPyPIPackageManager"): + # Create the PyPI package manager + logging.debug("Creating PyPI Package Manager...") + from PipInterface.PipPackagesWidget import PipPackagesWidget + self.pipWidget = PipPackagesWidget() + self.rToolbox.addItem(self.pipWidget, + UI.PixmapCache.getIcon("pypi"), + self.tr("PyPI")) + if Preferences.getUI("ShowCondaPackageManager"): # Create the conda package manager logging.debug("Creating Conda Package Manager...") @@ -848,7 +857,7 @@ self.rToolbox.addItem(self.condaWidget, UI.PixmapCache.getIcon("miniconda.png"), self.tr("Conda")) - + if Preferences.getUI("ShowCooperation"): # Create the chat part of the user interface logging.debug("Creating Chat Widget...") @@ -990,6 +999,15 @@ self.debugViewer, UI.PixmapCache.getIcon("debugViewer.png"), self.tr("Debug-Viewer")) + if Preferences.getUI("ShowPyPIPackageManager"): + # Create the PyPI package manager + logging.debug("Creating PyPI Package Manager...") + from PipInterface.PipPackagesWidget import PipPackagesWidget + self.pipWidget = PipPackagesWidget() + self.rightSidebar.addTab( + self.pipWidget, UI.PixmapCache.getIcon("pypi"), + self.tr("PyPI")) + if Preferences.getUI("ShowCondaPackageManager"): # Create the conda package manager logging.debug("Creating Conda Package Manager...")
--- a/VirtualEnv/VirtualenvManager.py Sat Feb 23 13:05:18 2019 +0100 +++ b/VirtualEnv/VirtualenvManager.py Sat Feb 23 15:46:15 2019 +0100 @@ -15,7 +15,7 @@ import json import copy -from PyQt5.QtCore import pyqtSlot, QObject +from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject from PyQt5.QtWidgets import QDialog from E5Gui import E5MessageBox @@ -27,9 +27,20 @@ class VirtualenvManager(QObject): """ Class implementing an object to manage Python virtual environments. + + @signal virtualEnvironmentAdded() emitted to indicate the addition of + a virtual environment + @signal virtualEnvironmentRemoved() emitted to indicate the removal and + deletion of a virtual environment + @signal virtualEnvironmentChanged(name) emitted to indicate a change of + a virtual environment """ DefaultKey = "<default>" + virtualEnvironmentAdded = pyqtSignal() + virtualEnvironmentRemoved = pyqtSignal() + virtualEnvironmentChanged = pyqtSignal(str) + def __init__(self, parent=None): """ Constructor @@ -234,6 +245,7 @@ self.__saveSettings() + self.virtualEnvironmentAdded.emit() if self.__virtualenvManagerDialog: self.__virtualenvManagerDialog.refresh() @@ -283,6 +295,7 @@ self.__saveSettings() + self.virtualEnvironmentChanged.emit(venvName) if self.__virtualenvManagerDialog: self.__virtualenvManagerDialog.refresh() @@ -368,6 +381,7 @@ self.__saveSettings() + self.virtualEnvironmentRemoved.emit() if self.__virtualenvManagerDialog: self.__virtualenvManagerDialog.refresh() @@ -421,6 +435,7 @@ self.__saveSettings() + self.virtualEnvironmentRemoved.emit() if self.__virtualenvManagerDialog: self.__virtualenvManagerDialog.refresh()
--- a/eric6.e4p Sat Feb 23 13:05:18 2019 +0100 +++ b/eric6.e4p Sat Feb 23 15:46:15 2019 +0100 @@ -471,6 +471,14 @@ <Source>Network/IRC/IrcWidget.py</Source> <Source>Network/IRC/__init__.py</Source> <Source>Network/__init__.py</Source> + <Source>PipInterface/Pip.py</Source> + <Source>PipInterface/PipDialog.py</Source> + <Source>PipInterface/PipFileSelectionDialog.py</Source> + <Source>PipInterface/PipFreezeDialog.py</Source> + <Source>PipInterface/PipPackageDetailsDialog.py</Source> + <Source>PipInterface/PipPackagesInputDialog.py</Source> + <Source>PipInterface/PipPackagesWidget.py</Source> + <Source>PipInterface/__init__.py</Source> <Source>PluginManager/PluginDetailsDialog.py</Source> <Source>PluginManager/PluginExceptions.py</Source> <Source>PluginManager/PluginInfoDialog.py</Source> @@ -519,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> @@ -541,18 +548,6 @@ <Source>Plugins/PluginWizardQRegExp.py</Source> <Source>Plugins/PluginWizardQRegularExpression.py</Source> <Source>Plugins/PluginWizardSetup.py</Source> - <Source>Plugins/UiExtensionPlugins/PipInterface/ConfigurationPage/PipPage.py</Source> - <Source>Plugins/UiExtensionPlugins/PipInterface/ConfigurationPage/__init__.py</Source> - <Source>Plugins/UiExtensionPlugins/PipInterface/Pip.py</Source> - <Source>Plugins/UiExtensionPlugins/PipInterface/PipDialog.py</Source> - <Source>Plugins/UiExtensionPlugins/PipInterface/PipFileSelectionDialog.py</Source> - <Source>Plugins/UiExtensionPlugins/PipInterface/PipFreezeDialog.py</Source> - <Source>Plugins/UiExtensionPlugins/PipInterface/PipListDialog.py</Source> - <Source>Plugins/UiExtensionPlugins/PipInterface/PipPackageDetailsDialog.py</Source> - <Source>Plugins/UiExtensionPlugins/PipInterface/PipPackagesInputDialog.py</Source> - <Source>Plugins/UiExtensionPlugins/PipInterface/PipSearchDialog.py</Source> - <Source>Plugins/UiExtensionPlugins/PipInterface/PipSelectionDialog.py</Source> - <Source>Plugins/UiExtensionPlugins/PipInterface/__init__.py</Source> <Source>Plugins/UiExtensionPlugins/Translator/ConfigurationPage/TranslatorPage.py</Source> <Source>Plugins/UiExtensionPlugins/Translator/ConfigurationPage/__init__.py</Source> <Source>Plugins/UiExtensionPlugins/Translator/Translator.py</Source> @@ -893,6 +888,7 @@ <Source>Preferences/ConfigurationPages/MultiProjectPage.py</Source> <Source>Preferences/ConfigurationPages/NetworkPage.py</Source> <Source>Preferences/ConfigurationPages/NotificationsPage.py</Source> + <Source>Preferences/ConfigurationPages/PipPage.py</Source> <Source>Preferences/ConfigurationPages/PluginManagerPage.py</Source> <Source>Preferences/ConfigurationPages/PrinterPage.py</Source> <Source>Preferences/ConfigurationPages/ProjectBrowserPage.py</Source> @@ -1722,10 +1718,10 @@ <Source>uninstall.py</Source> </Sources> <Forms> - <Form>CondaInterface/CondaNewEnvironmentDataDialog.ui</Form> <Form>CondaInterface/CondaExecDialog.ui</Form> <Form>CondaInterface/CondaExportDialog.ui</Form> <Form>CondaInterface/CondaInfoDialog.ui</Form> + <Form>CondaInterface/CondaNewEnvironmentDataDialog.ui</Form> <Form>CondaInterface/CondaPackageDetailsWidget.ui</Form> <Form>CondaInterface/CondaPackagesWidget.ui</Form> <Form>Cooperation/ChatWidget.ui</Form> @@ -1825,6 +1821,12 @@ <Form>Network/IRC/IrcNetworkWidget.ui</Form> <Form>Network/IRC/IrcServerEditDialog.ui</Form> <Form>Network/IRC/IrcWidget.ui</Form> + <Form>PipInterface/PipDialog.ui</Form> + <Form>PipInterface/PipFileSelectionDialog.ui</Form> + <Form>PipInterface/PipFreezeDialog.ui</Form> + <Form>PipInterface/PipPackageDetailsDialog.ui</Form> + <Form>PipInterface/PipPackagesInputDialog.ui</Form> + <Form>PipInterface/PipPackagesWidget.ui</Form> <Form>PluginManager/PluginDetailsDialog.ui</Form> <Form>PluginManager/PluginInfoDialog.ui</Form> <Form>PluginManager/PluginInstallDialog.ui</Form> @@ -1841,15 +1843,6 @@ <Form>Plugins/DocumentationPlugins/Ericapi/EricapiExecDialog.ui</Form> <Form>Plugins/DocumentationPlugins/Ericdoc/EricdocConfigDialog.ui</Form> <Form>Plugins/DocumentationPlugins/Ericdoc/EricdocExecDialog.ui</Form> - <Form>Plugins/UiExtensionPlugins/PipInterface/ConfigurationPage/PipPage.ui</Form> - <Form>Plugins/UiExtensionPlugins/PipInterface/PipDialog.ui</Form> - <Form>Plugins/UiExtensionPlugins/PipInterface/PipFileSelectionDialog.ui</Form> - <Form>Plugins/UiExtensionPlugins/PipInterface/PipFreezeDialog.ui</Form> - <Form>Plugins/UiExtensionPlugins/PipInterface/PipListDialog.ui</Form> - <Form>Plugins/UiExtensionPlugins/PipInterface/PipPackageDetailsDialog.ui</Form> - <Form>Plugins/UiExtensionPlugins/PipInterface/PipPackagesInputDialog.ui</Form> - <Form>Plugins/UiExtensionPlugins/PipInterface/PipSearchDialog.ui</Form> - <Form>Plugins/UiExtensionPlugins/PipInterface/PipSelectionDialog.ui</Form> <Form>Plugins/UiExtensionPlugins/Translator/ConfigurationPage/TranslatorPage.ui</Form> <Form>Plugins/UiExtensionPlugins/Translator/TranslatorWidget.ui</Form> <Form>Plugins/VcsPlugins/vcsGit/ConfigurationPage/GitPage.ui</Form> @@ -2073,6 +2066,7 @@ <Form>Preferences/ConfigurationPages/MultiProjectPage.ui</Form> <Form>Preferences/ConfigurationPages/NetworkPage.ui</Form> <Form>Preferences/ConfigurationPages/NotificationsPage.ui</Form> + <Form>Preferences/ConfigurationPages/PipPage.ui</Form> <Form>Preferences/ConfigurationPages/PluginManagerPage.ui</Form> <Form>Preferences/ConfigurationPages/PrinterPage.ui</Form> <Form>Preferences/ConfigurationPages/ProjectBrowserPage.ui</Form>