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