src/eric7/VirtualEnv/VirtualenvManagerWidgets.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 9146
409d93549d61
child 9221
bf71ee032bb4
equal deleted inserted replaced
9208:3fc8dfeb6ebe 9209:b99e7fd55fd3
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2018 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to manage the list of defined virtual
8 environments.
9 """
10
11 import os
12
13 from PyQt6.QtCore import pyqtSlot, Qt
14 from PyQt6.QtWidgets import (
15 QWidget, QDialog, QDialogButtonBox, QTreeWidgetItem, QHeaderView,
16 QVBoxLayout
17 )
18
19 from EricWidgets.EricPathPicker import EricPathPickerModes
20 from EricWidgets.EricMainWindow import EricMainWindow
21
22 from .Ui_VirtualenvManagerWidget import Ui_VirtualenvManagerWidget
23
24 import Utilities
25 import UI.PixmapCache
26
27
28 class VirtualenvManagerWidget(QWidget, Ui_VirtualenvManagerWidget):
29 """
30 Class implementing a widget to manage the list of defined virtual
31 environments.
32 """
33 IsGlobalRole = Qt.ItemDataRole.UserRole + 1
34 IsCondaRole = Qt.ItemDataRole.UserRole + 2
35 IsRemoteRole = Qt.ItemDataRole.UserRole + 3
36 ExecPathRole = Qt.ItemDataRole.UserRole + 4
37
38 def __init__(self, manager, parent=None):
39 """
40 Constructor
41
42 @param manager reference to the virtual environment manager
43 @type VirtualenvManager
44 @param parent reference to the parent widget
45 @type QWidget
46 """
47 super().__init__(parent)
48 self.setupUi(self)
49
50 self.__manager = manager
51
52 self.refreshButton.setIcon(UI.PixmapCache.getIcon("reload"))
53 self.addButton.setIcon(UI.PixmapCache.getIcon("plus"))
54 self.newButton.setIcon(UI.PixmapCache.getIcon("new"))
55 self.editButton.setIcon(UI.PixmapCache.getIcon("edit"))
56 self.upgradeButton.setIcon(UI.PixmapCache.getIcon("upgrade"))
57 self.removeButton.setIcon(UI.PixmapCache.getIcon("minus"))
58 self.removeAllButton.setIcon(UI.PixmapCache.getIcon("minus_3"))
59 self.deleteButton.setIcon(UI.PixmapCache.getIcon("fileDelete"))
60 self.deleteAllButton.setIcon(UI.PixmapCache.getIcon("fileDeleteList"))
61 self.saveButton.setIcon(UI.PixmapCache.getIcon("fileSave"))
62
63 baseDir = self.__manager.getVirtualEnvironmentsBaseDir()
64 if not baseDir:
65 baseDir = Utilities.getHomeDir()
66
67 self.envBaseDirectoryPicker.setMode(EricPathPickerModes.DIRECTORY_MODE)
68 self.envBaseDirectoryPicker.setWindowTitle(
69 self.tr("Virtualenv Base Directory"))
70 self.envBaseDirectoryPicker.setText(baseDir)
71
72 self.__populateVenvList()
73 self.__updateButtons()
74
75 self.venvList.header().setSortIndicator(0, Qt.SortOrder.AscendingOrder)
76
77 self.__manager.virtualEnvironmentsListChanged.connect(self.__refresh)
78
79 def __updateButtons(self):
80 """
81 Private method to update the enabled state of the various buttons.
82 """
83 selectedItemsCount = len(self.venvList.selectedItems())
84 topLevelItemCount = self.venvList.topLevelItemCount()
85
86 deletableSelectedItemCount = 0
87 for itm in self.venvList.selectedItems():
88 if (
89 itm.text(0) != "<default>" and
90 bool(itm.text(1)) and
91 not itm.data(0, VirtualenvManagerWidget.IsGlobalRole) and
92 not itm.data(0, VirtualenvManagerWidget.IsRemoteRole)
93 ):
94 deletableSelectedItemCount += 1
95
96 deletableItemCount = 0
97 for index in range(topLevelItemCount):
98 itm = self.venvList.topLevelItem(index)
99 if (
100 itm.text(0) != "<default>" and
101 bool(itm.text(1)) and
102 not itm.data(0, VirtualenvManagerWidget.IsRemoteRole)
103 ):
104 deletableItemCount += 1
105
106 canBeRemoved = (
107 selectedItemsCount == 1 and
108 self.venvList.selectedItems()[0].text(0) != "<default>"
109 )
110 canAllBeRemoved = (
111 topLevelItemCount == 1 and
112 self.venvList.topLevelItem(0).text(0) != "<default>"
113 )
114
115 self.editButton.setEnabled(selectedItemsCount == 1)
116
117 self.removeButton.setEnabled(selectedItemsCount > 1 or canBeRemoved)
118 self.removeAllButton.setEnabled(
119 topLevelItemCount > 1 or canAllBeRemoved)
120
121 self.deleteButton.setEnabled(deletableSelectedItemCount)
122 self.deleteAllButton.setEnabled(deletableItemCount)
123
124 if selectedItemsCount == 1:
125 venvName = self.venvList.selectedItems()[0].text(0)
126 venvDirectory = self.__manager.getVirtualenvDirectory(venvName)
127 self.upgradeButton.setEnabled(os.path.exists(os.path.join(
128 venvDirectory, "pyvenv.cfg")))
129 else:
130 self.upgradeButton.setEnabled(False)
131
132 @pyqtSlot()
133 def on_refreshButton_clicked(self):
134 """
135 Private slot to refresh the list of virtual environments.
136 """
137 self.__manager.reloadSettings()
138 self.__refresh()
139
140 @pyqtSlot()
141 def on_addButton_clicked(self):
142 """
143 Private slot to add a new entry.
144 """
145 from .VirtualenvAddEditDialog import VirtualenvAddEditDialog
146 dlg = VirtualenvAddEditDialog(
147 self.__manager,
148 baseDir=self.envBaseDirectoryPicker.text()
149 )
150 if dlg.exec() == QDialog.DialogCode.Accepted:
151 (venvName, venvDirectory, venvInterpreter, isGlobal, isConda,
152 isRemote, execPath) = dlg.getData()
153
154 self.__manager.addVirtualEnv(
155 venvName, venvDirectory, venvInterpreter, isGlobal, isConda,
156 isRemote, execPath)
157
158 @pyqtSlot()
159 def on_newButton_clicked(self):
160 """
161 Private slot to create a new virtual environment.
162 """
163 self.__manager.createVirtualEnv(
164 baseDir=self.envBaseDirectoryPicker.text())
165
166 @pyqtSlot()
167 def on_editButton_clicked(self):
168 """
169 Private slot to edit the selected entry.
170 """
171 selectedItem = self.venvList.selectedItems()[0]
172 oldVenvName = selectedItem.text(0)
173
174 from .VirtualenvAddEditDialog import VirtualenvAddEditDialog
175 dlg = VirtualenvAddEditDialog(
176 self.__manager, selectedItem.text(0),
177 selectedItem.text(1), selectedItem.text(2),
178 selectedItem.data(0, VirtualenvManagerWidget.IsGlobalRole),
179 selectedItem.data(0, VirtualenvManagerWidget.IsCondaRole),
180 selectedItem.data(0, VirtualenvManagerWidget.IsRemoteRole),
181 selectedItem.data(0, VirtualenvManagerWidget.ExecPathRole),
182 baseDir=self.envBaseDirectoryPicker.text()
183 )
184 if dlg.exec() == QDialog.DialogCode.Accepted:
185 (venvName, venvDirectory, venvInterpreter, isGlobal, isConda,
186 isRemote, execPath) = dlg.getData()
187 if venvName != oldVenvName:
188 self.__manager.renameVirtualEnv(
189 oldVenvName, venvName, venvDirectory, venvInterpreter,
190 isGlobal, isConda, isRemote, execPath)
191 else:
192 self.__manager.setVirtualEnv(
193 venvName, venvDirectory, venvInterpreter, isGlobal,
194 isConda, isRemote, execPath)
195
196 @pyqtSlot()
197 def on_upgradeButton_clicked(self):
198 """
199 Private slot to upgrade a virtual environment.
200 """
201 self.__manager.upgradeVirtualEnv(
202 self.venvList.selectedItems()[0].text(0))
203
204 @pyqtSlot()
205 def on_removeButton_clicked(self):
206 """
207 Private slot to remove all selected entries from the list but keep
208 their directories.
209 """
210 selectedVenvs = []
211 for itm in self.venvList.selectedItems():
212 selectedVenvs.append(itm.text(0))
213
214 if selectedVenvs:
215 self.__manager.removeVirtualEnvs(selectedVenvs)
216
217 @pyqtSlot()
218 def on_removeAllButton_clicked(self):
219 """
220 Private slot to remove all entries from the list but keep their
221 directories.
222 """
223 venvNames = []
224 for index in range(self.venvList.topLevelItemCount()):
225 itm = self.venvList.topLevelItem(index)
226 venvNames.append(itm.text(0))
227
228 if venvNames:
229 self.__manager.removeVirtualEnvs(venvNames)
230
231 @pyqtSlot()
232 def on_deleteButton_clicked(self):
233 """
234 Private slot to delete all selected entries from the list and disk.
235 """
236 selectedVenvs = []
237 for itm in self.venvList.selectedItems():
238 selectedVenvs.append(itm.text(0))
239
240 if selectedVenvs:
241 self.__manager.deleteVirtualEnvs(selectedVenvs)
242
243 @pyqtSlot()
244 def on_deleteAllButton_clicked(self):
245 """
246 Private slot to delete all entries from the list and disk.
247 """
248 venvNames = []
249 for index in range(self.venvList.topLevelItemCount()):
250 itm = self.venvList.topLevelItem(index)
251 venvNames.append(itm.text(0))
252
253 if venvNames:
254 self.__manager.deleteVirtualEnvs(venvNames)
255
256 @pyqtSlot()
257 def on_venvList_itemSelectionChanged(self):
258 """
259 Private slot handling a change of the selected items.
260 """
261 self.__updateButtons()
262
263 @pyqtSlot()
264 def __refresh(self):
265 """
266 Private slot to refresh the list of shown items.
267 """
268 # 1. remember selected entries
269 selectedVenvs = []
270 for itm in self.venvList.selectedItems():
271 selectedVenvs.append(itm.text(0))
272
273 # 2. clear the list
274 self.venvList.clear()
275
276 # 3. re-populate the list
277 self.__populateVenvList()
278
279 # 4. re-establish selection
280 for venvName in selectedVenvs:
281 itms = self.venvList.findItems(
282 venvName, Qt.MatchFlag.MatchExactly, 0)
283 if itms:
284 itms[0].setSelected(True)
285
286 def __populateVenvList(self):
287 """
288 Private method to populate the list of virtual environments.
289 """
290 environments = self.__manager.getEnvironmentEntries()
291 for venvName in environments:
292 itm = QTreeWidgetItem(self.venvList, [
293 venvName,
294 environments[venvName]["path"],
295 environments[venvName]["interpreter"],
296 ])
297 itm.setData(0, VirtualenvManagerWidget.IsGlobalRole,
298 environments[venvName]["is_global"])
299 itm.setData(0, VirtualenvManagerWidget.IsCondaRole,
300 environments[venvName]["is_conda"])
301 itm.setData(0, VirtualenvManagerWidget.IsRemoteRole,
302 environments[venvName]["is_remote"])
303 itm.setData(0, VirtualenvManagerWidget.ExecPathRole,
304 environments[venvName]["exec_path"])
305
306 # show remote environments with underlined font
307 if environments[venvName]["is_remote"]:
308 font = itm.font(0)
309 font.setUnderline(True)
310 for column in range(itm.columnCount()):
311 itm.setFont(column, font)
312 else:
313 # local environments
314
315 # show global environments with bold font
316 if environments[venvName]["is_global"]:
317 font = itm.font(0)
318 font.setBold(True)
319 for column in range(itm.columnCount()):
320 itm.setFont(column, font)
321
322 # show Anaconda environments with italic font
323 if environments[venvName]["is_conda"]:
324 font = itm.font(0)
325 font.setItalic(True)
326 for column in range(itm.columnCount()):
327 itm.setFont(column, font)
328
329 self.__resizeSections()
330
331 def __resizeSections(self):
332 """
333 Private method to resize the sections of the environment list to their
334 contents.
335 """
336 self.venvList.header().resizeSections(
337 QHeaderView.ResizeMode.ResizeToContents)
338 self.venvList.header().setStretchLastSection(True)
339
340 @pyqtSlot()
341 def on_saveButton_clicked(self):
342 """
343 Private slot to save the base directory name.
344 """
345 baseDir = self.envBaseDirectoryPicker.text()
346 self.__manager.setVirtualEnvironmentsBaseDir(baseDir)
347
348
349 class VirtualenvManagerDialog(QDialog):
350 """
351 Class implementing the virtual environments manager dialog variant.
352 """
353 def __init__(self, manager, parent=None):
354 """
355 Constructor
356
357 @param manager reference to the virtual environment manager
358 @type VirtualenvManager
359 @param parent reference to the parent widget
360 @type QWidget
361 """
362 super().__init__(parent)
363 self.setSizeGripEnabled(True)
364
365 self.__layout = QVBoxLayout(self)
366 self.setLayout(self.__layout)
367
368 self.cw = VirtualenvManagerWidget(manager, self)
369 self.__layout.addWidget(self.cw)
370
371 self.buttonBox = QDialogButtonBox(
372 QDialogButtonBox.StandardButton.Close,
373 Qt.Orientation.Horizontal,
374 self)
375 self.__layout.addWidget(self.buttonBox)
376
377 self.resize(700, 500)
378 self.setWindowTitle(self.tr("Manage Virtual Environments"))
379
380 self.buttonBox.accepted.connect(self.accept)
381 self.buttonBox.rejected.connect(self.reject)
382
383
384 class VirtualenvManagerWindow(EricMainWindow):
385 """
386 Main window class for the standalone virtual environments manager.
387 """
388 def __init__(self, parent=None):
389 """
390 Constructor
391
392 @param parent reference to the parent widget (QWidget)
393 """
394 super().__init__(parent)
395
396 from VirtualEnv.VirtualenvManager import VirtualenvManager
397 self.__virtualenvManager = VirtualenvManager(self)
398
399 self.__centralWidget = QWidget(self)
400 self.__layout = QVBoxLayout(self.__centralWidget)
401 self.__centralWidget.setLayout(self.__layout)
402
403 self.__virtualenvManagerWidget = VirtualenvManagerWidget(
404 self.__virtualenvManager, self.__centralWidget)
405 self.__layout.addWidget(self.__virtualenvManagerWidget)
406
407 self.__buttonBox = QDialogButtonBox(
408 QDialogButtonBox.StandardButton.Close,
409 Qt.Orientation.Horizontal,
410 self)
411 self.__layout.addWidget(self.__buttonBox)
412
413 self.setCentralWidget(self.__centralWidget)
414 self.resize(700, 500)
415 self.setWindowTitle(self.tr("Manage Virtual Environments"))
416
417 self.__buttonBox.accepted.connect(self.close)
418 self.__buttonBox.rejected.connect(self.close)

eric ide

mercurial