|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2007 - 2022 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a dialog to generate code for a Qt5 dialog. |
|
8 """ |
|
9 |
|
10 import os |
|
11 import json |
|
12 import contextlib |
|
13 |
|
14 from PyQt6.QtCore import ( |
|
15 pyqtSlot, Qt, QMetaObject, QRegularExpression, QSortFilterProxyModel, |
|
16 QProcess, QProcessEnvironment |
|
17 ) |
|
18 from PyQt6.QtGui import QStandardItemModel, QStandardItem, QBrush, QColor |
|
19 from PyQt6.QtWidgets import QDialog, QDialogButtonBox |
|
20 |
|
21 |
|
22 from EricWidgets.EricApplication import ericApp |
|
23 from EricWidgets import EricMessageBox |
|
24 |
|
25 from .Ui_CreateDialogCodeDialog import Ui_CreateDialogCodeDialog |
|
26 from .NewDialogClassDialog import NewDialogClassDialog |
|
27 |
|
28 from eric7config import getConfig |
|
29 |
|
30 import Globals |
|
31 import Preferences |
|
32 |
|
33 |
|
34 pyqtSignatureRole = Qt.ItemDataRole.UserRole + 1 |
|
35 pythonSignatureRole = Qt.ItemDataRole.UserRole + 2 |
|
36 rubySignatureRole = Qt.ItemDataRole.UserRole + 3 |
|
37 returnTypeRole = Qt.ItemDataRole.UserRole + 4 |
|
38 parameterTypesListRole = Qt.ItemDataRole.UserRole + 5 |
|
39 parameterNamesListRole = Qt.ItemDataRole.UserRole + 6 |
|
40 |
|
41 |
|
42 class CreateDialogCodeDialog(QDialog, Ui_CreateDialogCodeDialog): |
|
43 """ |
|
44 Class implementing a dialog to generate code for a Qt5 dialog. |
|
45 """ |
|
46 DialogClasses = { |
|
47 "QDialog", "QWidget", "QMainWindow", "QWizard", "QWizardPage", |
|
48 "QDockWidget", "QFrame", "QGroupBox", "QScrollArea", "QMdiArea", |
|
49 "QTabWidget", "QToolBox", "QStackedWidget" |
|
50 } |
|
51 Separator = 25 * "=" |
|
52 |
|
53 def __init__(self, formName, project, parent=None): |
|
54 """ |
|
55 Constructor |
|
56 |
|
57 @param formName name of the file containing the form (string) |
|
58 @param project reference to the project object |
|
59 @param parent parent widget if the dialog (QWidget) |
|
60 """ |
|
61 super().__init__(parent) |
|
62 self.setupUi(self) |
|
63 |
|
64 self.okButton = self.buttonBox.button( |
|
65 QDialogButtonBox.StandardButton.Ok) |
|
66 |
|
67 self.slotsView.header().hide() |
|
68 |
|
69 self.project = project |
|
70 |
|
71 self.formFile = formName |
|
72 filename, ext = os.path.splitext(self.formFile) |
|
73 self.srcFile = '{0}{1}'.format( |
|
74 filename, self.project.getDefaultSourceExtension()) |
|
75 |
|
76 self.slotsModel = QStandardItemModel() |
|
77 self.proxyModel = QSortFilterProxyModel() |
|
78 self.proxyModel.setDynamicSortFilter(True) |
|
79 self.proxyModel.setSourceModel(self.slotsModel) |
|
80 self.slotsView.setModel(self.proxyModel) |
|
81 |
|
82 # initialize some member variables |
|
83 self.__initError = False |
|
84 self.__module = None |
|
85 |
|
86 packagesRoot = self.project.getUicParameter("PackagesRoot") |
|
87 if packagesRoot: |
|
88 self.packagesPath = os.path.join(self.project.getProjectPath(), |
|
89 packagesRoot) |
|
90 else: |
|
91 self.packagesPath = self.project.getProjectPath() |
|
92 |
|
93 if os.path.exists(self.srcFile): |
|
94 vm = ericApp().getObject("ViewManager") |
|
95 ed = vm.getOpenEditor(self.srcFile) |
|
96 if ed and not vm.checkDirty(ed): |
|
97 self.__initError = True |
|
98 return |
|
99 |
|
100 with contextlib.suppress(ImportError): |
|
101 splitExt = os.path.splitext(self.srcFile) |
|
102 exts = [splitExt[1]] if len(splitExt) == 2 else None |
|
103 from Utilities import ModuleParser |
|
104 self.__module = ModuleParser.readModule( |
|
105 self.srcFile, extensions=exts, caching=False) |
|
106 |
|
107 if self.__module is not None: |
|
108 self.filenameEdit.setText(self.srcFile) |
|
109 |
|
110 classesList = [] |
|
111 vagueClassesList = [] |
|
112 for cls in list(self.__module.classes.values()): |
|
113 if not set(cls.super).isdisjoint( |
|
114 CreateDialogCodeDialog.DialogClasses): |
|
115 classesList.append(cls.name) |
|
116 else: |
|
117 vagueClassesList.append(cls.name) |
|
118 classesList.sort() |
|
119 self.classNameCombo.addItems(classesList) |
|
120 if vagueClassesList: |
|
121 if classesList: |
|
122 self.classNameCombo.addItem( |
|
123 CreateDialogCodeDialog.Separator) |
|
124 self.classNameCombo.addItems(sorted(vagueClassesList)) |
|
125 |
|
126 if ( |
|
127 os.path.exists(self.srcFile) and |
|
128 self.__module is not None and |
|
129 self.classNameCombo.count() == 0 |
|
130 ): |
|
131 self.__initError = True |
|
132 EricMessageBox.critical( |
|
133 self, |
|
134 self.tr("Create Dialog Code"), |
|
135 self.tr( |
|
136 """The file <b>{0}</b> exists but does not contain""" |
|
137 """ any classes.""").format(self.srcFile)) |
|
138 |
|
139 self.okButton.setEnabled(self.classNameCombo.count() > 0) |
|
140 |
|
141 self.__updateSlotsModel() |
|
142 |
|
143 def initError(self): |
|
144 """ |
|
145 Public method to determine, if there was an initialzation error. |
|
146 |
|
147 @return flag indicating an initialzation error (boolean) |
|
148 """ |
|
149 return self.__initError |
|
150 |
|
151 def __runUicLoadUi(self, command): |
|
152 """ |
|
153 Private method to run the UicLoadUi.py script with the given command |
|
154 and return the output. |
|
155 |
|
156 @param command uic command to be run |
|
157 @type str |
|
158 @return tuple of process output and error flag |
|
159 @rtype tuple of (str, bool) |
|
160 """ |
|
161 venvManager = ericApp().getObject("VirtualEnvManager") |
|
162 projectType = self.project.getProjectType() |
|
163 |
|
164 venvName = self.project.getProjectVenv(resolveDebugger=False) |
|
165 if not venvName: |
|
166 # no project specific environment, try a type specific one |
|
167 if projectType in ("PyQt5", "PySide2"): |
|
168 venvName = Preferences.getQt("PyQtVenvName") |
|
169 elif projectType in ("PyQt6", "E7Plugin", "PySide6"): |
|
170 venvName = Preferences.getQt("PyQt6VenvName") |
|
171 interpreter = venvManager.getVirtualenvInterpreter(venvName) |
|
172 execPath = venvManager.getVirtualenvExecPath(venvName) |
|
173 |
|
174 if not interpreter: |
|
175 interpreter = Globals.getPythonExecutable() |
|
176 |
|
177 env = QProcessEnvironment.systemEnvironment() |
|
178 if execPath: |
|
179 if env.contains("PATH"): |
|
180 env.insert( |
|
181 "PATH", os.pathsep.join([execPath, env.value("PATH")]) |
|
182 ) |
|
183 else: |
|
184 env.insert("PATH", execPath) |
|
185 |
|
186 if projectType in ("PyQt5", "PySide2"): |
|
187 loadUi = os.path.join(os.path.dirname(__file__), "UicLoadUi5.py") |
|
188 elif projectType in ("PyQt6", "E7Plugin", "PySide6"): |
|
189 loadUi = os.path.join(os.path.dirname(__file__), "UicLoadUi6.py") |
|
190 args = [ |
|
191 loadUi, |
|
192 command, |
|
193 self.formFile, |
|
194 self.packagesPath, |
|
195 ] |
|
196 |
|
197 uicText = "" |
|
198 ok = False |
|
199 |
|
200 proc = QProcess() |
|
201 proc.setWorkingDirectory(self.packagesPath) |
|
202 proc.setProcessEnvironment(env) |
|
203 proc.start(interpreter, args) |
|
204 started = proc.waitForStarted(5000) |
|
205 finished = proc.waitForFinished(30000) |
|
206 if started and finished: |
|
207 output = proc.readAllStandardOutput() |
|
208 outText = str(output, "utf-8", "replace") |
|
209 if proc.exitCode() == 0: |
|
210 ok = True |
|
211 uicText = outText.strip() |
|
212 else: |
|
213 EricMessageBox.critical( |
|
214 self, |
|
215 self.tr("uic error"), |
|
216 self.tr( |
|
217 """<p>There was an error loading the form <b>{0}</b>""" |
|
218 """.</p><p>{1}</p>""").format( |
|
219 self.formFile, outText) |
|
220 ) |
|
221 else: |
|
222 EricMessageBox.critical( |
|
223 self, |
|
224 self.tr("uic error"), |
|
225 self.tr( |
|
226 """<p>The project specific Python interpreter <b>{0}</b>""" |
|
227 """ could not be started or did not finish within 30""" |
|
228 """ seconds.</p>""").format(interpreter) |
|
229 ) |
|
230 |
|
231 return uicText, ok |
|
232 |
|
233 def __objectName(self): |
|
234 """ |
|
235 Private method to get the object name of a form. |
|
236 |
|
237 @return object name |
|
238 @rtype str |
|
239 """ |
|
240 objectName = "" |
|
241 |
|
242 output, ok = self.__runUicLoadUi("object_name") |
|
243 if ok and output: |
|
244 objectName = output |
|
245 |
|
246 return objectName |
|
247 |
|
248 def __className(self): |
|
249 """ |
|
250 Private method to get the class name of a form. |
|
251 |
|
252 @return class name |
|
253 @rtype str |
|
254 """ |
|
255 className = "" |
|
256 |
|
257 output, ok = self.__runUicLoadUi("class_name") |
|
258 if ok and output: |
|
259 className = output |
|
260 |
|
261 return className |
|
262 |
|
263 def __signatures(self): |
|
264 """ |
|
265 Private slot to get the signatures. |
|
266 |
|
267 @return list of signatures (list of strings) |
|
268 """ |
|
269 if self.__module is None: |
|
270 return [] |
|
271 |
|
272 signatures = [] |
|
273 clsName = self.classNameCombo.currentText() |
|
274 if clsName: |
|
275 cls = self.__module.classes[clsName] |
|
276 for meth in list(cls.methods.values()): |
|
277 if meth.name.startswith("on_"): |
|
278 if meth.pyqtSignature is not None: |
|
279 sig = ", ".join( |
|
280 [bytes(QMetaObject.normalizedType(t)).decode() |
|
281 for t in meth.pyqtSignature.split(",")]) |
|
282 signatures.append("{0}({1})".format(meth.name, sig)) |
|
283 else: |
|
284 signatures.append(meth.name) |
|
285 return signatures |
|
286 |
|
287 def __mapType(self, type_): |
|
288 """ |
|
289 Private method to map a type as reported by Qt's meta object to the |
|
290 correct Python type. |
|
291 |
|
292 @param type_ type as reported by Qt (QByteArray) |
|
293 @return mapped Python type (string) |
|
294 """ |
|
295 mapped = bytes(type_).decode() |
|
296 |
|
297 # I. always check for * |
|
298 mapped = mapped.replace("*", "") |
|
299 |
|
300 # 1. check for const |
|
301 mapped = mapped.replace("const ", "") |
|
302 |
|
303 # 2. replace QString and QStringList |
|
304 mapped = ( |
|
305 mapped |
|
306 .replace("QStringList", "list") |
|
307 .replace("QString", "str") |
|
308 ) |
|
309 |
|
310 # 3. replace double by float |
|
311 mapped = mapped.replace("double", "float") |
|
312 |
|
313 return mapped |
|
314 |
|
315 def __updateSlotsModel(self): |
|
316 """ |
|
317 Private slot to update the slots tree display. |
|
318 """ |
|
319 self.filterEdit.clear() |
|
320 |
|
321 output, ok = self.__runUicLoadUi("signatures") |
|
322 if ok and output: |
|
323 objectsList = json.loads(output.strip()) |
|
324 |
|
325 signatureList = self.__signatures() |
|
326 |
|
327 self.slotsModel.clear() |
|
328 self.slotsModel.setHorizontalHeaderLabels([""]) |
|
329 for objectDict in objectsList: |
|
330 itm = QStandardItem("{0} ({1})".format( |
|
331 objectDict["name"], |
|
332 objectDict["class_name"])) |
|
333 self.slotsModel.appendRow(itm) |
|
334 for methodDict in objectDict["methods"]: |
|
335 itm2 = QStandardItem(methodDict["signature"]) |
|
336 itm.appendRow(itm2) |
|
337 |
|
338 if ( |
|
339 self.__module is not None and |
|
340 (methodDict["methods"][0] in signatureList or |
|
341 methodDict["methods"][1] in signatureList) |
|
342 ): |
|
343 itm2.setFlags(Qt.ItemFlag.ItemIsEnabled) |
|
344 itm2.setCheckState(Qt.CheckState.Checked) |
|
345 if ericApp().usesDarkPalette(): |
|
346 itm2.setForeground(QBrush(QColor("#75bfff"))) |
|
347 else: |
|
348 itm2.setForeground(QBrush(Qt.GlobalColor.blue)) |
|
349 continue |
|
350 |
|
351 itm2.setData(methodDict["pyqt_signature"], |
|
352 pyqtSignatureRole) |
|
353 itm2.setData(methodDict["python_signature"], |
|
354 pythonSignatureRole) |
|
355 itm2.setData(methodDict["return_type"], |
|
356 returnTypeRole) |
|
357 itm2.setData(methodDict["parameter_types"], |
|
358 parameterTypesListRole) |
|
359 itm2.setData(methodDict["parameter_names"], |
|
360 parameterNamesListRole) |
|
361 |
|
362 itm2.setFlags( |
|
363 Qt.ItemFlag.ItemIsUserCheckable | |
|
364 Qt.ItemFlag.ItemIsEnabled | |
|
365 Qt.ItemFlag.ItemIsSelectable |
|
366 ) |
|
367 itm2.setCheckState(Qt.CheckState.Unchecked) |
|
368 |
|
369 self.slotsView.sortByColumn(0, Qt.SortOrder.AscendingOrder) |
|
370 |
|
371 def __generateCode(self): |
|
372 """ |
|
373 Private slot to generate the code as requested by the user. |
|
374 """ |
|
375 if ( |
|
376 self.filenameEdit.text().endswith(".rb") or |
|
377 self.project.getProjectLanguage() == "Ruby" |
|
378 ): |
|
379 # Ruby code generation is not supported |
|
380 pass |
|
381 else: |
|
382 # assume Python (our global default) |
|
383 self.__generatePythonCode() |
|
384 |
|
385 def __generatePythonCode(self): |
|
386 """ |
|
387 Private slot to generate Python code as requested by the user. |
|
388 """ |
|
389 if self.project.getProjectLanguage() != "Python3": |
|
390 EricMessageBox.critical( |
|
391 self, |
|
392 self.tr("Code Generation"), |
|
393 self.tr( |
|
394 """<p>Code generation for project language""" |
|
395 """ "{0}" is not supported.</p>""") |
|
396 .format(self.project.getProjectLanguage())) |
|
397 return |
|
398 |
|
399 # init some variables |
|
400 sourceImpl = [] |
|
401 appendAtIndex = -1 |
|
402 indentStr = " " |
|
403 slotsCode = [] |
|
404 |
|
405 if self.__module is None: |
|
406 # new file |
|
407 try: |
|
408 if self.project.getProjectType() == "PySide2": |
|
409 tmplName = os.path.join( |
|
410 getConfig('ericCodeTemplatesDir'), |
|
411 "impl_pyside2.py.tmpl") |
|
412 elif self.project.getProjectType() == "PySide6": |
|
413 tmplName = os.path.join( |
|
414 getConfig('ericCodeTemplatesDir'), |
|
415 "impl_pyside6.py.tmpl") |
|
416 elif self.project.getProjectType() == "PyQt5": |
|
417 tmplName = os.path.join( |
|
418 getConfig('ericCodeTemplatesDir'), |
|
419 "impl_pyqt5.py.tmpl") |
|
420 elif self.project.getProjectType() in [ |
|
421 "PyQt6", "E7Plugin" |
|
422 ]: |
|
423 tmplName = os.path.join( |
|
424 getConfig('ericCodeTemplatesDir'), |
|
425 "impl_pyqt6.py.tmpl") |
|
426 else: |
|
427 EricMessageBox.critical( |
|
428 self, |
|
429 self.tr("Code Generation"), |
|
430 self.tr( |
|
431 """<p>No code template file available for""" |
|
432 """ project type "{0}".</p>""") |
|
433 .format(self.project.getProjectType())) |
|
434 return |
|
435 with open(tmplName, 'r', encoding="utf-8") as tmplFile: |
|
436 template = tmplFile.read() |
|
437 except OSError as why: |
|
438 EricMessageBox.critical( |
|
439 self, |
|
440 self.tr("Code Generation"), |
|
441 self.tr( |
|
442 """<p>Could not open the code template file""" |
|
443 """ "{0}".</p><p>Reason: {1}</p>""") |
|
444 .format(tmplName, str(why))) |
|
445 return |
|
446 |
|
447 objName = self.__objectName() |
|
448 if objName: |
|
449 template = ( |
|
450 template |
|
451 .replace( |
|
452 "$FORMFILE$", |
|
453 os.path.splitext(os.path.basename(self.formFile))[0]) |
|
454 .replace("$FORMCLASS$", objName) |
|
455 .replace("$CLASSNAME$", self.classNameCombo.currentText()) |
|
456 .replace("$SUPERCLASS$", self.__className()) |
|
457 ) |
|
458 |
|
459 sourceImpl = template.splitlines(True) |
|
460 appendAtIndex = -1 |
|
461 |
|
462 # determine indent string |
|
463 for line in sourceImpl: |
|
464 if line.lstrip().startswith("def __init__"): |
|
465 indentStr = line.replace(line.lstrip(), "") |
|
466 break |
|
467 else: |
|
468 # extend existing file |
|
469 try: |
|
470 with open(self.srcFile, 'r', encoding="utf-8") as srcFile: |
|
471 sourceImpl = srcFile.readlines() |
|
472 if not sourceImpl[-1].endswith("\n"): |
|
473 sourceImpl[-1] = "{0}{1}".format(sourceImpl[-1], "\n") |
|
474 except OSError as why: |
|
475 EricMessageBox.critical( |
|
476 self, |
|
477 self.tr("Code Generation"), |
|
478 self.tr( |
|
479 """<p>Could not open the source file "{0}".</p>""" |
|
480 """<p>Reason: {1}</p>""") |
|
481 .format(self.srcFile, str(why))) |
|
482 return |
|
483 |
|
484 cls = self.__module.classes[self.classNameCombo.currentText()] |
|
485 if cls.endlineno == len(sourceImpl) or cls.endlineno == -1: |
|
486 appendAtIndex = -1 |
|
487 # delete empty lines at end |
|
488 while not sourceImpl[-1].strip(): |
|
489 del sourceImpl[-1] |
|
490 else: |
|
491 appendAtIndex = cls.endlineno - 1 |
|
492 while not sourceImpl[appendAtIndex].strip(): |
|
493 appendAtIndex -= 1 |
|
494 appendAtIndex += 1 |
|
495 |
|
496 # determine indent string |
|
497 for line in sourceImpl[cls.lineno:cls.endlineno + 1]: |
|
498 if line.lstrip().startswith("def __init__"): |
|
499 indentStr = line.replace(line.lstrip(), "") |
|
500 break |
|
501 |
|
502 # do the coding stuff |
|
503 pyqtSignatureFormat = ( |
|
504 '@Slot({0})' |
|
505 if self.project.getProjectType() in ("PySide2", "PySide6") else |
|
506 '@pyqtSlot({0})' |
|
507 ) |
|
508 for row in range(self.slotsModel.rowCount()): |
|
509 topItem = self.slotsModel.item(row) |
|
510 for childRow in range(topItem.rowCount()): |
|
511 child = topItem.child(childRow) |
|
512 if ( |
|
513 child.checkState() == Qt.CheckState.Checked and |
|
514 (child.flags() & Qt.ItemFlag.ItemIsUserCheckable == |
|
515 Qt.ItemFlag.ItemIsUserCheckable) |
|
516 ): |
|
517 slotsCode.append('{0}\n'.format(indentStr)) |
|
518 slotsCode.append('{0}{1}\n'.format( |
|
519 indentStr, |
|
520 pyqtSignatureFormat.format( |
|
521 child.data(pyqtSignatureRole)))) |
|
522 slotsCode.append('{0}def {1}:\n'.format( |
|
523 indentStr, child.data(pythonSignatureRole))) |
|
524 indentStr2 = indentStr * 2 |
|
525 slotsCode.append('{0}"""\n'.format(indentStr2)) |
|
526 slotsCode.append( |
|
527 '{0}Slot documentation goes here.\n'.format( |
|
528 indentStr2)) |
|
529 if ( |
|
530 child.data(returnTypeRole) or |
|
531 child.data(parameterTypesListRole) |
|
532 ): |
|
533 slotsCode.append('{0}\n'.format(indentStr2)) |
|
534 if child.data(parameterTypesListRole): |
|
535 for name, type_ in zip( |
|
536 child.data(parameterNamesListRole), |
|
537 child.data(parameterTypesListRole)): |
|
538 slotsCode.append( |
|
539 '{0}@param {1} DESCRIPTION\n'.format( |
|
540 indentStr2, name)) |
|
541 slotsCode.append('{0}@type {1}\n'.format( |
|
542 indentStr2, type_)) |
|
543 if child.data(returnTypeRole): |
|
544 slotsCode.append( |
|
545 '{0}@returns DESCRIPTION\n'.format( |
|
546 indentStr2)) |
|
547 slotsCode.append('{0}@rtype {1}\n'.format( |
|
548 indentStr2, child.data(returnTypeRole))) |
|
549 slotsCode.append('{0}"""\n'.format(indentStr2)) |
|
550 slotsCode.append('{0}# {1}: not implemented yet\n'.format( |
|
551 indentStr2, "TODO")) |
|
552 slotsCode.append('{0}raise NotImplementedError\n'.format( |
|
553 indentStr2)) |
|
554 |
|
555 if appendAtIndex == -1: |
|
556 sourceImpl.extend(slotsCode) |
|
557 else: |
|
558 sourceImpl[appendAtIndex:appendAtIndex] = slotsCode |
|
559 |
|
560 # write the new code |
|
561 newline = (None if self.project.useSystemEol() |
|
562 else self.project.getEolString()) |
|
563 fn = self.filenameEdit.text() |
|
564 try: |
|
565 with open(fn, 'w', encoding="utf-8", newline=newline) as srcFile: |
|
566 srcFile.write("".join(sourceImpl)) |
|
567 except OSError as why: |
|
568 EricMessageBox.critical( |
|
569 self, |
|
570 self.tr("Code Generation"), |
|
571 self.tr("""<p>Could not write the source file "{0}".</p>""" |
|
572 """<p>Reason: {1}</p>""") |
|
573 .format(fn, str(why))) |
|
574 return |
|
575 |
|
576 self.project.appendFile(fn) |
|
577 |
|
578 @pyqtSlot(int) |
|
579 def on_classNameCombo_activated(self, index): |
|
580 """ |
|
581 Private slot to handle the activated signal of the classname combo. |
|
582 |
|
583 @param index index of the activated item (integer) |
|
584 """ |
|
585 if (self.classNameCombo.currentText() == |
|
586 CreateDialogCodeDialog.Separator): |
|
587 self.okButton.setEnabled(False) |
|
588 self.filterEdit.clear() |
|
589 self.slotsModel.clear() |
|
590 self.slotsModel.setHorizontalHeaderLabels([""]) |
|
591 else: |
|
592 self.okButton.setEnabled(True) |
|
593 self.__updateSlotsModel() |
|
594 |
|
595 def on_filterEdit_textChanged(self, text): |
|
596 """ |
|
597 Private slot called, when thext of the filter edit has changed. |
|
598 |
|
599 @param text changed text (string) |
|
600 """ |
|
601 rx = QRegularExpression( |
|
602 text, |
|
603 QRegularExpression.PatternOption.CaseInsensitiveOption) |
|
604 self.proxyModel.setFilterRegularExpression(rx) |
|
605 |
|
606 @pyqtSlot() |
|
607 def on_newButton_clicked(self): |
|
608 """ |
|
609 Private slot called to enter the data for a new dialog class. |
|
610 """ |
|
611 path, file = os.path.split(self.srcFile) |
|
612 objName = self.__objectName() |
|
613 if objName: |
|
614 dlg = NewDialogClassDialog(objName, file, path, self) |
|
615 if dlg.exec() == QDialog.DialogCode.Accepted: |
|
616 className, fileName = dlg.getData() |
|
617 |
|
618 self.classNameCombo.clear() |
|
619 self.classNameCombo.addItem(className) |
|
620 self.srcFile = fileName |
|
621 self.filenameEdit.setText(self.srcFile) |
|
622 self.__module = None |
|
623 |
|
624 self.okButton.setEnabled(self.classNameCombo.count() > 0) |
|
625 |
|
626 def on_buttonBox_clicked(self, button): |
|
627 """ |
|
628 Private slot to handle the buttonBox clicked signal. |
|
629 |
|
630 @param button reference to the button that was clicked |
|
631 (QAbstractButton) |
|
632 """ |
|
633 if button == self.okButton: |
|
634 self.__generateCode() |
|
635 self.accept() |