Project/CreateDialogCodeDialog.py

changeset 6547
77c817301ca1
parent 6544
51996454f89f
child 6548
21f8260753b5
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):
         """

eric ide

mercurial