Merged with the conda branch to finalize the conda package manager development in the default branch.

Sat, 16 Feb 2019 15:36:36 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 16 Feb 2019 15:36:36 +0100
changeset 6768
ac6db5261d48
parent 6767
d25bbb8fa691 (current diff)
parent 6761
0b69fe8314e3 (diff)
child 6769
a2a9ef2da98a

Merged with the conda branch to finalize the conda package manager development in the default branch.

--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CondaInterface/Conda.py	Sat Feb 16 15:36:36 2019 +0100
@@ -0,0 +1,734 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Package implementing the conda GUI logic.
+"""
+
+from __future__ import unicode_literals
+try:
+    str = unicode       # __IGNORE_EXCEPTION__
+except NameError:
+    pass
+
+import json
+import os
+
+from PyQt5.QtCore import pyqtSignal, QObject, QProcess, QCoreApplication
+from PyQt5.QtWidgets import QDialog
+
+from E5Gui import E5MessageBox
+
+import Globals
+import Preferences
+
+from . import rootPrefix, condaVersion
+from .CondaExecDialog import CondaExecDialog
+
+
+class Conda(QObject):
+    """
+    Class implementing the conda GUI logic.
+    
+    @signal condaEnvironmentCreated() emitted to indicate the creation of
+        a new environment
+    @signal condaEnvironmentRemoved() emitted to indicate the removal of
+        an environment
+    """
+    condaEnvironmentCreated = pyqtSignal()
+    condaEnvironmentRemoved = pyqtSignal()
+    
+    RootName = QCoreApplication.translate("Conda", "<root>")
+    
+    def __init__(self, parent=None):
+        """
+        Constructor
+        
+        @param parent parent
+        @type QObject
+        """
+        super(Conda, self).__init__(parent)
+        
+        self.__ui = parent
+    
+    #######################################################################
+    ## environment related methods below
+    #######################################################################
+    
+    def createCondaEnvironment(self, arguments):
+        """
+        Public method to create a conda environment.
+        
+        @param arguments list of command line arguments
+        @type list of str
+        @return tuple containing a flag indicating success, the directory of
+            the created environment (aka. prefix) and the corresponding Python
+            interpreter
+        @rtype tuple of (bool, str, str)
+        """
+        args = ["create", "--json", "--yes"] + arguments
+        
+        dlg = CondaExecDialog("create", self.__ui)
+        dlg.start(args)
+        dlg.exec_()
+        ok, resultDict = dlg.getResult()
+        
+        if ok:
+            if "actions" in resultDict and \
+                    "PREFIX" in resultDict["actions"]:
+                prefix = resultDict["actions"]["PREFIX"]
+            elif "prefix" in resultDict:
+                prefix = resultDict["prefix"]
+            elif "dst_prefix" in resultDict:
+                prefix = resultDict["dst_prefix"]
+            else:
+                prefix = ""
+            
+            # determine Python executable
+            if prefix:
+                pathPrefixes = [
+                    prefix,
+                    rootPrefix()
+                ]
+            else:
+                pathPrefixes = [
+                    rootPrefix()
+                ]
+            for pathPrefix in pathPrefixes:
+                if Globals.isWindowsPlatform():
+                    python = os.path.join(pathPrefix, "python.exe")
+                else:
+                    python = os.path.join(pathPrefix, "bin", "python")
+                if os.path.exists(python):
+                    break
+            else:
+                python = ""
+            
+            self.condaEnvironmentCreated.emit()
+            return True, prefix, python
+        else:
+            return False, "", ""
+    
+    def removeCondaEnvironment(self, name="", prefix=""):
+        """
+        Public method to remove a conda environment.
+        
+        @param name name of the environment
+        @type str
+        @param prefix prefix of the environment
+        @type str
+        @return flag indicating success
+        @rtype bool
+        @exception RuntimeError raised to indicate an error in parameters
+        
+        Note: only one of name or prefix must be given.
+        """
+        if name and prefix:
+            raise RuntimeError("Only one of 'name' or 'prefix' must be given.")
+        
+        if not name and not prefix:
+            raise RuntimeError("One of 'name' or 'prefix' must be given.")
+        
+        args = [
+            "remove",
+            "--json",
+            "--quiet",
+            "--all",
+        ]
+        if name:
+            args.extend(["--name", name])
+        elif prefix:
+            args.extend(["--prefix", prefix])
+        
+        exe = Preferences.getConda("CondaExecutable")
+        if not exe:
+            exe = "conda"
+        
+        proc = QProcess()
+        proc.start(exe, args)
+        if not proc.waitForStarted(15000):
+            E5MessageBox.critical(
+                self.__ui,
+                self.tr("conda remove"),
+                self.tr("""The conda executable could not be started."""))
+            return False
+        else:
+            proc.waitForFinished(15000)
+            output = str(proc.readAllStandardOutput(),
+                         Preferences.getSystem("IOEncoding"),
+                         'replace').strip()
+            try:
+                jsonDict = json.loads(output)
+            except Exception:
+                E5MessageBox.critical(
+                    self.__ui,
+                    self.tr("conda remove"),
+                    self.tr("""The conda executable returned invalid data."""))
+                return False
+            
+            if "error" in jsonDict:
+                E5MessageBox.critical(
+                    self.__ui,
+                    self.tr("conda remove"),
+                    self.tr("<p>The conda executable returned an error.</p>"
+                            "<p>{0}</p>").format(jsonDict["message"]))
+                return False
+            
+            if jsonDict["success"]:
+                self.condaEnvironmentRemoved.emit()
+            
+            return jsonDict["success"]
+        
+        return False
+    
+    def getCondaEnvironmentsList(self):
+        """
+        Public method to get a list of all Conda environments.
+        
+        @return list of tuples containing the environment name and prefix
+        @rtype list of tuples of (str, str)
+        """
+        exe = Preferences.getConda("CondaExecutable")
+        if not exe:
+            exe = "conda"
+        
+        environmentsList = []
+        
+        proc = QProcess()
+        proc.start(exe, ["info", "--json"])
+        if proc.waitForStarted(15000):
+            if proc.waitForFinished(15000):
+                output = str(proc.readAllStandardOutput(),
+                             Preferences.getSystem("IOEncoding"),
+                             'replace').strip()
+                try:
+                    jsonDict = json.loads(output)
+                except Exception:
+                    jsonDict = {}
+                
+                if "envs" in jsonDict:
+                    for prefix in jsonDict["envs"][:]:
+                        if prefix == jsonDict["root_prefix"]:
+                            if not jsonDict["root_writable"]:
+                                # root prefix is listed but not writable
+                                continue
+                            name = self.RootName
+                        else:
+                            name = os.path.basename(prefix)
+                        
+                        environmentsList.append((name, prefix))
+        
+        return environmentsList
+    
+    #######################################################################
+    ## package related methods below
+    #######################################################################
+    
+    def getInstalledPackages(self, name="", prefix=""):
+        """
+        Public method to get a list of installed packages of a conda
+        environment.
+        
+        @param name name of the environment
+        @type str
+        @param prefix prefix of the environment
+        @type str
+        @return list of installed packages. Each entry is a tuple containing
+            the package name, version and build.
+        @rtype list of tuples of (str, str, str)
+        @exception RuntimeError raised to indicate an error in parameters
+        
+        Note: only one of name or prefix must be given.
+        """
+        if name and prefix:
+            raise RuntimeError("Only one of 'name' or 'prefix' must be given.")
+        
+        if not name and not prefix:
+            raise RuntimeError("One of 'name' or 'prefix' must be given.")
+        
+        args = [
+            "list",
+            "--json",
+        ]
+        if name:
+            args.extend(["--name", name])
+        elif prefix:
+            args.extend(["--prefix", prefix])
+        
+        exe = Preferences.getConda("CondaExecutable")
+        if not exe:
+            exe = "conda"
+        
+        packages = []
+        
+        proc = QProcess()
+        proc.start(exe, 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["build_string"]
+                        ))
+                    else:
+                        packages.append(tuple(package.rsplit("-", 2)))
+        
+        return packages
+    
+    def getUpdateablePackages(self, name="", prefix=""):
+        """
+        Public method to get a list of updateable packages of a conda
+        environment.
+        
+        @param name name of the environment
+        @type str
+        @param prefix prefix of the environment
+        @type str
+        @return list of installed packages. Each entry is a tuple containing
+            the package name, version and build.
+        @rtype list of tuples of (str, str, str)
+        @exception RuntimeError raised to indicate an error in parameters
+        
+        Note: only one of name or prefix must be given.
+        """
+        if name and prefix:
+            raise RuntimeError("Only one of 'name' or 'prefix' must be given.")
+        
+        if not name and not prefix:
+            raise RuntimeError("One of 'name' or 'prefix' must be given.")
+        
+        args = [
+            "update",
+            "--json",
+            "--quiet",
+            "--all",
+            "--dry-run",
+        ]
+        if name:
+            args.extend(["--name", name])
+        elif prefix:
+            args.extend(["--prefix", prefix])
+        
+        exe = Preferences.getConda("CondaExecutable")
+        if not exe:
+            exe = "conda"
+        
+        packages = []
+        
+        proc = QProcess()
+        proc.start(exe, args)
+        if proc.waitForStarted(15000):
+            if proc.waitForFinished(30000):
+                output = str(proc.readAllStandardOutput(),
+                             Preferences.getSystem("IOEncoding"),
+                             'replace').strip()
+                try:
+                    jsonDict = json.loads(output)
+                except Exception:
+                    jsonDict = {}
+                
+                if "actions" in jsonDict and "LINK" in jsonDict["actions"]:
+                    for linkEntry in jsonDict["actions"]["LINK"]:
+                        if isinstance(linkEntry, dict):
+                            packages.append((
+                                linkEntry["name"],
+                                linkEntry["version"],
+                                linkEntry["build_string"]
+                            ))
+                        else:
+                            package = linkEntry.split()[0]
+                            packages.append(tuple(package.rsplit("-", 2)))
+        
+        return packages
+    
+    def updatePackages(self, packages, name="", prefix=""):
+        """
+        Public method to update packages of a conda environment.
+        
+        @param packages list of package names to be updated
+        @type list of str
+        @param name name of the environment
+        @type str
+        @param prefix prefix of the environment
+        @type str
+        @return flag indicating success
+        @rtype bool
+        @exception RuntimeError raised to indicate an error in parameters
+        
+        Note: only one of name or prefix must be given.
+        """
+        if name and prefix:
+            raise RuntimeError("Only one of 'name' or 'prefix' must be given.")
+        
+        if not name and not prefix:
+            raise RuntimeError("One of 'name' or 'prefix' must be given.")
+        
+        if packages:
+            args = [
+                "update",
+                "--json",
+                "--yes",
+            ]
+            if name:
+                args.extend(["--name", name])
+            elif prefix:
+                args.extend(["--prefix", prefix])
+            args.extend(packages)
+            
+            dlg = CondaExecDialog("update", self.__ui)
+            dlg.start(args)
+            dlg.exec_()
+            ok, _ = dlg.getResult()
+        else:
+            ok = False
+        
+        return ok
+    
+    def updateAllPackages(self, name="", prefix=""):
+        """
+        Public method to update all packages of a conda environment.
+        
+        @param name name of the environment
+        @type str
+        @param prefix prefix of the environment
+        @type str
+        @return flag indicating success
+        @rtype bool
+        @exception RuntimeError raised to indicate an error in parameters
+        
+        Note: only one of name or prefix must be given.
+        """
+        if name and prefix:
+            raise RuntimeError("Only one of 'name' or 'prefix' must be given.")
+        
+        if not name and not prefix:
+            raise RuntimeError("One of 'name' or 'prefix' must be given.")
+        
+        args = [
+            "update",
+            "--json",
+            "--yes",
+            "--all"
+        ]
+        if name:
+            args.extend(["--name", name])
+        elif prefix:
+            args.extend(["--prefix", prefix])
+        
+        dlg = CondaExecDialog("update", self.__ui)
+        dlg.start(args)
+        dlg.exec_()
+        ok, _ = dlg.getResult()
+        
+        return ok
+    
+    def installPackages(self, packages, name="", prefix=""):
+        """
+        Public method to install packages into a conda environment.
+        
+        @param packages list of package names to be installed
+        @type list of str
+        @param name name of the environment
+        @type str
+        @param prefix prefix of the environment
+        @type str
+        @return flag indicating success
+        @rtype bool
+        @exception RuntimeError raised to indicate an error in parameters
+        
+        Note: only one of name or prefix must be given.
+        """
+        if name and prefix:
+            raise RuntimeError("Only one of 'name' or 'prefix' must be given.")
+        
+        if not name and not prefix:
+            raise RuntimeError("One of 'name' or 'prefix' must be given.")
+        
+        if packages:
+            args = [
+                "install",
+                "--json",
+                "--yes",
+            ]
+            if name:
+                args.extend(["--name", name])
+            elif prefix:
+                args.extend(["--prefix", prefix])
+            args.extend(packages)
+            
+            dlg = CondaExecDialog("install", self.__ui)
+            dlg.start(args)
+            dlg.exec_()
+            ok, _ = dlg.getResult()
+        else:
+            ok = False
+        
+        return ok
+    
+    def uninstallPackages(self, packages, name="", prefix=""):
+        """
+        Public method to uninstall packages of a conda environment (including
+        all no longer needed dependencies).
+        
+        @param packages list of package names to be uninstalled
+        @type list of str
+        @param name name of the environment
+        @type str
+        @param prefix prefix of the environment
+        @type str
+        @return flag indicating success
+        @rtype bool
+        @exception RuntimeError raised to indicate an error in parameters
+        
+        Note: only one of name or prefix must be given.
+        """
+        if name and prefix:
+            raise RuntimeError("Only one of 'name' or 'prefix' must be given.")
+        
+        if not name and not prefix:
+            raise RuntimeError("One of 'name' or 'prefix' must be given.")
+        
+        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 and"
+                    " their dependencies?"),
+                packages)
+            if dlg.exec_() == QDialog.Accepted:
+                args = [
+                    "remove",
+                    "--json",
+                    "--yes",
+                ]
+                if condaVersion() >= (4, 4, 0):
+                    args.append("--prune",)
+                if name:
+                    args.extend(["--name", name])
+                elif prefix:
+                    args.extend(["--prefix", prefix])
+                args.extend(packages)
+                
+                dlg = CondaExecDialog("remove", self.__ui)
+                dlg.start(args)
+                dlg.exec_()
+                ok, _ = dlg.getResult()
+            else:
+                ok = False
+        else:
+            ok = False
+        
+        return ok
+    
+    def searchPackages(self, pattern, fullNameOnly=False, packageSpec=False,
+                       platform="", name="", prefix=""):
+        """
+        Public method to search for a package pattern of a conda environment.
+        
+        @param pattern package search pattern
+        @type str
+        @param fullNameOnly flag indicating to search for full names only
+        @type bool
+        @param packageSpec flag indicating to search a package specification
+        @type bool
+        @param platform type of platform to be searched for
+        @type str
+        @param name name of the environment
+        @type str
+        @param prefix prefix of the environment
+        @type str
+        @return flag indicating success and a dictionary with package name as
+            key and list of dictionaries containing detailed data for the found
+            packages as values
+        @rtype tuple of (bool, dict of list of dict)
+        @exception RuntimeError raised to indicate an error in parameters
+        
+        Note: only one of name or prefix must be given.
+        """
+        if name and prefix:
+            raise RuntimeError("Only one of 'name' or 'prefix' must be given.")
+        
+        args = [
+            "search",
+            "--json",
+        ]
+        if fullNameOnly:
+            args.append("--full-name")
+        if packageSpec:
+            args.append("--spec")
+        if platform:
+            args.extend(["--platform", platform])
+        if name:
+            args.extend(["--name", name])
+        elif prefix:
+            args.extend(["--prefix", prefix])
+        args.append(pattern)
+        
+        exe = Preferences.getConda("CondaExecutable")
+        if not exe:
+            exe = "conda"
+        
+        packages = {}
+        ok = False
+        
+        proc = QProcess()
+        proc.start(exe, args)
+        if proc.waitForStarted(15000):
+            if proc.waitForFinished(30000):
+                output = str(proc.readAllStandardOutput(),
+                             Preferences.getSystem("IOEncoding"),
+                             'replace').strip()
+                try:
+                    packages = json.loads(output)
+                    ok = "error" not in packages
+                except Exception:
+                    # return values for errors is already set
+                    pass
+        
+        return ok, packages
+    
+    #######################################################################
+    ## special methods below
+    #######################################################################
+    
+    def updateConda(self):
+        """
+        Public method to update conda itself.
+        
+        @return flag indicating success
+        @rtype bool
+        """
+        args = [
+            "update",
+            "--json",
+            "--yes",
+            "conda"
+        ]
+        
+        dlg = CondaExecDialog("update", self.__ui)
+        dlg.start(args)
+        dlg.exec_()
+        ok, _ = dlg.getResult()
+        
+        return ok
+    
+    def writeDefaultConfiguration(self):
+        """
+        Public method to create a conda configuration with default values.
+        """
+        args = [
+            "config",
+            "--write-default",
+            "--quiet"
+        ]
+        
+        exe = Preferences.getConda("CondaExecutable")
+        if not exe:
+            exe = "conda"
+        
+        proc = QProcess()
+        proc.start(exe, args)
+        proc.waitForStarted(15000)
+        proc.waitForFinished(30000)
+    
+    def getCondaInformation(self):
+        """
+        Public method to get a dictionary containing information about conda.
+        
+        @return dictionary containing information about conda
+        @rtype dict
+        """
+        exe = Preferences.getConda("CondaExecutable")
+        if not exe:
+            exe = "conda"
+        
+        infoDict = {}
+        
+        proc = QProcess()
+        proc.start(exe, ["info", "--json"])
+        if proc.waitForStarted(15000):
+            if proc.waitForFinished(30000):
+                output = str(proc.readAllStandardOutput(),
+                             Preferences.getSystem("IOEncoding"),
+                             'replace').strip()
+                try:
+                    infoDict = json.loads(output)
+                except Exception:
+                    infoDict = {}
+        
+        return infoDict
+    
+    def runProcess(self, args):
+        """
+        Public method to execute the conda with the given arguments.
+        
+        The conda executable is called with the given arguments and
+        waited for its end.
+        
+        @param args list of command line arguments
+        @type list of str
+        @return tuple containing a flag indicating success and the output
+            of the process
+        @rtype tuple of (bool, str)
+        """
+        exe = Preferences.getConda("CondaExecutable")
+        if not exe:
+            exe = "conda"
+        
+        process = QProcess()
+        process.start(exe, args)
+        procStarted = process.waitForStarted(15000)
+        if procStarted:
+            finished = process.waitForFinished(30000)
+            if finished:
+                if process.exitCode() == 0:
+                    output = str(process.readAllStandardOutput(),
+                                 Preferences.getSystem("IOEncoding"),
+                                 'replace').strip()
+                    return True, output
+                else:
+                    return (False,
+                            self.tr("conda exited with an error ({0}).")
+                            .format(process.exitCode()))
+            else:
+                process.terminate()
+                process.waitForFinished(2000)
+                process.kill()
+                process.waitForFinished(3000)
+                return False, self.tr("conda did not finish within"
+                                      " 30 seconds.")
+        
+        return False, self.tr("conda could not be started.")
+    
+    def cleanConda(self, cleanAction):
+        """
+        Public method to update conda itself.
+        
+        @param cleanAction cleaning action to be performed (must be one of
+            the command line parameters without '--')
+        @type str
+        """
+        args = [
+            "clean",
+            "--yes",
+            "--{0}".format(cleanAction),
+        ]
+        
+        dlg = CondaExecDialog("clean", self.__ui)
+        dlg.start(args)
+        dlg.exec_()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CondaInterface/CondaExecDialog.py	Sat Feb 16 15:36:36 2019 +0100
@@ -0,0 +1,294 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to show the output of a conda execution.
+"""
+
+from __future__ import unicode_literals
+try:
+    str = unicode
+except NameError:
+    pass
+
+import json
+
+from PyQt5.QtCore import pyqtSlot, QProcess, QTimer
+from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton
+
+from E5Gui import E5MessageBox
+
+from .Ui_CondaExecDialog import Ui_CondaExecDialog
+
+import Preferences
+import Globals
+
+
+class CondaExecDialog(QDialog, Ui_CondaExecDialog):
+    """
+    Class implementing a dialog to show the output of a conda execution.
+    """
+    def __init__(self, command, parent=None):
+        """
+        Constructor
+        
+        @param command conda command executed
+        @type str
+        @param parent reference to the parent widget
+        @type QWidget
+        """
+        super(CondaExecDialog, self).__init__(parent)
+        self.setupUi(self)
+        
+        self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
+        self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
+        
+        self.__condaCommand = command
+        
+        self.__process = None
+        self.__condaExe = Preferences.getConda("CondaExecutable")
+        if not self.__condaExe:
+            self.__condaExe = "conda"
+    
+    @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.accept()
+        elif button == self.buttonBox.button(QDialogButtonBox.Cancel):
+            self.__finish(1, 0)
+    
+    def start(self, arguments):
+        """
+        Public slot to start the conda command.
+        
+        @param arguments commandline arguments for conda program
+        @type list of str
+        """
+        self.errorGroup.hide()
+        self.progressLabel.hide()
+        self.progressBar.hide()
+        
+        self.contents.clear()
+        self.errors.clear()
+        self.progressLabel.clear()
+        self.progressBar.setValue(0)
+        
+        self.__bufferedStdout = None
+        self.__json = "--json" in arguments
+        self.__firstProgress = True
+        self.__lastFetchFile = ""
+        
+        self.__statusOk = False
+        self.__result = None
+        
+        self.__logOutput(self.__condaExe + " " + " ".join(arguments) + "\n\n")
+        
+        self.__process = QProcess()
+        self.__process.readyReadStandardOutput.connect(self.__readStdout)
+        self.__process.readyReadStandardError.connect(self.__readStderr)
+        self.__process.finished.connect(self.__finish)
+        
+        self.__process.start(self.__condaExe, arguments)
+        procStarted = self.__process.waitForStarted(5000)
+        if not procStarted:
+            E5MessageBox.critical(
+                self,
+                self.tr("Conda Execution"),
+                self.tr("""The conda executable could not be started. Is it"""
+                        """ configured correctly?"""))
+            self.__finish(1, 0)
+        else:
+            self.__logOutput(self.tr("Operation started.\n"))
+    
+    def __finish(self, exitCode, exitStatus, giveUp=False):
+        """
+        Private slot called when the process finished.
+        
+        It is called when the process finished or
+        the user pressed the button.
+        
+        @param exitCode exit code of the process
+        @type int
+        @param exitStatus exit status of the process
+        @type QProcess.ExitStatus
+        @param giveUp flag indicating to not start another attempt
+        @type bool
+        """
+        if self.__process is not None and \
+           self.__process.state() != QProcess.NotRunning:
+            self.__process.terminate()
+            QTimer.singleShot(2000, self.__process.kill)
+            self.__process.waitForFinished(3000)
+        
+        self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
+        self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
+        self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
+        
+        self.progressLabel.hide()
+        self.progressBar.hide()
+        
+        self.__statusOk = exitCode == 0
+        
+        self.__logOutput(self.tr("Operation finished.\n"))
+        if not self.__json and self.__bufferedStdout:
+            self.__logOutput(self.__bufferedStdout)
+        
+        if self.__json and self.__bufferedStdout:
+            index = self.__bufferedStdout.find("{")
+            rindex = self.__bufferedStdout.rfind("}")
+            self.__bufferedStdout = self.__bufferedStdout[index:rindex + 1]
+            try:
+                self.__result = json.loads(self.__bufferedStdout)
+            except Exception as error:
+                self.__result = {}
+                self.__logError(str(error))
+                return
+            
+            if "error" in self.__result:
+                self.__logError(self.__result["error"])
+                self.__statusOk = False
+            elif "success" in self.__result and \
+                    not self.__result["success"]:
+                self.__logError(
+                    self.tr("Conda command '{0}' did not return success.")
+                    .format(self.__condaCommand))
+                if "message" in self.__result:
+                    self.__logError("\n")
+                    self.__logError(
+                        self.tr("\nConda Message: {0}").format(
+                            self.__result["message"]))
+                self.__statusOk = False
+            elif "message" in self.__result:
+                self.__logOutput(
+                    self.tr("\nConda Message: {0}").format(
+                        self.__result["message"]))
+    
+    def getResult(self):
+        """
+        Public method to the result of the command execution.
+        
+        @return tuple containing a flag indicating success and the result data.
+        @rtype tuple of (bool, dict)
+        """
+        return self.__statusOk, self.__result
+    
+    def __setProgressValues(self, jsonDict, progressType):
+        """
+        Private method to set the value of the progress bar.
+        
+        @param jsonDict dictionary containing the progress info
+        @type dict
+        @param progressType action type to check for
+        @type str
+        @return flag indicating success
+        @rtype bool
+        """
+        if progressType in jsonDict and "progress" in jsonDict:
+            if jsonDict["maxval"] == 1:
+                self.progressBar.setMaximum(100)
+                # percent values
+                self.progressBar.setValue(
+                    int(jsonDict["progress"] * 100))
+                parts = jsonDict["fetch"].split("|")
+                filename = parts[0].strip()
+                filesize = parts[1].strip()
+            else:
+                self.progressBar.setMaximum(jsonDict["maxval"])
+                self.progressBar.setValue(jsonDict["progress"])
+                filename = jsonDict["fetch"].strip()
+                filesize = Globals.dataString(int(jsonDict["maxval"]))
+            
+            self.progressLabel.setText(
+                self.tr("{0} (Size: {1})").format(filename, filesize))
+            
+            if progressType == "fetch":
+                if filename != self.__lastFetchFile:
+                    self.__logOutput(
+                        self.tr("Fetching {0} ...").format(filename))
+                    self.__lastFetchFile = filename
+                elif jsonDict["finished"]:
+                    self.__logOutput(self.tr(" Done.\n"))
+            
+            if self.__firstProgress:
+                self.progressLabel.show()
+                self.progressBar.show()
+                self.__firstProgress = False
+            
+            return True
+        
+        return False
+    
+    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.
+        """
+        all_stdout = str(self.__process.readAllStandardOutput(),
+                         Preferences.getSystem("IOEncoding"),
+                         'replace')
+        all_stdout = all_stdout.replace("\x00", "")
+        if self.__json:
+            for stdout in all_stdout.splitlines():
+                try:
+                    jsonDict = json.loads(stdout.replace("\x00", "").strip())
+                    if self.__setProgressValues(jsonDict, "fetch"):
+                        # nothing to do anymore
+                        pass
+                    elif "progress" not in jsonDict:
+                        if self.__bufferedStdout is None:
+                            self.__bufferedStdout = stdout
+                        else:
+                            self.__bufferedStdout += stdout
+                except (TypeError, ValueError):
+                    if self.__bufferedStdout is None:
+                        self.__bufferedStdout = stdout
+                    else:
+                        self.__bufferedStdout += stdout
+        else:
+            self.__logOutput(all_stdout)
+    
+    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.__process.setReadChannel(QProcess.StandardError)
+        
+        while self.__process.canReadLine():
+            stderr = str(self.__process.readLine(),
+                         Preferences.getSystem("IOEncoding"),
+                         'replace')
+            self.__logError(stderr)
+    
+    def __logOutput(self, stdout):
+        """
+        Private method to log some output.
+        
+        @param stdout output string to log
+        @type str
+        """
+        self.contents.insertPlainText(stdout)
+        self.contents.ensureCursorVisible()
+    
+    def __logError(self, stderr):
+        """
+        Private method to log an error.
+        
+        @param stderr error string to log
+        @type str
+        """
+        self.errorGroup.show()
+        self.errors.insertPlainText(stderr)
+        self.errors.ensureCursorVisible()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CondaInterface/CondaExecDialog.ui	Sat Feb 16 15:36:36 2019 +0100
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CondaExecDialog</class>
+ <widget class="QDialog" name="CondaExecDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>750</width>
+    <height>600</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Conda Execution</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_3">
+   <item>
+    <widget class="QGroupBox" name="messagesGroup">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+       <horstretch>0</horstretch>
+       <verstretch>3</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="title">
+      <string>Messages</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <item>
+       <widget class="QTextBrowser" name="contents">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+          <horstretch>0</horstretch>
+          <verstretch>3</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="whatsThis">
+         <string>&lt;b&gt;virtualenv Execution&lt;/b&gt;
+&lt;p&gt;This shows the output of the virtualenv command.&lt;/p&gt;</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="progressLabel"/>
+   </item>
+   <item>
+    <widget class="QProgressBar" name="progressBar"/>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="errorGroup">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+       <horstretch>0</horstretch>
+       <verstretch>1</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="title">
+      <string>Errors</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_2">
+      <item>
+       <widget class="QTextBrowser" name="errors">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+          <horstretch>0</horstretch>
+          <verstretch>1</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="whatsThis">
+         <string>&lt;b&gt;virtualenv Execution&lt;/b&gt;
+&lt;p&gt;This shows the errors of the virtualenv command.&lt;/p&gt;</string>
+        </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::Cancel|QDialogButtonBox::Close</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>contents</tabstop>
+  <tabstop>errors</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>CondaExecDialog</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>CondaExecDialog</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/CondaInterface/CondaExportDialog.py	Sat Feb 16 15:36:36 2019 +0100
@@ -0,0 +1,274 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to generate a requirements file for conda.
+"""
+
+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_CondaExportDialog import Ui_CondaExportDialog
+
+
+class CondaExportDialog(QDialog, Ui_CondaExportDialog):
+    """
+    Class implementing a dialog to generate a requirements file for conda.
+    """
+    def __init__(self, conda, envName, envPrefix, parent=None):
+        """
+        Constructor
+        
+        @param conda reference to the master object
+        @type Conda
+        @param envName name of the environment to create the requirements
+            file from
+        @type str
+        @param envPrefix prefix of the environment to create the requirements
+            file from
+        @type str
+        @param parent reference to the parent widget
+        @type QWidget
+        """
+        super(CondaExportDialog, 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.__conda = conda
+        self.__prefix = envPrefix
+        
+        self.environmentLabel.setText("<b>{0}</b>".format(envName))
+        
+        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_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
+        
+        args = [
+            "list",
+            "--export",
+            "--prefix",
+            self.__prefix,
+        ]
+        
+        QApplication.setOverrideCursor(Qt.WaitCursor)
+        success, output = self.__conda.runProcess(args)
+        
+        if success:
+            self.requirementsEdit.setPlainText(output)
+            self.__requirementsAvailable = True
+        else:
+            self.requirementsEdit.setPlainText(
+                self.tr("No output generated by conda."))
+        
+        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()
+            cline, cindex = aw.getCursorPosition()
+            aw.insertAt(self.requirementsEdit.toPlainText(), cline, cindex)
+            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/CondaInterface/CondaExportDialog.ui	Sat Feb 16 15:36:36 2019 +0100
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CondaExportDialog</class>
+ <widget class="QDialog" name="CondaExportDialog">
+  <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="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <layout class="QGridLayout" name="gridLayout_2">
+     <item row="0" column="0">
+      <widget class="QLabel" name="label_2">
+       <property name="text">
+        <string>Conda Environment:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="1">
+      <widget class="QLabel" name="environmentLabel">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="0">
+      <widget class="QLabel" name="label">
+       <property name="text">
+        <string>Requirements File:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="1">
+      <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="toolTip">
+        <string>Replace the current selection with the requirements text</string>
+       </property>
+       <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>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>CondaExportDialog</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>CondaExportDialog</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/CondaInterface/CondaInfoDialog.py	Sat Feb 16 15:36:36 2019 +0100
@@ -0,0 +1,140 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the conda information dialog.
+"""
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import Qt
+from PyQt5.QtWidgets import QDialog
+
+from .Ui_CondaInfoDialog import Ui_CondaInfoDialog
+
+import UI.PixmapCache
+
+
+class CondaInfoDialog(QDialog, Ui_CondaInfoDialog):
+    """
+    Class implementing the conda information dialog.
+    """
+    def __init__(self, infoDict, parent=None):
+        """
+        Constructor
+        
+        @param infoDict dictionary containing the information to be shown
+        @type dict
+        @param parent reference to the parent widget
+        @type QWidget
+        """
+        super(CondaInfoDialog, self).__init__(parent)
+        self.setupUi(self)
+        self.setWindowFlags(Qt.Window)
+        
+        self.iconLabel.setPixmap(
+            UI.PixmapCache.getPixmap("miniconda48.png"))
+        
+        # version information
+        if "conda_version" in infoDict:
+            self.condaVersionLabel.setText(
+                infoDict["conda_version"])
+        if "conda_build_version" in infoDict:
+            self.condaBuildVersionLabel.setText(
+                infoDict["conda_build_version"])
+        if "conda_env_version" in infoDict:
+            self.condaEnvVersionLabel.setText(
+                infoDict["conda_env_version"])
+        if "python_version" in infoDict:
+            self.pythonVersionLabel.setText(
+                infoDict["python_version"])
+        
+        # prefixes
+        if "active_prefix" in infoDict or "active_prefix_name" in infoDict:
+            if infoDict["active_prefix_name"] and infoDict["active_prefix"]:
+                self.activeEnvironmentEdit.setText(
+                    "{0} ({1})".format(infoDict["active_prefix_name"],
+                                       infoDict["active_prefix"]))
+            elif infoDict["active_prefix"]:
+                self.activeEnvironmentEdit.setText(
+                    infoDict["active_prefix"])
+            elif infoDict["active_prefix_name"]:
+                self.activeEnvironmentEdit.setText(
+                    infoDict["active_prefix_name"])
+            else:
+                self.activeEnvironmentEdit.setText(
+                    self.tr("None"))
+        else:
+            self.activeEnvironmentLabel.hide()
+            self.activeEnvironmentEdit.hide()
+        if "root_prefix" in infoDict:
+            if "root_writable" in infoDict and infoDict["root_writable"]:
+                self.baseEnvironmentEdit.setText(
+                    self.tr("{0} (writable)").format(infoDict["root_prefix"]))
+            else:
+                self.baseEnvironmentEdit.setText(
+                    infoDict["root_prefix"])
+        if "envs_dirs" in infoDict:
+            self.envDirsEdit.setPlainText(
+                "\n".join(infoDict["envs_dirs"]))
+        
+        # configurations
+        if "rc_path" in infoDict:
+            self.userConfigEdit.setText(
+                infoDict["rc_path"])
+        if "user_rc_path" in infoDict:
+            # overwrite with more specific info
+            self.userConfigEdit.setText(
+                infoDict["user_rc_path"])
+        if "sys_rc_path" in infoDict:
+            self.systemConfigEdit.setText(
+                infoDict["sys_rc_path"])
+        if "config_files" in infoDict:
+            self.configurationsEdit.setPlainText(
+                "\n".join(infoDict["config_files"]))
+        else:
+            self.configurationsLabel.hide()
+            self.configurationsEdit.hide()
+        
+        # channels
+        if "channels" in infoDict:
+            self.channelsEdit.setPlainText(
+                "\n".join(infoDict["channels"]))
+        
+        # various
+        if "pkgs_dirs" in infoDict:
+            self.cachesEdit.setPlainText(
+                "\n".join(infoDict["pkgs_dirs"]))
+        if "platform" in infoDict:
+            self.platformLabel.setText(
+                infoDict["platform"])
+        if "user_agent" in infoDict:
+            self.useragentEdit.setText(
+                infoDict["user_agent"])
+        else:
+            self.useragentLabel.hide()
+            self.useragentEdit.hide()
+        if "UID" in infoDict and "GID" in infoDict:
+            self.uidGidDataLabel.setText(
+                "{0}:{1}".format(infoDict["UID"], infoDict["GID"]))
+        else:
+            self.uidGidLabel.hide()
+            self.uidGidDataLabel.hide()
+        if "netrc_file" in infoDict:
+            if infoDict["netrc_file"]:
+                self.netrcEdit.setText(
+                    infoDict["netrc_file"])
+            else:
+                self.netrcEdit.setText(
+                    self.tr("None"))
+        else:
+            self.netrcLabel.hide()
+            self.netrcEdit.hide()
+        if "offline" in infoDict:
+            self.offlineCheckBox.setChecked(
+                infoDict["offline"])
+        
+        msh = self.minimumSizeHint()
+        self.resize(max(self.width(), msh.width()), msh.height())
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CondaInterface/CondaInfoDialog.ui	Sat Feb 16 15:36:36 2019 +0100
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CondaInfoDialog</class>
+ <widget class="QDialog" name="CondaInfoDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>650</width>
+    <height>669</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Conda Information</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <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="QLabel" name="iconLabel">
+       <property name="text">
+        <string>icon</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLabel" name="label">
+       <property name="text">
+        <string>&lt;h2&gt;Conda Information&lt;/h2&gt;</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>
+    </layout>
+   </item>
+   <item>
+    <layout class="QGridLayout" name="gridLayout">
+     <item row="0" column="0">
+      <widget class="QLabel" name="label_3">
+       <property name="text">
+        <string>conda Version:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="1">
+      <widget class="QLabel" name="condaVersionLabel"/>
+     </item>
+     <item row="1" column="0">
+      <widget class="QLabel" name="label_4">
+       <property name="text">
+        <string>conda-build Version:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="1">
+      <widget class="QLabel" name="condaBuildVersionLabel"/>
+     </item>
+     <item row="3" column="0">
+      <widget class="QLabel" name="label_5">
+       <property name="text">
+        <string>python Version:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="3" column="1">
+      <widget class="QLabel" name="pythonVersionLabel"/>
+     </item>
+     <item row="4" column="0">
+      <widget class="QLabel" name="activeEnvironmentLabel">
+       <property name="text">
+        <string>Active Environment:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="4" column="1">
+      <widget class="QLineEdit" name="activeEnvironmentEdit"/>
+     </item>
+     <item row="5" column="0">
+      <widget class="QLabel" name="label_6">
+       <property name="text">
+        <string>User Configuration:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="5" column="1">
+      <widget class="QLineEdit" name="userConfigEdit"/>
+     </item>
+     <item row="6" column="0">
+      <widget class="QLabel" name="label_17">
+       <property name="text">
+        <string>System Configuration:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="6" column="1">
+      <widget class="QLineEdit" name="systemConfigEdit"/>
+     </item>
+     <item row="7" column="0">
+      <widget class="QLabel" name="configurationsLabel">
+       <property name="text">
+        <string>Populated Configurations:</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+       </property>
+      </widget>
+     </item>
+     <item row="7" column="1">
+      <widget class="QPlainTextEdit" name="configurationsEdit"/>
+     </item>
+     <item row="8" column="0">
+      <widget class="QLabel" name="label_8">
+       <property name="text">
+        <string>Base Environment:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="8" column="1">
+      <widget class="QLineEdit" name="baseEnvironmentEdit"/>
+     </item>
+     <item row="9" column="0">
+      <widget class="QLabel" name="label_9">
+       <property name="text">
+        <string>Channel URLs:</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+       </property>
+      </widget>
+     </item>
+     <item row="9" column="1">
+      <widget class="QPlainTextEdit" name="channelsEdit"/>
+     </item>
+     <item row="10" column="0">
+      <widget class="QLabel" name="label_10">
+       <property name="text">
+        <string>Package Cache:</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+       </property>
+      </widget>
+     </item>
+     <item row="10" column="1">
+      <widget class="QPlainTextEdit" name="cachesEdit"/>
+     </item>
+     <item row="11" column="0">
+      <widget class="QLabel" name="label_11">
+       <property name="text">
+        <string>Environment Directories:</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+       </property>
+      </widget>
+     </item>
+     <item row="11" column="1">
+      <widget class="QPlainTextEdit" name="envDirsEdit"/>
+     </item>
+     <item row="12" column="0">
+      <widget class="QLabel" name="label_12">
+       <property name="text">
+        <string>Platform:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="12" column="1">
+      <widget class="QLabel" name="platformLabel"/>
+     </item>
+     <item row="13" column="0">
+      <widget class="QLabel" name="useragentLabel">
+       <property name="text">
+        <string>User-Agent:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="13" column="1">
+      <widget class="QLineEdit" name="useragentEdit"/>
+     </item>
+     <item row="14" column="0">
+      <widget class="QLabel" name="uidGidLabel">
+       <property name="text">
+        <string>UID:GID:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="14" column="1">
+      <widget class="QLabel" name="uidGidDataLabel"/>
+     </item>
+     <item row="15" column="0">
+      <widget class="QLabel" name="netrcLabel">
+       <property name="text">
+        <string>netrc File:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="15" column="1">
+      <widget class="QLineEdit" name="netrcEdit"/>
+     </item>
+     <item row="16" column="0">
+      <widget class="QLabel" name="label_16">
+       <property name="text">
+        <string>Offline Mode:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="16" column="1">
+      <widget class="QCheckBox" name="offlineCheckBox">
+       <property name="text">
+        <string/>
+       </property>
+      </widget>
+     </item>
+     <item row="2" column="0">
+      <widget class="QLabel" name="label_18">
+       <property name="text">
+        <string>conda-env Version:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="2" column="1">
+      <widget class="QLabel" name="condaEnvVersionLabel"/>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>CondaInfoDialog</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>CondaInfoDialog</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/CondaInterface/CondaNewEnvironmentDataDialog.py	Sat Feb 16 15:36:36 2019 +0100
@@ -0,0 +1,112 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to enter data for a new conda environment.
+"""
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import pyqtSlot
+from PyQt5.QtWidgets import QDialog, QDialogButtonBox
+
+from E5Gui.E5PathPicker import E5PathPickerModes
+
+from .Ui_CondaNewEnvironmentDataDialog import Ui_CondaNewEnvironmentDataDialog
+
+
+class CondaNewEnvironmentDataDialog(QDialog, Ui_CondaNewEnvironmentDataDialog):
+    """
+    Class implementing a dialog to enter data for a new conda environment.
+    """
+    def __init__(self, title, showRequirements, parent=None):
+        """
+        Constructor
+        
+        @param title tirle of the dialog
+        @type str
+        @param showRequirements flag indicating to show the requirements
+            file input widget
+        @type bool
+        @param parent reference to the parent widget
+        @type QWidget
+        """
+        super(CondaNewEnvironmentDataDialog, self).__init__(parent)
+        self.setupUi(self)
+        
+        self.setWindowTitle(title)
+        
+        self.__requirementsMode = showRequirements
+        
+        self.requirementsFilePicker.setMode(E5PathPickerModes.OpenFileMode)
+        self.requirementsFilePicker.setFilters(
+            self.tr("Text Files (*.txt);;All Files (*)"))
+        
+        self.requirementsLabel.setVisible(showRequirements)
+        self.requirementsFilePicker.setVisible(showRequirements)
+        
+        self.__updateOK()
+        
+        msh = self.minimumSizeHint()
+        self.resize(max(self.width(), msh.width()), msh.height())
+   
+    def __updateOK(self):
+        """
+        Private method to update the enabled state of the OK button.
+        """
+        enable = bool(self.nameEdit.text()) and bool(self.condaNameEdit.text())
+        if self.__requirementsMode:
+            enable &= bool(self.requirementsFilePicker.text())
+        
+        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(enable)
+    
+    @pyqtSlot(str)
+    def on_nameEdit_textChanged(self, txt):
+        """
+        Private slot to handle changes of the logical name.
+        
+        @param txt current text of the logical name entry
+        @type str
+        """
+        self.__updateOK()
+    
+    @pyqtSlot(str)
+    def on_condaNameEdit_textChanged(self, txt):
+        """
+        Private slot to handle changes of the conda name.
+        
+        @param txt current text of the conda name entry
+        @type str
+        """
+        self.__updateOK()
+    
+    @pyqtSlot(str)
+    def on_requirementsFilePicker_textChanged(self, txt):
+        """
+        Private slot to handle changes of the requirements file name.
+        
+        @param txt current text of the requirements file name entry
+        @type str
+        """
+        self.__updateOK()
+    
+    def getData(self):
+        """
+        Public method to get the entered data.
+        
+        @return tuple with the logical name of the new environment, the conda
+            name and the requirements file name
+        @rtype tuple of (str, str, str)
+        """
+        if self.__requirementsMode:
+            requirementsFile = self.requirementsFilePicker.text()
+        else:
+            requirementsFile = ""
+        
+        return (
+            self.nameEdit.text(),
+            self.condaNameEdit.text(),
+            requirementsFile
+        )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CondaInterface/CondaNewEnvironmentDataDialog.ui	Sat Feb 16 15:36:36 2019 +0100
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CondaNewEnvironmentDataDialog</class>
+ <widget class="QDialog" name="CondaNewEnvironmentDataDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>500</width>
+    <height>112</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QLabel" name="label_2">
+     <property name="text">
+      <string>Logical Name:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="E5ClearableLineEdit" name="nameEdit">
+     <property name="toolTip">
+      <string>Enter a unique name for the virtual environment to register it with the Virtual Environment Manager</string>
+     </property>
+     <property name="placeholderText">
+      <string>Name for registration of the virtual environment</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Conda Name:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="E5ClearableLineEdit" name="condaNameEdit">
+     <property name="toolTip">
+      <string>Enter the name of the virtual environment in Conda</string>
+     </property>
+     <property name="placeholderText">
+      <string>Name of the virtual environment in Conda</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0">
+    <widget class="QLabel" name="requirementsLabel">
+     <property name="text">
+      <string>Requirements File:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="1">
+    <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>
+   <item row="3" column="0" colspan="2">
+    <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>E5ClearableLineEdit</class>
+   <extends>QLineEdit</extends>
+   <header>E5Gui/E5LineEdit.h</header>
+  </customwidget>
+  <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>CondaNewEnvironmentDataDialog</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>CondaNewEnvironmentDataDialog</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/CondaInterface/CondaPackageDetailsWidget.py	Sat Feb 16 15:36:36 2019 +0100
@@ -0,0 +1,96 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a widget and a dialog to show package details.
+"""
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import Qt, QDateTime
+from PyQt5.QtWidgets import QWidget, QDialog, QVBoxLayout, QDialogButtonBox
+
+from .Ui_CondaPackageDetailsWidget import Ui_CondaPackageDetailsWidget
+
+from Globals import dataString
+
+
+class CondaPackageDetailsWidget(QWidget, Ui_CondaPackageDetailsWidget):
+    """
+    Class implementing a widget to show package details.
+    """
+    def __init__(self, details, parent=None):
+        """
+        Constructor
+        
+        @param details dictionary containing the package details
+        @type dict
+        @param parent reference to the parent widget
+        @type QWidget
+        """
+        super(CondaPackageDetailsWidget, self).__init__(parent)
+        self.setupUi(self)
+        
+        self.headerLabel.setText(self.tr("<b>{0} / {1} / {2}</b>").format(
+            details["name"], details["version"], details["build"]))
+        if "fn" in details:
+            self.filenameLabel.setText(details["fn"])
+        if "size" in details:
+            self.sizeLabel.setText(dataString(details["size"]))
+        if "channel" in details:
+            self.channelLabel.setText(details["channel"])
+        if "url" in details:
+            self.urlLabel.setText(details["url"])
+        if "md5" in details:
+            self.md5Label.setText(details["md5"])
+        if "license" in details:
+            self.licenseLabel.setText(details["license"])
+        if "subdir" in details:
+            self.platformLabel.setText(details["subdir"])
+        elif "platform" in details:
+            self.platformLabel.setText(details["platform"])
+        else:
+            self.platformLabel.setText(self.tr("unknown"))
+        if "depends" in details:
+            self.dependenciesEdit.setPlainText("\n".join(details["depends"]))
+        
+        if "timestamp" in details:
+            dt = QDateTime.fromMSecsSinceEpoch(details["timestamp"], Qt.UTC)
+            self.timestampLabel.setText(dt.toString("yyyy-MM-dd hh:mm:ss t"))
+        
+        self.resize(600, 450)
+
+
+class CondaPackageDetailsDialog(QDialog):
+    """
+    Class implementing a dialog to show package details.
+    """
+    def __init__(self, details, parent=None):
+        """
+        Constructor
+        
+        @param details dictionary containing the package details
+        @type dict
+        @param parent reference to the parent widget
+        @type QWidget
+        """
+        super(CondaPackageDetailsDialog, self).__init__(parent)
+        self.setSizeGripEnabled(True)
+        
+        self.__layout = QVBoxLayout(self)
+        self.setLayout(self.__layout)
+        
+        self.__cw = CondaPackageDetailsWidget(details, self)
+        size = self.__cw.size()
+        self.__layout.addWidget(self.__cw)
+        self.__buttonBox = QDialogButtonBox(self)
+        self.__buttonBox.setStandardButtons(QDialogButtonBox.Close)
+        self.__layout.addWidget(self.__buttonBox)
+        
+        self.resize(size)
+        self.setWindowTitle(self.tr("Package Details"))
+        
+        self.__buttonBox.accepted.connect(self.accept)
+        self.__buttonBox.rejected.connect(self.reject)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CondaInterface/CondaPackageDetailsWidget.ui	Sat Feb 16 15:36:36 2019 +0100
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CondaPackageDetailsWidget</class>
+ <widget class="QWidget" name="CondaPackageDetailsWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>600</width>
+    <height>450</height>
+   </rect>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0" colspan="2">
+    <widget class="QLabel" name="headerLabel">
+     <property name="text">
+      <string/>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="label_2">
+     <property name="text">
+      <string>Filename:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="QLabel" name="filenameLabel"/>
+   </item>
+   <item row="2" column="0">
+    <widget class="QLabel" name="label_3">
+     <property name="text">
+      <string>Size:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="1">
+    <widget class="QLabel" name="sizeLabel"/>
+   </item>
+   <item row="3" column="0">
+    <widget class="QLabel" name="label_5">
+     <property name="text">
+      <string>Channel:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="1">
+    <widget class="QLabel" name="channelLabel"/>
+   </item>
+   <item row="4" column="0">
+    <widget class="QLabel" name="label_4">
+     <property name="text">
+      <string>URL:</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="1">
+    <widget class="QLabel" name="urlLabel">
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="5" column="0">
+    <widget class="QLabel" name="label_6">
+     <property name="text">
+      <string>MD5:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="5" column="1">
+    <widget class="QLabel" name="md5Label"/>
+   </item>
+   <item row="6" column="0">
+    <widget class="QLabel" name="label_7">
+     <property name="text">
+      <string>Timestamp:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="6" column="1">
+    <widget class="QLabel" name="timestampLabel"/>
+   </item>
+   <item row="7" column="0">
+    <widget class="QLabel" name="label_8">
+     <property name="text">
+      <string>License:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="7" column="1">
+    <widget class="QLabel" name="licenseLabel"/>
+   </item>
+   <item row="8" column="0">
+    <widget class="QLabel" name="label_9">
+     <property name="text">
+      <string>Platform:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="8" column="1">
+    <widget class="QLabel" name="platformLabel"/>
+   </item>
+   <item row="9" column="0">
+    <widget class="QLabel" name="label_10">
+     <property name="text">
+      <string>Dependencies:</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+     </property>
+    </widget>
+   </item>
+   <item row="9" column="1">
+    <widget class="QPlainTextEdit" name="dependenciesEdit">
+     <property name="readOnly">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CondaInterface/CondaPackagesWidget.py	Sat Feb 16 15:36:36 2019 +0100
@@ -0,0 +1,714 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the conda packages management widget.
+"""
+
+from __future__ import unicode_literals
+
+import os
+
+from PyQt5.QtCore import pyqtSlot, Qt
+from PyQt5.QtGui import QCursor
+from PyQt5.QtWidgets import QWidget, QToolButton, QMenu, QTreeWidgetItem, \
+    QApplication, QLineEdit, QDialog
+
+from E5Gui import E5FileDialog, E5MessageBox, E5TextInputDialog
+from E5Gui.E5Application import e5App
+
+from .Ui_CondaPackagesWidget import Ui_CondaPackagesWidget
+
+import UI.PixmapCache
+
+import CondaInterface
+
+
+class CondaPackagesWidget(QWidget, Ui_CondaPackagesWidget):
+    """
+    Class implementing the conda packages management widget.
+    """
+    # Role definition of packages list
+    PackageVersionRole = Qt.UserRole + 1
+    PackageBuildRole = Qt.UserRole + 2
+    
+    # Role definitions of search results list
+    PackageDetailedDataRole = Qt.UserRole + 1
+    
+    def __init__(self, conda, parent=None):
+        """
+        Constructor
+        
+        @param conda reference to the conda interface
+        @type Conda
+        @param parent reference to the parent widget
+        @type QWidget
+        """
+        super(CondaPackagesWidget, self).__init__(parent)
+        self.setupUi(self)
+        
+        self.__conda = conda
+        
+        if not CondaInterface.isCondaAvailable():
+            self.baseWidget.hide()
+            self.searchWidget.hide()
+        
+        else:
+            self.notAvailableWidget.hide()
+            
+            self.__initCondaInterface()
+    
+    def __initCondaInterface(self):
+        """
+        Private method to initialize the conda interface elements.
+        """
+        self.statusLabel.hide()
+        
+        self.condaMenuButton.setObjectName(
+            "navigation_supermenu_button")
+        self.condaMenuButton.setIcon(UI.PixmapCache.getIcon("superMenu.png"))
+        self.condaMenuButton.setToolTip(self.tr("Conda Menu"))
+        self.condaMenuButton.setPopupMode(QToolButton.InstantPopup)
+        self.condaMenuButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
+        self.condaMenuButton.setFocusPolicy(Qt.NoFocus)
+        self.condaMenuButton.setAutoRaise(True)
+        self.condaMenuButton.setShowMenuInside(True)
+        
+        self.searchToggleButton.setIcon(UI.PixmapCache.getIcon("find.png"))
+        
+        if CondaInterface.condaVersion() >= (4, 4, 0):
+            self.searchOptionsWidget.hide()
+        else:
+            self.platformComboBox.addItems(sorted([
+                "", "win-32", "win-64", "osx-64", "linux-32", "linux-64",
+            ]))
+        
+        self.__initCondaMenu()
+        self.__populateEnvironments()
+        self.__updateActionButtons()
+        
+        self.searchWidget.hide()
+        
+        self.__conda.condaEnvironmentCreated.connect(
+            self.on_refreshButton_clicked)
+        self.__conda.condaEnvironmentRemoved.connect(
+            self.on_refreshButton_clicked)
+    
+    def __populateEnvironments(self):
+        """
+        Private method to get a list of environments and populate the selector.
+        """
+        environments = [("", "")] + sorted(
+            self.__conda.getCondaEnvironmentsList())
+        for environment in environments:
+            self.environmentsComboBox.addItem(environment[0], environment[1])
+    
+    def __initCondaMenu(self):
+        """
+        Private method to create the super menu and attach it to the super
+        menu button.
+        """
+        self.__condaMenu = QMenu(self)
+        self.__envActs = []
+        
+        self.__cleanMenu = QMenu(self.tr("Clean"), self)
+        self.__cleanMenu.addAction(
+            self.tr("All"), lambda: self.__conda.cleanConda("all"))
+        self.__cleanMenu.addAction(
+            self.tr("Cache"), lambda: self.__conda.cleanConda("index-cache"))
+        self.__cleanMenu.addAction(
+            self.tr("Lock Files"),
+            lambda: self.__conda.cleanConda("lock"))
+        self.__cleanMenu.addAction(
+            self.tr("Packages"), lambda: self.__conda.cleanConda("packages"))
+        self.__cleanMenu.addAction(
+            self.tr("Tarballs"), lambda: self.__conda.cleanConda("tarballs"))
+        
+        self.__condaMenu.addAction(
+            self.tr("About Conda..."), self.__aboutConda)
+        self.__condaMenu.addSeparator()
+        self.__condaMenu.addAction(
+            self.tr("Update Conda"), self.__conda.updateConda)
+        self.__condaMenu.addSeparator()
+        self.__envActs.append(self.__condaMenu.addAction(
+            self.tr("Install Packages"), self.__installPackages))
+        self.__envActs.append(self.__condaMenu.addAction(
+            self.tr("Install Requirements"), self.__installRequirements))
+        self.__condaMenu.addSeparator()
+        self.__envActs.append(self.__condaMenu.addAction(
+            self.tr("Generate Requirements"), self.__generateRequirements))
+        self.__condaMenu.addSeparator()
+        self.__condaMenu.addAction(
+            self.tr("Create Environment from Requirements"),
+            self.__createEnvironment)
+        self.__envActs.append(self.__condaMenu.addAction(
+            self.tr("Clone Environment"), self.__cloneEnvironment))
+        self.__deleteEnvAct = self.__condaMenu.addAction(
+            self.tr("Delete Environment"), self.__deleteEnvironment)
+        self.__condaMenu.addSeparator()
+        self.__condaMenu.addMenu(self.__cleanMenu)
+        self.__condaMenu.addSeparator()
+        self.__condaMenu.addAction(
+            self.tr("Edit User Configuration..."),
+            self.__editUserConfiguration)
+        self.__condaMenu.addSeparator()
+        self.__condaMenu.addAction(
+            self.tr("Configure..."), self.__condaConfigure)
+        
+        self.condaMenuButton.setMenu(self.__condaMenu)
+        
+        self.__condaMenu.aboutToShow.connect(self.__aboutToShowCondaMenu)
+    
+    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.
+        """
+        self.upgradeButton.setEnabled(
+            bool(self.__selectedUpdateableItems()))
+        self.uninstallButton.setEnabled(
+            bool(self.packagesList.selectedItems()))
+        self.upgradeAllButton.setEnabled(
+            bool(self.__allUpdateableItems()))
+    
+    @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.packagesList.clear()
+        prefix = self.environmentsComboBox.itemData(index)
+        if prefix:
+            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.__conda.getInstalledPackages(prefix=prefix)
+            for package, version, build in installedPackages:
+                itm = QTreeWidgetItem(self.packagesList, [package, version])
+                itm.setData(1, self.PackageVersionRole, version)
+                itm.setData(1, self.PackageBuildRole, build)
+            self.packagesList.setUpdatesEnabled(True)
+            self.statusLabel.setText(self.tr("Getting outdated packages..."))
+            QApplication.processEvents()
+            
+            # 2. update with update information
+            self.packagesList.setUpdatesEnabled(False)
+            updateablePackages = \
+                self.__conda.getUpdateablePackages(prefix=prefix)
+            for package, version, build in updateablePackages:
+                items = self.packagesList.findItems(
+                    package, Qt.MatchExactly | Qt.MatchCaseSensitive)
+                if items:
+                    itm = items[0]
+                    itm.setText(2, version)
+                    itm.setData(2, self.PackageVersionRole, version)
+                    itm.setData(2, self.PackageBuildRole, build)
+                    if itm.data(1, self.PackageVersionRole) == version:
+                        # build must be different, show in version display
+                        itm.setText(1, self.tr("{0} (Build: {1})").format(
+                            itm.data(1, self.PackageVersionRole),
+                            itm.data(1, self.PackageBuildRole),
+                        ))
+                        itm.setText(2, self.tr("{0} (Build: {1})").format(
+                            itm.data(2, self.PackageVersionRole),
+                            itm.data(2, self.PackageBuildRole),
+                        ))
+            
+            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()
+    
+    @pyqtSlot()
+    def on_packagesList_itemSelectionChanged(self):
+        """
+        Private slot to handle the selection of some items..
+        """
+        self.__updateActionButtons()
+    
+    @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:
+            prefix = self.environmentsComboBox.itemData(
+                self.environmentsComboBox.currentIndex())
+            ok = self.__conda.updatePackages(packages, prefix=prefix)
+            if ok:
+                self.on_refreshButton_clicked()
+    
+    @pyqtSlot()
+    def on_upgradeAllButton_clicked(self):
+        """
+        Private slot to upgrade all packages of the selected environment.
+        """
+        prefix = self.environmentsComboBox.itemData(
+            self.environmentsComboBox.currentIndex())
+        ok = self.__conda.updateAllPackages(prefix=prefix)
+        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:
+            prefix = self.environmentsComboBox.itemData(
+                self.environmentsComboBox.currentIndex())
+            ok = self.__conda.uninstallPackages(packages, prefix=prefix)
+            if ok:
+                self.on_refreshButton_clicked()
+    
+    #######################################################################
+    ## Search widget related methods below
+    #######################################################################
+    
+    def __updateSearchActionButtons(self):
+        """
+        Private method to update the action button states of the search widget.
+        """
+        enable = len(self.searchResultList.selectedItems()) == 1
+        self.installButton.setEnabled(
+            enable and self.environmentsComboBox.currentIndex() > 0)
+        self.showDetailsButton.setEnabled(
+            enable and bool(self.searchResultList.selectedItems()[0].parent()))
+    
+    def __doSearch(self):
+        """
+        Private method to search for packages.
+        """
+        self.searchResultList.clear()
+        pattern = self.searchEdit.text()
+        if pattern:
+            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
+            QApplication.processEvents()
+            
+            if CondaInterface.condaVersion() >= (4, 4, 0):
+                prefix = ""
+            else:
+                prefix = self.environmentsComboBox.itemData(
+                    self.environmentsComboBox.currentIndex())
+            ok, result = self.__conda.searchPackages(
+                pattern,
+                fullNameOnly=self.fullNameButton.isChecked(),
+                packageSpec=self.packageSpecButton.isChecked(),
+                platform=self.platformComboBox.currentText(),
+                prefix=prefix,
+            )
+            
+            if result:
+                if ok:
+                    self.searchResultList.setUpdatesEnabled(False)
+                    for package in result:
+                        itm = QTreeWidgetItem(self.searchResultList, [package])
+                        itm.setExpanded(False)
+                        for detail in result[package]:
+                            version = detail["version"]
+                            build = detail["build"]
+                            if "subdir" in detail:
+                                platform = detail["subdir"]
+                            elif "platform" in detail:
+                                platform = detail["platform"]
+                            else:
+                                platform = ""
+                            citm = QTreeWidgetItem(
+                                itm, ["", version, build, platform])
+                            citm.setData(0, self.PackageDetailedDataRole,
+                                         detail)
+                
+                    self.searchResultList.sortItems(0, Qt.AscendingOrder)
+                    self.searchResultList.resizeColumnToContents(0)
+                    self.searchResultList.setUpdatesEnabled(True)
+                else:
+                    QApplication.restoreOverrideCursor()
+                    try:
+                        message = result["message"]
+                    except KeyError:
+                        message = result["error"]
+                    E5MessageBox.warning(
+                        self,
+                        self.tr("Conda Search Package Error"),
+                        message)
+            QApplication.restoreOverrideCursor()
+    
+    def __showDetails(self, item):
+        """
+        Private method to show a dialog with details about a package item.
+        
+        @param item reference to the package item
+        @type QTreeWidgetItem
+        """
+        details = item.data(0, self.PackageDetailedDataRole)
+        if details:
+            from .CondaPackageDetailsWidget import CondaPackageDetailsDialog
+            dlg = CondaPackageDetailsDialog(details, self)
+            dlg.exec_()
+    
+    @pyqtSlot(str)
+    def on_searchEdit_textChanged(self, txt):
+        """
+        Private slot handling changes of the entered search specification.
+        
+        @param txt current search entry
+        @type str
+        """
+        self.searchButton.setEnabled(bool(txt))
+    
+    @pyqtSlot()
+    def on_searchEdit_returnPressed(self):
+        """
+        Private slot handling the user pressing the Return button in the
+        search edit.
+        """
+        self.__doSearch()
+    
+    @pyqtSlot()
+    def on_searchButton_clicked(self):
+        """
+        Private slot handling the press of the search button.
+        """
+        self.__doSearch()
+    
+    @pyqtSlot()
+    def on_installButton_clicked(self):
+        """
+        Private slot to install a selected package.
+        """
+        if len(self.searchResultList.selectedItems()) == 1:
+            item = self.searchResultList.selectedItems()[0]
+            if item.parent() is None:
+                # it is just the package item
+                package = item.text(0)
+            else:
+                # item with version and build
+                package = "{0}={1}={2}".format(
+                    item.parent().text(0),
+                    item.text(1),
+                    item.text(2),
+                )
+            
+            prefix = self.environmentsComboBox.itemData(
+                self.environmentsComboBox.currentIndex())
+            ok = self.__conda.installPackages([package], prefix=prefix)
+            if ok:
+                self.on_refreshButton_clicked()
+    
+    @pyqtSlot()
+    def on_showDetailsButton_clicked(self):
+        """
+        Private slot handling the 'Show Details' button.
+        """
+        item = self.searchResultList.selectedItems()[0]
+        self.__showDetails(item)
+    
+    @pyqtSlot()
+    def on_searchResultList_itemSelectionChanged(self):
+        """
+        Private slot handling a change of selected search results.
+        """
+        self.__updateSearchActionButtons()
+    
+    @pyqtSlot(QTreeWidgetItem)
+    def on_searchResultList_itemExpanded(self, item):
+        """
+        Private slot handling the expansion of an item.
+        
+        @param item reference to the expanded item
+        @type QTreeWidgetItem
+        """
+        for col in range(1, self.searchResultList.columnCount()):
+            self.searchResultList.resizeColumnToContents(col)
+    
+    @pyqtSlot(QTreeWidgetItem, int)
+    def on_searchResultList_itemDoubleClicked(self, item, column):
+        """
+        Private slot handling a double click of an item.
+        
+        @param item reference to the item that was double clicked
+        @type QTreeWidgetItem
+        @param column column of the double click
+        @type int
+        """
+        if item.parent() is not None:
+            self.__showDetails(item)
+    
+    @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.searchEdit.setFocus(Qt.OtherFocusReason)
+            self.searchEdit.selectAll()
+            
+            self.__updateSearchActionButtons()
+    
+    #######################################################################
+    ## Menu related methods below
+    #######################################################################
+    
+    @pyqtSlot()
+    def __aboutToShowCondaMenu(self):
+        """
+        Private slot to handle the conda menu about to be shown.
+        """
+        selectedEnvironment = self.environmentsComboBox.currentText()
+        enable = selectedEnvironment not in [""]
+        for act in self.__envActs:
+            act.setEnabled(enable)
+        
+        self.__deleteEnvAct.setEnabled(
+            selectedEnvironment not in ["", self.__conda.RootName])
+    
+    @pyqtSlot()
+    def __aboutConda(self):
+        """
+        Private slot to show some information about the conda installation.
+        """
+        infoDict = self.__conda.getCondaInformation()
+        
+        from .CondaInfoDialog import CondaInfoDialog
+        dlg = CondaInfoDialog(infoDict, self)
+        dlg.exec_()
+    
+    @pyqtSlot()
+    def __installPackages(self):
+        """
+        Private slot to install packages.
+        """
+        prefix = self.environmentsComboBox.itemData(
+            self.environmentsComboBox.currentIndex())
+        if prefix:
+            ok, packageSpecs = E5TextInputDialog.getText(
+                self,
+                self.tr("Install Packages"),
+                self.tr("Package Specifications (separated by whitespace):"),
+                QLineEdit.Normal,
+                minimumWidth=600)
+            if ok and packageSpecs.strip():
+                packages = [p.strip() for p in packageSpecs.split()]
+                ok = self.__conda.installPackages(packages, prefix=prefix)
+                if ok:
+                    self.on_refreshButton_clicked()
+    
+    @pyqtSlot()
+    def __installRequirements(self):
+        """
+        Private slot to install packages from requirements files.
+        """
+        prefix = self.environmentsComboBox.itemData(
+            self.environmentsComboBox.currentIndex())
+        if prefix:
+            requirements = E5FileDialog.getOpenFileNames(
+                self,
+                self.tr("Install Packages"),
+                "",
+                self.tr("Text Files (*.txt);;All Files (*)"))
+            if requirements:
+                args = []
+                for requirement in requirements:
+                    args.extend(["--file", requirement])
+                ok = self.__conda.installPackages(args, prefix=prefix)
+                if ok:
+                    self.on_refreshButton_clicked()
+    
+    @pyqtSlot()
+    def __generateRequirements(self):
+        """
+        Private slot to generate a requirements file.
+        """
+        prefix = self.environmentsComboBox.itemData(
+            self.environmentsComboBox.currentIndex())
+        if prefix:
+            env = self.environmentsComboBox.currentText()
+            
+            from .CondaExportDialog import CondaExportDialog
+            
+            self.__requirementsDialog = CondaExportDialog(
+                self.__conda, env, prefix)
+            self.__requirementsDialog.show()
+            QApplication.processEvents()
+            self.__requirementsDialog.start()
+    
+    @pyqtSlot()
+    def __cloneEnvironment(self):
+        """
+        Private slot to clone a conda environment.
+        """
+        from .CondaNewEnvironmentDataDialog import \
+            CondaNewEnvironmentDataDialog
+        
+        prefix = self.environmentsComboBox.itemData(
+            self.environmentsComboBox.currentIndex())
+        if prefix:
+            dlg = CondaNewEnvironmentDataDialog(self.tr("Clone Environment"),
+                                                False, self)
+            if dlg.exec_() == QDialog.Accepted:
+                virtEnvName, envName, _ = dlg.getData()
+                args = [
+                    "--name",
+                    envName.strip(),
+                    "--clone",
+                    prefix,
+                ]
+                ok, prefix, interpreter = \
+                    self.__conda.createCondaEnvironment(args)
+                if ok:
+                    e5App().getObject("VirtualEnvManager").addVirtualEnv(
+                        virtEnvName, prefix, interpreter, isConda=True)
+    
+    @pyqtSlot()
+    def __createEnvironment(self):
+        """
+        Private slot to create a conda environment from a requirements file.
+        """
+        from .CondaNewEnvironmentDataDialog import \
+            CondaNewEnvironmentDataDialog
+        
+        dlg = CondaNewEnvironmentDataDialog(self.tr("Create Environment"),
+                                            True, self)
+        if dlg.exec_() == QDialog.Accepted:
+            virtEnvName, envName, requirements = dlg.getData()
+            args = [
+                "--name",
+                envName.strip(),
+                "--file",
+                requirements,
+            ]
+            ok, prefix, interpreter = \
+                self.__conda.createCondaEnvironment(args)
+            if ok:
+                e5App().getObject("VirtualEnvManager").addVirtualEnv(
+                    virtEnvName, prefix, interpreter, isConda=True)
+    
+    @pyqtSlot()
+    def __deleteEnvironment(self):
+        """
+        Private slot to delete a conda environment.
+        """
+        envName = self.environmentsComboBox.currentText()
+        ok = E5MessageBox.yesNo(
+            self,
+            self.tr("Delete Environment"),
+            self.tr("""<p>Shal the environment <b>{0}</b> really be"""
+                    """ deleted?</p>""").format(envName)
+        )
+        if ok:
+            self.__conda.removeCondaEnvironment(name=envName)
+    
+    @pyqtSlot()
+    def __editUserConfiguration(self):
+        """
+        Private slot to edit the user configuration.
+        """
+        from QScintilla.MiniEditor import MiniEditor
+        
+        cfgFile = CondaInterface.userConfiguration()
+        if not cfgFile:
+            return
+        
+        if not os.path.exists(cfgFile):
+            self.__conda.writeDefaultConfiguration()
+        
+        # check, if the destination is writeable
+        if not os.access(cfgFile, os.W_OK):
+            E5MessageBox.critical(
+                None,
+                self.tr("Edit Configuration"),
+                self.tr("""The configuration file "{0}" does not exist"""
+                        """ or is not writable."""))
+            return
+        
+        self.__editor = MiniEditor(cfgFile, "YAML")
+        self.__editor.show()
+    
+    @pyqtSlot()
+    def __condaConfigure(self):
+        """
+        Private slot to open the configuration page.
+        """
+        e5App().getObject("UserInterface").showPreferences("condaPage")
+    
+    @pyqtSlot()
+    def on_recheckButton_clicked(self):
+        """
+        Private slot to re-check the availability of conda and adjust the
+        interface if it became available.
+        """
+        if CondaInterface.isCondaAvailable():
+            self.__initCondaInterface()
+            
+            self.notAvailableWidget.hide()
+            self.baseWidget.show()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CondaInterface/CondaPackagesWidget.ui	Sat Feb 16 15:36:36 2019 +0100
@@ -0,0 +1,484 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CondaPackagesWidget</class>
+ <widget class="QWidget" name="CondaPackagesWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>600</width>
+    <height>600</height>
+   </rect>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_5">
+   <item>
+    <widget class="QWidget" name="notAvailableWidget" 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>
+       <spacer name="verticalSpacer">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>5</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QLabel" name="notAvailableLabel">
+        <property name="text">
+         <string>&lt;h2&gt;conda is not available&lt;/h2&gt;</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignCenter</set>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout_6">
+        <item>
+         <spacer name="horizontalSpacer_5">
+          <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="QPushButton" name="recheckButton">
+          <property name="toolTip">
+           <string>Press to re-check the availability of conda</string>
+          </property>
+          <property name="text">
+           <string>Re-Check</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="horizontalSpacer_6">
+          <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>
+      <item>
+       <spacer name="verticalSpacer_2">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>2</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QWidget" name="baseWidget" native="true">
+     <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">
+        <item>
+         <widget class="QComboBox" name="environmentsComboBox"/>
+        </item>
+        <item>
+         <widget class="E5ToolButton" name="condaMenuButton"/>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <widget class="QLabel" name="statusLabel"/>
+      </item>
+      <item>
+       <widget class="QTreeWidget" name="packagesList">
+        <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>
+        <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>
+      </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="QPushButton" name="refreshButton">
+          <property name="toolTip">
+           <string>Press to refresh the lists</string>
+          </property>
+          <property name="text">
+           <string>&amp;Refresh</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="upgradeButton">
+          <property name="toolTip">
+           <string>Press to upgrade the selected packages</string>
+          </property>
+          <property name="text">
+           <string>Up&amp;grade</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="upgradeAllButton">
+          <property name="toolTip">
+           <string>Press to upgrade all listed packages</string>
+          </property>
+          <property name="text">
+           <string>Upgrade &amp;All</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="uninstallButton">
+          <property name="toolTip">
+           <string>Press to uninstall the selected package</string>
+          </property>
+          <property name="text">
+           <string>&amp;Uninstall</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="QHBoxLayout" name="horizontalLayout_4">
+        <item>
+         <widget class="QLineEdit" name="searchEdit">
+          <property name="placeholderText">
+           <string>Enter search specification</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>&amp;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>
+         <item>
+          <layout class="QHBoxLayout" name="horizontalLayout_5">
+           <item>
+            <widget class="QRadioButton" name="patternButton">
+             <property name="toolTip">
+              <string>Search string is a pattern (default)</string>
+             </property>
+             <property name="text">
+              <string>Search Pattern</string>
+             </property>
+             <property name="checked">
+              <bool>true</bool>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QRadioButton" name="fullNameButton">
+             <property name="toolTip">
+              <string>Search string is a full name</string>
+             </property>
+             <property name="text">
+              <string>Full Name</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QRadioButton" name="packageSpecButton">
+             <property name="toolTip">
+              <string>Search string is a package specification</string>
+             </property>
+             <property name="text">
+              <string>Package Specification</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="Line" name="line">
+             <property name="orientation">
+              <enum>Qt::Vertical</enum>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="label">
+             <property name="text">
+              <string>Platform:</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QComboBox" name="platformComboBox">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="toolTip">
+              <string>Select the platform</string>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item>
+       <widget class="QTreeWidget" name="searchResultList">
+        <property name="alternatingRowColors">
+         <bool>true</bool>
+        </property>
+        <column>
+         <property name="text">
+          <string>Package</string>
+         </property>
+        </column>
+        <column>
+         <property name="text">
+          <string>Version</string>
+         </property>
+        </column>
+        <column>
+         <property name="text">
+          <string>Build</string>
+         </property>
+        </column>
+        <column>
+         <property name="text">
+          <string>Platform</string>
+         </property>
+        </column>
+       </widget>
+      </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="QPushButton" name="installButton">
+          <property name="toolTip">
+           <string>Press to install the selected package (by name or package specification)</string>
+          </property>
+          <property name="text">
+           <string>&amp;Install</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="showDetailsButton">
+          <property name="toolTip">
+           <string>Press to show details for the selected entry</string>
+          </property>
+          <property name="text">
+           <string>Show Details...</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>condaMenuButton</tabstop>
+  <tabstop>packagesList</tabstop>
+  <tabstop>refreshButton</tabstop>
+  <tabstop>upgradeButton</tabstop>
+  <tabstop>upgradeAllButton</tabstop>
+  <tabstop>uninstallButton</tabstop>
+  <tabstop>searchToggleButton</tabstop>
+  <tabstop>searchEdit</tabstop>
+  <tabstop>searchButton</tabstop>
+  <tabstop>patternButton</tabstop>
+  <tabstop>fullNameButton</tabstop>
+  <tabstop>packageSpecButton</tabstop>
+  <tabstop>platformComboBox</tabstop>
+  <tabstop>searchResultList</tabstop>
+  <tabstop>installButton</tabstop>
+  <tabstop>showDetailsButton</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CondaInterface/__init__.py	Sat Feb 16 15:36:36 2019 +0100
@@ -0,0 +1,135 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Package implementing the various conda related modules.
+"""
+
+from __future__ import unicode_literals
+try:
+    str = unicode
+except NameError:
+    pass
+
+import json
+
+from PyQt5.QtCore import QCoreApplication, QProcess
+
+import Preferences
+
+__CondaVersion = tuple()
+__CondaVersionStr = ""
+__CondaRootPrefix = ""
+__CondaUserConfig = ""
+
+__initialized = False
+
+
+def __initializeCondaInterface():
+    """
+    Private module function to (re-)initialize the conda interface.
+    """
+    global __CondaVersionStr, __CondaVersion, __CondaRootPrefix, \
+        __CondaUserConfig, __initialized
+    
+    if not __initialized:
+        exe = Preferences.getConda("CondaExecutable")
+        if not exe:
+            exe = "conda"
+        
+        proc = QProcess()
+        proc.start(exe, ["info", "--json"])
+        if not proc.waitForStarted(15000):
+            __CondaVersionStr = QCoreApplication.translate(
+                "CondaInterface",
+                '<conda not found or not configured.>')
+        else:
+            proc.waitForFinished(15000)
+            output = str(proc.readAllStandardOutput(),
+                         Preferences.getSystem("IOEncoding"),
+                         'replace').strip()
+            try:
+                jsonDict = json.loads(output)
+            except Exception:
+                __CondaVersionStr = QCoreApplication.translate(
+                    "CondaInterface",
+                    '<conda returned invalid data.')
+                return
+            
+            __CondaVersionStr = jsonDict["conda_version"]
+            __CondaVersion = tuple(
+                int(i) for i in __CondaVersionStr.split(".")
+            )
+            __CondaRootPrefix = jsonDict["root_prefix"]
+            if "user_rc_path" in jsonDict:
+                __CondaUserConfig = jsonDict["user_rc_path"]
+            elif "rc_path" in jsonDict:
+                __CondaUserConfig = jsonDict["rc_path"]
+            
+            __initialized = True
+
+
+def condaVersion():
+    """
+    Module function to get the conda version.
+    
+    @return tuple containing the conda version
+    @rtype tuple of (int, int, int)
+    """
+    __initializeCondaInterface()
+    return __CondaVersion
+
+
+def condaVersionStr():
+    """
+    Module function to get the conda version as a string.
+    
+    @return conda version as a string
+    @rtype str
+    """
+    __initializeCondaInterface()
+    return __CondaVersionStr
+
+
+def rootPrefix():
+    """
+    Module function to get the root prefix.
+    
+    @return root prefix
+    @rtype str
+    """
+    __initializeCondaInterface()
+    return __CondaRootPrefix
+
+
+def userConfiguration():
+    """
+    Module function to get the path of the user configuration file.
+    
+    @return path of the user configuration file
+    @rtype str
+    """
+    __initializeCondaInterface()
+    return __CondaUserConfig
+
+
+def isCondaAvailable():
+    """
+    Module function to check the availability of conda.
+    
+    @return flag indicating conda availability
+    @rtype bool
+    """
+    __initializeCondaInterface()
+    return bool(__CondaVersion)
+
+
+def resetInterface():
+    """
+    Module function to reset the conda interface.
+    """
+    global __initialized
+    
+    __initialized = False
--- a/Globals/__init__.py	Sat Feb 16 13:02:35 2019 +0100
+++ b/Globals/__init__.py	Sat Feb 16 15:36:36 2019 +0100
@@ -412,6 +412,32 @@
     return QByteArray(txt)
 
 
+def dataString(size):
+    """
+    Module function to generate a formatted size string.
+    
+    @param size size to be formatted
+    @type int
+    @return formatted data string
+    @rtype str
+    """
+    if size < 1024:
+        return QCoreApplication.translate(
+            "Globals", "{0:.1f} Bytes").format(size)
+    elif size < 1024 * 1024:
+        size /= 1024
+        return QCoreApplication.translate(
+            "Globals", "{0:.1f} KiB").format(size)
+    elif size < 1024 * 1024 * 1024:
+        size /= 1024 * 1024
+        return QCoreApplication.translate(
+            "Globals", "{0:.2f} MiB").format(size)
+    else:
+        size /= 1024 * 1024 * 1024
+        return QCoreApplication.translate(
+            "Globals", "{0:.2f} GiB").format(size)
+
+
 ###############################################################################
 ## functions for converting QSetting return types to valid types
 ###############################################################################
--- a/Preferences/ConfigurationDialog.py	Sat Feb 16 13:02:35 2019 +0100
+++ b/Preferences/ConfigurationDialog.py	Sat Feb 16 15:36:36 2019 +0100
@@ -142,6 +142,9 @@
                 "applicationPage":
                 [self.tr("Application"), "preferences-application.png",
                  "ApplicationPage", None, None],
+                "condaPage":
+                [self.tr("Conda"), "miniconda.png",
+                 "CondaPage", None, None],
                 "cooperationPage":
                 [self.tr("Cooperation"), "preferences-cooperation.png",
                  "CooperationPage", None, None],
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Preferences/ConfigurationPages/CondaPage.py	Sat Feb 16 15:36:36 2019 +0100
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the conda configuration page.
+"""
+
+from __future__ import unicode_literals
+
+from E5Gui.E5PathPicker import E5PathPickerModes
+
+from .ConfigurationPageBase import ConfigurationPageBase
+from .Ui_CondaPage import Ui_CondaPage
+
+import Preferences
+
+
+class CondaPage(ConfigurationPageBase, Ui_CondaPage):
+    """
+    Class implementing the conda configuration page.
+    """
+    def __init__(self):
+        """
+        Constructor
+        """
+        super(CondaPage, self).__init__()
+        self.setupUi(self)
+        self.setObjectName("CondaPage")
+        
+        self.condaExePicker.setMode(E5PathPickerModes.OpenFileMode)
+        self.condaExePicker.setToolTip(self.tr(
+            "Press to select the conda executable via a file selection"
+            " dialog."))
+        
+        # set initial values
+        self.__condaExecutable = Preferences.getConda("CondaExecutable")
+        self.condaExePicker.setText(self.__condaExecutable)
+        
+    def save(self):
+        """
+        Public slot to save the conda configuration.
+        """
+        condaExecutable = self.condaExePicker.text()
+        if condaExecutable != self.__condaExecutable:
+            Preferences.setConda("CondaExecutable", condaExecutable)
+            
+            import CondaInterface
+            CondaInterface.resetInterface()
+    
+
+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 = CondaPage()
+    return page
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Preferences/ConfigurationPages/CondaPage.ui	Sat Feb 16 15:36:36 2019 +0100
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CondaPage</class>
+ <widget class="QWidget" name="CondaPage">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>585</width>
+    <height>431</height>
+   </rect>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <item>
+    <widget class="QLabel" name="headerLabel">
+     <property name="text">
+      <string>&lt;b&gt;Configure &quot;conda&quot; support&lt;/b&gt;</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="Line" name="line13">
+     <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">
+     <property name="title">
+      <string>conda Executable</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <item>
+       <widget class="E5PathPicker" name="condaExePicker" native="true">
+        <property name="focusPolicy">
+         <enum>Qt::StrongFocus</enum>
+        </property>
+        <property name="toolTip">
+         <string>Enter the path to the conda executable.</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLabel" name="textLabel1_4">
+        <property name="text">
+         <string>&lt;b&gt;Note:&lt;/b&gt; Leave this entry empty to use the default value (conda or conda.exe).</string>
+        </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>292</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>E5PathPicker</class>
+   <extends>QWidget</extends>
+   <header>E5Gui/E5PathPicker.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
--- a/Preferences/ConfigurationPages/InterfacePage.py	Sat Feb 16 13:02:35 2019 +0100
+++ b/Preferences/ConfigurationPages/InterfacePage.py	Sat Feb 16 15:36:36 2019 +0100
@@ -102,6 +102,8 @@
         # right side
         self.codeDocumentationViewerCheckBox.setChecked(
             Preferences.getUI("ShowCodeDocumentationViewer"))
+        self.condaCheckBox.setChecked(
+            Preferences.getUI("ShowCondaPackageManager"))
         self.cooperationCheckBox.setChecked(
             Preferences.getUI("ShowCooperation"))
         self.ircCheckBox.setChecked(
@@ -200,6 +202,9 @@
             "ShowCodeDocumentationViewer",
             self.codeDocumentationViewerCheckBox.isChecked())
         Preferences.setUI(
+            "ShowCondaPackageManager",
+            self.condaCheckBox.isChecked())
+        Preferences.setUI(
             "ShowCooperation",
             self.cooperationCheckBox.isChecked())
         Preferences.setUI(
--- a/Preferences/ConfigurationPages/InterfacePage.ui	Sat Feb 16 13:02:35 2019 +0100
+++ b/Preferences/ConfigurationPages/InterfacePage.ui	Sat Feb 16 15:36:36 2019 +0100
@@ -517,6 +517,16 @@
           </widget>
          </item>
          <item row="0" column="1">
+          <widget class="QCheckBox" name="condaCheckBox">
+           <property name="toolTip">
+            <string>Select to activate the conda package manager widget</string>
+           </property>
+           <property name="text">
+            <string>Conda Package Manager</string>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="0">
           <widget class="QCheckBox" name="cooperationCheckBox">
            <property name="toolTip">
             <string>Select to activate the Cooperation widget</string>
@@ -526,7 +536,7 @@
            </property>
           </widget>
          </item>
-         <item row="1" column="0">
+         <item row="1" column="1">
           <widget class="QCheckBox" name="ircCheckBox">
            <property name="toolTip">
             <string>Select to activate the IRC widget</string>
@@ -632,6 +642,7 @@
   <tabstop>fileBrowserCheckBox</tabstop>
   <tabstop>symbolsCheckBox</tabstop>
   <tabstop>codeDocumentationViewerCheckBox</tabstop>
+  <tabstop>condaCheckBox</tabstop>
   <tabstop>cooperationCheckBox</tabstop>
   <tabstop>ircCheckBox</tabstop>
   <tabstop>numbersCheckBox</tabstop>
--- a/Preferences/ProgramsDialog.py	Sat Feb 16 13:02:35 2019 +0100
+++ b/Preferences/ProgramsDialog.py	Sat Feb 16 15:36:36 2019 +0100
@@ -215,8 +215,17 @@
             Utilities.isWindowsPlatform() and "rbrcc.exe" or "rbrcc",
             '-version', 'Ruby Resource Compiler', -1)
         
-        # 5. do the CORBA and Protobuf programs
-        # 5a. omniORB
+        # 5. do the Conda program(s)
+        exe = Preferences.getConda("CondaExecutable")
+        if not exe:
+            exe = "conda"
+            if Utilities.isWindowsPlatform():
+                exe += ".exe"
+        self.__createProgramEntry(
+            self.tr("conda Manager"), exe, '--version', 'conda', -1)
+        
+        # 6. do the CORBA and Protobuf programs
+        # 6a. omniORB
         exe = Preferences.getCorba("omniidl")
         if not exe:
             exe = "omniidl"
@@ -224,7 +233,7 @@
                 exe += ".exe"
         self.__createProgramEntry(
             self.tr("CORBA IDL Compiler"), exe, '-V', 'omniidl', -1)
-        # 5b. protobuf
+        # 6b. protobuf
         exe = Preferences.getProtobuf("protoc")
         if not exe:
             exe = "protoc"
@@ -232,7 +241,7 @@
                 exe += ".exe"
         self.__createProgramEntry(
             self.tr("Protobuf Compiler"), exe, '--version', 'libprotoc', -1)
-        # 5c. grpc
+        # 6c. grpc
         exe = Preferences.getProtobuf("grpcPython")
         if not exe:
             exe = sys.executable
@@ -240,7 +249,7 @@
             self.tr("gRPC Compiler"), exe, '--version', 'libprotoc', -1,
             exeModule=['-m', 'grpc_tools.protoc'])
         
-        # 6. do the spell checking entry
+        # 7. do the spell checking entry
         try:
             import enchant
             try:
@@ -257,7 +266,7 @@
         self.__createEntry(
             self.tr("Spell Checker - PyEnchant"), text, version)
         
-        # 7. do the pygments entry
+        # 8. do the pygments entry
         try:
             import pygments
             try:
@@ -274,7 +283,7 @@
         self.__createEntry(
             self.tr("Source Highlighter - Pygments"), text, version)
         
-        # do the plugin related programs
+        # 9. do the plugin related programs
         pm = e5App().getObject("PluginManager")
         for info in pm.getPluginExeDisplayData():
             if info["programEntry"]:
--- a/Preferences/__init__.py	Sat Feb 16 13:02:35 2019 +0100
+++ b/Preferences/__init__.py	Sat Feb 16 15:36:36 2019 +0100
@@ -171,6 +171,7 @@
         "ShowFileBrowser": True,                # left side
         "ShowSymbolsViewer": True,              # left side
         "ShowCodeDocumentationViewer": True,    # right side
+        "ShowCondaPackageManager": True,        # right side
         "ShowCooperation": True,                # right side
         "ShowIrc": True,                        # right side
         "ShowNumbersViewer": True,              # bottom side
@@ -1581,6 +1582,11 @@
         "Provider": "disabled",
         "ShowInfoOnOpenParenthesis": True,
     }
+    
+    # defaults for conda
+    condaDefaults = {
+        "CondaExecutable": "",
+    }
 
 
 def readToolGroups(prefClass=Prefs):
@@ -1984,9 +1990,10 @@
                "LayoutShellEmbedded", "LayoutFileBrowserEmbedded",
                "CheckErrorLog", "NotificationsEnabled", "DynamicOnlineCheck",
                "OpenCrashSessionOnStartup", "CrashSessionEnabled",
-               "ShowCodeDocumentationViewer", "ShowCooperation", "ShowIrc",
-               "ShowTemplateViewer", "ShowFileBrowser", "ShowSymbolsViewer",
-               "ShowNumbersViewer", "UseNativeMenuBar"]:
+               "ShowCodeDocumentationViewer", "ShowCondaPackageManager",
+               "ShowCooperation", "ShowIrc", "ShowTemplateViewer",
+               "ShowFileBrowser", "ShowSymbolsViewer", "ShowNumbersViewer",
+               "UseNativeMenuBar"]:
         return toBool(prefClass.settings.value(
             "UI/" + key, prefClass.uiDefaults[key]))
     elif key in ["TabViewManagerFilenameLength", "CaptionFilenameLength",
@@ -3721,7 +3728,7 @@
     
     @param key the key of the value to get
     @param prefClass preferences class used as the storage area
-    @return the requested editor colour
+    @return the requested Code Documentation Viewer value
     """
     if key in ["ShowInfoAsRichText", "ShowInfoOnOpenParenthesis"]:
         return toBool(prefClass.settings.value(
@@ -3744,6 +3751,30 @@
     prefClass.settings.setValue("CodeDocumentationViewer/" + key, value)
 
 
+def getConda(key, prefClass=Prefs):
+    """
+    Module function to retrieve the conda related settings.
+    
+    @param key the key of the value to get
+    @param prefClass preferences class used as the storage area
+    @return the requested conda value
+    """
+    return prefClass.settings.value(
+        "Conda/" + key,
+        prefClass.condaDefaults[key])
+
+
+def setConda(key, value, prefClass=Prefs):
+    """
+    Module function to store the conda 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("Conda/" + key, value)
+
+
 def getGeometry(key, prefClass=Prefs):
     """
     Module function to retrieve the display geometry.
--- a/UI/UserInterface.py	Sat Feb 16 13:02:35 2019 +0100
+++ b/UI/UserInterface.py	Sat Feb 16 15:36:36 2019 +0100
@@ -231,6 +231,11 @@
         # load the view profiles
         self.profiles = Preferences.getUI("ViewProfiles2")
         
+        # Generate the conda interface
+        from CondaInterface.Conda import Conda
+        self.condaInterface = Conda(self)
+        e5App().registerObject("Conda", self.condaInterface)
+        
         # Generate the virtual environment manager
         from VirtualEnv.VirtualenvManager import VirtualenvManager
         self.virtualenvManager = VirtualenvManager(self)
@@ -835,6 +840,15 @@
                               UI.PixmapCache.getIcon("debugViewer.png"),
                               self.tr("Debug-Viewer"))
         
+        if Preferences.getUI("ShowCondaPackageManager"):
+            # Create the conda package manager
+            logging.debug("Creating Conda Package Manager...")
+            from CondaInterface.CondaPackagesWidget import CondaPackagesWidget
+            self.condaWidget = CondaPackagesWidget(self.condaInterface)
+            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...")
@@ -976,6 +990,15 @@
             self.debugViewer, UI.PixmapCache.getIcon("debugViewer.png"),
             self.tr("Debug-Viewer"))
 
+        if Preferences.getUI("ShowCondaPackageManager"):
+            # Create the conda package manager
+            logging.debug("Creating Conda Package Manager...")
+            from CondaInterface.CondaPackagesWidget import CondaPackagesWidget
+            self.condaWidget = CondaPackagesWidget(self.condaInterface)
+            self.rightSidebar.addTab(
+                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...")
--- a/VirtualEnv/VirtualenvConfigurationDialog.py	Sat Feb 16 13:02:35 2019 +0100
+++ b/VirtualEnv/VirtualenvConfigurationDialog.py	Sat Feb 16 15:36:36 2019 +0100
@@ -28,6 +28,8 @@
 import Preferences
 import Utilities
 
+import CondaInterface
+
 
 class VirtualenvConfigurationDialog(QDialog, Ui_VirtualenvConfigurationDialog):
     """
@@ -60,22 +62,55 @@
         self.pythonExecPicker.setDefaultDirectory(
             sys.executable.replace("w.exe", ".exe"))
         
+        self.condaTargetDirectoryPicker.setMode(
+            E5PathPickerModes.DirectoryMode)
+        self.condaTargetDirectoryPicker.setWindowTitle(
+            self.tr("Conda Environment Location"))
+        self.condaTargetDirectoryPicker.setDefaultDirectory(
+            Utilities.getHomeDir())
+        
+        self.condaCloneDirectoryPicker.setMode(
+            E5PathPickerModes.DirectoryMode)
+        self.condaCloneDirectoryPicker.setWindowTitle(
+            self.tr("Conda Environment Location"))
+        self.condaCloneDirectoryPicker.setDefaultDirectory(
+            Utilities.getHomeDir())
+        
+        self.condaRequirementsFilePicker.setMode(
+            E5PathPickerModes.OpenFileMode)
+        self.condaRequirementsFilePicker.setWindowTitle(
+            self.tr("Conda Requirements File"))
+        self.condaRequirementsFilePicker.setDefaultDirectory(
+            Utilities.getHomeDir())
+        self.condaRequirementsFilePicker.setFilters(
+            self.tr("Text Files (*.txt);;All Files (*)"))
+        
         self.__versionRe = re.compile(r""".*?(\d+\.\d+\.\d+).*""")
         
         self.__virtualenvFound = False
         self.__pyvenvFound = False
+        self.__condaFound = False
         self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
         
         self.__mandatoryStyleSheet = "QLineEdit {border: 2px solid;}"
         self.targetDirectoryPicker.setStyleSheet(self.__mandatoryStyleSheet)
         self.nameEdit.setStyleSheet(self.__mandatoryStyleSheet)
+        self.condaTargetDirectoryPicker.setStyleSheet(
+            self.__mandatoryStyleSheet)
+        self.condaNameEdit.setStyleSheet(self.__mandatoryStyleSheet)
         
         self.__setVirtualenvVersion()
         self.__setPyvenvVersion()
-        if self.__virtualenvFound:
+        self.__setCondaVersion()
+        if self.__pyvenvFound:
+            self.pyvenvButton.setChecked(True)
+        elif self.__virtualenvFound:
             self.virtualenvButton.setChecked(True)
-        elif self.__pyvenvFound:
-            self.pyvenvButton.setChecked(True)
+        elif self.__condaFound:
+            self.condaButton.setChecked(True)
+        
+        self.condaInsecureCheckBox.setEnabled(
+            CondaInterface.condaVersion() >= (4, 3, 18))
         
         msh = self.minimumSizeHint()
         self.resize(max(self.width(), msh.width()), msh.height())
@@ -84,17 +119,31 @@
         """
         Private method to update the enabled status of the OK button.
         """
-        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(
-            (self.__virtualenvFound or self.__pyvenvFound) and
-            bool(self.targetDirectoryPicker.text()) and
-            bool(self.nameEdit.text())
-        )
+        if self.virtualenvButton.isChecked() or self.pyvenvButton.isChecked():
+            self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(
+                (self.__virtualenvFound or self.__pyvenvFound) and
+                bool(self.targetDirectoryPicker.text()) and
+                bool(self.nameEdit.text())
+            )
+        elif self.condaButton.isChecked():
+            enable = bool(self.condaNameEdit.text()) or \
+                bool(self.condaTargetDirectoryPicker.text())
+            if self.condaSpecialsGroup.isChecked():
+                if self.condaCloneButton.isChecked():
+                    enable &= bool(self.condaCloneNameEdit.text()) or \
+                        bool(self.condaCloneDirectoryPicker.text())
+                elif self.condaRequirementsButton.isChecked():
+                    enable &= bool(self.condaRequirementsFilePicker.text())
+            self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(enable)
+        else:
+            self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
     
     def __updateUi(self):
         """
         Private method to update the UI depending on the selected
         virtual environment creator (virtualenv or pyvenv).
         """
+        # venv page
         enable = self.virtualenvButton.isChecked()
         self.extraSearchPathLabel.setEnabled(enable)
         self.extraSearchPathPicker.setEnabled(enable)
@@ -108,6 +157,20 @@
         self.noSetuptoolsCheckBox.setEnabled(enable)
         self.symlinkCheckBox.setEnabled(not enable)
         self.upgradeCheckBox.setEnabled(not enable)
+        
+        # conda page
+        enable = not self.condaSpecialsGroup.isChecked()
+        self.condaPackagesEdit.setEnabled(enable)
+        self.condaPythonEdit.setEnabled(enable)
+        self.condaInsecureCheckBox.setEnabled(
+            enable and CondaInterface.condaVersion() >= (4, 3, 18))
+        self.condaDryrunCheckBox.setEnabled(enable)
+        
+        # select page
+        if self.condaButton.isChecked():
+            self.venvStack.setCurrentWidget(self.condaPage)
+        else:
+            self.venvStack.setCurrentWidget(self.venvPage)
     
     @pyqtSlot(str)
     def on_targetDirectoryPicker_textChanged(self, txt):
@@ -151,6 +214,88 @@
         """
         self.__updateUi()
     
+    @pyqtSlot(bool)
+    def on_condaButton_toggled(self, checked):
+        """
+        Private slot to react to the selection of 'conda'.
+        
+        @param checked state of the checkbox
+        @type bool
+        """
+        self.__updateUi()
+    
+    @pyqtSlot(str)
+    def on_condaNameEdit_textChanged(self, txt):
+        """
+        Private slot handling a change of the conda environment name.
+        
+        @param txt environment name
+        @type str
+        """
+        self.__updateOK()
+    
+    @pyqtSlot(str)
+    def on_condaTargetDirectoryPicker_textChanged(self, txt):
+        """
+        Private slot handling a change of the conda target directory.
+        
+        @param txt target directory
+        @type str
+        """
+        self.__updateOK()
+    
+    @pyqtSlot()
+    def on_condaSpecialsGroup_clicked(self):
+        """
+        Private slot handling the selection of the specials group.
+        """
+        self.__updateOK()
+        self.__updateUi()
+    
+    @pyqtSlot(str)
+    def on_condaCloneNameEdit_textChanged(self, txt):
+        """
+        Private slot handling a change of the conda source environment name.
+        
+        @param txt name of the environment to be cloned
+        @type str
+        """
+        self.__updateOK()
+    
+    @pyqtSlot(str)
+    def on_condaCloneDirectoryPicker_textChanged(self, txt):
+        """
+        Private slot handling a change of the cloned from directory.
+        
+        @param txt target directory
+        @type str
+        """
+        self.__updateOK()
+    
+    @pyqtSlot()
+    def on_condaCloneButton_clicked(self):
+        """
+        Private slot handling the selection of the clone button.
+        """
+        self.__updateOK()
+    
+    @pyqtSlot()
+    def on_condaRequirementsButton_clicked(self):
+        """
+        Private slot handling the selection of the requirements button.
+        """
+        self.__updateOK()
+    
+    @pyqtSlot(str)
+    def on_condaRequirementsFilePicker_textChanged(self, txt):
+        """
+        Private slot handling a change of the requirements file entry.
+        
+        @param txt current text of the requirements file entry
+        @type str
+        """
+        self.__updateOK()
+    
     def __setVirtualenvVersion(self):
         """
         Private method to determine the virtualenv version and set the
@@ -259,6 +404,18 @@
         if not self.__pyvenvFound:
             self.pyvenvButton.setChecked(False)
     
+    def __setCondaVersion(self):
+        """
+        Private method to determine the conda version and set the respective
+        label.
+        """
+        self.__condaFound = bool(CondaInterface.condaVersion())
+        self.condaButton.setText(self.tr(
+            "conda Version: {0}".format(CondaInterface.condaVersionStr())))
+        self.condaButton.setEnabled(self.__condaFound)
+        if not self.__condaFound:
+            self.condaButton.setChecked(False)
+    
     def __generateTargetDir(self):
         """
         Private method to generate a valid target directory path.
@@ -281,75 +438,123 @@
         @rtype list of str
         """
         args = []
-        if self.virtualenvButton.isChecked():
-            if self.extraSearchPathPicker.text():
-                args.append("--extra-search-dir={0}".format(
-                    Utilities.toNativeSeparators(
-                        self.extraSearchPathPicker.text())))
-            if self.promptPrefixEdit.text():
-                args.append("--prompt={0}".format(
-                    self.promptPrefixEdit.text().replace(" ", "_")))
-            if self.pythonExecPicker.text():
-                args.append("--python={0}".format(
-                    Utilities.toNativeSeparators(
-                        self.pythonExecPicker.text())))
-            elif self.versionComboBox.currentText():
-                args.append("--python=python{0}".format(
-                    self.versionComboBox.currentText()))
-            if self.verbositySpinBox.value() == 1:
-                args.append("--verbose")
-            elif self.verbositySpinBox.value() == -1:
-                args.append("--quiet")
-            if self.clearCheckBox.isChecked():
-                args.append("--clear")
-            if self.systemCheckBox.isChecked():
-                args.append("--system-site-packages")
-            if self.unzipCheckBox.isChecked():
-                args.append("--unzip-setuptools")
-            if self.noSetuptoolsCheckBox.isChecked():
-                args.append("--no-setuptools")
-            if self.noPipCcheckBox.isChecked():
-                args.append("--no-pip")
-            if self.copyCheckBox.isChecked():
-                args.append("--always-copy")
-        elif self.pyvenvButton.isChecked():
-            if self.clearCheckBox.isChecked():
-                args.append("--clear")
-            if self.systemCheckBox.isChecked():
-                args.append("--system-site-packages")
-            if self.noPipCcheckBox.isChecked():
-                args.append("--without-pip")
-            if self.copyCheckBox.isChecked():
-                args.append("--copies")
-            if self.symlinkCheckBox.isChecked():
-                args.append("--symlinks")
-            if self.upgradeCheckBox.isChecked():
-                args.append("--upgrade")
-        targetDirectory = self.__generateTargetDir()
-        args.append(targetDirectory)
+        if self.condaButton.isChecked():
+            if bool(self.condaNameEdit.text()):
+                args.extend(["--name", self.condaNameEdit.text()])
+            if bool(self.condaTargetDirectoryPicker.text()):
+                args.extend(["--prefix",
+                             self.condaTargetDirectoryPicker.text()])
+            if self.condaSpecialsGroup.isChecked():
+                if self.condaCloneButton.isChecked():
+                    if bool(self.condaCloneNameEdit.text()):
+                        args.extend(
+                            ["--clone", self.condaCloneNameEdit.text()]
+                        )
+                    elif bool(self.condaCloneDirectoryPicker.text()):
+                        args.extend(["--clone",
+                                     self.condaCloneDirectoryPicker.text()])
+                elif self.condaRequirementsButton.isChecked():
+                    args.extend(
+                        ["--file", self.condaRequirementsFilePicker.text()]
+                    )
+            if self.condaInsecureCheckBox.isChecked():
+                args.append("--insecure")
+            if self.condaDryrunCheckBox.isChecked():
+                args.append("--dry-run")
+            if not self.condaSpecialsGroup.isChecked():
+                if bool(self.condaPythonEdit.text()):
+                    args.append("python={0}".format(
+                        self.condaPythonEdit.text()))
+                if bool(self.condaPackagesEdit.text()):
+                    args.extend(self.condaPackagesEdit.text().split())
+        else:
+            if self.virtualenvButton.isChecked():
+                if self.extraSearchPathPicker.text():
+                    args.append("--extra-search-dir={0}".format(
+                        Utilities.toNativeSeparators(
+                            self.extraSearchPathPicker.text())))
+                if self.promptPrefixEdit.text():
+                    args.append("--prompt={0}".format(
+                        self.promptPrefixEdit.text().replace(" ", "_")))
+                if self.pythonExecPicker.text():
+                    args.append("--python={0}".format(
+                        Utilities.toNativeSeparators(
+                            self.pythonExecPicker.text())))
+                elif self.versionComboBox.currentText():
+                    args.append("--python=python{0}".format(
+                        self.versionComboBox.currentText()))
+                if self.verbositySpinBox.value() == 1:
+                    args.append("--verbose")
+                elif self.verbositySpinBox.value() == -1:
+                    args.append("--quiet")
+                if self.clearCheckBox.isChecked():
+                    args.append("--clear")
+                if self.systemCheckBox.isChecked():
+                    args.append("--system-site-packages")
+                if self.unzipCheckBox.isChecked():
+                    args.append("--unzip-setuptools")
+                if self.noSetuptoolsCheckBox.isChecked():
+                    args.append("--no-setuptools")
+                if self.noPipCcheckBox.isChecked():
+                    args.append("--no-pip")
+                if self.copyCheckBox.isChecked():
+                    args.append("--always-copy")
+            elif self.pyvenvButton.isChecked():
+                if self.clearCheckBox.isChecked():
+                    args.append("--clear")
+                if self.systemCheckBox.isChecked():
+                    args.append("--system-site-packages")
+                if self.noPipCcheckBox.isChecked():
+                    args.append("--without-pip")
+                if self.copyCheckBox.isChecked():
+                    args.append("--copies")
+                if self.symlinkCheckBox.isChecked():
+                    args.append("--symlinks")
+                if self.upgradeCheckBox.isChecked():
+                    args.append("--upgrade")
+            targetDirectory = self.__generateTargetDir()
+            args.append(targetDirectory)
+        
         return args
 
     def getData(self):
         """
         Public method to retrieve the dialog data.
         
-        @return tuple containing a flag indicating the pyvenv selection, the
-            process arguments, a name for the virtual environment, a flag
-            indicating to open the target directory after creation, a flag
-            indicating to write a log file, a flag indicating to write a
-            script, the name of the target directory and the name of the
-            Python interpreter to use
-        @rtype tuple of (bool, list of str, str, bool, bool, bool, str, str)
+        @return dictionary containing the data for the two environment
+            variants. The keys for both variants are 'arguments' containing the
+            command line arguments, 'logicalName' containing the environment
+            name to be used with the virtual env manager and 'envType'
+            containing the environment type (virtualenv, pyvenv or conda). The
+            virtualenv/pyvenv specific keys are 'openTarget' containg a flag to
+            open the target directory after creation, 'createLog' containing a
+            flag to write a log file, 'createScript' containing a flag to write
+            a script, 'targetDirectory' containing the target directory and
+            'pythonExe' containing the Python interpreter to be used. The
+            conda specific key is 'command' giving the conda command to be
+            executed (always 'create').
+        @rtype dict
         """
         args = self.__generateArguments()
-        targetDirectory = self.__generateTargetDir()
-        return (
-            self.pyvenvButton.isChecked(),
-            args,
-            self.nameEdit.text(),
-            self.openCheckBox.isChecked(),
-            self.logCheckBox.isChecked(),
-            self.scriptCheckBox.isChecked(),
-            targetDirectory,
-            Utilities.toNativeSeparators(self.pythonExecPicker.text()),
-        )
+        resultDict = {
+            "arguments": args,
+            "logicalName": self.nameEdit.text(),
+        }
+        if self.condaButton.isChecked():
+            resultDict.update({
+                "envType": "conda",
+                "command": "create",
+            })
+        else:
+            resultDict.update({
+                "envType": ("pyvenv" if self.pyvenvButton.isChecked() else
+                            "virtualenv"),
+                "openTarget": self.openCheckBox.isChecked(),
+                "createLog": self.logCheckBox.isChecked(),
+                "createScript": self.scriptCheckBox.isChecked(),
+                "targetDirectory": self.__generateTargetDir(),
+                "pythonExe": Utilities.toNativeSeparators(
+                    self.pythonExecPicker.text()),
+            })
+        
+        return resultDict
--- a/VirtualEnv/VirtualenvConfigurationDialog.ui	Sat Feb 16 13:02:35 2019 +0100
+++ b/VirtualEnv/VirtualenvConfigurationDialog.ui	Sat Feb 16 15:36:36 2019 +0100
@@ -7,11 +7,11 @@
     <x>0</x>
     <y>0</y>
     <width>700</width>
-    <height>592</height>
+    <height>654</height>
    </rect>
   </property>
   <property name="windowTitle">
-   <string>Virtualenv Configuration</string>
+   <string>Virtual Environment Configuration</string>
   </property>
   <property name="sizeGripEnabled">
    <bool>true</bool>
@@ -68,6 +68,22 @@
         </property>
        </widget>
       </item>
+      <item row="2" column="0">
+       <widget class="QRadioButton" name="condaButton">
+        <property name="font">
+         <font>
+          <weight>75</weight>
+          <bold>true</bold>
+         </font>
+        </property>
+        <property name="toolTip">
+         <string>Select to use 'conda'</string>
+        </property>
+        <property name="text">
+         <string notr="true">0.0</string>
+        </property>
+       </widget>
+      </item>
      </layout>
     </widget>
    </item>
@@ -93,332 +109,611 @@
     </layout>
    </item>
    <item>
-    <widget class="QGroupBox" name="groupBox">
-     <property name="title">
-      <string>Paths</string>
+    <widget class="QStackedWidget" name="venvStack">
+     <property name="currentIndex">
+      <number>1</number>
      </property>
-     <layout class="QGridLayout" name="gridLayout">
-      <item row="0" column="0">
-       <widget class="QLabel" name="label">
-        <property name="text">
-         <string>Target Directory:</string>
-        </property>
-       </widget>
-      </item>
-      <item row="0" column="1">
-       <widget class="E5PathPicker" name="targetDirectoryPicker" native="true">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="focusPolicy">
-         <enum>Qt::WheelFocus</enum>
-        </property>
-        <property name="toolTip">
-         <string>Enter the target directory for the virtual environment</string>
-        </property>
-       </widget>
-      </item>
-      <item row="1" column="0">
-       <widget class="QLabel" name="extraSearchPathLabel">
-        <property name="text">
-         <string>Extra Search Path:</string>
-        </property>
-       </widget>
-      </item>
-      <item row="1" column="1">
-       <widget class="E5PathPicker" name="extraSearchPathPicker" native="true">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="focusPolicy">
-         <enum>Qt::WheelFocus</enum>
-        </property>
-        <property name="toolTip">
-         <string>Enter the extra search path to look for setuptools/pip</string>
-        </property>
-       </widget>
-      </item>
-      <item row="2" column="0">
-       <widget class="QLabel" name="promptPrefixLabel">
-        <property name="text">
-         <string>Prompt Prefix:</string>
-        </property>
-       </widget>
-      </item>
-      <item row="2" column="1">
-       <widget class="E5ClearableLineEdit" name="promptPrefixEdit">
-        <property name="toolTip">
-         <string>Enter the prompt prefix for the virtual environment</string>
-        </property>
-        <property name="placeholderText">
-         <string>Prompt prefix for the virtual environment</string>
-        </property>
-       </widget>
-      </item>
-      <item row="3" column="0">
-       <widget class="QLabel" name="label_5">
-        <property name="text">
-         <string>Python Executable:</string>
-        </property>
-       </widget>
-      </item>
-      <item row="3" column="1">
-       <widget class="E5PathPicker" name="pythonExecPicker" native="true">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="focusPolicy">
-         <enum>Qt::WheelFocus</enum>
-        </property>
-        <property name="toolTip">
-         <string>Enter the Python interpreter for the virtual environment</string>
-        </property>
-       </widget>
-      </item>
-     </layout>
-    </widget>
-   </item>
-   <item>
-    <widget class="QGroupBox" name="groupBox_2">
-     <property name="title">
-      <string>Options</string>
-     </property>
-     <layout class="QGridLayout" name="gridLayout_2">
-      <item row="0" column="0">
-       <layout class="QHBoxLayout" name="horizontalLayout_3">
-        <item>
-         <widget class="QLabel" name="verbosityLabel">
-          <property name="text">
-           <string>Verbosity:</string>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <widget class="QSpinBox" name="verbositySpinBox">
-          <property name="toolTip">
-           <string>Select the verbosity (-1: quiet, 0: normal, 1: verbose)</string>
-          </property>
-          <property name="alignment">
-           <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-          </property>
-          <property name="minimum">
-           <number>-1</number>
-          </property>
-          <property name="maximum">
-           <number>1</number>
-          </property>
-         </widget>
-        </item>
-        <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>
-       </layout>
-      </item>
-      <item row="0" column="1">
-       <layout class="QHBoxLayout" name="horizontalLayout">
-        <item>
-         <widget class="QLabel" name="versionLabel">
-          <property name="text">
-           <string>Python Version:</string>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <widget class="QComboBox" name="versionComboBox">
-          <property name="toolTip">
-           <string>Select the Python version (empty for current)</string>
-          </property>
-          <item>
+     <widget class="QWidget" name="venvPage">
+      <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>
+        <widget class="QGroupBox" name="groupBox">
+         <property name="title">
+          <string>Paths</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout">
+          <item row="0" column="0">
+           <widget class="QLabel" name="label">
+            <property name="text">
+             <string>Target Directory:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="E5PathPicker" name="targetDirectoryPicker" native="true">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="focusPolicy">
+             <enum>Qt::WheelFocus</enum>
+            </property>
+            <property name="toolTip">
+             <string>Enter the target directory for the virtual environment</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="0">
+           <widget class="QLabel" name="extraSearchPathLabel">
+            <property name="text">
+             <string>Extra Search Path:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <widget class="E5PathPicker" name="extraSearchPathPicker" native="true">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="focusPolicy">
+             <enum>Qt::WheelFocus</enum>
+            </property>
+            <property name="toolTip">
+             <string>Enter the extra search path to look for setuptools/pip</string>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="0">
+           <widget class="QLabel" name="promptPrefixLabel">
+            <property name="text">
+             <string>Prompt Prefix:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="1">
+           <widget class="E5ClearableLineEdit" name="promptPrefixEdit">
+            <property name="toolTip">
+             <string>Enter the prompt prefix for the virtual environment</string>
+            </property>
+            <property name="placeholderText">
+             <string>Prompt prefix for the virtual environment</string>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="0">
+           <widget class="QLabel" name="label_5">
+            <property name="text">
+             <string>Python Executable:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="1">
+           <widget class="E5PathPicker" name="pythonExecPicker" native="true">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="focusPolicy">
+             <enum>Qt::WheelFocus</enum>
+            </property>
+            <property name="toolTip">
+             <string>Enter the Python interpreter for the virtual environment</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="groupBox_2">
+         <property name="title">
+          <string>Options</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_2">
+          <item row="0" column="0">
+           <layout class="QHBoxLayout" name="horizontalLayout_3">
+            <item>
+             <widget class="QLabel" name="verbosityLabel">
+              <property name="text">
+               <string>Verbosity:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QSpinBox" name="verbositySpinBox">
+              <property name="toolTip">
+               <string>Select the verbosity (-1: quiet, 0: normal, 1: verbose)</string>
+              </property>
+              <property name="alignment">
+               <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+              </property>
+              <property name="minimum">
+               <number>-1</number>
+              </property>
+              <property name="maximum">
+               <number>1</number>
+              </property>
+             </widget>
+            </item>
+            <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>
+           </layout>
+          </item>
+          <item row="0" column="1">
+           <layout class="QHBoxLayout" name="horizontalLayout">
+            <item>
+             <widget class="QLabel" name="versionLabel">
+              <property name="text">
+               <string>Python Version:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QComboBox" name="versionComboBox">
+              <property name="toolTip">
+               <string>Select the Python version (empty for current)</string>
+              </property>
+              <item>
+               <property name="text">
+                <string notr="true"/>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string notr="true">2.6</string>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string notr="true">2.7</string>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string notr="true">3.4</string>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string notr="true">3.5</string>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string notr="true">3.6</string>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string notr="true">3.7</string>
+               </property>
+              </item>
+             </widget>
+            </item>
+            <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>
+           </layout>
+          </item>
+          <item row="1" column="0">
+           <widget class="QCheckBox" name="systemCheckBox">
+            <property name="toolTip">
+             <string>Select to give the virtualenv access to the global site-packages</string>
+            </property>
+            <property name="text">
+             <string>System-wide Python Packages</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <widget class="QCheckBox" name="unzipCheckBox">
+            <property name="toolTip">
+             <string>Select to unzip setuptools when installing it</string>
+            </property>
+            <property name="text">
+             <string>Unzip Setuptool to virtualenv</string>
+            </property>
+            <property name="checked">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="0">
+           <widget class="QCheckBox" name="noSetuptoolsCheckBox">
+            <property name="toolTip">
+             <string>Select to not install setuptools (or pip) in the new virtualenv</string>
+            </property>
+            <property name="text">
+             <string>Don't install 'setuptool' (or pip) in the virtualenv</string>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="1">
+           <widget class="QCheckBox" name="noPipCcheckBox">
+            <property name="toolTip">
+             <string>Select to not install pip in the new virtualenv</string>
+            </property>
+            <property name="text">
+             <string>Don't install 'pip' in the virtualenv</string>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="0">
+           <widget class="QCheckBox" name="clearCheckBox">
+            <property name="toolTip">
+             <string>Select to clear the target first</string>
+            </property>
+            <property name="text">
+             <string>Clear out the target directory</string>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="1">
+           <widget class="QCheckBox" name="copyCheckBox">
+            <property name="toolTip">
+             <string>Select to always copy files rather than symlinking</string>
+            </property>
+            <property name="text">
+             <string>Always copy files</string>
+            </property>
+           </widget>
+          </item>
+          <item row="4" column="0">
+           <widget class="QCheckBox" name="symlinkCheckBox">
+            <property name="toolTip">
+             <string>Select to use symlinks instead of copies</string>
+            </property>
+            <property name="text">
+             <string>Use Symbolic Links</string>
+            </property>
+           </widget>
+          </item>
+          <item row="4" column="1">
+           <widget class="QCheckBox" name="upgradeCheckBox">
+            <property name="toolTip">
+             <string>Select to upgrade a virtual environment</string>
+            </property>
+            <property name="text">
+             <string>Upgrade</string>
+            </property>
+           </widget>
+          </item>
+          <item row="5" column="0">
+           <widget class="QCheckBox" name="logCheckBox">
+            <property name="toolTip">
+             <string>Select to generate a log file in the target directory</string>
+            </property>
+            <property name="text">
+             <string>Save a log file in the target directory after creation</string>
+            </property>
+            <property name="checked">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="5" column="1">
+           <widget class="QCheckBox" name="scriptCheckBox">
+            <property name="toolTip">
+             <string>Select to write a shell script/batch file to regenerate the virtualenv</string>
+            </property>
+            <property name="text">
+             <string>Save virtualenv generation script</string>
+            </property>
+            <property name="checked">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="6" column="0">
+           <widget class="QCheckBox" name="openCheckBox">
+            <property name="toolTip">
+             <string>Open the newly created virtualenv in a file manager window</string>
+            </property>
+            <property name="text">
+             <string>Open target directory after creation</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="condaPage">
+      <layout class="QVBoxLayout" name="verticalLayout_3">
+       <item>
+        <widget class="QGroupBox" name="groupBox_4">
+         <property name="title">
+          <string>Target Environment Specification</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_4">
+          <item row="0" column="0">
+           <widget class="QLabel" name="label_3">
+            <property name="text">
+             <string>Name:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="E5ClearableLineEdit" name="condaNameEdit">
+            <property name="toolTip">
+             <string>Enter the name for the environment</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="0">
+           <widget class="QLabel" name="label_4">
+            <property name="text">
+             <string>Path:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <widget class="E5PathPicker" name="condaTargetDirectoryPicker" native="true">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="focusPolicy">
+             <enum>Qt::WheelFocus</enum>
+            </property>
+            <property name="toolTip">
+             <string>Enter the target directory for the conda environment</string>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="0" colspan="2">
+           <widget class="QLabel" name="label_6">
+            <property name="text">
+             <string>&lt;b&gt;Note:&lt;/b&gt; Only one of the above entries is mandatory.</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="condaSpecialsGroup">
+         <property name="title">
+          <string>Special Operations</string>
+         </property>
+         <property name="checkable">
+          <bool>true</bool>
+         </property>
+         <property name="checked">
+          <bool>false</bool>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_5">
+          <item row="0" column="0">
+           <widget class="QRadioButton" name="condaCloneButton">
+            <property name="toolTip">
+             <string>Select to clone an environment</string>
+            </property>
+            <property name="text">
+             <string>Clone Environment</string>
+            </property>
+            <property name="checked">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="QRadioButton" name="condaRequirementsButton">
+            <property name="statusTip">
+             <string>Select to create the environment from a requirements file</string>
+            </property>
+            <property name="text">
+             <string>from Requirements</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="0">
+           <widget class="QFrame" name="condaCloneFrame">
+            <property name="frameShape">
+             <enum>QFrame::StyledPanel</enum>
+            </property>
+            <property name="frameShadow">
+             <enum>QFrame::Raised</enum>
+            </property>
+            <layout class="QGridLayout" name="gridLayout_7">
+             <item row="0" column="0">
+              <widget class="QLabel" name="label_8">
+               <property name="text">
+                <string>Name:</string>
+               </property>
+              </widget>
+             </item>
+             <item row="0" column="1">
+              <widget class="E5ClearableLineEdit" name="condaCloneNameEdit">
+               <property name="toolTip">
+                <string>Enter the name of the environment to be cloned</string>
+               </property>
+              </widget>
+             </item>
+             <item row="1" column="0">
+              <widget class="QLabel" name="label_7">
+               <property name="text">
+                <string>Path:</string>
+               </property>
+              </widget>
+             </item>
+             <item row="1" column="1">
+              <widget class="E5PathPicker" name="condaCloneDirectoryPicker" native="true">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="focusPolicy">
+                <enum>Qt::WheelFocus</enum>
+               </property>
+               <property name="toolTip">
+                <string>Enter the directory of the environment to be cloned</string>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <widget class="QFrame" name="condaRequirementsFrame">
+            <property name="enabled">
+             <bool>false</bool>
+            </property>
+            <property name="frameShape">
+             <enum>QFrame::StyledPanel</enum>
+            </property>
+            <property name="frameShadow">
+             <enum>QFrame::Raised</enum>
+            </property>
+            <layout class="QVBoxLayout" name="verticalLayout_4">
+             <item>
+              <widget class="E5PathPicker" name="condaRequirementsFilePicker" 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>
+             <item>
+              <spacer name="verticalSpacer">
+               <property name="orientation">
+                <enum>Qt::Vertical</enum>
+               </property>
+               <property name="sizeHint" stdset="0">
+                <size>
+                 <width>20</width>
+                 <height>37</height>
+                </size>
+               </property>
+              </spacer>
+             </item>
+            </layout>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_4">
+         <item>
+          <widget class="QLabel" name="label_9">
            <property name="text">
-            <string notr="true"/>
-           </property>
-          </item>
-          <item>
-           <property name="text">
-            <string notr="true">2.6</string>
+            <string>Package Specs:</string>
            </property>
-          </item>
-          <item>
-           <property name="text">
-            <string notr="true">2.7</string>
+          </widget>
+         </item>
+         <item>
+          <widget class="E5ClearableLineEdit" name="condaPackagesEdit">
+           <property name="toolTip">
+            <string>Enter the package specifications for the environment</string>
            </property>
-          </item>
-          <item>
-           <property name="text">
-            <string notr="true">3.4</string>
-           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="groupBox_5">
+         <property name="title">
+          <string>Options</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_6">
+          <item row="0" column="0">
+           <widget class="QLabel" name="versionLabel_2">
+            <property name="text">
+             <string>Python Version:</string>
+            </property>
+           </widget>
           </item>
-          <item>
-           <property name="text">
-            <string notr="true">3.5</string>
-           </property>
-          </item>
-          <item>
-           <property name="text">
-            <string notr="true">3.6</string>
-           </property>
-          </item>
-          <item>
-           <property name="text">
-            <string notr="true">3.7</string>
-           </property>
+          <item row="0" column="1">
+           <widget class="E5ClearableLineEdit" name="condaPythonEdit">
+            <property name="toolTip">
+             <string>Enter the Python version for the environment</string>
+            </property>
+           </widget>
           </item>
-         </widget>
-        </item>
-        <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>
-       </layout>
-      </item>
-      <item row="1" column="0">
-       <widget class="QCheckBox" name="systemCheckBox">
-        <property name="toolTip">
-         <string>Select to give the virtualenv access to the global site-packages</string>
-        </property>
-        <property name="text">
-         <string>System-wide Python Packages</string>
-        </property>
-       </widget>
-      </item>
-      <item row="1" column="1">
-       <widget class="QCheckBox" name="unzipCheckBox">
-        <property name="toolTip">
-         <string>Select to unzip setuptools when installing it</string>
-        </property>
-        <property name="text">
-         <string>Unzip Setuptool to virtualenv</string>
-        </property>
-        <property name="checked">
-         <bool>true</bool>
-        </property>
-       </widget>
-      </item>
-      <item row="2" column="0">
-       <widget class="QCheckBox" name="noSetuptoolsCheckBox">
-        <property name="toolTip">
-         <string>Select to not install setuptools (or pip) in the new virtualenv</string>
-        </property>
-        <property name="text">
-         <string>Don't install 'setuptool' (or pip) in the virtualenv</string>
-        </property>
-       </widget>
-      </item>
-      <item row="2" column="1">
-       <widget class="QCheckBox" name="noPipCcheckBox">
-        <property name="toolTip">
-         <string>Select to not install pip in the new virtualenv</string>
-        </property>
-        <property name="text">
-         <string>Don't install 'pip' in the virtualenv</string>
-        </property>
-       </widget>
-      </item>
-      <item row="3" column="0">
-       <widget class="QCheckBox" name="clearCheckBox">
-        <property name="toolTip">
-         <string>Select to clear the target first</string>
-        </property>
-        <property name="text">
-         <string>Clear out the target directory</string>
-        </property>
-       </widget>
-      </item>
-      <item row="3" column="1">
-       <widget class="QCheckBox" name="copyCheckBox">
-        <property name="toolTip">
-         <string>Select to always copy files rather than symlinking</string>
-        </property>
-        <property name="text">
-         <string>Always copy files</string>
-        </property>
-       </widget>
-      </item>
-      <item row="4" column="0">
-       <widget class="QCheckBox" name="symlinkCheckBox">
-        <property name="toolTip">
-         <string>Select to use symlinks instead of copies</string>
-        </property>
-        <property name="text">
-         <string>Use Symbolic Links</string>
-        </property>
-       </widget>
-      </item>
-      <item row="4" column="1">
-       <widget class="QCheckBox" name="upgradeCheckBox">
-        <property name="toolTip">
-         <string>Select to upgrade a virtual environment</string>
-        </property>
-        <property name="text">
-         <string>Upgrade</string>
-        </property>
-       </widget>
-      </item>
-      <item row="5" column="0">
-       <widget class="QCheckBox" name="logCheckBox">
-        <property name="toolTip">
-         <string>Select to generate a log file in the target directory</string>
-        </property>
-        <property name="text">
-         <string>Save a log file in the target directory after creation</string>
-        </property>
-        <property name="checked">
-         <bool>true</bool>
-        </property>
-       </widget>
-      </item>
-      <item row="5" column="1">
-       <widget class="QCheckBox" name="scriptCheckBox">
-        <property name="toolTip">
-         <string>Select to write a shell script/batch file to regenerate the virtualenv</string>
-        </property>
-        <property name="text">
-         <string>Save virtualenv generation script</string>
-        </property>
-        <property name="checked">
-         <bool>true</bool>
-        </property>
-       </widget>
-      </item>
-      <item row="6" column="0">
-       <widget class="QCheckBox" name="openCheckBox">
-        <property name="toolTip">
-         <string>Open the newly created virtualenv in a file manager window</string>
-        </property>
-        <property name="text">
-         <string>Open target directory after creation</string>
-        </property>
-       </widget>
-      </item>
-     </layout>
+          <item row="1" column="0" colspan="2">
+           <widget class="QCheckBox" name="condaInsecureCheckBox">
+            <property name="text">
+             <string>Allow insecure SSL connections</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="2">
+           <widget class="QCheckBox" name="condaDryrunCheckBox">
+            <property name="toolTip">
+             <string>Select to perform just a dry-run</string>
+            </property>
+            <property name="text">
+             <string>Perform dry-run</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="2">
+           <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>
+        </widget>
+       </item>
+      </layout>
+     </widget>
     </widget>
    </item>
    <item>
@@ -449,6 +744,7 @@
  <tabstops>
   <tabstop>virtualenvButton</tabstop>
   <tabstop>pyvenvButton</tabstop>
+  <tabstop>condaButton</tabstop>
   <tabstop>nameEdit</tabstop>
   <tabstop>targetDirectoryPicker</tabstop>
   <tabstop>extraSearchPathPicker</tabstop>
@@ -467,6 +763,18 @@
   <tabstop>logCheckBox</tabstop>
   <tabstop>scriptCheckBox</tabstop>
   <tabstop>openCheckBox</tabstop>
+  <tabstop>condaNameEdit</tabstop>
+  <tabstop>condaTargetDirectoryPicker</tabstop>
+  <tabstop>condaSpecialsGroup</tabstop>
+  <tabstop>condaCloneButton</tabstop>
+  <tabstop>condaCloneNameEdit</tabstop>
+  <tabstop>condaCloneDirectoryPicker</tabstop>
+  <tabstop>condaRequirementsButton</tabstop>
+  <tabstop>condaRequirementsFilePicker</tabstop>
+  <tabstop>condaPackagesEdit</tabstop>
+  <tabstop>condaPythonEdit</tabstop>
+  <tabstop>condaInsecureCheckBox</tabstop>
+  <tabstop>condaDryrunCheckBox</tabstop>
  </tabstops>
  <resources/>
  <connections>
@@ -477,8 +785,8 @@
    <slot>accept()</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>248</x>
-     <y>254</y>
+     <x>257</x>
+     <y>644</y>
     </hint>
     <hint type="destinationlabel">
      <x>157</x>
@@ -493,8 +801,8 @@
    <slot>reject()</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>316</x>
-     <y>260</y>
+     <x>325</x>
+     <y>644</y>
     </hint>
     <hint type="destinationlabel">
      <x>286</x>
@@ -502,5 +810,37 @@
     </hint>
    </hints>
   </connection>
+  <connection>
+   <sender>condaCloneButton</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>condaCloneFrame</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>108</x>
+     <y>361</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>78</x>
+     <y>380</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>condaRequirementsButton</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>condaRequirementsFrame</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>431</x>
+     <y>359</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>427</x>
+     <y>381</y>
+    </hint>
+   </hints>
+  </connection>
  </connections>
 </ui>
--- a/VirtualEnv/VirtualenvExecDialog.py	Sat Feb 16 13:02:35 2019 +0100
+++ b/VirtualEnv/VirtualenvExecDialog.py	Sat Feb 16 15:36:36 2019 +0100
@@ -33,28 +33,13 @@
     This class starts a QProcess and displays a dialog that
     shows the output of the virtualenv or pyvenv process.
     """
-    def __init__(self, pyvenv, targetDir, venvName, openTarget, createLog,
-                 createScript, interpreter, venvManager, parent=None):
+    def __init__(self, configuration, venvManager, parent=None):
         """
         Constructor
         
-        @param pyvenv flag indicating the use of 'pyvenv'
-        @type bool
-        @param targetDir name of the virtualenv directory
-        @type str
-        @param venvName logical name for the virtual environment
-        @type str
-        @param openTarget flag indicating to open the virtualenv directory
-            in a file manager
-        @type bool
-        @param createLog flag indicating to create a log file of the
-            creation process
-        @type bool
-        @param createScript flag indicating to create a script to recreate
-            the virtual environment
-        @type bool
-        @param interpreter name of the python interpreter to use
-        @type str
+        @param configuration dictionary containing the configuration parameters
+            as returned by the command configuration dialog
+        @type dict
         @param venvManager reference to the virtual environment manager
         @type VirtualenvManager
         @param parent reference to the parent widget
@@ -66,21 +51,22 @@
         self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
         self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
         
-        self.__pyvenv = pyvenv
-        self.__targetDir = targetDir
-        self.__openTarget = openTarget
-        self.__createLog = createLog
-        self.__createScript = createScript
-        self.__venvName = venvName
+        self.__pyvenv = configuration["envType"] == "pyvenv"
+        self.__targetDir = configuration["targetDirectory"]
+        self.__openTarget = configuration["openTarget"]
+        self.__createLog = configuration["createLog"]
+        self.__createScript = configuration["createScript"]
+        self.__venvName = configuration["logicalName"]
         self.__venvManager = venvManager
         
         self.__process = None
         self.__cmd = ""
         
-        if pyvenv:
+        if self.__pyvenv:
             self.__calls = []
-            if interpreter:
-                self.__calls.append((interpreter, ["-m", "venv"]))
+            if configuration["pythonExe"]:
+                self.__calls.append((configuration["pythonExe"],
+                                     ["-m", "venv"]))
             self.__calls.extend([
                 (sys.executable.replace("w.exe", ".exe"),
                  ["-m", "venv"]),
@@ -250,7 +236,7 @@
         """
         Private method to log some output.
         
-        @param s output sstring to log (string)
+        @param s output string to log (string)
         """
         self.contents.insertPlainText(s)
         self.contents.ensureCursorVisible()
--- a/VirtualEnv/VirtualenvManager.py	Sat Feb 16 13:02:35 2019 +0100
+++ b/VirtualEnv/VirtualenvManager.py	Sat Feb 16 15:36:36 2019 +0100
@@ -19,9 +19,9 @@
 from PyQt5.QtWidgets import QDialog
 
 from E5Gui import E5MessageBox
+from E5Gui.E5Application import e5App
 
 import Preferences
-import Utilities
 
 
 class VirtualenvManager(QObject):
@@ -152,17 +152,25 @@
         
         dlg = VirtualenvConfigurationDialog()
         if dlg.exec_() == QDialog.Accepted:
-            (pyvenv, args, name, openTarget, createLog, createScript,
-             targetDir, interpreter) = dlg.getData()
+            resultDict = dlg.getData()
             
-            # now do the call
-            from .VirtualenvExecDialog import VirtualenvExecDialog
-            dia = VirtualenvExecDialog(pyvenv, targetDir, name, openTarget,
-                                       createLog, createScript, interpreter,
-                                       self)
-            dia.show()
-            dia.start(args)
-            dia.exec_()
+            if resultDict["envType"] == "conda":
+                # create the conda environment
+                conda = e5App().getObject("Conda")
+                ok, prefix, interpreter = conda.createCondaEnvironment(
+                    resultDict["arguments"])
+                if ok and "--dry-run" not in resultDict["arguments"]:
+                    self.addVirtualEnv(resultDict["logicalName"],
+                                       prefix,
+                                       venvInterpreter=interpreter,
+                                       isConda=True)
+            else:
+                # now do the call
+                from .VirtualenvExecDialog import VirtualenvExecDialog
+                dia = VirtualenvExecDialog(resultDict, self)
+                dia.show()
+                dia.start(resultDict["arguments"])
+                dia.exec_()
     
     def addVirtualEnv(self, venvName, venvDirectory, venvInterpreter="",
                       venvVariant=3, isGlobal=False, isConda=False,
@@ -197,7 +205,14 @@
                 .format(venvName),
                 icon=E5MessageBox.Warning)
             if not ok:
-                return
+                from .VirtualenvNameDialog import VirtualenvNameDialog
+                dlg = VirtualenvNameDialog(
+                    list(self.__virtualEnvironments.keys()),
+                    venvName)
+                if dlg.exec_() != QDialog.Accepted:
+                    return
+                
+                venvName = dlg.getName()
         
         if not venvInterpreter:
             from .VirtualenvInterpreterSelectionDialog import \
@@ -205,9 +220,6 @@
             dlg = VirtualenvInterpreterSelectionDialog(venvName, venvDirectory)
             if dlg.exec_() == QDialog.Accepted:
                 venvInterpreter, venvVariant = dlg.getData()
-                if not Utilities.startswithPath(venvInterpreter,
-                                                venvDirectory):
-                    isGlobal = True
         
         if venvInterpreter:
             self.__virtualEnvironments[venvName] = {
@@ -342,9 +354,17 @@
             if dlg.exec_() == QDialog.Accepted:
                 for venvName in venvNames:
                     if self.__isEnvironmentDeleteable(venvName):
-                        shutil.rmtree(
-                            self.__virtualEnvironments[venvName]["path"], True)
-                        del self.__virtualEnvironments[venvName]
+                        if self.isCondaEnvironment(venvName):
+                            conda = e5App().getObject("Conda")
+                            path = self.__virtualEnvironments[venvName]["path"]
+                            res = conda.removeCondaEnvironment(prefix=path)
+                            if res:
+                                del self.__virtualEnvironments[venvName]
+                        else:
+                            shutil.rmtree(
+                                self.__virtualEnvironments[venvName]["path"],
+                                True)
+                            del self.__virtualEnvironments[venvName]
                 
                 self.__saveSettings()
                 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VirtualEnv/VirtualenvNameDialog.py	Sat Feb 16 15:36:36 2019 +0100
@@ -0,0 +1,63 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to enter the logical name for a new virtual
+environment.
+"""
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import pyqtSlot, Qt
+from PyQt5.QtWidgets import QDialog, QDialogButtonBox
+
+from .Ui_VirtualenvNameDialog import Ui_VirtualenvNameDialog
+
+
+class VirtualenvNameDialog(QDialog, Ui_VirtualenvNameDialog):
+    """
+    Class implementing a dialog to enter the logical name for a new virtual
+    environment.
+    """
+    def __init__(self, environments, currentName, parent=None):
+        """
+        Constructor
+        
+        @param environments list of environment names to be shown
+        @type list of str
+        @param currentName name to be shown in the name edit
+        @type str
+        @param parent reference to the parent widget
+        @type QWidget
+        """
+        super(VirtualenvNameDialog, self).__init__(parent)
+        self.setupUi(self)
+        
+        self.envsList.addItems(environments)
+        self.nameEdit.setText(currentName)
+        
+        self.nameEdit.setFocus(Qt.OtherFocusReason)
+        self.nameEdit.selectAll()
+    
+    @pyqtSlot(str)
+    def on_nameEdit_textChanged(self, txt):
+        """
+        Private slot to handle a change of the environment name.
+        
+        @param txt contens of the name edit
+        @type str
+        """
+        items = self.envsList.findItems(txt, Qt.MatchExactly)
+        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(
+            bool(txt) and len(items) == 0)
+    
+    def getName(self):
+        """
+        Public method to get the entered name.
+        
+        @return name for the environment
+        @rtype str
+        """
+        return self.nameEdit.text()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VirtualEnv/VirtualenvNameDialog.ui	Sat Feb 16 15:36:36 2019 +0100
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>VirtualenvNameDialog</class>
+ <widget class="QDialog" name="VirtualenvNameDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>450</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Virtualenv Name</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QListWidget" name="envsList">
+     <property name="editTriggers">
+      <set>QAbstractItemView::NoEditTriggers</set>
+     </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>
+   <item>
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Enter a logical name for the virtual environment:</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="E5ClearableLineEdit" name="nameEdit">
+     <property name="toolTip">
+      <string>Enter a unique name for the virtual environment</string>
+     </property>
+     <property name="placeholderText">
+      <string>Name for the virtual environment</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>E5ClearableLineEdit</class>
+   <extends>QLineEdit</extends>
+   <header>E5Gui/E5LineEdit.h</header>
+  </customwidget>
+ </customwidgets>
+ <tabstops>
+  <tabstop>envsList</tabstop>
+  <tabstop>nameEdit</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>VirtualenvNameDialog</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>VirtualenvNameDialog</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/eric6.e4p	Sat Feb 16 13:02:35 2019 +0100
+++ b/eric6.e4p	Sat Feb 16 15:36:36 2019 +0100
@@ -16,6 +16,14 @@
   <TranslationPattern>i18n/eric6_%language%.ts</TranslationPattern>
   <Eol index="1"/>
   <Sources>
+    <Source>CondaInterface/Conda.py</Source>
+    <Source>CondaInterface/CondaExecDialog.py</Source>
+    <Source>CondaInterface/CondaExportDialog.py</Source>
+    <Source>CondaInterface/CondaInfoDialog.py</Source>
+    <Source>CondaInterface/CondaNewEnvironmentDataDialog.py</Source>
+    <Source>CondaInterface/CondaPackageDetailsWidget.py</Source>
+    <Source>CondaInterface/CondaPackagesWidget.py</Source>
+    <Source>CondaInterface/__init__.py</Source>
     <Source>Cooperation/ChatWidget.py</Source>
     <Source>Cooperation/Connection.py</Source>
     <Source>Cooperation/CooperationClient.py</Source>
@@ -838,6 +846,7 @@
     <Source>Plugins/__init__.py</Source>
     <Source>Preferences/ConfigurationDialog.py</Source>
     <Source>Preferences/ConfigurationPages/ApplicationPage.py</Source>
+    <Source>Preferences/ConfigurationPages/CondaPage.py</Source>
     <Source>Preferences/ConfigurationPages/ConfigurationPageBase.py</Source>
     <Source>Preferences/ConfigurationPages/CooperationPage.py</Source>
     <Source>Preferences/ConfigurationPages/CorbaPage.py</Source>
@@ -1419,6 +1428,7 @@
     <Source>VirtualEnv/VirtualenvInterpreterSelectionDialog.py</Source>
     <Source>VirtualEnv/VirtualenvManager.py</Source>
     <Source>VirtualEnv/VirtualenvManagerDialog.py</Source>
+    <Source>VirtualEnv/VirtualenvNameDialog.py</Source>
     <Source>VirtualEnv/__init__.py</Source>
     <Source>WebBrowser/AdBlock/AdBlockDialog.py</Source>
     <Source>WebBrowser/AdBlock/AdBlockExceptionsDialog.py</Source>
@@ -1712,6 +1722,12 @@
     <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/CondaPackageDetailsWidget.ui</Form>
+    <Form>CondaInterface/CondaPackagesWidget.ui</Form>
     <Form>Cooperation/ChatWidget.ui</Form>
     <Form>DataViews/CodeMetricsDialog.ui</Form>
     <Form>DataViews/PyCoverageDialog.ui</Form>
@@ -2011,6 +2027,7 @@
     <Form>Plugins/WizardPlugins/QRegularExpressionWizard/QRegularExpressionWizardRepeatDialog.ui</Form>
     <Form>Plugins/WizardPlugins/SetupWizard/SetupWizardDialog.ui</Form>
     <Form>Preferences/ConfigurationPages/ApplicationPage.ui</Form>
+    <Form>Preferences/ConfigurationPages/CondaPage.ui</Form>
     <Form>Preferences/ConfigurationPages/CooperationPage.ui</Form>
     <Form>Preferences/ConfigurationPages/CorbaPage.ui</Form>
     <Form>Preferences/ConfigurationPages/DebuggerGeneralPage.ui</Form>
@@ -2143,6 +2160,7 @@
     <Form>VirtualEnv/VirtualenvExecDialog.ui</Form>
     <Form>VirtualEnv/VirtualenvInterpreterSelectionDialog.ui</Form>
     <Form>VirtualEnv/VirtualenvManagerDialog.ui</Form>
+    <Form>VirtualEnv/VirtualenvNameDialog.ui</Form>
     <Form>WebBrowser/AdBlock/AdBlockDialog.ui</Form>
     <Form>WebBrowser/AdBlock/AdBlockExceptionsDialog.ui</Form>
     <Form>WebBrowser/Bookmarks/AddBookmarkDialog.ui</Form>
@@ -2243,14 +2261,14 @@
   </Resources>
   <Others>
     <Other>.hgignore</Other>
-    <Other>APIs/Python/zope-2.10.7.api</Other>
-    <Other>APIs/Python/zope-2.11.2.api</Other>
-    <Other>APIs/Python/zope-3.3.1.api</Other>
     <Other>APIs/Python3/PyQt4.bas</Other>
     <Other>APIs/Python3/PyQt5.bas</Other>
     <Other>APIs/Python3/QScintilla2.bas</Other>
     <Other>APIs/Python3/eric6.api</Other>
     <Other>APIs/Python3/eric6.bas</Other>
+    <Other>APIs/Python/zope-2.10.7.api</Other>
+    <Other>APIs/Python/zope-2.11.2.api</Other>
+    <Other>APIs/Python/zope-3.3.1.api</Other>
     <Other>APIs/QSS/qss.api</Other>
     <Other>APIs/Ruby/Ruby-1.8.7.api</Other>
     <Other>APIs/Ruby/Ruby-1.8.7.bas</Other>
Binary file icons/default/miniconda.svgz has changed
Binary file icons/default/miniconda48.svgz has changed

eric ide

mercurial