52 @param parent reference to the parent widget |
63 @param parent reference to the parent widget |
53 @type QWidget |
64 @type QWidget |
54 """ |
65 """ |
55 super().__init__(parent) |
66 super().__init__(parent) |
56 self.setupUi(self) |
67 self.setupUi(self) |
57 |
68 |
58 self.__venvName = venvName |
69 self.__venvName = venvName |
59 self.__manager = manager |
70 self.__manager = manager |
60 self.__editMode = bool(venvName) |
71 self.__editMode = bool(venvName) |
61 |
72 |
62 if self.__editMode: |
73 if self.__editMode: |
63 self.setWindowTitle(self.tr("Edit Virtual Environment")) |
74 self.setWindowTitle(self.tr("Edit Virtual Environment")) |
64 else: |
75 else: |
65 self.setWindowTitle(self.tr("Add Virtual Environment")) |
76 self.setWindowTitle(self.tr("Add Virtual Environment")) |
66 |
77 |
67 self.__envBaseDir = baseDir |
78 self.__envBaseDir = baseDir |
68 if not self.__envBaseDir: |
79 if not self.__envBaseDir: |
69 self.__envBaseDir = Utilities.getHomeDir() |
80 self.__envBaseDir = Utilities.getHomeDir() |
70 |
81 |
71 self.targetDirectoryPicker.setMode(EricPathPickerModes.DIRECTORY_MODE) |
82 self.targetDirectoryPicker.setMode(EricPathPickerModes.DIRECTORY_MODE) |
72 self.targetDirectoryPicker.setWindowTitle( |
83 self.targetDirectoryPicker.setWindowTitle( |
73 self.tr("Virtualenv Target Directory")) |
84 self.tr("Virtualenv Target Directory") |
|
85 ) |
74 self.targetDirectoryPicker.setDefaultDirectory(self.__envBaseDir) |
86 self.targetDirectoryPicker.setDefaultDirectory(self.__envBaseDir) |
75 |
87 |
76 self.pythonExecPicker.setMode(EricPathPickerModes.OPEN_FILE_MODE) |
88 self.pythonExecPicker.setMode(EricPathPickerModes.OPEN_FILE_MODE) |
77 self.pythonExecPicker.setWindowTitle( |
89 self.pythonExecPicker.setWindowTitle(self.tr("Python Interpreter")) |
78 self.tr("Python Interpreter")) |
90 self.pythonExecPicker.setDefaultDirectory(Globals.getPythonExecutable()) |
79 self.pythonExecPicker.setDefaultDirectory( |
91 |
80 Globals.getPythonExecutable()) |
92 self.execPathEdit.setToolTip( |
81 |
93 self.tr( |
82 self.execPathEdit.setToolTip(self.tr( |
94 "Enter the executable search path to be prepended to the PATH" |
83 "Enter the executable search path to be prepended to the PATH" |
95 " environment variable. Use '{0}' as the separator." |
84 " environment variable. Use '{0}' as the separator.").format( |
96 ).format(os.pathsep) |
85 os.pathsep) |
97 ) |
86 ) |
98 |
87 |
|
88 self.nameEdit.setText(venvName) |
99 self.nameEdit.setText(venvName) |
89 if venvDirectory: |
100 if venvDirectory: |
90 self.targetDirectoryPicker.setText(venvDirectory, |
101 self.targetDirectoryPicker.setText(venvDirectory, toNative=not isRemote) |
91 toNative=not isRemote) |
102 else: |
92 else: |
103 self.targetDirectoryPicker.setText(self.__envBaseDir, toNative=not isRemote) |
93 self.targetDirectoryPicker.setText(self.__envBaseDir, |
|
94 toNative=not isRemote) |
|
95 if not venvInterpreter and venvDirectory and not isRemote: |
104 if not venvInterpreter and venvDirectory and not isRemote: |
96 py = self.__detectPythonInterpreter(venvDirectory) |
105 py = self.__detectPythonInterpreter(venvDirectory) |
97 self.pythonExecPicker.setText(py) |
106 self.pythonExecPicker.setText(py) |
98 else: |
107 else: |
99 self.pythonExecPicker.setText(venvInterpreter, |
108 self.pythonExecPicker.setText(venvInterpreter, toNative=not isRemote) |
100 toNative=not isRemote) |
109 |
101 |
|
102 self.globalCheckBox.setChecked(isGlobal) |
110 self.globalCheckBox.setChecked(isGlobal) |
103 self.anacondaCheckBox.setChecked(isConda) |
111 self.anacondaCheckBox.setChecked(isConda) |
104 self.remoteCheckBox.setChecked(isRemote) |
112 self.remoteCheckBox.setChecked(isRemote) |
105 self.execPathEdit.setText(execPath) |
113 self.execPathEdit.setText(execPath) |
106 |
114 |
107 self.__updateOk() |
115 self.__updateOk() |
108 |
116 |
109 self.nameEdit.setFocus(Qt.FocusReason.OtherFocusReason) |
117 self.nameEdit.setFocus(Qt.FocusReason.OtherFocusReason) |
110 |
118 |
111 def __updateOk(self): |
119 def __updateOk(self): |
112 """ |
120 """ |
113 Private slot to update the state of the OK button. |
121 Private slot to update the state of the OK button. |
114 """ |
122 """ |
115 enable = ( |
123 enable = ( |
116 (bool(self.nameEdit.text()) and |
124 ( |
117 (self.nameEdit.text() == self.__venvName or |
125 bool(self.nameEdit.text()) |
118 self.__manager.isUnique(self.nameEdit.text()))) |
126 and ( |
119 if self.__editMode else |
127 self.nameEdit.text() == self.__venvName |
120 (bool(self.nameEdit.text()) and |
128 or self.__manager.isUnique(self.nameEdit.text()) |
121 self.__manager.isUnique(self.nameEdit.text())) |
129 ) |
122 ) |
130 ) |
123 |
131 if self.__editMode |
|
132 else ( |
|
133 bool(self.nameEdit.text()) |
|
134 and self.__manager.isUnique(self.nameEdit.text()) |
|
135 ) |
|
136 ) |
|
137 |
124 if not self.globalCheckBox.isChecked(): |
138 if not self.globalCheckBox.isChecked(): |
125 enable &= ( |
139 enable &= self.remoteCheckBox.isChecked() or ( |
126 self.remoteCheckBox.isChecked() or ( |
140 bool(self.targetDirectoryPicker.text()) |
127 bool(self.targetDirectoryPicker.text()) and |
141 and self.targetDirectoryPicker.text() != self.__envBaseDir |
128 self.targetDirectoryPicker.text() != self.__envBaseDir and |
142 and os.path.exists(self.targetDirectoryPicker.text()) |
129 os.path.exists(self.targetDirectoryPicker.text()) |
143 ) |
130 ) |
144 |
131 ) |
|
132 |
|
133 enable = ( |
145 enable = ( |
134 enable and |
146 enable |
135 bool(self.pythonExecPicker.text()) and ( |
147 and bool(self.pythonExecPicker.text()) |
136 self.remoteCheckBox.isChecked() or |
148 and ( |
137 os.access(self.pythonExecPicker.text(), os.X_OK) |
149 self.remoteCheckBox.isChecked() |
138 ) |
150 or os.access(self.pythonExecPicker.text(), os.X_OK) |
139 ) |
151 ) |
140 |
152 ) |
141 self.buttonBox.button( |
153 |
142 QDialogButtonBox.StandardButton.Ok).setEnabled(enable) |
154 self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(enable) |
143 |
155 |
144 def __detectPythonInterpreter(self, venvDirectory): |
156 def __detectPythonInterpreter(self, venvDirectory): |
145 """ |
157 """ |
146 Private method to search for a suitable Python interpreter inside an |
158 Private method to search for a suitable Python interpreter inside an |
147 environment. |
159 environment. |
148 |
160 |
149 @param venvDirectory directory for the virtual environment |
161 @param venvDirectory directory for the virtual environment |
150 @type str |
162 @type str |
151 @return detected Python interpreter or empty string |
163 @return detected Python interpreter or empty string |
152 @rtype str |
164 @rtype str |
153 """ |
165 """ |
157 candidates = ( |
169 candidates = ( |
158 os.path.join(venvDirectory, "Scripts", "python.exe"), |
170 os.path.join(venvDirectory, "Scripts", "python.exe"), |
159 os.path.join(venvDirectory, "python.exe"), |
171 os.path.join(venvDirectory, "python.exe"), |
160 ) |
172 ) |
161 else: |
173 else: |
162 candidates = ( |
174 candidates = (os.path.join(venvDirectory, "bin", "python3"),) |
163 os.path.join(venvDirectory, "bin", "python3"), |
|
164 ) |
|
165 for py in candidates: |
175 for py in candidates: |
166 if os.path.exists(py): |
176 if os.path.exists(py): |
167 return py |
177 return py |
168 |
178 |
169 return "" |
179 return "" |
170 |
180 |
171 @pyqtSlot(str) |
181 @pyqtSlot(str) |
172 def on_nameEdit_textChanged(self, txt): |
182 def on_nameEdit_textChanged(self, txt): |
173 """ |
183 """ |
174 Private slot to handle changes of the logical name. |
184 Private slot to handle changes of the logical name. |
175 |
185 |
176 @param txt current logical name |
186 @param txt current logical name |
177 @type str |
187 @type str |
178 """ |
188 """ |
179 self.__updateOk() |
189 self.__updateOk() |
180 |
190 |
181 @pyqtSlot(str) |
191 @pyqtSlot(str) |
182 def on_targetDirectoryPicker_textChanged(self, txt): |
192 def on_targetDirectoryPicker_textChanged(self, txt): |
183 """ |
193 """ |
184 Private slot to handle changes of the virtual environment directory. |
194 Private slot to handle changes of the virtual environment directory. |
185 |
195 |
186 @param txt virtual environment directory |
196 @param txt virtual environment directory |
187 @type str |
197 @type str |
188 """ |
198 """ |
189 self.__updateOk() |
199 self.__updateOk() |
190 |
200 |
191 if txt: |
201 if txt: |
192 self.pythonExecPicker.setDefaultDirectory(txt) |
202 self.pythonExecPicker.setDefaultDirectory(txt) |
193 else: |
203 else: |
194 self.pythonExecPicker.setDefaultDirectory( |
204 self.pythonExecPicker.setDefaultDirectory(Globals.getPythonExecutable()) |
195 Globals.getPythonExecutable()) |
|
196 py = self.__detectPythonInterpreter(txt) |
205 py = self.__detectPythonInterpreter(txt) |
197 if py: |
206 if py: |
198 self.pythonExecPicker.setText(py) |
207 self.pythonExecPicker.setText(py) |
199 |
208 |
200 @pyqtSlot(str) |
209 @pyqtSlot(str) |
201 def on_pythonExecPicker_textChanged(self, txt): |
210 def on_pythonExecPicker_textChanged(self, txt): |
202 """ |
211 """ |
203 Private slot to handle changes of the virtual environment interpreter. |
212 Private slot to handle changes of the virtual environment interpreter. |
204 |
213 |
205 @param txt virtual environment interpreter |
214 @param txt virtual environment interpreter |
206 @type str |
215 @type str |
207 """ |
216 """ |
208 self.__updateOk() |
217 self.__updateOk() |
209 |
218 |
210 @pyqtSlot(bool) |
219 @pyqtSlot(bool) |
211 def on_globalCheckBox_toggled(self, checked): |
220 def on_globalCheckBox_toggled(self, checked): |
212 """ |
221 """ |
213 Private slot handling a change of the global check box state. |
222 Private slot handling a change of the global check box state. |
214 |
223 |
215 @param checked state of the check box |
224 @param checked state of the check box |
216 @type bool |
225 @type bool |
217 """ |
226 """ |
218 self.__updateOk() |
227 self.__updateOk() |
219 |
228 |
220 @pyqtSlot(bool) |
229 @pyqtSlot(bool) |
221 def on_remoteCheckBox_toggled(self, checked): |
230 def on_remoteCheckBox_toggled(self, checked): |
222 """ |
231 """ |
223 Private slot handling a change of the remote check box state. |
232 Private slot handling a change of the remote check box state. |
224 |
233 |
225 @param checked state of the check box |
234 @param checked state of the check box |
226 @type bool |
235 @type bool |
227 """ |
236 """ |
228 self.__updateOk() |
237 self.__updateOk() |
229 |
238 |
230 @pyqtSlot(bool) |
239 @pyqtSlot(bool) |
231 def on_anacondaCheckBox_clicked(self, checked): |
240 def on_anacondaCheckBox_clicked(self, checked): |
232 """ |
241 """ |
233 Private slot handling a user click on this check box. |
242 Private slot handling a user click on this check box. |
234 |
243 |
235 @param checked state of the check box |
244 @param checked state of the check box |
236 @type bool |
245 @type bool |
237 """ |
246 """ |
238 if checked and not bool(self.execPathEdit.text()): |
247 if checked and not bool(self.execPathEdit.text()): |
239 # prepopulate the execPathEdit widget |
248 # prepopulate the execPathEdit widget |
240 if Utilities.isWindowsPlatform(): |
249 if Utilities.isWindowsPlatform(): |
241 self.execPathEdit.setText(os.pathsep.join([ |
250 self.execPathEdit.setText( |
242 self.targetDirectoryPicker.text(), |
251 os.pathsep.join( |
243 os.path.join(self.targetDirectoryPicker.text(), |
252 [ |
244 "Scripts"), |
253 self.targetDirectoryPicker.text(), |
245 os.path.join(self.targetDirectoryPicker.text(), |
254 os.path.join(self.targetDirectoryPicker.text(), "Scripts"), |
246 "Library", "bin"), |
255 os.path.join( |
247 ])) |
256 self.targetDirectoryPicker.text(), "Library", "bin" |
|
257 ), |
|
258 ] |
|
259 ) |
|
260 ) |
248 else: |
261 else: |
249 self.execPathEdit.setText( |
262 self.execPathEdit.setText( |
250 os.path.join(self.targetDirectoryPicker.text(), |
263 os.path.join(self.targetDirectoryPicker.text(), "bin"), |
251 "bin"), |
264 ) |
252 ) |
265 |
253 |
|
254 def getData(self): |
266 def getData(self): |
255 """ |
267 """ |
256 Public method to retrieve the entered data. |
268 Public method to retrieve the entered data. |
257 |
269 |
258 @return tuple containing the logical name, the directory, the |
270 @return tuple containing the logical name, the directory, the |
259 interpreter of the virtual environment, a flag indicating a |
271 interpreter of the virtual environment, a flag indicating a |
260 global environment, a flag indicating an Anaconda environment, |
272 global environment, a flag indicating an Anaconda environment, |
261 a flag indicating a remotely accessed environment and a string |
273 a flag indicating a remotely accessed environment and a string |
262 to be prepended to the PATH environment variable |
274 to be prepended to the PATH environment variable |