src/eric7/MicroPython/Devices/CircuitPythonUpdater/RequirementsDialog.py

branch
eric7
changeset 9756
9854647c8c5c
parent 9741
901caff48307
child 10439
21c28b0f9e41
equal deleted inserted replaced
9755:1a09700229e7 9756:9854647c8c5c
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to generate a requirements file.
8 """
9
10 import os
11
12 import circup
13
14 from PyQt6.QtCore import pyqtSlot
15 from PyQt6.QtGui import QGuiApplication
16 from PyQt6.QtWidgets import QAbstractButton, QDialog, QDialogButtonBox
17
18 from eric7.EricWidgets import EricFileDialog, EricMessageBox
19 from eric7.EricWidgets.EricApplication import ericApp
20 from eric7.EricWidgets.EricPathPicker import EricPathPickerModes
21 from eric7.SystemUtilities import FileSystemUtilities
22
23 from .Ui_RequirementsDialog import Ui_RequirementsDialog
24
25
26 class RequirementsDialog(QDialog, Ui_RequirementsDialog):
27 """
28 Class implementing a dialog to generate a requirements file.
29 """
30
31 def __init__(self, devicePath, parent=None):
32 """
33 Constructor
34
35 @param devicePath path to the connected board
36 @type str
37 @param parent reference to the parent widget (defaults to None)
38 @type QWidget (optional)
39 """
40 super().__init__(parent)
41 self.setupUi(self)
42
43 self.__title = self.tr("Generate Requirements")
44
45 self.__refreshButton = self.buttonBox.addButton(
46 self.tr("&Refresh"), QDialogButtonBox.ButtonRole.ActionRole
47 )
48
49 self.requirementsFilePicker.setMode(EricPathPickerModes.SAVE_FILE_MODE)
50 self.requirementsFilePicker.setFilters(
51 self.tr("Text Files (*.txt);;All Files (*)")
52 )
53
54 self.__devicePath = devicePath
55
56 self.__requirementsEdited = False
57 self.__requirementsAvailable = False
58
59 self.__generateRequirements()
60
61 def __updateButtons(self):
62 """
63 Private method to set the state of the various buttons.
64 """
65 self.saveButton.setEnabled(
66 self.__requirementsAvailable
67 and bool(self.requirementsFilePicker.text())
68 and os.path.isabs(self.requirementsFilePicker.text())
69 )
70 self.saveToButton.setEnabled(self.__requirementsAvailable)
71 self.copyButton.setEnabled(self.__requirementsAvailable)
72
73 aw = ericApp().getObject("ViewManager").activeWindow()
74 if aw and self.__requirementsAvailable:
75 self.insertButton.setEnabled(True)
76 self.replaceAllButton.setEnabled(True)
77 self.replaceSelectionButton.setEnabled(aw.hasSelectedText())
78 else:
79 self.insertButton.setEnabled(False)
80 self.replaceAllButton.setEnabled(False)
81 self.replaceSelectionButton.setEnabled(False)
82
83 @pyqtSlot(str)
84 def on_requirementsFilePicker_textChanged(self, txt):
85 """
86 Private slot handling a change of the requirements file name.
87
88 @param txt name of the requirements file
89 @type str
90 """
91 self.__updateButtons()
92
93 @pyqtSlot()
94 def on_requirementsEdit_textChanged(self):
95 """
96 Private slot handling changes of the requirements text.
97 """
98 self.__requirementsEdited = True
99
100 @pyqtSlot(QAbstractButton)
101 def on_buttonBox_clicked(self, button):
102 """
103 Private slot called by a button of the button box clicked.
104
105 @param button button that was clicked
106 @type QAbstractButton
107 """
108 if button == self.buttonBox.button(QDialogButtonBox.StandardButton.Close):
109 self.close()
110 elif button == self.__refreshButton:
111 self.__generateRequirements()
112
113 def __generateRequirements(self):
114 """
115 Private slot to generate the requirements specifiers list.
116 """
117 ok = (
118 EricMessageBox.yesNo(
119 self,
120 self.__title,
121 self.tr(
122 """The requirements were changed. Do you want"""
123 """ to overwrite these changes?"""
124 ),
125 )
126 if self.__requirementsEdited
127 else True
128 )
129 if ok:
130 self.requirementsEdit.clear()
131 self.__requirementsAvailable = False
132
133 if not bool(self.requirementsFilePicker.text()):
134 self.requirementsFilePicker.setText("requirements.txt")
135
136 fileName = FileSystemUtilities.toNativeSeparators(
137 self.requirementsFilePicker.text()
138 )
139 if fileName and not os.path.isabs(fileName):
140 fileName = ""
141
142 modules = circup.find_modules(self.__devicePath, circup.get_bundles_list())
143 specifiers = []
144 if modules:
145 for module in modules:
146 specifiers.append(
147 "{0}=={1}".format(module.name, module.device_version)
148 )
149
150 if specifiers:
151 self.requirementsEdit.setPlainText("\n".join(specifiers) + "\n")
152 self.__requirementsAvailable = True
153 else:
154 self.requirementsEdit.setPlainText(
155 self.tr("No package specifiers generated.")
156 )
157
158 self.__updateButtons()
159
160 self.__requirementsEdited = False
161
162 def __writeToFile(self, fileName):
163 """
164 Private method to write the requirements text to a file.
165
166 @param fileName name of the file to write to
167 @type str
168 """
169 if os.path.exists(fileName):
170 ok = EricMessageBox.warning(
171 self,
172 self.__title,
173 self.tr(
174 """The file <b>{0}</b> already exists. Do you want"""
175 """ to overwrite it?"""
176 ).format(fileName),
177 )
178 if not ok:
179 return
180
181 txt = self.requirementsEdit.toPlainText()
182 try:
183 with open(fileName, "w") as f:
184 f.write(txt)
185 except OSError as err:
186 EricMessageBox.critical(
187 self,
188 self.__title,
189 self.tr(
190 """<p>The requirements could not be written"""
191 """ to <b>{0}</b>.</p><p>Reason: {1}</p>"""
192 ).format(fileName, str(err)),
193 )
194
195 @pyqtSlot()
196 def on_saveButton_clicked(self):
197 """
198 Private slot to save the requirements text to the requirements file.
199 """
200 fileName = self.requirementsFilePicker.text()
201 self.__writeToFile(fileName)
202
203 @pyqtSlot()
204 def on_saveToButton_clicked(self):
205 """
206 Private slot to write the requirements text to a new file.
207 """
208 fileName, selectedFilter = EricFileDialog.getSaveFileNameAndFilter(
209 self,
210 self.__title,
211 os.path.expanduser("~"),
212 self.tr("Text Files (*.txt);;All Files (*)"),
213 None,
214 EricFileDialog.DontConfirmOverwrite,
215 )
216 if fileName:
217 ext = os.path.splitext(fileName)[1]
218 if not ext:
219 ex = selectedFilter.split("(*")[1].split(")")[0]
220 if ex:
221 fileName += ex
222 self.__writeToFile(fileName)
223
224 @pyqtSlot()
225 def on_copyButton_clicked(self):
226 """
227 Private slot to copy the requirements text to the clipboard.
228 """
229 txt = self.requirementsEdit.toPlainText()
230 cb = QGuiApplication.clipboard()
231 cb.setText(txt)
232
233 @pyqtSlot()
234 def on_insertButton_clicked(self):
235 """
236 Private slot to insert the requirements text at the cursor position
237 of the current editor.
238 """
239 aw = ericApp().getObject("ViewManager").activeWindow()
240 if aw:
241 aw.beginUndoAction()
242 aw.insert(self.requirementsEdit.toPlainText())
243 aw.endUndoAction()
244
245 @pyqtSlot()
246 def on_replaceSelectionButton_clicked(self):
247 """
248 Private slot to replace the selected text of the current editor
249 with the requirements text.
250 """
251 aw = ericApp().getObject("ViewManager").activeWindow()
252 if aw:
253 aw.beginUndoAction()
254 aw.replaceSelectedText(self.requirementsEdit.toPlainText())
255 aw.endUndoAction()
256
257 @pyqtSlot()
258 def on_replaceAllButton_clicked(self):
259 """
260 Private slot to replace the text of the current editor with the
261 requirements text.
262 """
263 aw = ericApp().getObject("ViewManager").activeWindow()
264 if aw:
265 aw.setText(self.requirementsEdit.toPlainText())

eric ide

mercurial