diff -r 30829a28e969 -r 77c817301ca1 Project/CreateDialogCodeDialog.py --- a/Project/CreateDialogCodeDialog.py Sun Oct 14 18:24:49 2018 +0200 +++ b/Project/CreateDialogCodeDialog.py Wed Oct 17 19:53:13 2018 +0200 @@ -8,13 +8,17 @@ """ from __future__ import unicode_literals +try: + str = unicode # __IGNORE_EXCEPTION__ +except NameError: + pass import os -import sys +import json import xml.etree.ElementTree from PyQt5.QtCore import QMetaObject, QByteArray, QRegExp, Qt, pyqtSlot, \ - QMetaMethod, QSortFilterProxyModel + QMetaMethod, QSortFilterProxyModel, QProcess from PyQt5.QtGui import QStandardItemModel, QBrush, QStandardItem from PyQt5.QtWidgets import QWidget, QDialog, QDialogButtonBox, QAction from PyQt5 import uic @@ -30,8 +34,6 @@ from Globals import qVersionTuple -import Utilities - pyqtSignatureRole = Qt.UserRole + 1 pythonSignatureRole = Qt.UserRole + 2 @@ -145,70 +147,130 @@ """ return self.__initError - def __loadUi(self, formFile, package=""): + def __objectNameExternal(self): """ - Private method to load a form file and instantiate the defined form. + Private method to get the object name of a form via an external + interpreter. - @param formFile path of the form file to be loaded - @type str - @param package base path to be used for relative imports - @type str - @return instantiated form - @rtype QWidget + @return object name + @rtype str """ - oldSysPath = [] interpreter = self.project.getDebugProperty("INTERPRETER") - if interpreter: - oldSysPath = sys.path[:] - sys.path = oldSysPath + Utilities.getSysPath(interpreter) + objectName = "" + + loadUi = os.path.join(os.path.dirname(__file__), "UicLoadUi.py") + args = [ + loadUi, + "object_name", + self.formFile, + self.project.getProjectPath(), + ] - dlg = uic.loadUi(formFile, package=package) + proc = QProcess() + proc.start(interpreter, args) + finished = proc.waitForFinished(30000) + if finished: + text = proc.readAllStandardOutput() + if proc.exitCode() == 0: + objectName = str(text, "utf-8", "replace").strip() + else: + errorText = str(text, "utf-8", "replace") + E5MessageBox.critical( + self, + self.tr("uic error"), + self.tr( + """<p>There was an error loading the form <b>{0}</b>""" + """.</p><p>{1}</p>""").format( + self.formFile, errorText)) - if oldSysPath: - sys.path = oldSysPath - - return dlg + return objectName def __objectName(self): """ - Private method to get the object name of the dialog. + Private method to get the object name of a form. - @return object name (string) + @return object name + @rtype str + """ + if self.project.getDebugProperty("INTERPRETER"): + return self.__objectNameExternal() + else: + try: + dlg = uic.loadUi( + self.formFile, package=self.project.getProjectPath()) + return dlg.objectName() + except (AttributeError, ImportError, + xml.etree.ElementTree.ParseError) as err: + E5MessageBox.critical( + self, + self.tr("uic error"), + self.tr( + """<p>There was an error loading the form <b>{0}</b>""" + """.</p><p>{1}</p>""").format(self.formFile, str(err))) + return "" + + def __classNameExternal(self): + """ + Private method to get the class name of a form via an external + interpreter. + + @return class name + @rtype str """ - try: - dlg = self.__loadUi( - self.formFile, package=self.project.getProjectPath()) - return dlg.objectName() - except (AttributeError, ImportError, - xml.etree.ElementTree.ParseError) as err: - E5MessageBox.critical( - self, - self.tr("uic error"), - self.tr( - """<p>There was an error loading the form <b>{0}</b>""" - """.</p><p>{1}</p>""").format(self.formFile, str(err))) - return "" + interpreter = self.project.getDebugProperty("INTERPRETER") + className = "" + + loadUi = os.path.join(os.path.dirname(__file__), "UicLoadUi.py") + args = [ + loadUi, + "class_name", + self.formFile, + self.project.getProjectPath(), + ] + proc = QProcess() + proc.start(interpreter, args) + finished = proc.waitForFinished(30000) + if finished: + text = proc.readAllStandardOutput() + if proc.exitCode() == 0: + className = str(text, "utf-8", "replace").strip() + else: + errorText = str(text, "utf-8", "replace") + E5MessageBox.critical( + self, + self.tr("uic error"), + self.tr( + """<p>There was an error loading the form <b>{0}</b>""" + """.</p><p>{1}</p>""").format( + self.formFile, errorText)) + + return className + def __className(self): """ - Private method to get the class name of the dialog. + Private method to get the class name of a form. - @return class name (sting) + @return class name + @rtype str """ - try: - dlg = self.__loadUi( - self.formFile, package=self.project.getProjectPath()) - return dlg.metaObject().className() - except (AttributeError, ImportError, - xml.etree.ElementTree.ParseError) as err: - E5MessageBox.critical( - self, - self.tr("uic error"), - self.tr( - """<p>There was an error loading the form <b>{0}</b>""" - """.</p><p>{1}</p>""").format(self.formFile, str(err))) - return "" - + if self.project.getDebugProperty("INTERPRETER"): + return self.__objectNameExternal() + else: + try: + dlg = uic.loadUi( + self.formFile, package=self.project.getProjectPath()) + return dlg.metaObject().className() + except (AttributeError, ImportError, + xml.etree.ElementTree.ParseError) as err: + E5MessageBox.critical( + self, + self.tr("uic error"), + self.tr( + """<p>There was an error loading the form <b>{0}</b>""" + """.</p><p>{1}</p>""").format(self.formFile, str(err))) + return "" + def __signatures(self): """ Private slot to get the signatures. @@ -243,148 +305,239 @@ """ mapped = bytes(type_).decode() + # I. always check for * + mapped = mapped.replace("*", "") + if self.project.getProjectLanguage() != "Python2" or \ self.project.getProjectType in ("PySide", "PySide2"): # 1. check for const mapped = mapped.replace("const ", "") - # 2. check for * - mapped = mapped.replace("*", "") - - # 3. replace QString and QStringList + # 2. replace QString and QStringList mapped = mapped.replace("QStringList", "list")\ .replace("QString", "str") - # 4. replace double by float + # 3. replace double by float mapped = mapped.replace("double", "float") return mapped + + def __updateSlotsModelExternal(self): + """ + Private slot to update the slots tree display getting the data via an + external interpreter. + """ + interpreter = self.project.getDebugProperty("INTERPRETER") + objectsList = [] + loadUi = os.path.join(os.path.dirname(__file__), "UicLoadUi.py") + args = [ + loadUi, + "signatures", + self.formFile, + self.project.getProjectPath(), + ] + + proc = QProcess() + proc.start(interpreter, args) + finished = proc.waitForFinished(30000) + if not finished: + return + + text = proc.readAllStandardOutput() + if proc.exitCode() != 0: + errorText = str(text, "utf-8", "replace") + E5MessageBox.critical( + self, + self.tr("uic error"), + self.tr( + """<p>There was an error loading the form <b>{0}</b>""" + """.</p><p>{1}</p>""").format( + self.formFile, errorText)) + else: + objectsListStr = str(text, "utf-8", "replace").strip() + objectsList = json.loads(objectsListStr) + + signatureList = self.__signatures() + + for objectDict in objectsList: + itm = QStandardItem("{0} ({1})".format( + objectDict["name"], + objectDict["class_name"])) + self.slotsModel.appendRow(itm) + for methodDict in objectDict["methods"]: + itm2 = QStandardItem(methodDict["signature"]) + itm.appendRow(itm2) + + if self.__module is not None: + if methodDict["methods"][0] in signatureList or \ + methodDict["methods"][1] in signatureList: + itm2.setFlags( + Qt.ItemFlags(Qt.ItemIsEnabled)) + itm2.setCheckState(Qt.Checked) + itm2.setForeground(QBrush(Qt.blue)) + continue + + itm2.setData(methodDict["pyqt_signature"], + pyqtSignatureRole) + itm2.setData(methodDict["python_signature"], + pythonSignatureRole) + itm2.setData(methodDict["return_type"], + returnTypeRole) + itm2.setData(methodDict["parameter_types"], + parameterTypesListRole) + itm2.setData(methodDict["parameter_names"], + parameterNamesListRole) + + itm2.setFlags(Qt.ItemFlags( + Qt.ItemIsUserCheckable | + Qt.ItemIsEnabled | + Qt.ItemIsSelectable) + ) + itm2.setCheckState(Qt.Unchecked) + + self.slotsView.sortByColumn(0, Qt.AscendingOrder) + def __updateSlotsModel(self): """ Private slot to update the slots tree display. """ self.filterEdit.clear() - try: - dlg = self.__loadUi( - self.formFile, package=self.project.getProjectPath()) - objects = dlg.findChildren(QWidget) + dlg.findChildren(QAction) - - signatureList = self.__signatures() - - self.slotsModel.clear() - self.slotsModel.setHorizontalHeaderLabels([""]) - for obj in objects: - name = obj.objectName() - if not name or name.startswith("qt_"): - # ignore un-named or internal objects - continue + if self.project.getDebugProperty("INTERPRETER"): + self.__updateSlotsModelExternal() + else: + try: + dlg = uic.loadUi( + self.formFile, package=self.project.getProjectPath()) + objects = dlg.findChildren(QWidget) + dlg.findChildren(QAction) + + signatureList = self.__signatures() - metaObject = obj.metaObject() - className = metaObject.className() - itm = QStandardItem("{0} ({1})".format(name, className)) - self.slotsModel.appendRow(itm) - for index in range(metaObject.methodCount()): - metaMethod = metaObject.method(index) - if metaMethod.methodType() == QMetaMethod.Signal: - if qVersionTuple() >= (5, 0, 0): - itm2 = QStandardItem("on_{0}_{1}".format( - name, - bytes(metaMethod.methodSignature()).decode())) - else: - itm2 = QStandardItem("on_{0}_{1}".format( - name, metaMethod.signature())) - itm.appendRow(itm2) - if self.__module is not None: + self.slotsModel.clear() + self.slotsModel.setHorizontalHeaderLabels([""]) + for obj in objects: + name = obj.objectName() + if not name or name.startswith("qt_"): + # ignore un-named or internal objects + continue + + metaObject = obj.metaObject() + className = metaObject.className() + itm = QStandardItem("{0} ({1})".format(name, className)) + self.slotsModel.appendRow(itm) + for index in range(metaObject.methodCount()): + metaMethod = metaObject.method(index) + if metaMethod.methodType() == QMetaMethod.Signal: if qVersionTuple() >= (5, 0, 0): - method = "on_{0}_{1}".format( + itm2 = QStandardItem("on_{0}_{1}".format( name, bytes(metaMethod.methodSignature()) - .decode().split("(")[0]) + .decode() + )) else: - method = "on_{0}_{1}".format( - name, metaMethod.signature().split("(")[0]) - method2 = "{0}({1})".format( - method, ", ".join( - [self.__mapType(t) - for t in metaMethod.parameterTypes()])) - - if method2 in signatureList or \ - method in signatureList: - itm2.setFlags(Qt.ItemFlags(Qt.ItemIsEnabled)) - itm2.setCheckState(Qt.Checked) - itm2.setForeground(QBrush(Qt.blue)) - continue - - returnType = self.__mapType( - metaMethod.typeName().encode()) - if returnType == 'void': - returnType = "" - parameterTypesList = [ - self.__mapType(t) - for t in metaMethod.parameterTypes()] - pyqtSignature = ", ".join(parameterTypesList) - - parameterNames = metaMethod.parameterNames() - if parameterNames: - for index in range(len(parameterNames)): - if not parameterNames[index]: - parameterNames[index] = \ - QByteArray("p{0:d}".format(index) - .encode("utf-8")) - parameterNamesList = [bytes(n).decode() - for n in parameterNames] - methNamesSig = ", ".join(parameterNamesList) - - if methNamesSig: - if qVersionTuple() >= (5, 0, 0): - pythonSignature = \ - "on_{0}_{1}(self, {2})".format( + itm2 = QStandardItem("on_{0}_{1}".format( + name, metaMethod.signature() + )) + itm.appendRow(itm2) + if self.__module is not None: + if qVersionTuple() >= (5, 0, 0): + method = "on_{0}_{1}".format( name, bytes(metaMethod.methodSignature()) - .decode().split("(")[0], - methNamesSig) - else: - pythonSignature = \ - "on_{0}_{1}(self, {2})".format( + .decode().split("(")[0]) + else: + method = "on_{0}_{1}".format( name, - metaMethod.signature().split("(")[0], - methNamesSig) - else: - if qVersionTuple() >= (5, 0, 0): - pythonSignature = "on_{0}_{1}(self)".format( - name, - bytes(metaMethod.methodSignature()) - .decode().split("(")[0]) + metaMethod.signature().split("(")[0]) + method2 = "{0}({1})".format( + method, + ", ".join([ + self.__mapType(t) + for t in metaMethod.parameterTypes() + ]) + ) + + if method2 in signatureList or \ + method in signatureList: + itm2.setFlags( + Qt.ItemFlags(Qt.ItemIsEnabled)) + itm2.setCheckState(Qt.Checked) + itm2.setForeground(QBrush(Qt.blue)) + continue + + returnType = self.__mapType( + metaMethod.typeName().encode()) + if returnType == 'void': + returnType = "" + parameterTypesList = [ + self.__mapType(t) + for t in metaMethod.parameterTypes()] + pyqtSignature = ", ".join(parameterTypesList) + + parameterNames = metaMethod.parameterNames() + if parameterNames: + for index in range(len(parameterNames)): + if not parameterNames[index]: + parameterNames[index] = \ + QByteArray("p{0:d}".format(index) + .encode("utf-8")) + parameterNamesList = [bytes(n).decode() + for n in parameterNames] + methNamesSig = ", ".join(parameterNamesList) + + if methNamesSig: + if qVersionTuple() >= (5, 0, 0): + pythonSignature = \ + "on_{0}_{1}(self, {2})".format( + name, + bytes(metaMethod.methodSignature()) + .decode().split("(")[0], + methNamesSig) + else: + pythonSignature = \ + "on_{0}_{1}(self, {2})".format( + name, + metaMethod.signature() + .split("(")[0], + methNamesSig) else: - pythonSignature = "on_{0}_{1}(self)".format( - name, - metaMethod.signature().split("(")[0]) - itm2.setData(pyqtSignature, pyqtSignatureRole) - itm2.setData(pythonSignature, pythonSignatureRole) - itm2.setData(returnType, returnTypeRole) - itm2.setData(parameterTypesList, - parameterTypesListRole) - itm2.setData(parameterNamesList, - parameterNamesListRole) - - itm2.setFlags(Qt.ItemFlags( - Qt.ItemIsUserCheckable | - Qt.ItemIsEnabled | - Qt.ItemIsSelectable) - ) - itm2.setCheckState(Qt.Unchecked) - - self.slotsView.sortByColumn(0, Qt.AscendingOrder) - except (AttributeError, ImportError, - xml.etree.ElementTree.ParseError) as err: - E5MessageBox.critical( - self, - self.tr("uic error"), - self.tr( - """<p>There was an error loading the form <b>{0}</b>""" - """.</p><p>{1}</p>""").format(self.formFile, str(err))) + if qVersionTuple() >= (5, 0, 0): + pythonSignature = "on_{0}_{1}(self)"\ + .format( + name, + bytes(metaMethod.methodSignature()) + .decode().split("(")[0]) + else: + pythonSignature = "on_{0}_{1}(self)"\ + .format( + name, + metaMethod.signature().split( + "(")[0]) + itm2.setData(pyqtSignature, pyqtSignatureRole) + itm2.setData(pythonSignature, pythonSignatureRole) + itm2.setData(returnType, returnTypeRole) + itm2.setData(parameterTypesList, + parameterTypesListRole) + itm2.setData(parameterNamesList, + parameterNamesListRole) + + itm2.setFlags(Qt.ItemFlags( + Qt.ItemIsUserCheckable | + Qt.ItemIsEnabled | + Qt.ItemIsSelectable) + ) + itm2.setCheckState(Qt.Unchecked) + + self.slotsView.sortByColumn(0, Qt.AscendingOrder) + except (AttributeError, ImportError, + xml.etree.ElementTree.ParseError) as err: + E5MessageBox.critical( + self, + self.tr("uic error"), + self.tr( + """<p>There was an error loading the form <b>{0}</b>""" + """.</p><p>{1}</p>""").format(self.formFile, str(err))) def __generateCode(self): """