28 |
33 |
29 class CondaPackagesWidget(QWidget, Ui_CondaPackagesWidget): |
34 class CondaPackagesWidget(QWidget, Ui_CondaPackagesWidget): |
30 """ |
35 """ |
31 Class implementing the conda packages management widget. |
36 Class implementing the conda packages management widget. |
32 """ |
37 """ |
|
38 |
33 # Role definition of packages list |
39 # Role definition of packages list |
34 PackageVersionRole = Qt.ItemDataRole.UserRole + 1 |
40 PackageVersionRole = Qt.ItemDataRole.UserRole + 1 |
35 PackageBuildRole = Qt.ItemDataRole.UserRole + 2 |
41 PackageBuildRole = Qt.ItemDataRole.UserRole + 2 |
36 |
42 |
37 # Role definitions of search results list |
43 # Role definitions of search results list |
38 PackageDetailedDataRole = Qt.ItemDataRole.UserRole + 1 |
44 PackageDetailedDataRole = Qt.ItemDataRole.UserRole + 1 |
39 |
45 |
40 def __init__(self, conda, parent=None): |
46 def __init__(self, conda, parent=None): |
41 """ |
47 """ |
42 Constructor |
48 Constructor |
43 |
49 |
44 @param conda reference to the conda interface |
50 @param conda reference to the conda interface |
45 @type Conda |
51 @type Conda |
46 @param parent reference to the parent widget |
52 @param parent reference to the parent widget |
47 @type QWidget |
53 @type QWidget |
48 """ |
54 """ |
49 super().__init__(parent) |
55 super().__init__(parent) |
50 self.setupUi(self) |
56 self.setupUi(self) |
51 |
57 |
52 self.layout().setContentsMargins(0, 3, 0, 0) |
58 self.layout().setContentsMargins(0, 3, 0, 0) |
53 |
59 |
54 self.__conda = conda |
60 self.__conda = conda |
55 |
61 |
56 if not CondaInterface.isCondaAvailable(): |
62 if not CondaInterface.isCondaAvailable(): |
57 self.baseWidget.hide() |
63 self.baseWidget.hide() |
58 self.searchWidget.hide() |
64 self.searchWidget.hide() |
59 |
65 |
60 else: |
66 else: |
61 self.notAvailableWidget.hide() |
67 self.notAvailableWidget.hide() |
62 |
68 |
63 self.__initCondaInterface() |
69 self.__initCondaInterface() |
64 |
70 |
65 def __initCondaInterface(self): |
71 def __initCondaInterface(self): |
66 """ |
72 """ |
67 Private method to initialize the conda interface elements. |
73 Private method to initialize the conda interface elements. |
68 """ |
74 """ |
69 self.statusLabel.hide() |
75 self.statusLabel.hide() |
70 |
76 |
71 self.condaMenuButton.setObjectName( |
77 self.condaMenuButton.setObjectName("conda_supermenu_button") |
72 "conda_supermenu_button") |
|
73 self.condaMenuButton.setIcon(UI.PixmapCache.getIcon("superMenu")) |
78 self.condaMenuButton.setIcon(UI.PixmapCache.getIcon("superMenu")) |
74 self.condaMenuButton.setToolTip(self.tr("Conda Menu")) |
79 self.condaMenuButton.setToolTip(self.tr("Conda Menu")) |
75 self.condaMenuButton.setPopupMode( |
80 self.condaMenuButton.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup) |
76 QToolButton.ToolButtonPopupMode.InstantPopup) |
81 self.condaMenuButton.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly) |
77 self.condaMenuButton.setToolButtonStyle( |
|
78 Qt.ToolButtonStyle.ToolButtonIconOnly) |
|
79 self.condaMenuButton.setFocusPolicy(Qt.FocusPolicy.NoFocus) |
82 self.condaMenuButton.setFocusPolicy(Qt.FocusPolicy.NoFocus) |
80 self.condaMenuButton.setAutoRaise(True) |
83 self.condaMenuButton.setAutoRaise(True) |
81 self.condaMenuButton.setShowMenuInside(True) |
84 self.condaMenuButton.setShowMenuInside(True) |
82 |
85 |
83 self.refreshButton.setIcon(UI.PixmapCache.getIcon("reload")) |
86 self.refreshButton.setIcon(UI.PixmapCache.getIcon("reload")) |
84 self.upgradeButton.setIcon(UI.PixmapCache.getIcon("1uparrow")) |
87 self.upgradeButton.setIcon(UI.PixmapCache.getIcon("1uparrow")) |
85 self.upgradeAllButton.setIcon(UI.PixmapCache.getIcon("2uparrow")) |
88 self.upgradeAllButton.setIcon(UI.PixmapCache.getIcon("2uparrow")) |
86 self.uninstallButton.setIcon(UI.PixmapCache.getIcon("minus")) |
89 self.uninstallButton.setIcon(UI.PixmapCache.getIcon("minus")) |
87 self.searchToggleButton.setIcon(UI.PixmapCache.getIcon("find")) |
90 self.searchToggleButton.setIcon(UI.PixmapCache.getIcon("find")) |
88 self.searchButton.setIcon(UI.PixmapCache.getIcon("findNext")) |
91 self.searchButton.setIcon(UI.PixmapCache.getIcon("findNext")) |
89 self.installButton.setIcon(UI.PixmapCache.getIcon("plus")) |
92 self.installButton.setIcon(UI.PixmapCache.getIcon("plus")) |
90 self.showDetailsButton.setIcon(UI.PixmapCache.getIcon("info")) |
93 self.showDetailsButton.setIcon(UI.PixmapCache.getIcon("info")) |
91 |
94 |
92 if CondaInterface.condaVersion() >= (4, 4, 0): |
95 if CondaInterface.condaVersion() >= (4, 4, 0): |
93 self.searchOptionsWidget.hide() |
96 self.searchOptionsWidget.hide() |
94 else: |
97 else: |
95 self.platformComboBox.addItems(sorted([ |
98 self.platformComboBox.addItems( |
96 "", "win-32", "win-64", "osx-64", "linux-32", "linux-64", |
99 sorted( |
97 ])) |
100 [ |
98 |
101 "", |
|
102 "win-32", |
|
103 "win-64", |
|
104 "osx-64", |
|
105 "linux-32", |
|
106 "linux-64", |
|
107 ] |
|
108 ) |
|
109 ) |
|
110 |
99 self.__initCondaMenu() |
111 self.__initCondaMenu() |
100 self.__populateEnvironments() |
112 self.__populateEnvironments() |
101 self.__updateActionButtons() |
113 self.__updateActionButtons() |
102 |
114 |
103 self.searchWidget.hide() |
115 self.searchWidget.hide() |
104 |
116 |
105 self.__conda.condaEnvironmentCreated.connect( |
117 self.__conda.condaEnvironmentCreated.connect(self.on_refreshButton_clicked) |
106 self.on_refreshButton_clicked) |
118 self.__conda.condaEnvironmentRemoved.connect(self.on_refreshButton_clicked) |
107 self.__conda.condaEnvironmentRemoved.connect( |
119 |
108 self.on_refreshButton_clicked) |
|
109 |
|
110 def __populateEnvironments(self): |
120 def __populateEnvironments(self): |
111 """ |
121 """ |
112 Private method to get a list of environments and populate the selector. |
122 Private method to get a list of environments and populate the selector. |
113 """ |
123 """ |
114 environments = [("", "")] + sorted( |
124 environments = [("", "")] + sorted(self.__conda.getCondaEnvironmentsList()) |
115 self.__conda.getCondaEnvironmentsList()) |
|
116 for environment in environments: |
125 for environment in environments: |
117 self.environmentsComboBox.addItem(environment[0], environment[1]) |
126 self.environmentsComboBox.addItem(environment[0], environment[1]) |
118 |
127 |
119 def __initCondaMenu(self): |
128 def __initCondaMenu(self): |
120 """ |
129 """ |
121 Private method to create the super menu and attach it to the super |
130 Private method to create the super menu and attach it to the super |
122 menu button. |
131 menu button. |
123 """ |
132 """ |
124 self.__condaMenu = QMenu(self) |
133 self.__condaMenu = QMenu(self) |
125 self.__envActs = [] |
134 self.__envActs = [] |
126 |
135 |
127 self.__cleanMenu = QMenu(self.tr("Clean"), self) |
136 self.__cleanMenu = QMenu(self.tr("Clean"), self) |
128 self.__cleanMenu.addAction( |
137 self.__cleanMenu.addAction( |
129 self.tr("All"), lambda: self.__conda.cleanConda("all")) |
138 self.tr("All"), lambda: self.__conda.cleanConda("all") |
|
139 ) |
130 self.__cleanMenu.addAction( |
140 self.__cleanMenu.addAction( |
131 self.tr("Cache"), lambda: self.__conda.cleanConda("index-cache")) |
141 self.tr("Cache"), lambda: self.__conda.cleanConda("index-cache") |
|
142 ) |
132 self.__cleanMenu.addAction( |
143 self.__cleanMenu.addAction( |
133 self.tr("Lock Files"), |
144 self.tr("Lock Files"), lambda: self.__conda.cleanConda("lock") |
134 lambda: self.__conda.cleanConda("lock")) |
145 ) |
135 self.__cleanMenu.addAction( |
146 self.__cleanMenu.addAction( |
136 self.tr("Packages"), lambda: self.__conda.cleanConda("packages")) |
147 self.tr("Packages"), lambda: self.__conda.cleanConda("packages") |
|
148 ) |
137 self.__cleanMenu.addAction( |
149 self.__cleanMenu.addAction( |
138 self.tr("Tarballs"), lambda: self.__conda.cleanConda("tarballs")) |
150 self.tr("Tarballs"), lambda: self.__conda.cleanConda("tarballs") |
139 |
151 ) |
140 self.__condaMenu.addAction( |
152 |
141 self.tr("About Conda..."), self.__aboutConda) |
153 self.__condaMenu.addAction(self.tr("About Conda..."), self.__aboutConda) |
|
154 self.__condaMenu.addSeparator() |
|
155 self.__condaMenu.addAction(self.tr("Update Conda"), self.__conda.updateConda) |
|
156 self.__condaMenu.addSeparator() |
|
157 self.__envActs.append( |
|
158 self.__condaMenu.addAction( |
|
159 self.tr("Install Packages"), self.__installPackages |
|
160 ) |
|
161 ) |
|
162 self.__envActs.append( |
|
163 self.__condaMenu.addAction( |
|
164 self.tr("Install Requirements"), self.__installRequirements |
|
165 ) |
|
166 ) |
|
167 self.__condaMenu.addSeparator() |
|
168 self.__envActs.append( |
|
169 self.__condaMenu.addAction( |
|
170 self.tr("Generate Requirements"), self.__generateRequirements |
|
171 ) |
|
172 ) |
142 self.__condaMenu.addSeparator() |
173 self.__condaMenu.addSeparator() |
143 self.__condaMenu.addAction( |
174 self.__condaMenu.addAction( |
144 self.tr("Update Conda"), self.__conda.updateConda) |
175 self.tr("Create Environment from Requirements"), self.__createEnvironment |
145 self.__condaMenu.addSeparator() |
176 ) |
146 self.__envActs.append(self.__condaMenu.addAction( |
177 self.__envActs.append( |
147 self.tr("Install Packages"), self.__installPackages)) |
178 self.__condaMenu.addAction( |
148 self.__envActs.append(self.__condaMenu.addAction( |
179 self.tr("Clone Environment"), self.__cloneEnvironment |
149 self.tr("Install Requirements"), self.__installRequirements)) |
180 ) |
150 self.__condaMenu.addSeparator() |
181 ) |
151 self.__envActs.append(self.__condaMenu.addAction( |
|
152 self.tr("Generate Requirements"), self.__generateRequirements)) |
|
153 self.__condaMenu.addSeparator() |
|
154 self.__condaMenu.addAction( |
|
155 self.tr("Create Environment from Requirements"), |
|
156 self.__createEnvironment) |
|
157 self.__envActs.append(self.__condaMenu.addAction( |
|
158 self.tr("Clone Environment"), self.__cloneEnvironment)) |
|
159 self.__deleteEnvAct = self.__condaMenu.addAction( |
182 self.__deleteEnvAct = self.__condaMenu.addAction( |
160 self.tr("Delete Environment"), self.__deleteEnvironment) |
183 self.tr("Delete Environment"), self.__deleteEnvironment |
|
184 ) |
161 self.__condaMenu.addSeparator() |
185 self.__condaMenu.addSeparator() |
162 self.__condaMenu.addMenu(self.__cleanMenu) |
186 self.__condaMenu.addMenu(self.__cleanMenu) |
163 self.__condaMenu.addSeparator() |
187 self.__condaMenu.addSeparator() |
164 self.__condaMenu.addAction( |
188 self.__condaMenu.addAction( |
165 self.tr("Edit User Configuration..."), |
189 self.tr("Edit User Configuration..."), self.__editUserConfiguration |
166 self.__editUserConfiguration) |
190 ) |
167 self.__condaMenu.addSeparator() |
191 self.__condaMenu.addSeparator() |
168 self.__condaMenu.addAction( |
192 self.__condaMenu.addAction(self.tr("Configure..."), self.__condaConfigure) |
169 self.tr("Configure..."), self.__condaConfigure) |
193 |
170 |
|
171 self.condaMenuButton.setMenu(self.__condaMenu) |
194 self.condaMenuButton.setMenu(self.__condaMenu) |
172 |
195 |
173 self.__condaMenu.aboutToShow.connect(self.__aboutToShowCondaMenu) |
196 self.__condaMenu.aboutToShow.connect(self.__aboutToShowCondaMenu) |
174 |
197 |
175 def __selectedUpdateableItems(self): |
198 def __selectedUpdateableItems(self): |
176 """ |
199 """ |
177 Private method to get a list of selected items that can be updated. |
200 Private method to get a list of selected items that can be updated. |
178 |
201 |
179 @return list of selected items that can be updated |
202 @return list of selected items that can be updated |
180 @rtype list of QTreeWidgetItem |
203 @rtype list of QTreeWidgetItem |
181 """ |
204 """ |
182 return [ |
205 return [itm for itm in self.packagesList.selectedItems() if bool(itm.text(2))] |
183 itm for itm in self.packagesList.selectedItems() |
206 |
184 if bool(itm.text(2)) |
|
185 ] |
|
186 |
|
187 def __allUpdateableItems(self): |
207 def __allUpdateableItems(self): |
188 """ |
208 """ |
189 Private method to get a list of all items that can be updated. |
209 Private method to get a list of all items that can be updated. |
190 |
210 |
191 @return list of all items that can be updated |
211 @return list of all items that can be updated |
192 @rtype list of QTreeWidgetItem |
212 @rtype list of QTreeWidgetItem |
193 """ |
213 """ |
194 updateableItems = [] |
214 updateableItems = [] |
195 for index in range(self.packagesList.topLevelItemCount()): |
215 for index in range(self.packagesList.topLevelItemCount()): |
196 itm = self.packagesList.topLevelItem(index) |
216 itm = self.packagesList.topLevelItem(index) |
197 if itm.text(2): |
217 if itm.text(2): |
198 updateableItems.append(itm) |
218 updateableItems.append(itm) |
199 |
219 |
200 return updateableItems |
220 return updateableItems |
201 |
221 |
202 def __updateActionButtons(self): |
222 def __updateActionButtons(self): |
203 """ |
223 """ |
204 Private method to set the state of the action buttons. |
224 Private method to set the state of the action buttons. |
205 """ |
225 """ |
206 self.upgradeButton.setEnabled( |
226 self.upgradeButton.setEnabled(bool(self.__selectedUpdateableItems())) |
207 bool(self.__selectedUpdateableItems())) |
227 self.uninstallButton.setEnabled(bool(self.packagesList.selectedItems())) |
208 self.uninstallButton.setEnabled( |
228 self.upgradeAllButton.setEnabled(bool(self.__allUpdateableItems())) |
209 bool(self.packagesList.selectedItems())) |
229 |
210 self.upgradeAllButton.setEnabled( |
|
211 bool(self.__allUpdateableItems())) |
|
212 |
|
213 @pyqtSlot(int) |
230 @pyqtSlot(int) |
214 def on_environmentsComboBox_currentIndexChanged(self, index): |
231 def on_environmentsComboBox_currentIndexChanged(self, index): |
215 """ |
232 """ |
216 Private slot handling the selection of a conda environment. |
233 Private slot handling the selection of a conda environment. |
217 |
234 |
218 @param index index of the selected conda environment |
235 @param index index of the selected conda environment |
219 @type int |
236 @type int |
220 """ |
237 """ |
221 self.packagesList.clear() |
238 self.packagesList.clear() |
222 prefix = self.environmentsComboBox.itemData(index) |
239 prefix = self.environmentsComboBox.itemData(index) |
223 if prefix: |
240 if prefix: |
224 self.statusLabel.show() |
241 self.statusLabel.show() |
225 self.statusLabel.setText(self.tr("Getting installed packages...")) |
242 self.statusLabel.setText(self.tr("Getting installed packages...")) |
226 |
243 |
227 with EricOverrideCursor(): |
244 with EricOverrideCursor(): |
228 # 1. populate with installed packages |
245 # 1. populate with installed packages |
229 self.packagesList.setUpdatesEnabled(False) |
246 self.packagesList.setUpdatesEnabled(False) |
230 installedPackages = self.__conda.getInstalledPackages( |
247 installedPackages = self.__conda.getInstalledPackages(prefix=prefix) |
231 prefix=prefix) |
|
232 for package, version, build in installedPackages: |
248 for package, version, build in installedPackages: |
233 itm = QTreeWidgetItem(self.packagesList, |
249 itm = QTreeWidgetItem(self.packagesList, [package, version]) |
234 [package, version]) |
|
235 itm.setData(1, self.PackageVersionRole, version) |
250 itm.setData(1, self.PackageVersionRole, version) |
236 itm.setData(1, self.PackageBuildRole, build) |
251 itm.setData(1, self.PackageBuildRole, build) |
237 self.packagesList.setUpdatesEnabled(True) |
252 self.packagesList.setUpdatesEnabled(True) |
238 self.statusLabel.setText( |
253 self.statusLabel.setText(self.tr("Getting outdated packages...")) |
239 self.tr("Getting outdated packages...")) |
|
240 QApplication.processEvents() |
254 QApplication.processEvents() |
241 |
255 |
242 # 2. update with update information |
256 # 2. update with update information |
243 self.packagesList.setUpdatesEnabled(False) |
257 self.packagesList.setUpdatesEnabled(False) |
244 updateablePackages = self.__conda.getUpdateablePackages( |
258 updateablePackages = self.__conda.getUpdateablePackages(prefix=prefix) |
245 prefix=prefix) |
|
246 for package, version, build in updateablePackages: |
259 for package, version, build in updateablePackages: |
247 items = self.packagesList.findItems( |
260 items = self.packagesList.findItems( |
248 package, |
261 package, |
249 Qt.MatchFlag.MatchExactly | |
262 Qt.MatchFlag.MatchExactly | Qt.MatchFlag.MatchCaseSensitive, |
250 Qt.MatchFlag.MatchCaseSensitive) |
263 ) |
251 if items: |
264 if items: |
252 itm = items[0] |
265 itm = items[0] |
253 itm.setText(2, version) |
266 itm.setText(2, version) |
254 itm.setData(2, self.PackageVersionRole, version) |
267 itm.setData(2, self.PackageVersionRole, version) |
255 itm.setData(2, self.PackageBuildRole, build) |
268 itm.setData(2, self.PackageBuildRole, build) |
256 if itm.data(1, self.PackageVersionRole) == version: |
269 if itm.data(1, self.PackageVersionRole) == version: |
257 # build must be different, show in version display |
270 # build must be different, show in version display |
258 itm.setText(1, self.tr("{0} (Build: {1})").format( |
271 itm.setText( |
259 itm.data(1, self.PackageVersionRole), |
272 1, |
260 itm.data(1, self.PackageBuildRole), |
273 self.tr("{0} (Build: {1})").format( |
261 )) |
274 itm.data(1, self.PackageVersionRole), |
262 itm.setText(2, self.tr("{0} (Build: {1})").format( |
275 itm.data(1, self.PackageBuildRole), |
263 itm.data(2, self.PackageVersionRole), |
276 ), |
264 itm.data(2, self.PackageBuildRole), |
277 ) |
265 )) |
278 itm.setText( |
266 |
279 2, |
|
280 self.tr("{0} (Build: {1})").format( |
|
281 itm.data(2, self.PackageVersionRole), |
|
282 itm.data(2, self.PackageBuildRole), |
|
283 ), |
|
284 ) |
|
285 |
267 self.packagesList.sortItems(0, Qt.SortOrder.AscendingOrder) |
286 self.packagesList.sortItems(0, Qt.SortOrder.AscendingOrder) |
268 for col in range(self.packagesList.columnCount()): |
287 for col in range(self.packagesList.columnCount()): |
269 self.packagesList.resizeColumnToContents(col) |
288 self.packagesList.resizeColumnToContents(col) |
270 self.packagesList.setUpdatesEnabled(True) |
289 self.packagesList.setUpdatesEnabled(True) |
271 self.statusLabel.hide() |
290 self.statusLabel.hide() |
272 |
291 |
273 self.__updateActionButtons() |
292 self.__updateActionButtons() |
274 self.__updateSearchActionButtons() |
293 self.__updateSearchActionButtons() |
275 |
294 |
276 @pyqtSlot() |
295 @pyqtSlot() |
277 def on_packagesList_itemSelectionChanged(self): |
296 def on_packagesList_itemSelectionChanged(self): |
278 """ |
297 """ |
279 Private slot to handle the selection of some items.. |
298 Private slot to handle the selection of some items.. |
280 """ |
299 """ |
281 self.__updateActionButtons() |
300 self.__updateActionButtons() |
282 |
301 |
283 @pyqtSlot() |
302 @pyqtSlot() |
284 def on_refreshButton_clicked(self): |
303 def on_refreshButton_clicked(self): |
285 """ |
304 """ |
286 Private slot to refresh the display. |
305 Private slot to refresh the display. |
287 """ |
306 """ |
288 currentEnvironment = self.environmentsComboBox.currentText() |
307 currentEnvironment = self.environmentsComboBox.currentText() |
289 self.environmentsComboBox.clear() |
308 self.environmentsComboBox.clear() |
290 self.packagesList.clear() |
309 self.packagesList.clear() |
291 |
310 |
292 with EricOverrideCursor(): |
311 with EricOverrideCursor(): |
293 self.__populateEnvironments() |
312 self.__populateEnvironments() |
294 |
313 |
295 index = self.environmentsComboBox.findText( |
314 index = self.environmentsComboBox.findText( |
296 currentEnvironment, |
315 currentEnvironment, |
297 Qt.MatchFlag.MatchExactly | Qt.MatchFlag.MatchCaseSensitive) |
316 Qt.MatchFlag.MatchExactly | Qt.MatchFlag.MatchCaseSensitive, |
|
317 ) |
298 if index != -1: |
318 if index != -1: |
299 self.environmentsComboBox.setCurrentIndex(index) |
319 self.environmentsComboBox.setCurrentIndex(index) |
300 |
320 |
301 self.__updateActionButtons() |
321 self.__updateActionButtons() |
302 |
322 |
303 @pyqtSlot() |
323 @pyqtSlot() |
304 def on_upgradeButton_clicked(self): |
324 def on_upgradeButton_clicked(self): |
305 """ |
325 """ |
306 Private slot to upgrade selected packages of the selected environment. |
326 Private slot to upgrade selected packages of the selected environment. |
307 """ |
327 """ |
308 packages = [itm.text(0) for itm in self.__selectedUpdateableItems()] |
328 packages = [itm.text(0) for itm in self.__selectedUpdateableItems()] |
309 if packages: |
329 if packages: |
310 prefix = self.environmentsComboBox.itemData( |
330 prefix = self.environmentsComboBox.itemData( |
311 self.environmentsComboBox.currentIndex()) |
331 self.environmentsComboBox.currentIndex() |
|
332 ) |
312 ok = self.__conda.updatePackages(packages, prefix=prefix) |
333 ok = self.__conda.updatePackages(packages, prefix=prefix) |
313 if ok: |
334 if ok: |
314 self.on_refreshButton_clicked() |
335 self.on_refreshButton_clicked() |
315 |
336 |
316 @pyqtSlot() |
337 @pyqtSlot() |
317 def on_upgradeAllButton_clicked(self): |
338 def on_upgradeAllButton_clicked(self): |
318 """ |
339 """ |
319 Private slot to upgrade all packages of the selected environment. |
340 Private slot to upgrade all packages of the selected environment. |
320 """ |
341 """ |
321 prefix = self.environmentsComboBox.itemData( |
342 prefix = self.environmentsComboBox.itemData( |
322 self.environmentsComboBox.currentIndex()) |
343 self.environmentsComboBox.currentIndex() |
|
344 ) |
323 ok = self.__conda.updateAllPackages(prefix=prefix) |
345 ok = self.__conda.updateAllPackages(prefix=prefix) |
324 if ok: |
346 if ok: |
325 self.on_refreshButton_clicked() |
347 self.on_refreshButton_clicked() |
326 |
348 |
327 @pyqtSlot() |
349 @pyqtSlot() |
328 def on_uninstallButton_clicked(self): |
350 def on_uninstallButton_clicked(self): |
329 """ |
351 """ |
330 Private slot to remove selected packages of the selected environment. |
352 Private slot to remove selected packages of the selected environment. |
331 """ |
353 """ |
332 packages = [itm.text(0) for itm in self.packagesList.selectedItems()] |
354 packages = [itm.text(0) for itm in self.packagesList.selectedItems()] |
333 if packages: |
355 if packages: |
334 prefix = self.environmentsComboBox.itemData( |
356 prefix = self.environmentsComboBox.itemData( |
335 self.environmentsComboBox.currentIndex()) |
357 self.environmentsComboBox.currentIndex() |
|
358 ) |
336 ok = self.__conda.uninstallPackages(packages, prefix=prefix) |
359 ok = self.__conda.uninstallPackages(packages, prefix=prefix) |
337 if ok: |
360 if ok: |
338 self.on_refreshButton_clicked() |
361 self.on_refreshButton_clicked() |
339 |
362 |
340 ####################################################################### |
363 ####################################################################### |
341 ## Search widget related methods below |
364 ## Search widget related methods below |
342 ####################################################################### |
365 ####################################################################### |
343 |
366 |
344 def __updateSearchActionButtons(self): |
367 def __updateSearchActionButtons(self): |
345 """ |
368 """ |
346 Private method to update the action button states of the search widget. |
369 Private method to update the action button states of the search widget. |
347 """ |
370 """ |
348 enable = len(self.searchResultList.selectedItems()) == 1 |
371 enable = len(self.searchResultList.selectedItems()) == 1 |
349 self.installButton.setEnabled( |
372 self.installButton.setEnabled( |
350 enable and self.environmentsComboBox.currentIndex() > 0) |
373 enable and self.environmentsComboBox.currentIndex() > 0 |
|
374 ) |
351 self.showDetailsButton.setEnabled( |
375 self.showDetailsButton.setEnabled( |
352 enable and bool(self.searchResultList.selectedItems()[0].parent())) |
376 enable and bool(self.searchResultList.selectedItems()[0].parent()) |
353 |
377 ) |
|
378 |
354 def __doSearch(self): |
379 def __doSearch(self): |
355 """ |
380 """ |
356 Private method to search for packages. |
381 Private method to search for packages. |
357 """ |
382 """ |
358 self.searchResultList.clear() |
383 self.searchResultList.clear() |
359 pattern = self.searchEdit.text() |
384 pattern = self.searchEdit.text() |
360 if pattern: |
385 if pattern: |
361 with EricOverrideCursor(): |
386 with EricOverrideCursor(): |
362 prefix = ( |
387 prefix = ( |
363 "" |
388 "" |
364 if CondaInterface.condaVersion() >= (4, 4, 0) else |
389 if CondaInterface.condaVersion() >= (4, 4, 0) |
365 self.environmentsComboBox.itemData( |
390 else self.environmentsComboBox.itemData( |
366 self.environmentsComboBox.currentIndex()) |
391 self.environmentsComboBox.currentIndex() |
|
392 ) |
367 ) |
393 ) |
368 ok, result = self.__conda.searchPackages( |
394 ok, result = self.__conda.searchPackages( |
369 pattern, |
395 pattern, |
370 fullNameOnly=self.fullNameButton.isChecked(), |
396 fullNameOnly=self.fullNameButton.isChecked(), |
371 packageSpec=self.packageSpecButton.isChecked(), |
397 packageSpec=self.packageSpecButton.isChecked(), |
372 platform=self.platformComboBox.currentText(), |
398 platform=self.platformComboBox.currentText(), |
373 prefix=prefix, |
399 prefix=prefix, |
374 ) |
400 ) |
375 |
401 |
376 if ok and result: |
402 if ok and result: |
377 self.searchResultList.setUpdatesEnabled(False) |
403 self.searchResultList.setUpdatesEnabled(False) |
378 for package in result: |
404 for package in result: |
379 itm = QTreeWidgetItem(self.searchResultList, |
405 itm = QTreeWidgetItem(self.searchResultList, [package]) |
380 [package]) |
|
381 itm.setExpanded(False) |
406 itm.setExpanded(False) |
382 for detail in result[package]: |
407 for detail in result[package]: |
383 version = detail["version"] |
408 version = detail["version"] |
384 build = detail["build"] |
409 build = detail["build"] |
385 if "subdir" in detail: |
410 if "subdir" in detail: |
386 platform = detail["subdir"] |
411 platform = detail["subdir"] |
387 elif "platform" in detail: |
412 elif "platform" in detail: |
388 platform = detail["platform"] |
413 platform = detail["platform"] |
389 else: |
414 else: |
390 platform = "" |
415 platform = "" |
391 citm = QTreeWidgetItem( |
416 citm = QTreeWidgetItem(itm, ["", version, build, platform]) |
392 itm, ["", version, build, platform]) |
417 citm.setData(0, self.PackageDetailedDataRole, detail) |
393 citm.setData(0, self.PackageDetailedDataRole, |
418 |
394 detail) |
419 self.searchResultList.sortItems(0, Qt.SortOrder.AscendingOrder) |
395 |
|
396 self.searchResultList.sortItems( |
|
397 0, Qt.SortOrder.AscendingOrder) |
|
398 self.searchResultList.resizeColumnToContents(0) |
420 self.searchResultList.resizeColumnToContents(0) |
399 self.searchResultList.setUpdatesEnabled(True) |
421 self.searchResultList.setUpdatesEnabled(True) |
400 if not ok: |
422 if not ok: |
401 try: |
423 try: |
402 message = result["message"] |
424 message = result["message"] |
403 except KeyError: |
425 except KeyError: |
404 message = result["error"] |
426 message = result["error"] |
405 EricMessageBox.warning( |
427 EricMessageBox.warning( |
406 self, |
428 self, self.tr("Conda Search Package Error"), message |
407 self.tr("Conda Search Package Error"), |
429 ) |
408 message) |
430 |
409 |
|
410 def __showDetails(self, item): |
431 def __showDetails(self, item): |
411 """ |
432 """ |
412 Private method to show a dialog with details about a package item. |
433 Private method to show a dialog with details about a package item. |
413 |
434 |
414 @param item reference to the package item |
435 @param item reference to the package item |
415 @type QTreeWidgetItem |
436 @type QTreeWidgetItem |
416 """ |
437 """ |
417 details = item.data(0, self.PackageDetailedDataRole) |
438 details = item.data(0, self.PackageDetailedDataRole) |
418 if details: |
439 if details: |
419 from .CondaPackageDetailsWidget import CondaPackageDetailsDialog |
440 from .CondaPackageDetailsWidget import CondaPackageDetailsDialog |
|
441 |
420 dlg = CondaPackageDetailsDialog(details, self) |
442 dlg = CondaPackageDetailsDialog(details, self) |
421 dlg.exec() |
443 dlg.exec() |
422 |
444 |
423 @pyqtSlot(str) |
445 @pyqtSlot(str) |
424 def on_searchEdit_textChanged(self, txt): |
446 def on_searchEdit_textChanged(self, txt): |
425 """ |
447 """ |
426 Private slot handling changes of the entered search specification. |
448 Private slot handling changes of the entered search specification. |
427 |
449 |
428 @param txt current search entry |
450 @param txt current search entry |
429 @type str |
451 @type str |
430 """ |
452 """ |
431 self.searchButton.setEnabled(bool(txt)) |
453 self.searchButton.setEnabled(bool(txt)) |
432 |
454 |
433 @pyqtSlot() |
455 @pyqtSlot() |
434 def on_searchEdit_returnPressed(self): |
456 def on_searchEdit_returnPressed(self): |
435 """ |
457 """ |
436 Private slot handling the user pressing the Return button in the |
458 Private slot handling the user pressing the Return button in the |
437 search edit. |
459 search edit. |
438 """ |
460 """ |
439 self.__doSearch() |
461 self.__doSearch() |
440 |
462 |
441 @pyqtSlot() |
463 @pyqtSlot() |
442 def on_searchButton_clicked(self): |
464 def on_searchButton_clicked(self): |
443 """ |
465 """ |
444 Private slot handling the press of the search button. |
466 Private slot handling the press of the search button. |
445 """ |
467 """ |
446 self.__doSearch() |
468 self.__doSearch() |
447 |
469 |
448 @pyqtSlot() |
470 @pyqtSlot() |
449 def on_installButton_clicked(self): |
471 def on_installButton_clicked(self): |
450 """ |
472 """ |
451 Private slot to install a selected package. |
473 Private slot to install a selected package. |
452 """ |
474 """ |
460 package = "{0}={1}={2}".format( |
482 package = "{0}={1}={2}".format( |
461 item.parent().text(0), |
483 item.parent().text(0), |
462 item.text(1), |
484 item.text(1), |
463 item.text(2), |
485 item.text(2), |
464 ) |
486 ) |
465 |
487 |
466 prefix = self.environmentsComboBox.itemData( |
488 prefix = self.environmentsComboBox.itemData( |
467 self.environmentsComboBox.currentIndex()) |
489 self.environmentsComboBox.currentIndex() |
|
490 ) |
468 ok = self.__conda.installPackages([package], prefix=prefix) |
491 ok = self.__conda.installPackages([package], prefix=prefix) |
469 if ok: |
492 if ok: |
470 self.on_refreshButton_clicked() |
493 self.on_refreshButton_clicked() |
471 |
494 |
472 @pyqtSlot() |
495 @pyqtSlot() |
473 def on_showDetailsButton_clicked(self): |
496 def on_showDetailsButton_clicked(self): |
474 """ |
497 """ |
475 Private slot handling the 'Show Details' button. |
498 Private slot handling the 'Show Details' button. |
476 """ |
499 """ |
477 item = self.searchResultList.selectedItems()[0] |
500 item = self.searchResultList.selectedItems()[0] |
478 self.__showDetails(item) |
501 self.__showDetails(item) |
479 |
502 |
480 @pyqtSlot() |
503 @pyqtSlot() |
481 def on_searchResultList_itemSelectionChanged(self): |
504 def on_searchResultList_itemSelectionChanged(self): |
482 """ |
505 """ |
483 Private slot handling a change of selected search results. |
506 Private slot handling a change of selected search results. |
484 """ |
507 """ |
485 self.__updateSearchActionButtons() |
508 self.__updateSearchActionButtons() |
486 |
509 |
487 @pyqtSlot(QTreeWidgetItem) |
510 @pyqtSlot(QTreeWidgetItem) |
488 def on_searchResultList_itemExpanded(self, item): |
511 def on_searchResultList_itemExpanded(self, item): |
489 """ |
512 """ |
490 Private slot handling the expansion of an item. |
513 Private slot handling the expansion of an item. |
491 |
514 |
492 @param item reference to the expanded item |
515 @param item reference to the expanded item |
493 @type QTreeWidgetItem |
516 @type QTreeWidgetItem |
494 """ |
517 """ |
495 for col in range(1, self.searchResultList.columnCount()): |
518 for col in range(1, self.searchResultList.columnCount()): |
496 self.searchResultList.resizeColumnToContents(col) |
519 self.searchResultList.resizeColumnToContents(col) |
497 |
520 |
498 @pyqtSlot(QTreeWidgetItem, int) |
521 @pyqtSlot(QTreeWidgetItem, int) |
499 def on_searchResultList_itemDoubleClicked(self, item, column): |
522 def on_searchResultList_itemDoubleClicked(self, item, column): |
500 """ |
523 """ |
501 Private slot handling a double click of an item. |
524 Private slot handling a double click of an item. |
502 |
525 |
503 @param item reference to the item that was double clicked |
526 @param item reference to the item that was double clicked |
504 @type QTreeWidgetItem |
527 @type QTreeWidgetItem |
505 @param column column of the double click |
528 @param column column of the double click |
506 @type int |
529 @type int |
507 """ |
530 """ |
508 if item.parent() is not None: |
531 if item.parent() is not None: |
509 self.__showDetails(item) |
532 self.__showDetails(item) |
510 |
533 |
511 @pyqtSlot(bool) |
534 @pyqtSlot(bool) |
512 def on_searchToggleButton_toggled(self, checked): |
535 def on_searchToggleButton_toggled(self, checked): |
513 """ |
536 """ |
514 Private slot to togle the search widget. |
537 Private slot to togle the search widget. |
515 |
538 |
516 @param checked state of the search widget button |
539 @param checked state of the search widget button |
517 @type bool |
540 @type bool |
518 """ |
541 """ |
519 self.searchWidget.setVisible(checked) |
542 self.searchWidget.setVisible(checked) |
520 |
543 |
521 if checked: |
544 if checked: |
522 self.searchEdit.setFocus(Qt.FocusReason.OtherFocusReason) |
545 self.searchEdit.setFocus(Qt.FocusReason.OtherFocusReason) |
523 self.searchEdit.selectAll() |
546 self.searchEdit.selectAll() |
524 |
547 |
525 self.__updateSearchActionButtons() |
548 self.__updateSearchActionButtons() |
526 |
549 |
527 ####################################################################### |
550 ####################################################################### |
528 ## Menu related methods below |
551 ## Menu related methods below |
529 ####################################################################### |
552 ####################################################################### |
530 |
553 |
531 @pyqtSlot() |
554 @pyqtSlot() |
532 def __aboutToShowCondaMenu(self): |
555 def __aboutToShowCondaMenu(self): |
533 """ |
556 """ |
534 Private slot to handle the conda menu about to be shown. |
557 Private slot to handle the conda menu about to be shown. |
535 """ |
558 """ |
536 selectedEnvironment = self.environmentsComboBox.currentText() |
559 selectedEnvironment = self.environmentsComboBox.currentText() |
537 enable = selectedEnvironment not in [""] |
560 enable = selectedEnvironment not in [""] |
538 for act in self.__envActs: |
561 for act in self.__envActs: |
539 act.setEnabled(enable) |
562 act.setEnabled(enable) |
540 |
563 |
541 self.__deleteEnvAct.setEnabled( |
564 self.__deleteEnvAct.setEnabled( |
542 selectedEnvironment not in ["", self.__conda.RootName]) |
565 selectedEnvironment not in ["", self.__conda.RootName] |
543 |
566 ) |
|
567 |
544 @pyqtSlot() |
568 @pyqtSlot() |
545 def __aboutConda(self): |
569 def __aboutConda(self): |
546 """ |
570 """ |
547 Private slot to show some information about the conda installation. |
571 Private slot to show some information about the conda installation. |
548 """ |
572 """ |
549 infoDict = self.__conda.getCondaInformation() |
573 infoDict = self.__conda.getCondaInformation() |
550 |
574 |
551 from .CondaInfoDialog import CondaInfoDialog |
575 from .CondaInfoDialog import CondaInfoDialog |
|
576 |
552 dlg = CondaInfoDialog(infoDict, self) |
577 dlg = CondaInfoDialog(infoDict, self) |
553 dlg.exec() |
578 dlg.exec() |
554 |
579 |
555 @pyqtSlot() |
580 @pyqtSlot() |
556 def __installPackages(self): |
581 def __installPackages(self): |
557 """ |
582 """ |
558 Private slot to install packages. |
583 Private slot to install packages. |
559 """ |
584 """ |
560 prefix = self.environmentsComboBox.itemData( |
585 prefix = self.environmentsComboBox.itemData( |
561 self.environmentsComboBox.currentIndex()) |
586 self.environmentsComboBox.currentIndex() |
|
587 ) |
562 if prefix: |
588 if prefix: |
563 ok, packageSpecs = EricTextInputDialog.getText( |
589 ok, packageSpecs = EricTextInputDialog.getText( |
564 self, |
590 self, |
565 self.tr("Install Packages"), |
591 self.tr("Install Packages"), |
566 self.tr("Package Specifications (separated by whitespace):"), |
592 self.tr("Package Specifications (separated by whitespace):"), |
567 QLineEdit.EchoMode.Normal, |
593 QLineEdit.EchoMode.Normal, |
568 minimumWidth=600) |
594 minimumWidth=600, |
|
595 ) |
569 if ok and packageSpecs.strip(): |
596 if ok and packageSpecs.strip(): |
570 packages = [p.strip() for p in packageSpecs.split()] |
597 packages = [p.strip() for p in packageSpecs.split()] |
571 ok = self.__conda.installPackages(packages, prefix=prefix) |
598 ok = self.__conda.installPackages(packages, prefix=prefix) |
572 if ok: |
599 if ok: |
573 self.on_refreshButton_clicked() |
600 self.on_refreshButton_clicked() |
574 |
601 |
575 @pyqtSlot() |
602 @pyqtSlot() |
576 def __installRequirements(self): |
603 def __installRequirements(self): |
577 """ |
604 """ |
578 Private slot to install packages from requirements files. |
605 Private slot to install packages from requirements files. |
579 """ |
606 """ |
580 prefix = self.environmentsComboBox.itemData( |
607 prefix = self.environmentsComboBox.itemData( |
581 self.environmentsComboBox.currentIndex()) |
608 self.environmentsComboBox.currentIndex() |
|
609 ) |
582 if prefix: |
610 if prefix: |
583 requirements = EricFileDialog.getOpenFileNames( |
611 requirements = EricFileDialog.getOpenFileNames( |
584 self, |
612 self, |
585 self.tr("Install Packages"), |
613 self.tr("Install Packages"), |
586 "", |
614 "", |
587 self.tr("Text Files (*.txt);;All Files (*)")) |
615 self.tr("Text Files (*.txt);;All Files (*)"), |
|
616 ) |
588 if requirements: |
617 if requirements: |
589 args = [] |
618 args = [] |
590 for requirement in requirements: |
619 for requirement in requirements: |
591 args.extend(["--file", requirement]) |
620 args.extend(["--file", requirement]) |
592 ok = self.__conda.installPackages(args, prefix=prefix) |
621 ok = self.__conda.installPackages(args, prefix=prefix) |
593 if ok: |
622 if ok: |
594 self.on_refreshButton_clicked() |
623 self.on_refreshButton_clicked() |
595 |
624 |
596 @pyqtSlot() |
625 @pyqtSlot() |
597 def __generateRequirements(self): |
626 def __generateRequirements(self): |
598 """ |
627 """ |
599 Private slot to generate a requirements file. |
628 Private slot to generate a requirements file. |
600 """ |
629 """ |
601 prefix = self.environmentsComboBox.itemData( |
630 prefix = self.environmentsComboBox.itemData( |
602 self.environmentsComboBox.currentIndex()) |
631 self.environmentsComboBox.currentIndex() |
|
632 ) |
603 if prefix: |
633 if prefix: |
604 env = self.environmentsComboBox.currentText() |
634 env = self.environmentsComboBox.currentText() |
605 |
635 |
606 from .CondaExportDialog import CondaExportDialog |
636 from .CondaExportDialog import CondaExportDialog |
607 |
637 |
608 self.__requirementsDialog = CondaExportDialog( |
638 self.__requirementsDialog = CondaExportDialog(self.__conda, env, prefix) |
609 self.__conda, env, prefix) |
|
610 self.__requirementsDialog.show() |
639 self.__requirementsDialog.show() |
611 QApplication.processEvents() |
640 QApplication.processEvents() |
612 self.__requirementsDialog.start() |
641 self.__requirementsDialog.start() |
613 |
642 |
614 @pyqtSlot() |
643 @pyqtSlot() |
615 def __cloneEnvironment(self): |
644 def __cloneEnvironment(self): |
616 """ |
645 """ |
617 Private slot to clone a conda environment. |
646 Private slot to clone a conda environment. |
618 """ |
647 """ |
619 from .CondaNewEnvironmentDataDialog import ( |
648 from .CondaNewEnvironmentDataDialog import CondaNewEnvironmentDataDialog |
620 CondaNewEnvironmentDataDialog) |
649 |
621 |
|
622 prefix = self.environmentsComboBox.itemData( |
650 prefix = self.environmentsComboBox.itemData( |
623 self.environmentsComboBox.currentIndex()) |
651 self.environmentsComboBox.currentIndex() |
|
652 ) |
624 if prefix: |
653 if prefix: |
625 dlg = CondaNewEnvironmentDataDialog(self.tr("Clone Environment"), |
654 dlg = CondaNewEnvironmentDataDialog( |
626 False, self) |
655 self.tr("Clone Environment"), False, self |
|
656 ) |
627 if dlg.exec() == QDialog.DialogCode.Accepted: |
657 if dlg.exec() == QDialog.DialogCode.Accepted: |
628 virtEnvName, envName, _ = dlg.getData() |
658 virtEnvName, envName, _ = dlg.getData() |
629 args = [ |
659 args = [ |
630 "--name", |
660 "--name", |
631 envName.strip(), |
661 envName.strip(), |
632 "--clone", |
662 "--clone", |
633 prefix, |
663 prefix, |
634 ] |
664 ] |
635 ok, prefix, interpreter = self.__conda.createCondaEnvironment( |
665 ok, prefix, interpreter = self.__conda.createCondaEnvironment(args) |
636 args) |
|
637 if ok: |
666 if ok: |
638 ericApp().getObject("VirtualEnvManager").addVirtualEnv( |
667 ericApp().getObject("VirtualEnvManager").addVirtualEnv( |
639 virtEnvName, prefix, interpreter, isConda=True) |
668 virtEnvName, prefix, interpreter, isConda=True |
640 |
669 ) |
|
670 |
641 @pyqtSlot() |
671 @pyqtSlot() |
642 def __createEnvironment(self): |
672 def __createEnvironment(self): |
643 """ |
673 """ |
644 Private slot to create a conda environment from a requirements file. |
674 Private slot to create a conda environment from a requirements file. |
645 """ |
675 """ |
646 from .CondaNewEnvironmentDataDialog import ( |
676 from .CondaNewEnvironmentDataDialog import CondaNewEnvironmentDataDialog |
647 CondaNewEnvironmentDataDialog) |
677 |
648 |
678 dlg = CondaNewEnvironmentDataDialog(self.tr("Create Environment"), True, self) |
649 dlg = CondaNewEnvironmentDataDialog(self.tr("Create Environment"), |
|
650 True, self) |
|
651 if dlg.exec() == QDialog.DialogCode.Accepted: |
679 if dlg.exec() == QDialog.DialogCode.Accepted: |
652 virtEnvName, envName, requirements = dlg.getData() |
680 virtEnvName, envName, requirements = dlg.getData() |
653 args = [ |
681 args = [ |
654 "--name", |
682 "--name", |
655 envName.strip(), |
683 envName.strip(), |