示例#1
0
class EDGVLayerLoader(QObject):
    def __init__(self, iface, abstractDb, loadCentroids):
        """Constructor."""
        super(EDGVLayerLoader, self).__init__()

        self.abstractDb = abstractDb
        self.uri = QgsDataSourceUri()
        self.iface = iface
        self.utils = Utils()
        self.logErrorDict = dict()
        self.errorLog = ''
        self.geomTypeDict = self.abstractDb.getGeomTypeDict(loadCentroids)
        self.geomDict = self.abstractDb.getGeomDict(self.geomTypeDict)
        self.correspondenceDict = {
            'POINT': 'Point',
            'MULTIPOINT': 'Point',
            'LINESTRING': 'Line',
            'MULTILINESTRING': 'Line',
            'POLYGON': 'Area',
            'MULTIPOLYGON': 'Area'
        }

    def preLoadStep(self, inputList):
        if len(inputList) == 0:
            return [], False
        else:
            if isinstance(inputList[0], dict):
                lyrList = [i['tableName'] for i in inputList]
                return lyrList, True
            else:
                return inputList, False

    def load(self,
             inputList,
             useQml=False,
             uniqueLoad=False,
             useInheritance=False,
             stylePath=None,
             onlyWithElements=False,
             geomFilterList=[],
             isEdgv=True,
             customForm=False,
             loadEditingStructure=False,
             parent=None):
        return None

    def getStyle(self, stylePath, className):
        if 'db:' in stylePath['style']:
            return self.abstractDb.getStyle(stylePath['style'].split(':')[-1],
                                            className)
        else:
            return self.getStyleFromFile(stylePath['style'], className)

    def getStyleFromFile(self, stylePath, className):
        styleName = "{0}.qml".format(className)
        if styleName.lower() in [f.lower() for f in os.listdir(stylePath)]:
            qml = self.utils.parseStyle(os.path.join(stylePath, styleName))
            # dsgtools have the right to write on its own directory
            # a temporary file "temp.qml"
            tempPath = os.path.join(stylePath, "temp.qml")
            with open(tempPath, "w", encoding='utf-8') as f:
                f.writelines(qml)
                f.close()
            return tempPath
        else:
            return None

    def prepareLoad(self):
        dbName = self.abstractDb.getDatabaseName()
        groupList = iface.legendInterface().groups()
        if dbName in groupList:
            return groupList.index(dbName)
        else:
            parentTreeNode = iface.legendInterface().addGroup(
                self.abstractDb.getDatabaseName(), -1)
            return parentTreeNode

    def createMeasureColumn(self, layer):
        if layer.geometryType() == QgsWkbTypes.PolygonGeometry:
            layer.addExpressionField(
                '$area', QgsField(self.tr('area_otf'), QVariant.Double))
        elif layer.geometryType() == QgsWkbTypes.LineGeometry:
            layer.addExpressionField(
                '$length', QgsField(self.tr('lenght_otf'), QVariant.Double))
        return layer

    def getDatabaseGroup(self, rootNode):
        dbName = self.abstractDb.getDatabaseName()
        return self.createGroup(dbName, rootNode)

    def getLyrDict(self, inputList, isEdgv=True):
        """
        Builds lyrDict in order to build loading tree
        lyrList: list of layers to be loaded
        isEdgv: optional parameter to indicate when db is not edgv. If db is not edgv, layers will be grouped by schema.
        """
        lyrDict = dict()
        if isinstance(inputList, list):
            if len(inputList) > 0:
                if isinstance(inputList[0], dict):
                    for elem in inputList:
                        if elem['geomType'] == 'GEOMETRY':
                            continue
                        if self.correspondenceDict[
                                elem['geomType']] not in list(lyrDict.keys()):
                            lyrDict[self.correspondenceDict[
                                elem['geomType']]] = dict()
                        if elem['cat'] not in list(
                                lyrDict[self.correspondenceDict[
                                    elem['geomType']]].keys()):
                            lyrDict[self.correspondenceDict[elem['geomType']]][
                                elem['cat']] = []
                        lyrDict[self.correspondenceDict[elem['geomType']]][
                            elem['cat']].append(elem)
                else:
                    for type in list(self.geomTypeDict.keys()):
                        # some tables are only registered as GEOMETRY and should not be considered
                        if type == 'GEOMETRY':
                            continue
                        if self.correspondenceDict[type] not in list(
                                lyrDict.keys()):
                            lyrDict[self.correspondenceDict[type]] = dict()
                        for lyr in self.geomTypeDict[type]:
                            if lyr in inputList:
                                if isEdgv:
                                    cat = lyr.split('_')[0]
                                else:
                                    cat = self.abstractDb.getTableSchemaFromDb(
                                        lyr)
                                if cat not in list(lyrDict[
                                        self.correspondenceDict[type]].keys()):
                                    lyrDict[self.correspondenceDict[type]][
                                        cat] = []
                                lyrDict[self.correspondenceDict[type]][
                                    cat].append(lyr)
                    for type in list(lyrDict.keys()):
                        if lyrDict[type] == dict():
                            lyrDict.pop(type)
        return lyrDict

    def prepareGroups(self, rootNode, lyrDict):
        aux = dict()
        groupDict = dict()
        groupNodeList = list(lyrDict.keys())
        groupNodeList.sort(reverse=True)
        for geomNodeName in groupNodeList:
            groupDict[geomNodeName] = dict()
            geomNode = self.createGroup(geomNodeName, rootNode)
            catList = list(lyrDict[geomNodeName].keys())
            catList.sort()
            for catNodeName in catList:
                groupDict[geomNodeName][catNodeName] = self.createGroup(
                    catNodeName, geomNode)
        return groupDict

    def createGroup(self, groupName, rootNode):
        groupNode = rootNode.findGroup(groupName)
        if groupNode:
            return groupNode
        else:
            return rootNode.addGroup(groupName)

    def loadDomains(self, layerList, dbRootNode, edgvVersion):
        if edgvVersion not in ('FTer_2a_Ed', '3.0'):
            return dict()
        domLayerDict = dict()
        try:
            qmlDict = self.abstractDb.getQmlDict(layerList)
        except:
            return dict()
        domainNode = self.createGroup(self.tr("Domains"), dbRootNode)
        loadedDomainsDict = {} if not domainNode.findLayers() else {
            i.layer().name(): i.layer()
            for i in domainNode.findLayers()
        }
        for lyr in layerList:
            if lyr in qmlDict:
                for attr in qmlDict[lyr]:
                    domain = qmlDict[lyr][attr]
                    domLyr = self.getDomainLyr(domain, loadedDomainsDict,
                                               domainNode)
                    if lyr not in list(domLayerDict.keys()):
                        domLayerDict[lyr] = dict()
                    if attr not in list(domLayerDict[lyr].keys()):
                        domLayerDict[lyr][attr] = domLyr
        return domLayerDict

    def getDomainLyr(self, domain, loadedDomainsDict, domainNode):
        if domain in loadedDomainsDict:
            return loadedDomainsDict[domain]
        domainLyr = self.loadDomain(domain, domainNode)
        loadedDomainsDict[domain] = domainLyr
        return domainLyr

    def logError(self):
        msg = ''
        for lyr in self.logErrorDict:
            msg += self.tr(
                'Error for lyr ') + lyr + ': ' + self.logErrorDict[lyr] + '\n'
        self.errorLog += msg

    def setDataSource(self, schema, layer, geomColumn, sql, pkColumn='id'):
        self.uri.setDataSource(schema, layer, geomColumn, sql, pkColumn)
        if sql == '':
            self.uri.disableSelectAtId(False)
        else:
            self.uri.disableSelectAtId(True)

    def setDomainsAndRestrictionsWithQml(self, vlayer):
        qmldir = ''
        try:
            qmldir, qmlType = self.abstractDb.getQml(vlayer.name())
        except Exception as e:
            QgsMessageLog.logMessage(':'.join(e.args), "DSGTools Plugin",
                                     Qgis.Critical)
            return None
        if qmlType == 'db':
            tempPath = os.path.join(os.path.dirname(__file__), "temp.qml")
            with open(tempPath, "w", encoding='utf-8') as f:
                f.writelines(qmldir)
                f.close()
            vlayer.loadNamedStyle(tempPath, True)
            os.remove(tempPath)
        else:
            vlayerQml = os.path.join(qmldir, vlayer.name() + '.qml')
            #treat case of qml with multi
            vlayer.loadNamedStyle(vlayerQml, True)
        return vlayer

    def removeEmptyNodes(self, dbNode):
        for geomNode in dbNode.children():
            if not geomNode.findLayers():
                dbNode.removeChildNode(geomNode)
                continue
            for catNode in geomNode.children():
                if not catNode.findLayers():
                    geomNode.removeChildNode(catNode)

    def getParams(self, inputParam):
        if isinstance(inputParam, dict):
            lyrName = inputParam['lyrName']
            schema = inputParam['tableSchema']
            geomColumn = inputParam['geom']
            tableName = inputParam['tableName']
            srid = self.geomDict['tablePerspective'][tableName]['srid']
        elif isinstance(inputParam, tuple):
            schema, tableName = inputParam
            lyrName = tableName
            geomColumn, srid = '', ''
        else:
            lyrName = inputParam
            tableName = self.geomDict['tablePerspective'][lyrName]['tableName']
            schema = self.geomDict['tablePerspective'][lyrName]['schema']
            geomColumn = self.geomDict['tablePerspective'][lyrName][
                'geometryColumn']
            srid = self.geomDict['tablePerspective'][lyrName]['srid']
        return lyrName, schema, geomColumn, tableName, srid

    def getLayerByName(self, layer):
        """
        Return the layer layer from a given layer name.
        :param layer: (str) layer name.
        :return: (QgsVectorLayer) vector layer. 
        """
        try:
            # self.provider is added on children classes
            return QgsVectorLayer(self.uri.uri(), layer, self.provider)
        except:
            return None

    def getComplexLayerByName(self, layer):
        """
        Return the layer layer from a given layer name.
        :param layer: (str) layer name.
        :return: (QgsVectorLayer) vector layer. 
        """
        try:
            # self.provider is added on children classes]
            schema, table = self.abstractDb.getTableSchema(layer)
            return QgsVectorLayer(self.uri.uri(), table, self.provider)
        except:
            return None

    def buildJoin(self, originalLyr, originalLyrFieldName, joinnedLyr,
                  joinLyrFieldName):
        """
        Builds a join bewteen lyr and joinnedLyr.
        :param originalLyr: QgsVectorLayer original layer;
        :param originalLyrFieldName: (str) name of the field;
        :param joinnedLyr: QgsVectorLayer lyr to be joinned to originalLayer;
        :param joinLyrFieldName: (str) name of the join field name (usually primary key of joinnedLyr)
        """
        joinObject = QgsVectorLayerJoinInfo()
        joinObject.setJoinFieldName(joinLyrFieldName)
        joinObject.setTargetFieldName(originalLyrFieldName)
        joinObject.setJoinLayer(joinnedLyr)
        joinObject.setJoinFieldNamesSubset()
        joinObject.upsertOnEdit(True)  #set to enable edit on original lyr
        joinObject.setCascadedDelete(True)
        joinObject.setDynamicFormEnabled(True)
        joinObject.setEditable(True)
        joinObject.setUsingMemoryCache(True)
        originalLyr.addJoin(joinObject)