Merged with default branch. conda

Wed, 13 Feb 2019 20:39:58 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Wed, 13 Feb 2019 20:39:58 +0100
branch
conda
changeset 6740
46bb5e2df095
parent 6739
110ab101766a (diff)
parent 6735
31e263d49c04 (current diff)
child 6741
33a82a20dd3a

Merged with default branch.

Documentation/Help/source.qch file | annotate | diff | comparison | revisions
UI/UserInterface.py file | annotate | diff | comparison | revisions
VirtualEnv/VirtualenvManager.py file | annotate | diff | comparison | revisions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CondaInterface/Conda.py	Wed Feb 13 20:39:58 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	Wed Feb 13 20:39:58 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	Wed Feb 13 20:39:58 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	Wed Feb 13 20:39:58 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	Wed Feb 13 20:39:58 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	Wed Feb 13 20:39:58 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	Wed Feb 13 20:39:58 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	Wed Feb 13 20:39:58 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	Wed Feb 13 20:39:58 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	Wed Feb 13 20:39:58 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	Wed Feb 13 20:39:58 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	Wed Feb 13 20:39:58 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	Wed Feb 13 20:39:58 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	Wed Feb 13 20:39:58 2019 +0100
@@ -0,0 +1,134 @@
+# -*- 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	Wed Feb 13 18:59:31 2019 +0100
+++ b/Globals/__init__.py	Wed Feb 13 20:39:58 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	Wed Feb 13 18:59:31 2019 +0100
+++ b/Preferences/ConfigurationDialog.py	Wed Feb 13 20:39:58 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	Wed Feb 13 20:39:58 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	Wed Feb 13 20:39:58 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/ProgramsDialog.py	Wed Feb 13 18:59:31 2019 +0100
+++ b/Preferences/ProgramsDialog.py	Wed Feb 13 20:39:58 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	Wed Feb 13 18:59:31 2019 +0100
+++ b/Preferences/__init__.py	Wed Feb 13 20:39:58 2019 +0100
@@ -1580,6 +1580,11 @@
         "Provider": "disabled",
         "ShowInfoOnOpenParenthesis": True,
     }
+    
+    # defaults for conda
+    condaDefaults = {
+        "CondaExecutable": "",
+    }
 
 
 def readToolGroups(prefClass=Prefs):
@@ -3720,7 +3725,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(
@@ -3743,6 +3748,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	Wed Feb 13 18:59:31 2019 +0100
+++ b/UI/UserInterface.py	Wed Feb 13 20:39:58 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,14 @@
                               UI.PixmapCache.getIcon("debugViewer.png"),
                               self.tr("Debug-Viewer"))
         
+        # 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 +989,14 @@
             self.debugViewer, UI.PixmapCache.getIcon("debugViewer.png"),
             self.tr("Debug-Viewer"))
 
+        # 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	Wed Feb 13 18:59:31 2019 +0100
+++ b/VirtualEnv/VirtualenvConfigurationDialog.py	Wed Feb 13 20:39:58 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	Wed Feb 13 18:59:31 2019 +0100
+++ b/VirtualEnv/VirtualenvConfigurationDialog.ui	Wed Feb 13 20:39:58 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	Wed Feb 13 18:59:31 2019 +0100
+++ b/VirtualEnv/VirtualenvExecDialog.py	Wed Feb 13 20:39:58 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	Wed Feb 13 18:59:31 2019 +0100
+++ b/VirtualEnv/VirtualenvManager.py	Wed Feb 13 20:39:58 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	Wed Feb 13 20:39:58 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	Wed Feb 13 20:39:58 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	Wed Feb 13 18:59:31 2019 +0100
+++ b/eric6.e4p	Wed Feb 13 20:39:58 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.png has changed
Binary file icons/default/miniconda48.png has changed

eric ide

mercurial