143 |
145 |
144 @return flag indicating an initialzation error (boolean) |
146 @return flag indicating an initialzation error (boolean) |
145 """ |
147 """ |
146 return self.__initError |
148 return self.__initError |
147 |
149 |
148 def __loadUi(self, formFile, package=""): |
150 def __objectNameExternal(self): |
149 """ |
151 """ |
150 Private method to load a form file and instantiate the defined form. |
152 Private method to get the object name of a form via an external |
151 |
153 interpreter. |
152 @param formFile path of the form file to be loaded |
154 |
153 @type str |
155 @return object name |
154 @param package base path to be used for relative imports |
156 @rtype str |
155 @type str |
157 """ |
156 @return instantiated form |
|
157 @rtype QWidget |
|
158 """ |
|
159 oldSysPath = [] |
|
160 interpreter = self.project.getDebugProperty("INTERPRETER") |
158 interpreter = self.project.getDebugProperty("INTERPRETER") |
161 if interpreter: |
159 objectName = "" |
162 oldSysPath = sys.path[:] |
160 |
163 sys.path = oldSysPath + Utilities.getSysPath(interpreter) |
161 loadUi = os.path.join(os.path.dirname(__file__), "UicLoadUi.py") |
164 |
162 args = [ |
165 dlg = uic.loadUi(formFile, package=package) |
163 loadUi, |
166 |
164 "object_name", |
167 if oldSysPath: |
165 self.formFile, |
168 sys.path = oldSysPath |
166 self.project.getProjectPath(), |
169 |
167 ] |
170 return dlg |
168 |
|
169 proc = QProcess() |
|
170 proc.start(interpreter, args) |
|
171 finished = proc.waitForFinished(30000) |
|
172 if finished: |
|
173 text = proc.readAllStandardOutput() |
|
174 if proc.exitCode() == 0: |
|
175 objectName = str(text, "utf-8", "replace").strip() |
|
176 else: |
|
177 errorText = str(text, "utf-8", "replace") |
|
178 E5MessageBox.critical( |
|
179 self, |
|
180 self.tr("uic error"), |
|
181 self.tr( |
|
182 """<p>There was an error loading the form <b>{0}</b>""" |
|
183 """.</p><p>{1}</p>""").format( |
|
184 self.formFile, errorText)) |
|
185 |
|
186 return objectName |
171 |
187 |
172 def __objectName(self): |
188 def __objectName(self): |
173 """ |
189 """ |
174 Private method to get the object name of the dialog. |
190 Private method to get the object name of a form. |
175 |
191 |
176 @return object name (string) |
192 @return object name |
177 """ |
193 @rtype str |
178 try: |
194 """ |
179 dlg = self.__loadUi( |
195 if self.project.getDebugProperty("INTERPRETER"): |
180 self.formFile, package=self.project.getProjectPath()) |
196 return self.__objectNameExternal() |
181 return dlg.objectName() |
197 else: |
182 except (AttributeError, ImportError, |
198 try: |
183 xml.etree.ElementTree.ParseError) as err: |
199 dlg = uic.loadUi( |
184 E5MessageBox.critical( |
200 self.formFile, package=self.project.getProjectPath()) |
185 self, |
201 return dlg.objectName() |
186 self.tr("uic error"), |
202 except (AttributeError, ImportError, |
187 self.tr( |
203 xml.etree.ElementTree.ParseError) as err: |
188 """<p>There was an error loading the form <b>{0}</b>""" |
204 E5MessageBox.critical( |
189 """.</p><p>{1}</p>""").format(self.formFile, str(err))) |
205 self, |
190 return "" |
206 self.tr("uic error"), |
191 |
207 self.tr( |
|
208 """<p>There was an error loading the form <b>{0}</b>""" |
|
209 """.</p><p>{1}</p>""").format(self.formFile, str(err))) |
|
210 return "" |
|
211 |
|
212 def __classNameExternal(self): |
|
213 """ |
|
214 Private method to get the class name of a form via an external |
|
215 interpreter. |
|
216 |
|
217 @return class name |
|
218 @rtype str |
|
219 """ |
|
220 interpreter = self.project.getDebugProperty("INTERPRETER") |
|
221 className = "" |
|
222 |
|
223 loadUi = os.path.join(os.path.dirname(__file__), "UicLoadUi.py") |
|
224 args = [ |
|
225 loadUi, |
|
226 "class_name", |
|
227 self.formFile, |
|
228 self.project.getProjectPath(), |
|
229 ] |
|
230 |
|
231 proc = QProcess() |
|
232 proc.start(interpreter, args) |
|
233 finished = proc.waitForFinished(30000) |
|
234 if finished: |
|
235 text = proc.readAllStandardOutput() |
|
236 if proc.exitCode() == 0: |
|
237 className = str(text, "utf-8", "replace").strip() |
|
238 else: |
|
239 errorText = str(text, "utf-8", "replace") |
|
240 E5MessageBox.critical( |
|
241 self, |
|
242 self.tr("uic error"), |
|
243 self.tr( |
|
244 """<p>There was an error loading the form <b>{0}</b>""" |
|
245 """.</p><p>{1}</p>""").format( |
|
246 self.formFile, errorText)) |
|
247 |
|
248 return className |
|
249 |
192 def __className(self): |
250 def __className(self): |
193 """ |
251 """ |
194 Private method to get the class name of the dialog. |
252 Private method to get the class name of a form. |
195 |
253 |
196 @return class name (sting) |
254 @return class name |
197 """ |
255 @rtype str |
198 try: |
256 """ |
199 dlg = self.__loadUi( |
257 if self.project.getDebugProperty("INTERPRETER"): |
200 self.formFile, package=self.project.getProjectPath()) |
258 return self.__objectNameExternal() |
201 return dlg.metaObject().className() |
259 else: |
202 except (AttributeError, ImportError, |
260 try: |
203 xml.etree.ElementTree.ParseError) as err: |
261 dlg = uic.loadUi( |
204 E5MessageBox.critical( |
262 self.formFile, package=self.project.getProjectPath()) |
205 self, |
263 return dlg.metaObject().className() |
206 self.tr("uic error"), |
264 except (AttributeError, ImportError, |
207 self.tr( |
265 xml.etree.ElementTree.ParseError) as err: |
208 """<p>There was an error loading the form <b>{0}</b>""" |
266 E5MessageBox.critical( |
209 """.</p><p>{1}</p>""").format(self.formFile, str(err))) |
267 self, |
210 return "" |
268 self.tr("uic error"), |
211 |
269 self.tr( |
|
270 """<p>There was an error loading the form <b>{0}</b>""" |
|
271 """.</p><p>{1}</p>""").format(self.formFile, str(err))) |
|
272 return "" |
|
273 |
212 def __signatures(self): |
274 def __signatures(self): |
213 """ |
275 """ |
214 Private slot to get the signatures. |
276 Private slot to get the signatures. |
215 |
277 |
216 @return list of signatures (list of strings) |
278 @return list of signatures (list of strings) |
241 @param type_ type as reported by Qt (QByteArray) |
303 @param type_ type as reported by Qt (QByteArray) |
242 @return mapped Python type (string) |
304 @return mapped Python type (string) |
243 """ |
305 """ |
244 mapped = bytes(type_).decode() |
306 mapped = bytes(type_).decode() |
245 |
307 |
|
308 # I. always check for * |
|
309 mapped = mapped.replace("*", "") |
|
310 |
246 if self.project.getProjectLanguage() != "Python2" or \ |
311 if self.project.getProjectLanguage() != "Python2" or \ |
247 self.project.getProjectType in ("PySide", "PySide2"): |
312 self.project.getProjectType in ("PySide", "PySide2"): |
248 # 1. check for const |
313 # 1. check for const |
249 mapped = mapped.replace("const ", "") |
314 mapped = mapped.replace("const ", "") |
250 |
315 |
251 # 2. check for * |
316 # 2. replace QString and QStringList |
252 mapped = mapped.replace("*", "") |
|
253 |
|
254 # 3. replace QString and QStringList |
|
255 mapped = mapped.replace("QStringList", "list")\ |
317 mapped = mapped.replace("QStringList", "list")\ |
256 .replace("QString", "str") |
318 .replace("QString", "str") |
257 |
319 |
258 # 4. replace double by float |
320 # 3. replace double by float |
259 mapped = mapped.replace("double", "float") |
321 mapped = mapped.replace("double", "float") |
260 |
322 |
261 return mapped |
323 return mapped |
262 |
324 |
263 def __updateSlotsModel(self): |
325 def __updateSlotsModelExternal(self): |
264 """ |
326 """ |
265 Private slot to update the slots tree display. |
327 Private slot to update the slots tree display getting the data via an |
266 """ |
328 external interpreter. |
267 self.filterEdit.clear() |
329 """ |
268 |
330 interpreter = self.project.getDebugProperty("INTERPRETER") |
269 try: |
331 objectsList = [] |
270 dlg = self.__loadUi( |
332 |
271 self.formFile, package=self.project.getProjectPath()) |
333 loadUi = os.path.join(os.path.dirname(__file__), "UicLoadUi.py") |
272 objects = dlg.findChildren(QWidget) + dlg.findChildren(QAction) |
334 args = [ |
273 |
335 loadUi, |
274 signatureList = self.__signatures() |
336 "signatures", |
275 |
337 self.formFile, |
276 self.slotsModel.clear() |
338 self.project.getProjectPath(), |
277 self.slotsModel.setHorizontalHeaderLabels([""]) |
339 ] |
278 for obj in objects: |
340 |
279 name = obj.objectName() |
341 proc = QProcess() |
280 if not name or name.startswith("qt_"): |
342 proc.start(interpreter, args) |
281 # ignore un-named or internal objects |
343 finished = proc.waitForFinished(30000) |
282 continue |
344 if not finished: |
283 |
345 return |
284 metaObject = obj.metaObject() |
346 |
285 className = metaObject.className() |
347 text = proc.readAllStandardOutput() |
286 itm = QStandardItem("{0} ({1})".format(name, className)) |
348 if proc.exitCode() != 0: |
287 self.slotsModel.appendRow(itm) |
349 errorText = str(text, "utf-8", "replace") |
288 for index in range(metaObject.methodCount()): |
|
289 metaMethod = metaObject.method(index) |
|
290 if metaMethod.methodType() == QMetaMethod.Signal: |
|
291 if qVersionTuple() >= (5, 0, 0): |
|
292 itm2 = QStandardItem("on_{0}_{1}".format( |
|
293 name, |
|
294 bytes(metaMethod.methodSignature()).decode())) |
|
295 else: |
|
296 itm2 = QStandardItem("on_{0}_{1}".format( |
|
297 name, metaMethod.signature())) |
|
298 itm.appendRow(itm2) |
|
299 if self.__module is not None: |
|
300 if qVersionTuple() >= (5, 0, 0): |
|
301 method = "on_{0}_{1}".format( |
|
302 name, |
|
303 bytes(metaMethod.methodSignature()) |
|
304 .decode().split("(")[0]) |
|
305 else: |
|
306 method = "on_{0}_{1}".format( |
|
307 name, metaMethod.signature().split("(")[0]) |
|
308 method2 = "{0}({1})".format( |
|
309 method, ", ".join( |
|
310 [self.__mapType(t) |
|
311 for t in metaMethod.parameterTypes()])) |
|
312 |
|
313 if method2 in signatureList or \ |
|
314 method in signatureList: |
|
315 itm2.setFlags(Qt.ItemFlags(Qt.ItemIsEnabled)) |
|
316 itm2.setCheckState(Qt.Checked) |
|
317 itm2.setForeground(QBrush(Qt.blue)) |
|
318 continue |
|
319 |
|
320 returnType = self.__mapType( |
|
321 metaMethod.typeName().encode()) |
|
322 if returnType == 'void': |
|
323 returnType = "" |
|
324 parameterTypesList = [ |
|
325 self.__mapType(t) |
|
326 for t in metaMethod.parameterTypes()] |
|
327 pyqtSignature = ", ".join(parameterTypesList) |
|
328 |
|
329 parameterNames = metaMethod.parameterNames() |
|
330 if parameterNames: |
|
331 for index in range(len(parameterNames)): |
|
332 if not parameterNames[index]: |
|
333 parameterNames[index] = \ |
|
334 QByteArray("p{0:d}".format(index) |
|
335 .encode("utf-8")) |
|
336 parameterNamesList = [bytes(n).decode() |
|
337 for n in parameterNames] |
|
338 methNamesSig = ", ".join(parameterNamesList) |
|
339 |
|
340 if methNamesSig: |
|
341 if qVersionTuple() >= (5, 0, 0): |
|
342 pythonSignature = \ |
|
343 "on_{0}_{1}(self, {2})".format( |
|
344 name, |
|
345 bytes(metaMethod.methodSignature()) |
|
346 .decode().split("(")[0], |
|
347 methNamesSig) |
|
348 else: |
|
349 pythonSignature = \ |
|
350 "on_{0}_{1}(self, {2})".format( |
|
351 name, |
|
352 metaMethod.signature().split("(")[0], |
|
353 methNamesSig) |
|
354 else: |
|
355 if qVersionTuple() >= (5, 0, 0): |
|
356 pythonSignature = "on_{0}_{1}(self)".format( |
|
357 name, |
|
358 bytes(metaMethod.methodSignature()) |
|
359 .decode().split("(")[0]) |
|
360 else: |
|
361 pythonSignature = "on_{0}_{1}(self)".format( |
|
362 name, |
|
363 metaMethod.signature().split("(")[0]) |
|
364 itm2.setData(pyqtSignature, pyqtSignatureRole) |
|
365 itm2.setData(pythonSignature, pythonSignatureRole) |
|
366 itm2.setData(returnType, returnTypeRole) |
|
367 itm2.setData(parameterTypesList, |
|
368 parameterTypesListRole) |
|
369 itm2.setData(parameterNamesList, |
|
370 parameterNamesListRole) |
|
371 |
|
372 itm2.setFlags(Qt.ItemFlags( |
|
373 Qt.ItemIsUserCheckable | |
|
374 Qt.ItemIsEnabled | |
|
375 Qt.ItemIsSelectable) |
|
376 ) |
|
377 itm2.setCheckState(Qt.Unchecked) |
|
378 |
|
379 self.slotsView.sortByColumn(0, Qt.AscendingOrder) |
|
380 except (AttributeError, ImportError, |
|
381 xml.etree.ElementTree.ParseError) as err: |
|
382 E5MessageBox.critical( |
350 E5MessageBox.critical( |
383 self, |
351 self, |
384 self.tr("uic error"), |
352 self.tr("uic error"), |
385 self.tr( |
353 self.tr( |
386 """<p>There was an error loading the form <b>{0}</b>""" |
354 """<p>There was an error loading the form <b>{0}</b>""" |
387 """.</p><p>{1}</p>""").format(self.formFile, str(err))) |
355 """.</p><p>{1}</p>""").format( |
|
356 self.formFile, errorText)) |
|
357 else: |
|
358 objectsListStr = str(text, "utf-8", "replace").strip() |
|
359 objectsList = json.loads(objectsListStr) |
|
360 |
|
361 signatureList = self.__signatures() |
|
362 |
|
363 for objectDict in objectsList: |
|
364 itm = QStandardItem("{0} ({1})".format( |
|
365 objectDict["name"], |
|
366 objectDict["class_name"])) |
|
367 self.slotsModel.appendRow(itm) |
|
368 for methodDict in objectDict["methods"]: |
|
369 itm2 = QStandardItem(methodDict["signature"]) |
|
370 itm.appendRow(itm2) |
|
371 |
|
372 if self.__module is not None: |
|
373 if methodDict["methods"][0] in signatureList or \ |
|
374 methodDict["methods"][1] in signatureList: |
|
375 itm2.setFlags( |
|
376 Qt.ItemFlags(Qt.ItemIsEnabled)) |
|
377 itm2.setCheckState(Qt.Checked) |
|
378 itm2.setForeground(QBrush(Qt.blue)) |
|
379 continue |
|
380 |
|
381 itm2.setData(methodDict["pyqt_signature"], |
|
382 pyqtSignatureRole) |
|
383 itm2.setData(methodDict["python_signature"], |
|
384 pythonSignatureRole) |
|
385 itm2.setData(methodDict["return_type"], |
|
386 returnTypeRole) |
|
387 itm2.setData(methodDict["parameter_types"], |
|
388 parameterTypesListRole) |
|
389 itm2.setData(methodDict["parameter_names"], |
|
390 parameterNamesListRole) |
|
391 |
|
392 itm2.setFlags(Qt.ItemFlags( |
|
393 Qt.ItemIsUserCheckable | |
|
394 Qt.ItemIsEnabled | |
|
395 Qt.ItemIsSelectable) |
|
396 ) |
|
397 itm2.setCheckState(Qt.Unchecked) |
|
398 |
|
399 self.slotsView.sortByColumn(0, Qt.AscendingOrder) |
|
400 |
|
401 def __updateSlotsModel(self): |
|
402 """ |
|
403 Private slot to update the slots tree display. |
|
404 """ |
|
405 self.filterEdit.clear() |
|
406 |
|
407 if self.project.getDebugProperty("INTERPRETER"): |
|
408 self.__updateSlotsModelExternal() |
|
409 else: |
|
410 try: |
|
411 dlg = uic.loadUi( |
|
412 self.formFile, package=self.project.getProjectPath()) |
|
413 objects = dlg.findChildren(QWidget) + dlg.findChildren(QAction) |
|
414 |
|
415 signatureList = self.__signatures() |
|
416 |
|
417 self.slotsModel.clear() |
|
418 self.slotsModel.setHorizontalHeaderLabels([""]) |
|
419 for obj in objects: |
|
420 name = obj.objectName() |
|
421 if not name or name.startswith("qt_"): |
|
422 # ignore un-named or internal objects |
|
423 continue |
|
424 |
|
425 metaObject = obj.metaObject() |
|
426 className = metaObject.className() |
|
427 itm = QStandardItem("{0} ({1})".format(name, className)) |
|
428 self.slotsModel.appendRow(itm) |
|
429 for index in range(metaObject.methodCount()): |
|
430 metaMethod = metaObject.method(index) |
|
431 if metaMethod.methodType() == QMetaMethod.Signal: |
|
432 if qVersionTuple() >= (5, 0, 0): |
|
433 itm2 = QStandardItem("on_{0}_{1}".format( |
|
434 name, |
|
435 bytes(metaMethod.methodSignature()) |
|
436 .decode() |
|
437 )) |
|
438 else: |
|
439 itm2 = QStandardItem("on_{0}_{1}".format( |
|
440 name, metaMethod.signature() |
|
441 )) |
|
442 itm.appendRow(itm2) |
|
443 if self.__module is not None: |
|
444 if qVersionTuple() >= (5, 0, 0): |
|
445 method = "on_{0}_{1}".format( |
|
446 name, |
|
447 bytes(metaMethod.methodSignature()) |
|
448 .decode().split("(")[0]) |
|
449 else: |
|
450 method = "on_{0}_{1}".format( |
|
451 name, |
|
452 metaMethod.signature().split("(")[0]) |
|
453 method2 = "{0}({1})".format( |
|
454 method, |
|
455 ", ".join([ |
|
456 self.__mapType(t) |
|
457 for t in metaMethod.parameterTypes() |
|
458 ]) |
|
459 ) |
|
460 |
|
461 if method2 in signatureList or \ |
|
462 method in signatureList: |
|
463 itm2.setFlags( |
|
464 Qt.ItemFlags(Qt.ItemIsEnabled)) |
|
465 itm2.setCheckState(Qt.Checked) |
|
466 itm2.setForeground(QBrush(Qt.blue)) |
|
467 continue |
|
468 |
|
469 returnType = self.__mapType( |
|
470 metaMethod.typeName().encode()) |
|
471 if returnType == 'void': |
|
472 returnType = "" |
|
473 parameterTypesList = [ |
|
474 self.__mapType(t) |
|
475 for t in metaMethod.parameterTypes()] |
|
476 pyqtSignature = ", ".join(parameterTypesList) |
|
477 |
|
478 parameterNames = metaMethod.parameterNames() |
|
479 if parameterNames: |
|
480 for index in range(len(parameterNames)): |
|
481 if not parameterNames[index]: |
|
482 parameterNames[index] = \ |
|
483 QByteArray("p{0:d}".format(index) |
|
484 .encode("utf-8")) |
|
485 parameterNamesList = [bytes(n).decode() |
|
486 for n in parameterNames] |
|
487 methNamesSig = ", ".join(parameterNamesList) |
|
488 |
|
489 if methNamesSig: |
|
490 if qVersionTuple() >= (5, 0, 0): |
|
491 pythonSignature = \ |
|
492 "on_{0}_{1}(self, {2})".format( |
|
493 name, |
|
494 bytes(metaMethod.methodSignature()) |
|
495 .decode().split("(")[0], |
|
496 methNamesSig) |
|
497 else: |
|
498 pythonSignature = \ |
|
499 "on_{0}_{1}(self, {2})".format( |
|
500 name, |
|
501 metaMethod.signature() |
|
502 .split("(")[0], |
|
503 methNamesSig) |
|
504 else: |
|
505 if qVersionTuple() >= (5, 0, 0): |
|
506 pythonSignature = "on_{0}_{1}(self)"\ |
|
507 .format( |
|
508 name, |
|
509 bytes(metaMethod.methodSignature()) |
|
510 .decode().split("(")[0]) |
|
511 else: |
|
512 pythonSignature = "on_{0}_{1}(self)"\ |
|
513 .format( |
|
514 name, |
|
515 metaMethod.signature().split( |
|
516 "(")[0]) |
|
517 itm2.setData(pyqtSignature, pyqtSignatureRole) |
|
518 itm2.setData(pythonSignature, pythonSignatureRole) |
|
519 itm2.setData(returnType, returnTypeRole) |
|
520 itm2.setData(parameterTypesList, |
|
521 parameterTypesListRole) |
|
522 itm2.setData(parameterNamesList, |
|
523 parameterNamesListRole) |
|
524 |
|
525 itm2.setFlags(Qt.ItemFlags( |
|
526 Qt.ItemIsUserCheckable | |
|
527 Qt.ItemIsEnabled | |
|
528 Qt.ItemIsSelectable) |
|
529 ) |
|
530 itm2.setCheckState(Qt.Unchecked) |
|
531 |
|
532 self.slotsView.sortByColumn(0, Qt.AscendingOrder) |
|
533 except (AttributeError, ImportError, |
|
534 xml.etree.ElementTree.ParseError) as err: |
|
535 E5MessageBox.critical( |
|
536 self, |
|
537 self.tr("uic error"), |
|
538 self.tr( |
|
539 """<p>There was an error loading the form <b>{0}</b>""" |
|
540 """.</p><p>{1}</p>""").format(self.formFile, str(err))) |
388 |
541 |
389 def __generateCode(self): |
542 def __generateCode(self): |
390 """ |
543 """ |
391 Private slot to generate the code as requested by the user. |
544 Private slot to generate the code as requested by the user. |
392 """ |
545 """ |