Plugins/UiExtensionPlugins/PipInterface/PipFreezeDialog.py

changeset 6011
e6af0dcfbb35
child 6048
82ad8ec9548c
equal deleted inserted replaced
6010:7ef7d47a0ad5 6011:e6af0dcfbb35
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2015 - 2017 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to generate a requirements file.
8 """
9
10 from __future__ import unicode_literals
11 try:
12 str = unicode # __IGNORE_EXCEPTION__
13 except NameError:
14 pass
15
16 import os
17
18 from PyQt5.QtCore import pyqtSlot, Qt
19 from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton, \
20 QApplication
21
22 from E5Gui import E5MessageBox, E5FileDialog
23 from E5Gui.E5Application import e5App
24
25 from .Ui_PipFreezeDialog import Ui_PipFreezeDialog
26
27 import Utilities
28 import UI.PixmapCache
29
30
31 class PipFreezeDialog(QDialog, Ui_PipFreezeDialog):
32 """
33 Class implementing a dialog to generate a requirements file.
34 """
35 def __init__(self, pip, plugin, parent=None):
36 """
37 Constructor
38
39 @param pip reference to the master object (Pip)
40 @param plugin reference to the plugin object (ToolPipPlugin)
41 @param parent reference to the parent widget (QWidget)
42 """
43 super(PipFreezeDialog, self).__init__(parent)
44 self.setupUi(self)
45 self.setWindowFlags(Qt.Window)
46
47 self.__refreshButton = self.buttonBox.addButton(
48 self.tr("&Refresh"), QDialogButtonBox.ActionRole)
49
50 self.fileButton.setIcon(UI.PixmapCache.getIcon("open.png"))
51
52 self.__pip = pip
53
54 self.__default = self.tr("<Default>")
55 pipExecutables = sorted(plugin.getPreferences("PipExecutables"))
56 self.pipComboBox.addItem(self.__default)
57 self.pipComboBox.addItems(pipExecutables)
58
59 self.__requirementsEdited = False
60 self.__requirementsAvailable = False
61
62 self.__updateButtons()
63
64 def closeEvent(self, e):
65 """
66 Protected slot implementing a close event handler.
67
68 @param e close event (QCloseEvent)
69 """
70 QApplication.restoreOverrideCursor()
71 e.accept()
72
73 @pyqtSlot(str)
74 def on_pipComboBox_activated(self, txt):
75 """
76 Private slot handling the selection of a pip executable.
77
78 @param txt path of the pip executable (string)
79 """
80 self.__refresh()
81
82 @pyqtSlot(bool)
83 def on_localCheckBox_clicked(self, checked):
84 """
85 Private slot handling the switching of the local mode.
86
87 @param checked state of the local check box (boolean)
88 """
89 self.__refresh()
90
91 @pyqtSlot(str)
92 def on_requirementsFileEdit_textChanged(self, txt):
93 """
94 Private slot handling a change of the requirements file name.
95
96 @param txt name of the requirements file (string)
97 """
98 self.__updateButtons()
99
100 @pyqtSlot()
101 def on_fileButton_clicked(self):
102 """
103 Private slot to enter the requirements file via a file selection
104 dialog.
105 """
106 fileName = E5FileDialog.getOpenFileName(
107 self,
108 self.tr("Select the requirements file"),
109 self.requirementsFileEdit.text() or os.path.expanduser("~"),
110 self.tr("Text Files (*.txt);;All Files (*)")
111 )
112 if fileName:
113 self.requirementsFileEdit.setText(
114 Utilities.toNativeSeparators(fileName))
115
116 @pyqtSlot()
117 def on_requirementsEdit_textChanged(self):
118 """
119 Private slot handling changes of the requirements text.
120 """
121 self.__requirementsEdited = True
122
123 @pyqtSlot(QAbstractButton)
124 def on_buttonBox_clicked(self, button):
125 """
126 Private slot called by a button of the button box clicked.
127
128 @param button button that was clicked (QAbstractButton)
129 """
130 if button == self.buttonBox.button(QDialogButtonBox.Close):
131 self.close()
132 elif button == self.__refreshButton:
133 self.__refresh()
134
135 def __refresh(self):
136 """
137 Private slot to refresh the displayed list.
138 """
139 if self.__requirementsEdited:
140 ok = E5MessageBox.yesNo(
141 self,
142 self.tr("Generate Requirements"),
143 self.tr("""The requirements were changed. Do you want"""
144 """ to overwrite these changes?"""))
145 else:
146 ok = True
147 if ok:
148 self.start()
149
150 def start(self):
151 """
152 Public method to start the command.
153 """
154 self.requirementsEdit.clear()
155 self.__requirementsAvailable = False
156
157 command = self.pipComboBox.currentText()
158 if command == self.__default:
159 command = ""
160
161 args = ["freeze"]
162 if self.localCheckBox.isChecked():
163 args.append("--local")
164 if self.requirementsFileEdit.text():
165 fileName = Utilities.toNativeSeparators(
166 self.requirementsFileEdit.text())
167 if os.path.exists(fileName):
168 args.append("--requirement")
169 args.append(fileName)
170
171 QApplication.setOverrideCursor(Qt.WaitCursor)
172 success, output = self.__pip.runProcess(
173 args, cmd=command)
174
175 if success:
176 self.requirementsEdit.setPlainText(output)
177 self.__requirementsAvailable = True
178 else:
179 self.requirementsEdit.setPlainText(
180 self.tr("No output generated by 'pip freeze'."))
181
182 QApplication.restoreOverrideCursor()
183 self.__updateButtons()
184
185 self.__requirementsEdited = False
186
187 def __updateButtons(self):
188 """
189 Private method to set the state of the various buttons.
190 """
191 self.saveButton.setEnabled(
192 self.__requirementsAvailable and
193 bool(self.requirementsFileEdit.text())
194 )
195 self.saveToButton.setEnabled(self.__requirementsAvailable)
196 self.copyButton.setEnabled(self.__requirementsAvailable)
197
198 aw = e5App().getObject("ViewManager").activeWindow()
199 if aw and self.__requirementsAvailable:
200 self.insertButton.setEnabled(True)
201 self.replaceAllButton.setEnabled(True)
202 self.replaceSelectionButton.setEnabled(
203 aw.hasSelectedText())
204 else:
205 self.insertButton.setEnabled(False)
206 self.replaceAllButton.setEnabled(False)
207 self.replaceSelectionButton.setEnabled(False)
208
209 def __writeToFile(self, fileName):
210 """
211 Private method to write the requirements text to a file.
212
213 @param fileName name of the file to write to (string)
214 """
215 if os.path.exists(fileName):
216 ok = E5MessageBox.warning(
217 self,
218 self.tr("Generate Requirements"),
219 self.tr("""The file <b>{0}</b> already exists. Do you want"""
220 """ to overwrite it?""").format(fileName))
221 if not ok:
222 return
223
224 try:
225 f = open(fileName, "w")
226 f.write(self.requirementsEdit.toPlainText())
227 f.close()
228 except (OSError, IOError) as err:
229 E5MessageBox.critical(
230 self,
231 self.tr("Generate Requirements"),
232 self.tr("""<p>The requirements could not be written"""
233 """ to <b>{0}</b>.</p><p>Reason: {1}</p>""")
234 .format(fileName, str(err)))
235
236 @pyqtSlot()
237 def on_saveButton_clicked(self):
238 """
239 Private slot to save the requirements text to the requirements file.
240 """
241 fileName = self.requirementsFileEdit.text()
242 self.__writeToFile(fileName)
243
244 @pyqtSlot()
245 def on_saveToButton_clicked(self):
246 """
247 Private slot to write the requirements text to a new file.
248 """
249 fileName, selectedFilter = E5FileDialog.getSaveFileNameAndFilter(
250 self,
251 self.tr("Generate Requirements"),
252 os.path.expanduser("~"),
253 self.tr("Text Files (*.txt);;All Files (*)"),
254 None,
255 E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite)
256 )
257 if fileName:
258 ext = os.path.splitext(fileName)[1]
259 if not ext:
260 ex = selectedFilter.split("(*")[1].split(")")[0]
261 if ex:
262 fileName += ex
263 self.__writeToFile(fileName)
264
265 @pyqtSlot()
266 def on_copyButton_clicked(self):
267 """
268 Private slot to copy the requirements text to the clipboard.
269 """
270 txt = self.requirementsEdit.toPlainText()
271 cb = QApplication.clipboard()
272 cb.setText(txt)
273
274 @pyqtSlot()
275 def on_insertButton_clicked(self):
276 """
277 Private slot to insert the requirements text at the cursor position
278 of the current editor.
279 """
280 aw = e5App().getObject("ViewManager").activeWindow()
281 if aw:
282 aw.beginUndoAction()
283 aw.insert(self.requirementsEdit.toPlainText())
284 aw.endUndoAction()
285
286 @pyqtSlot()
287 def on_replaceSelectionButton_clicked(self):
288 """
289 Private slot to replace the selected text of the current editor
290 with the requirements text.
291 """
292 aw = e5App().getObject("ViewManager").activeWindow()
293 if aw:
294 aw.beginUndoAction()
295 aw.replaceSelectedText(self.requirementsEdit.toPlainText())
296 aw.endUndoAction()
297
298 @pyqtSlot()
299 def on_replaceAllButton_clicked(self):
300 """
301 Private slot to replace the text of the current editor with the
302 requirements text.
303 """
304 aw = e5App().getObject("ViewManager").activeWindow()
305 if aw:
306 aw.setText(self.requirementsEdit.toPlainText())

eric ide

mercurial