Conda: implemented the package search and 'Show Details' functionality. conda

Sat, 09 Feb 2019 16:43:49 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 09 Feb 2019 16:43:49 +0100
branch
conda
changeset 6712
91fa67e8ebbc
parent 6706
d792e054cde2
child 6713
84024511120e

Conda: implemented the package search and 'Show Details' functionality.

CondaInterface/Conda.py file | annotate | diff | comparison | revisions
CondaInterface/CondaPackageDetailsWidget.py file | annotate | diff | comparison | revisions
CondaInterface/CondaPackageDetailsWidget.ui file | annotate | diff | comparison | revisions
CondaInterface/CondaPackagesWidget.py file | annotate | diff | comparison | revisions
CondaInterface/CondaPackagesWidget.ui file | annotate | diff | comparison | revisions
eric6.e4p file | annotate | diff | comparison | revisions
--- a/CondaInterface/Conda.py	Thu Feb 07 18:54:38 2019 +0100
+++ b/CondaInterface/Conda.py	Sat Feb 09 16:43:49 2019 +0100
@@ -516,3 +516,70 @@
             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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CondaInterface/CondaPackageDetailsWidget.py	Sat Feb 09 16:43:49 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.fromSecsSinceEpoch(details["timestamp"], Qt.UTC)
+            self.timestampLabel.setText(dt.toString("yyyy-MM-dd hh:mm:ss t"))
+        
+        self.resize(600, 500)
+
+
+class CondaPackageDetailsDialog(QDialog):
+    """
+    Class implementing a dialog to show package details.
+    """
+    def __init__(self, details, parent=None):
+        """
+        Constructor
+        
+        @param details dictionary containing the package details
+        @type dict
+        @param parent reference to the parent widget
+        @type QWidget
+        """
+        super(CondaPackageDetailsDialog, self).__init__(parent)
+        self.setSizeGripEnabled(True)
+        
+        self.__layout = QVBoxLayout(self)
+        self.setLayout(self.__layout)
+        
+        self.__cw = CondaPackageDetailsWidget(details, self)
+        size = self.__cw.size()
+        self.__layout.addWidget(self.__cw)
+        self.__buttonBox = QDialogButtonBox(self)
+        self.__buttonBox.setStandardButtons(QDialogButtonBox.Close)
+        self.__layout.addWidget(self.__buttonBox)
+        
+        self.resize(size)
+        self.setWindowTitle(self.tr("Package Details"))
+        
+        self.__buttonBox.accepted.connect(self.accept)
+        self.__buttonBox.rejected.connect(self.reject)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CondaInterface/CondaPackageDetailsWidget.ui	Sat Feb 09 16:43:49 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>612</width>
+    <height>492</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>
--- a/CondaInterface/CondaPackagesWidget.py	Thu Feb 07 18:54:38 2019 +0100
+++ b/CondaInterface/CondaPackagesWidget.py	Sat Feb 09 16:43:49 2019 +0100
@@ -14,18 +14,26 @@
 from PyQt5.QtWidgets import QWidget, QToolButton, QMenu, QTreeWidgetItem, \
     QApplication
 
+from E5Gui import E5MessageBox
+
 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
@@ -50,10 +58,21 @@
         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(
@@ -164,10 +183,12 @@
                         ))
             
             self.packagesList.sortItems(0, Qt.AscendingOrder)
+            self.packagesList.resizeColumnToContents(0)
             self.packagesList.setUpdatesEnabled(True)
             QApplication.restoreOverrideCursor()
         
         self.__updateActionButtons()
+        self.__updateSearchActionButtons()
     
     @pyqtSlot()
     def on_packagesList_itemSelectionChanged(self):
@@ -234,3 +255,173 @@
             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()
+            
+            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.show()
+    
+    @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):
+        """
+        Slot documentation goes here.
+        """
+        # TODO: not implemented yet
+        raise NotImplementedError
+    
+    @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()
--- a/CondaInterface/CondaPackagesWidget.ui	Thu Feb 07 18:54:38 2019 +0100
+++ b/CondaInterface/CondaPackagesWidget.ui	Sat Feb 09 16:43:49 2019 +0100
@@ -7,10 +7,10 @@
     <x>0</x>
     <y>0</y>
     <width>639</width>
-    <height>443</height>
+    <height>573</height>
    </rect>
   </property>
-  <layout class="QVBoxLayout" name="verticalLayout">
+  <layout class="QVBoxLayout" name="verticalLayout_3">
    <item>
     <layout class="QHBoxLayout" name="horizontalLayout">
      <item>
@@ -123,8 +123,219 @@
        </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>
+   <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>
@@ -134,6 +345,25 @@
    <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>
--- a/eric6.e4p	Thu Feb 07 18:54:38 2019 +0100
+++ b/eric6.e4p	Sat Feb 09 16:43:49 2019 +0100
@@ -18,6 +18,7 @@
   <Sources>
     <Source>CondaInterface/Conda.py</Source>
     <Source>CondaInterface/CondaExecDialog.py</Source>
+    <Source>CondaInterface/CondaPackageDetailsWidget.py</Source>
     <Source>CondaInterface/CondaPackagesWidget.py</Source>
     <Source>CondaInterface/__init__.py</Source>
     <Source>Cooperation/ChatWidget.py</Source>
@@ -1719,6 +1720,7 @@
   </Sources>
   <Forms>
     <Form>CondaInterface/CondaExecDialog.ui</Form>
+    <Form>CondaInterface/CondaPackageDetailsWidget.ui</Form>
     <Form>CondaInterface/CondaPackagesWidget.ui</Form>
     <Form>Cooperation/ChatWidget.ui</Form>
     <Form>DataViews/CodeMetricsDialog.ui</Form>

eric ide

mercurial