예제 #1
0
    def test_joined_layers_conversion(self):
        v1 = QgsVectorLayer("Point?field=id:integer&field=b_id:integer&field=c_id:integer&field=name:string", "A", "memory")
        self.assertEqual(v1.isValid(), True)
        v2 = QgsVectorLayer("Point?field=id:integer&field=bname:string&field=bfield:integer", "B", "memory")
        self.assertEqual(v2.isValid(), True)
        v3 = QgsVectorLayer("Point?field=id:integer&field=cname:string", "C", "memory")
        self.assertEqual(v3.isValid(), True)
        QgsProject.instance().addMapLayers([v1, v2, v3])
        joinInfo = QgsVectorLayerJoinInfo()
        joinInfo.setTargetFieldName("b_id")
        joinInfo.setJoinLayer(v2)
        joinInfo.setJoinFieldName("id")
        #joinInfo.setPrefix("B_")
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 6)

        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(df.query(), 'SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS B_bname, j1.bfield AS B_bfield FROM {} AS t LEFT JOIN {} AS j1 ON t."b_id"=j1."id"'.format(v1.id(), v2.id()))

        # with a field subset
        v1.removeJoin(v2.id())
        joinInfo.setJoinFieldNamesSubset(["bname"])
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 5)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(df.query(), 'SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS B_bname FROM {} AS t LEFT JOIN {} AS j1 ON t."b_id"=j1."id"'.format(v1.id(), v2.id()))
        joinInfo.setJoinFieldNamesSubset(None)

        # add a table prefix to the join
        v1.removeJoin(v2.id())
        joinInfo.setPrefix("BB_")
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 6)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(df.query(), 'SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS BB_bname, j1.bfield AS BB_bfield FROM {} AS t LEFT JOIN {} AS j1 ON t."b_id"=j1."id"'.format(v1.id(), v2.id()))
        joinInfo.setPrefix("")
        v1.removeJoin(v2.id())
        v1.addJoin(joinInfo)

        # add another join
        joinInfo2 = QgsVectorLayerJoinInfo()
        joinInfo2.setTargetFieldName("c_id")
        joinInfo2.setJoinLayer(v3)
        joinInfo2.setJoinFieldName("id")
        v1.addJoin(joinInfo2)
        self.assertEqual(len(v1.fields()), 7)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(df.query(), ('SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS B_bname, j1.bfield AS B_bfield, j2.cname AS C_cname FROM {} AS t ' +
                                      'LEFT JOIN {} AS j1 ON t."b_id"=j1."id" ' +
                                      'LEFT JOIN {} AS j2 ON t."c_id"=j2."id"').format(v1.id(), v2.id(), v3.id()))

        QgsProject.instance().removeMapLayers([v1.id(), v2.id(), v3.id()])
예제 #2
0
    def test_JoinUsingExpression(self):
        """ test joining a layer using a virtual field """
        joinLayer = QgsVectorLayer(
            "Point?field=x:string&field=y:integer&field=z:integer",
            "joinlayer", "memory")
        pr = joinLayer.dataProvider()
        f1 = QgsFeature()
        f1.setAttributes(["foo", 246, 321])
        f2 = QgsFeature()
        f2.setAttributes(["bar", 456, 654])
        self.assertTrue(pr.addFeatures([f1, f2]))

        layer = QgsVectorLayer(
            "Point?field=fldtxt:string&field=fldint:integer", "addfeat",
            "memory")
        pr = layer.dataProvider()
        f = QgsFeature()
        f.setAttributes(["test", 123])
        self.assertTrue(pr.addFeatures([f]))
        layer.addExpressionField('"fldint"*2',
                                 QgsField('exp1', QVariant.LongLong))

        QgsProject.instance().addMapLayers([layer, joinLayer])

        join = QgsVectorLayerJoinInfo()
        join.setTargetFieldName("exp1")
        join.setJoinLayer(joinLayer)
        join.setJoinFieldName("y")
        join.setUsingMemoryCache(True)
        layer.addJoin(join)

        f = QgsFeature()
        fi = layer.getFeatures()
        self.assertTrue(fi.nextFeature(f))
        attrs = f.attributes()
        self.assertEqual(attrs[0], "test")
        self.assertEqual(attrs[1], 123)
        self.assertEqual(attrs[2], "foo")
        self.assertEqual(attrs[3], 321)
        self.assertEqual(attrs[4], 246)
        self.assertFalse(fi.nextFeature(f))

        QgsProject.instance().removeMapLayers([layer.id(), joinLayer.id()])
예제 #3
0
 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)
예제 #4
0
    def joinLayer(self, targetlayer, pkfield, sourcelayer, fkfield):
        """
        Join the results of the SQL Server query to the pg layer
        """

        joinInfo = QgsVectorLayerJoinInfo()
        # Backward compatbility QGIS3=>2
        if qversion == 3:
            joinInfo.setTargetFieldName(pkfield)
            joinInfo.setJoinLayer(sourcelayer)
            joinInfo.setJoinFieldName(fkfield)
            joinInfo.setUsingMemoryCache(True)
        else:  # QGIS 2
            joinInfo.targetFieldName = pkfield
            joinInfo.joinLayerId = sourcelayer.id()
            joinInfo.joinFieldName = fkfield
            joinInfo.memoryCache = True
        targetlayer.addJoin(joinInfo)
        targetlayer.updateFields()
        return targetlayer
예제 #5
0
 def complete_fields(self, layer):
     """Join shapefile to csv and fill in the missing fields based on sub ID"""
     infoLyr = QgsVectorLayer(f'file:///{str(CSV)}?delimiter=,','classes','delimitedtext')
     QgsProject.instance().addMapLayer(infoLyr)
     csv_field = 'Int_SubNum'
     shp_field = 'HabitatSub'
     joinObject = QgsVectorLayerJoinInfo()
     joinObject.setJoinFieldName(csv_field)
     joinObject.setTargetFieldName(shp_field)
     joinObject.setJoinLayerId(infoLyr.id())
     joinObject.setUsingMemoryCache(True)
     joinObject.setJoinLayer(infoLyr)
     layer.addJoin(joinObject)
     layer.startEditing()
     ha_areas = []
     for feature in layer.getFeatures():
         shp_fields = ['HabitatTyp', 'HabitatT_1', 'HabitatS_1', 'MMU_HA']
         csv_fields = ['classes_Int_num', 'classes_Int_cls', 'classes_Int_SubCls', 'classes_MMU_']
         for shp, csv in zip(shp_fields, csv_fields):
             f = layer.fields().indexFromName(csv)
             f_ = layer.fields().indexFromName(shp)
             layer.changeAttributeValue(feature.id(), f_, feature[f])
         area_km = layer.fields().indexFromName('Area_KM')
         area_ha = layer.fields().indexFromName('Area_HA')
         orthoid_field = layer.fields().indexFromName('OrthoID')
         id_field = layer.fields().indexFromName('Id')
         layer.changeAttributeValue(feature.id(), area_km, feature.geometry().area() / 10**6)
         layer.changeAttributeValue(feature.id(), area_ha, feature.geometry().area() / 10**4)
         ha_areas.append(feature.geometry().area() / 10**4)
         layer.changeAttributeValue(feature.id(), orthoid_field, feature[0])
         layer.changeAttributeValue(feature.id(), id_field, feature.id())
         
     layer.removeJoin(infoLyr.id())
     QgsProject.instance().removeMapLayer(infoLyr)
     fields_to_drop = set(['RuleID', 'Shape_Leng', 'Shape_Area'])
     field_ids = []
     for field in layer.fields():
         if field.name() in fields_to_drop:
             field_ids.append(layer.fields().indexFromName(field.name()))
     layer.dataProvider().deleteAttributes(field_ids)
     layer.commitChanges()
예제 #6
0
    def test_JoinUsingExpression2(self):
        """ test joining a layer using a virtual field (the other way!) """
        joinLayer = QgsVectorLayer(
            "Point?field=x:string&field=y:integer&field=z:integer",
            "joinlayer", "memory")
        pr = joinLayer.dataProvider()
        f1 = QgsFeature()
        f1.setAttributes(["foo", 246, 321])
        f2 = QgsFeature()
        f2.setAttributes(["bar", 456, 654])
        self.assertTrue(pr.addFeatures([f1, f2]))
        joinLayer.addExpressionField('"y"/2', QgsField('exp1', QVariant.LongLong))

        layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer",
                               "addfeat", "memory")
        pr = layer.dataProvider()
        f = QgsFeature()
        f.setAttributes(["test", 123])
        self.assertTrue(pr.addFeatures([f]))

        QgsProject.instance().addMapLayers([layer, joinLayer])

        join = QgsVectorLayerJoinInfo()
        join.setTargetFieldName("fldint")
        join.setJoinLayer(joinLayer)
        join.setJoinFieldName("exp1")
        join.setUsingMemoryCache(True)
        layer.addJoin(join)

        f = QgsFeature()
        fi = layer.getFeatures()
        self.assertTrue(fi.nextFeature(f))
        attrs = f.attributes()
        self.assertEqual(attrs[0], "test")
        self.assertEqual(attrs[1], 123)
        self.assertEqual(attrs[2], "foo")
        self.assertEqual(attrs[3], 246)
        self.assertEqual(attrs[4], 321)
        self.assertFalse(fi.nextFeature(f))

        QgsProject.instance().removeMapLayers([layer.id(), joinLayer.id()])
예제 #7
0
    def add_joins(self, feedback):
        """ Add all joins between tables. """
        for definition in self.attribute_joins:
            definition = dict(definition)
            join_layer = definition['join_layer']
            layer_add_join = definition['layer_add_join']

            feedback.pushInfo('Ajout de la jointure {} sur {}'.format(
                join_layer, layer_add_join))

            definition['join_layer'] = self.input_layers[join_layer]

            definition['layer_add_join'] = self.input_layers[layer_add_join]

            for join in definition['layer_add_join'].vectorJoins():
                if definition['join_layer'] == join.joinLayer():
                    definition['layer_add_join'].removeJoin(
                        join.joinLayer().id())
                    feedback.pushDebugInfo(
                        'Removing pre-existing join between {} and {}'.format(
                            definition['layer_add_join'].name(),
                            definition['join_layer'].name()))

            join_habitat = QgsVectorLayerJoinInfo()
            join_habitat.setJoinFieldName(definition['join_field_name'])
            join_habitat.setJoinLayerId(definition['join_layer'].id())
            join_habitat.setTargetFieldName(definition['target_field_name'])
            join_habitat.setPrefix(definition['prefix'])
            join_habitat.setJoinLayer(definition['join_layer'])
            if 'block_list' in definition:
                if Qgis.QGIS_VERSION_INT >= 31400:
                    join_habitat.setJoinFieldNamesBlockList(
                        definition['block_list'])
                else:
                    join_habitat.setJoinFieldNamesBlackList(
                        definition['block_list'])
            if not definition['layer_add_join'].addJoin(join_habitat):
                raise Exception('Join not added {}'.format(
                    definition['join_field_name']))
            self.success_join += 1
예제 #8
0
    def test_JoinUsingFeatureRequestExpression(self):
        """ test requesting features using a filter expression which requires joined columns """
        joinLayer = QgsVectorLayer(
            "Point?field=x:string&field=y:integer&field=z:integer",
            "joinlayer", "memory")
        pr = joinLayer.dataProvider()
        f1 = QgsFeature()
        f1.setAttributes(["foo", 123, 321])
        f2 = QgsFeature()
        f2.setAttributes(["bar", 124, 654])
        self.assertTrue(pr.addFeatures([f1, f2]))

        layer = QgsVectorLayer(
            "Point?field=fldtxt:string&field=fldint:integer", "addfeat",
            "memory")
        pr = layer.dataProvider()
        f1 = QgsFeature()
        f1.setAttributes(["test", 123])
        f2 = QgsFeature()
        f2.setAttributes(["test", 124])
        self.assertTrue(pr.addFeatures([f1, f2]))

        QgsProject.instance().addMapLayers([layer, joinLayer])

        join = QgsVectorLayerJoinInfo()
        join.setTargetFieldName("fldint")
        join.setJoinLayer(joinLayer)
        join.setJoinFieldName("y")
        join.setUsingMemoryCache(True)
        layer.addJoin(join)

        f = QgsFeature()
        fi = layer.getFeatures(QgsFeatureRequest().setFlags(
            QgsFeatureRequest.SubsetOfAttributes).setFilterExpression(
                'joinlayer_z=654'))
        self.assertTrue(fi.nextFeature(f))
        self.assertEqual(f['fldint'], 124)
        self.assertEqual(f['joinlayer_z'], 654)

        QgsProject.instance().removeMapLayers([layer.id(), joinLayer.id()])
예제 #9
0
 def joinTables(self):
     d, f = self.lyrPair()
     for k, v in d.items():
         target = QgsProject.instance().mapLayer(k)
         layerToJoin = QgsProject.instance().mapLayer(v)
         fieldToJoin = QgsProject.instance()
         symb = QgsVectorLayerJoinInfo()
         symb.setJoinFieldName('id_feature')
         symb.setTargetFieldName('id')
         symb.setJoinLayerId(layerToJoin.id())
         symb.setUsingMemoryCache(True)
         symb.setEditable(True)
         symb.setDynamicFormEnabled(True)
         symb.setUpsertOnEdit(True)
         symb.setPrefix('')
         symb.setJoinFieldNamesSubset([
             'ocultar', 'legenda', 'tamanhotxt', 'justtxt', 'orient_txt',
             'orient_simb', 'offset_txt', 'offset_simb', 'prioridade',
             'offset_txt_x', 'offset_txt_y'
         ])
         symb.setJoinLayer(layerToJoin)
         target.addJoin(symb)
예제 #10
0
    def configureLayer(self, layer, context, feedback):
        # rename and style the output layer here
        layer.setName(self.layerName)
        layer.loadNamedStyle(
            os.path.join(os.path.dirname(__file__), 'styles', self.styleName))
        layer.triggerRepaint()

        # set up custom variable identifying the added layers
        layer.setCustomProperty(NOAA_LAYER_TYPE, self.layerType)

        # if both layers are available (meaning both post processors have run) then configure joins
        stationsLayer = currentStationsLayer()
        predictionsLayer = currentPredictionsLayer()
        if stationsLayer is not None and predictionsLayer is not None:
            joinInfo = QgsVectorLayerJoinInfo()
            joinInfo.setJoinLayer(stationsLayer)
            joinInfo.setTargetFieldName('station')
            joinInfo.setJoinFieldName('station')
            joinInfo.setJoinFieldNamesSubset(
                ['name', 'timeZoneId', 'timeZoneUTC', 'surface'])
            joinInfo.setPrefix('station_')
            predictionsLayer.addJoin(joinInfo)

            localTimeField = QgsField('local_time', QVariant.DateTime)
            predictionsLayer.addExpressionField(
                'convert_to_time_zone(time, station_timeZoneUTC, station_timeZoneId)',
                localTimeField)

            displayDateField = QgsField('display_date', QVariant.String)
            predictionsLayer.addExpressionField(
                "format_date(convert_to_time_zone(time, station_timeZoneUTC, station_timeZoneId), 'MM/dd')",
                displayDateField)

            displayTimeField = QgsField('display_time', QVariant.String)
            predictionsLayer.addExpressionField(
                "format_date(convert_to_time_zone(time, station_timeZoneUTC, station_timeZoneId), 'hh:mm a')",
                displayTimeField)

            predictionsLayer.updateFields()
예제 #11
0
 def joinTables(self):
     d, f = self.lyrPair()
     for k, v in d.items():
         target = QgsProject.instance().mapLayer(k)
         layerToJoin = QgsProject.instance().mapLayer(v)
         """  # tests for previous joined layers - under research
         i = QgsProject.instance().mapLayers().values()
         for layer in i:
             fh_lyr = layer
             joinsInfo = fh_lyr.vectorJoins()
             
             if joinsInfo != 0:
                 QMessageBox.critical(iface.mainWindow(), "Error",
                                     "Previously Joins already exists! Please remove joins and try again.")
                 break  # ask for remove previous joins. use removeJoinTables()
             else:
         """
         # target.removeJoin(layerToJoin.id())
         fieldToJoin = QgsProject.instance()
         symb = QgsVectorLayerJoinInfo()
         symb.setJoinFieldName('id_feature')
         symb.setTargetFieldName('id')
         symb.setJoinLayerId(layerToJoin.id())
         symb.setUsingMemoryCache(True)
         symb.setEditable(True)
         symb.setDynamicFormEnabled(True)
         symb.setUpsertOnEdit(True)
         symb.setPrefix('')
         symb.setJoinFieldNamesSubset([
             'ocultar', 'legenda', 'tamanhotxt', 'justtxt', 'orient_txt',
             'orient_simb', 'offset_txt', 'offset_simb', 'prioridade',
             'offset_txt_x', 'offset_txt_y'
         ])
         symb.setJoinLayer(layerToJoin)
         target.addJoin(symb)
         layerToJoin.startEditing()
         target.triggerRepaint()
예제 #12
0
    def test_JoinUsingFeatureRequestExpression(self):
        """ test requesting features using a filter expression which requires joined columns """
        joinLayer = QgsVectorLayer(
            "Point?field=x:string&field=y:integer&field=z:integer",
            "joinlayer", "memory")
        pr = joinLayer.dataProvider()
        f1 = QgsFeature()
        f1.setAttributes(["foo", 123, 321])
        f2 = QgsFeature()
        f2.setAttributes(["bar", 124, 654])
        self.assertTrue(pr.addFeatures([f1, f2]))

        layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer",
                               "addfeat", "memory")
        pr = layer.dataProvider()
        f1 = QgsFeature()
        f1.setAttributes(["test", 123])
        f2 = QgsFeature()
        f2.setAttributes(["test", 124])
        self.assertTrue(pr.addFeatures([f1, f2]))

        QgsProject.instance().addMapLayers([layer, joinLayer])

        join = QgsVectorLayerJoinInfo()
        join.setTargetFieldName("fldint")
        join.setJoinLayer(joinLayer)
        join.setJoinFieldName("y")
        join.setUsingMemoryCache(True)
        layer.addJoin(join)

        f = QgsFeature()
        fi = layer.getFeatures(QgsFeatureRequest().setFlags(QgsFeatureRequest.SubsetOfAttributes).setFilterExpression('joinlayer_z=654'))
        self.assertTrue(fi.nextFeature(f))
        self.assertEqual(f['fldint'], 124)
        self.assertEqual(f['joinlayer_z'], 654)

        QgsProject.instance().removeMapLayers([layer.id(), joinLayer.id()])
예제 #13
0
    def test_value_exists_joins(self):
        """Test that unique values in fields from joined layers, see GH #36167"""

        p = QgsProject()
        main_layer = QgsVectorLayer("Point?field=fid:integer", "main_layer",
                                    "memory")
        self.assertTrue(main_layer.isValid())
        # Attr layer is joined with layer on fk ->
        attr_layer = QgsVectorLayer("Point?field=id:integer&field=fk:integer",
                                    "attr_layer", "memory")
        self.assertTrue(attr_layer.isValid())

        p.addMapLayers([main_layer, attr_layer])
        join_info = QgsVectorLayerJoinInfo()
        join_info.setJoinLayer(attr_layer)
        join_info.setJoinFieldName('fk')
        join_info.setTargetFieldName('fid')
        join_info.setUsingMemoryCache(True)
        main_layer.addJoin(join_info)
        main_layer.updateFields()
        join_buffer = main_layer.joinBuffer()
        self.assertTrue(join_buffer.containsJoins())
        self.assertEqual(main_layer.fields().names(), ['fid', 'attr_layer_id'])

        f = QgsFeature(main_layer.fields())
        f.setAttributes([1])
        main_layer.dataProvider().addFeatures([f])

        f = QgsFeature(attr_layer.fields())
        f.setAttributes([1, 1])
        attr_layer.dataProvider().addFeatures([f])

        self.assertTrue(QgsVectorLayerUtils.valueExists(main_layer, 0, 1))
        self.assertTrue(QgsVectorLayerUtils.valueExists(main_layer, 1, 1))
        self.assertFalse(QgsVectorLayerUtils.valueExists(main_layer, 0, 2))
        self.assertFalse(QgsVectorLayerUtils.valueExists(main_layer, 1, 2))
예제 #14
0
    def processAlgorithm(self, parameters, context, feedback):
        self.layers = self.parameterAsLayerList(parameters, self.INPUTS,
                                                context)
        self.drop = self.parameterAsBool(parameters, self.DROP_EXISTING_JOINS,
                                         context)
        # return {}

        # def postProcess(self, context, feedback):
        #     # We try to use postProcess instead of processAlgorithm to propagate joins in the project.
        #     layers = self.layers
        #     drop = self.drop

        total = len(self.layers)
        failed = []
        feedback.pushDebugInfo('{} layer(s) have been selected.'.format(total))

        for i, layer in enumerate(self.layers):
            # Just trying on more time to get the real layer
            layer = context.project().mapLayer(layer.id())
            if not layer:
                feedback.reportError(
                    'Layer {} has not been found in the project. Skipping…'.
                    format(layer.name()))
                continue

            feedback.pushInfo('Processing layer \'{}\' with ID {}'.format(
                layer.name(), layer.id()))

            joined_fields = []

            if self.drop:
                for vector_join in layer.vectorJoins():
                    feedback.pushInfo('Removing join \'{}\''.format(
                        vector_join.joinFieldName()))
                    layer.removeJoin(vector_join.joinLayerId())

            for field in layer.fields():
                widget = field.editorWidgetSetup()

                if not widget.type() == 'ValueRelation':
                    continue

                config = widget.config()
                target_layer = config['Layer']
                target_field = config['Key']

                source_field = field.name()

                join_layer = context.project().mapLayer(target_layer)
                if not join_layer:
                    feedback.reportError(
                        "The layer \"{}\" linked to the field \"{}\" has not been found in the project. "
                        "Skipping this ValueRelation…".format(
                            target_layer, source_field))
                    continue

                join = QgsVectorLayerJoinInfo()
                join.setJoinLayerId(target_layer)
                join.setJoinFieldName(target_field)
                join.setTargetFieldName(source_field)
                join.setUsingMemoryCache(True)

                feedback.pushInfo(
                    'Adding join on \'{}\' with prefix \'{}\''.format(
                        field.name(), self.prefix.format(join_layer.name())))
                join.setPrefix(self.prefix.format(join_layer.name()))
                if not layer.addJoin(join):
                    failed.append(layer.name())
                    feedback.reportError(
                        'Failed to add the join on {} {}'.format(
                            layer.name(), field.name()))
                    continue

                for join_field in join_layer.fields():
                    joined_fields.append(
                        self.prefix.format(join_layer.name()) +
                        join_field.name())

            # Uncheck WMS
            feedback.pushInfo('Unchecking WMS fields')
            # if Qgis.QGIS_VERSION_INT < 31800:
            layer.setExcludeAttributesWms(joined_fields)
            # else:
            #     # Fix for QGIS >= 3.16
            #     for field in joined_fields:
            #         layer.setFieldConfigurationFlag(
            #             layer.fields().indexFromName(field), QgsField.HideFromWms, True)
            feedback.pushDebugInfo(', '.join(layer.excludeAttributesWms()))

            # Uncheck WFS for ids
            id_fields = [
                f for f in joined_fields
                if f.endswith('_fid') or f.endswith('_id')
            ]
            feedback.pushInfo('Unchecking WFS fields')
            # if Qgis.QGIS_VERSION_INT < 31800:
            layer.setExcludeAttributesWfs(id_fields)
            # else:
            #     # Fix for QGIS >= 3.16
            #     for field in id_fields:
            #         layer.setFieldConfigurationFlag(
            #             layer.fields().indexFromName(field), QgsField.HideFromWfs, True)
            feedback.pushDebugInfo(', '.join(layer.excludeAttributesWfs()))

            feedback.setProgress((i + 1) / total * 100)
            # layer.reload() It does nothing, not enough to propagate the join

        if failed:
            msg = 'Some joins failed to be added for : {}'.format(
                ', '.join(failed))
            raise QgsProcessingException(msg)

        feedback.reportError(
            'Everything went fine, BUT you must save your project and reopen it. Joins, WMS and WFS are '
            'not appearing otherwise.')

        return {}
예제 #15
0
    def test_joined_layers_conversion(self):
        v1 = QgsVectorLayer(
            "Point?field=id:integer&field=b_id:integer&field=c_id:integer&field=name:string",
            "A", "memory")
        self.assertEqual(v1.isValid(), True)
        v2 = QgsVectorLayer(
            "Point?field=id:integer&field=bname:string&field=bfield:integer",
            "B", "memory")
        self.assertEqual(v2.isValid(), True)
        v3 = QgsVectorLayer("Point?field=id:integer&field=cname:string", "C",
                            "memory")
        self.assertEqual(v3.isValid(), True)
        QgsProject.instance().addMapLayers([v1, v2, v3])
        joinInfo = QgsVectorLayerJoinInfo()
        joinInfo.setTargetFieldName("b_id")
        joinInfo.setJoinLayer(v2)
        joinInfo.setJoinFieldName("id")
        #joinInfo.setPrefix("B_")
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 6)

        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(
            df.query(),
            'SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS B_bname, j1.bfield AS B_bfield FROM {} AS t LEFT JOIN {} AS j1 ON t."b_id"=j1."id"'
            .format(v1.id(), v2.id()))

        # with a field subset
        v1.removeJoin(v2.id())
        joinInfo.setJoinFieldNamesSubset(["bname"])
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 5)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(
            df.query(),
            'SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS B_bname FROM {} AS t LEFT JOIN {} AS j1 ON t."b_id"=j1."id"'
            .format(v1.id(), v2.id()))
        joinInfo.setJoinFieldNamesSubset(None)

        # add a table prefix to the join
        v1.removeJoin(v2.id())
        joinInfo.setPrefix("BB_")
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 6)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(
            df.query(),
            'SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS BB_bname, j1.bfield AS BB_bfield FROM {} AS t LEFT JOIN {} AS j1 ON t."b_id"=j1."id"'
            .format(v1.id(), v2.id()))
        joinInfo.setPrefix("")
        v1.removeJoin(v2.id())
        v1.addJoin(joinInfo)

        # add another join
        joinInfo2 = QgsVectorLayerJoinInfo()
        joinInfo2.setTargetFieldName("c_id")
        joinInfo2.setJoinLayer(v3)
        joinInfo2.setJoinFieldName("id")
        v1.addJoin(joinInfo2)
        self.assertEqual(len(v1.fields()), 7)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(df.query(), (
            'SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS B_bname, j1.bfield AS B_bfield, j2.cname AS C_cname FROM {} AS t '
            + 'LEFT JOIN {} AS j1 ON t."b_id"=j1."id" ' +
            'LEFT JOIN {} AS j2 ON t."c_id"=j2."id"').format(
                v1.id(), v2.id(), v3.id()))

        QgsProject.instance().removeMapLayers([v1.id(), v2.id(), v3.id()])
    def processAlgorithm(self, parameters, context, feedback):

        t_file = self.parameterAsVectorLayer(
            parameters,
            self.FILE_TABLE,
            context
        )
        t_troncon = self.parameterAsVectorLayer(
            parameters,
            self.SEGMENTS_TABLE,
            context
        )
        t_obs = self.parameterAsVectorLayer(
            parameters,
            self.OBSERVATIONS_TABLE,
            context
        )
        t_regard = self.parameterAsVectorLayer(
            parameters,
            self.MANHOLES_TABLE,
            context
        )

        g_regard = self.parameterAsVectorLayer(
            parameters,
            self.GEOM_MANHOLES,
            context
        )
        g_troncon = self.parameterAsVectorLayer(
            parameters,
            self.GEOM_SEGMENT,
            context
        )
        g_obs = self.parameterAsVectorLayer(
            parameters,
            self.GEOM_OBSERVATION,
            context
        )

        v_regard = self.parameterAsVectorLayer(
            parameters,
            self.VIEW_MANHOLES_GEOLOCALIZED,
            context
        )

        # define variables
        variables = context.project().customVariables()
        variables['itv_rerau_t_file'] = t_file.id()
        variables['itv_rerau_t_troncon'] = t_troncon.id()
        variables['itv_rerau_t_obs'] = t_obs.id()
        variables['itv_rerau_t_regard'] = t_regard.id()

        variables['itv_rerau_g_regard'] = g_regard.id()
        variables['itv_rerau_g_troncon'] = g_troncon.id()
        variables['itv_rerau_g_obs'] = g_obs.id()

        context.project().setCustomVariables(variables)

        # define relations
        relations = [
            {
                'id': 'fk_obs_id_file',
                'name': tr('Link File - Observation'),
                'referencingLayer': t_obs.id(),
                'referencingField': 'id_file',
                'referencedLayer': t_file.id(),
                'referencedField': 'id'
            }, {
                'id': 'fk_regard_id_file',
                'name': tr('Link File - Manhole'),
                'referencingLayer': t_regard.id(),
                'referencingField': 'id_file',
                'referencedLayer': t_file.id(),
                'referencedField': 'id'
            }, {
                'id': 'fk_troncon_id_file',
                'name': tr('Link File - Pipe segment'),
                'referencingLayer': t_troncon.id(),
                'referencingField': 'id_file',
                'referencedLayer': t_file.id(),
                'referencedField': 'id'
            }, {
                'id': 'fk_obs_id_troncon',
                'name': tr('Link Pipe segment - Observation'),
                'referencingLayer': t_obs.id(),
                'referencingField': 'id_troncon',
                'referencedLayer': t_troncon.id(),
                'referencedField': 'id'
            }, {
                'id': 'fk_regard_id_geom_regard',
                'name': tr('Link Manhole inspection - Reference'),
                'referencingLayer': t_regard.id(),
                'referencingField': 'id_geom_regard',
                'referencedLayer': g_regard.id(),
                'referencedField': 'id'
            }, {
                'id': 'fk_troncon_id_geom_trononc',
                'name': tr('Link Pipe segment inspection - Reference'),
                'referencingLayer': t_troncon.id(),
                'referencingField': 'id_geom_troncon',
                'referencedLayer': g_troncon.id(),
                'referencedField': 'id'
            }
        ]

        relation_manager = context.project().relationManager()
        for rel_def in relations:
            feedback.pushInfo(
                'Link: {}'.format(rel_def['name'])
            )
            rel = QgsRelation()
            rel.setId(rel_def['id'])
            rel.setName(rel_def['name'])
            rel.setReferencingLayer(rel_def['referencingLayer'])
            rel.setReferencedLayer(rel_def['referencedLayer'])
            rel.addFieldPair(
                rel_def['referencingField'],
                rel_def['referencedField']
            )
            rel.setStrength(QgsRelation.Association)
            relation_manager.addRelation(rel)
            feedback.pushInfo(
                'Count relations {}'.format(
                    len(relation_manager.relations())
                )
            )

        joins = [
            {
                'layer': t_obs,
                'targetField': 'id_troncon',
                'joinLayer': t_troncon,
                'joinField': 'id',
                'fieldNamesSubset': ['ack']
            }, {
                'layer': g_obs,
                'targetField': 'id',
                'joinLayer': t_obs,
                'joinField': 'id',
                'fieldNamesSubset': []
            }
        ]
        for j_def in joins:
            layer = j_def['layer']

            join = QgsVectorLayerJoinInfo()
            join.setJoinFieldName(j_def['joinField'])
            join.setJoinLayerId(j_def['joinLayer'].id())
            join.setTargetFieldName(j_def['targetField'])

            if j_def['fieldNamesSubset']:
                join.setJoinFieldNamesSubset(j_def['fieldNamesSubset'])

            join.setUsingMemoryCache(False)
            join.setPrefix('')
            join.setEditable(False)
            join.setCascadedDelete(False)

            join.setJoinLayer(j_def['joinLayer'])

            layer.addJoin(join)
            layer.updateFields()

        # load styles
        styles = [
            {
                'layer': t_file,
                'namedStyles': [
                    {
                        'file': 'itv_file_fields.qml',
                        'type': QgsMapLayer.Fields
                    }, {
                        'file': 'itv_file_actions.qml',
                        'type': QgsMapLayer.Actions
                    }
                ]
            }, {
                'layer': t_troncon,
                'namedStyles': [
                    {
                        'file': 'itv_troncon_fields.qml',
                        'type': QgsMapLayer.Fields
                    }, {
                        'file': 'itv_troncon_table.qml',
                        'type': QgsMapLayer.AttributeTable
                    }
                ]
            }, {
                'layer': t_obs,
                'namedStyles': [
                    {
                        'file': 'itv_obs_fields.qml',
                        'type': QgsMapLayer.Fields
                    }, {
                        'file': 'itv_obs_table.qml',
                        'type': QgsMapLayer.AttributeTable
                    }
                ]
            }, {
                'layer': t_regard,
                'namedStyles': [
                    {
                        'file': 'itv_regard_fields.qml',
                        'type': QgsMapLayer.Fields
                    }, {
                        'file': 'itv_regard_forms.qml',
                        'type': QgsMapLayer.Forms
                    }, {
                        'file': 'itv_regard_table.qml',
                        'type': QgsMapLayer.AttributeTable
                    }
                ]
            }, {
                'layer': g_regard,
                'namedStyles': [
                    {
                        'file': 'itv_geom_regard_fields.qml',
                        'type': QgsMapLayer.Fields
                    }, {
                        'file': 'itv_geom_regard_symbology.qml',
                        'type': QgsMapLayer.Symbology
                    }
                ]
            }, {
                'layer': g_troncon,
                'namedStyles': [
                    {
                        'file': 'itv_geom_troncon_fields.qml',
                        'type': QgsMapLayer.Fields
                    }, {
                        'file': 'itv_geom_troncon_symbology.qml',
                        'type': QgsMapLayer.Symbology
                    }, {
                        'file': 'itv_geom_troncon_actions.qml',
                        'type': QgsMapLayer.Actions
                    }
                ]
            }, {
                'layer': g_obs,
                'namedStyles': [
                    {
                        'file': 'itv_geom_obs_fields.qml',
                        'type': QgsMapLayer.Fields
                    }, {
                        'file': 'itv_geom_obs_symbology.qml',
                        'type': QgsMapLayer.Symbology
                    }
                ]
            }, {
                'layer': v_regard,
                'namedStyles': [
                    {
                        'file': 'itv_view_regard_fields.qml',
                        'type': QgsMapLayer.Fields
                    }, {
                        'file': 'itv_view_regard_symbology.qml',
                        'type': QgsMapLayer.Symbology
                    }, {
                        'file': 'itv_view_regard_labeling.qml',
                        'type': QgsMapLayer.Labeling
                    }
                ]
            }
        ]
        for style in styles:
            layer = style['layer']
            for n_style in style['namedStyles']:
                layer.loadNamedStyle(
                    resources_path('styles', n_style['file']),
                    categories=n_style['type']
                )
                # layer.saveStyleToDatabase('style', 'default style', True, '')
                layer.triggerRepaint()

        # Creation de la symbologie g_obs
        g_obs_rules = (
            'BAA', 'BAB', 'BAC', 'BAD', 'BAE', 'BAF', 'BAG', 'BAH',
            'BAI', 'BAJ', 'BAK', 'BAL', 'BAM', 'BAN', 'BAO', 'BAP',
            'BBA', 'BBB', 'BBC', 'BBD', 'BBE', 'BBF', 'BBG', 'BBH',
            'BCA', 'BCB', 'BCC', 'BDA', 'BDB', 'BDC', 'BDD', 'BDE',
            'BDF', 'BDG'
        )
        g_obs_rule_descs = {
            'BAA': 'Déformation',
            'BAB': 'Fissure',
            'BAC': 'Rupture/Effondrement',
            'BAD': 'Elt maçonnerie',
            'BAE': 'Mortier manquant',
            'BAF': 'Dégradation de surface',
            'BAG': 'Branchement pénétrant',
            'BAH': 'Raccordement défectueux',
            'BAI': 'Joint étanchéité apparent',
            'BAJ': 'Déplacement d\'assemblage',
            'BAK': 'Défaut de révêtement',
            'BAL': 'Réparation défectueuse',
            'BAM': 'Défaut soudure',
            'BAN': 'Conduite poreuse',
            'BAO': 'Sol visible',
            'BAP': 'Trou visible',
            'BBA': 'Racines',
            'BBB': 'Dépots Adhérents',
            'BBC': 'Dépôts',
            'BBD': 'Entrée de terre',
            'BBE': 'Autres obstacles',
            'BBF': 'Infiltration',
            'BBG': 'Exfiltration',
            'BBH': 'Vermine',
            'BCA': 'Raccordement',
            'BCB': 'Réparation',
            'BCC': 'Courbure de collecteur',
            'BDA': 'Photographie générale',
            'BDB': 'Remarque générale',
            'BDC': 'Inspection abandonnée',
            'BDD': 'Niveau d\'eau',
            'BDE': 'Ecoulement dans une canlisation entrante',
            'BDF': 'Atmosphère canalisation',
            'BDG': 'Perte de visibilité'
        }
        g_obs_rootrule = QgsRuleBasedRenderer.Rule(None)
        rendering_pass_idx = len(g_obs_rules)
        for rule in g_obs_rules:
            # get svg path
            svg_path = resources_path('styles', 'img_obs', rule + '.svg')
            # create svg symbol layer
            svg_symbol_layer = QgsSvgMarkerSymbolLayer(svg_path)
            svg_symbol_layer.setRenderingPass(rendering_pass_idx)
            # create white square symbol layer for the backend
            simple_symbol_layer = QgsSimpleMarkerSymbolLayer(
                shape=QgsSimpleMarkerSymbolLayerBase.Circle,
                size=svg_symbol_layer.size(),
                color=QColor('white'),
                strokeColor=QColor('white')
            )
            simple_symbol_layer.setRenderingPass(rendering_pass_idx)
            # create marker
            svg_marker = QgsMarkerSymbol()
            # set the backend symbol layer
            svg_marker.changeSymbolLayer(0, simple_symbol_layer)
            # add svg symbol layer
            svg_marker.appendSymbolLayer(svg_symbol_layer)
            # create rule
            svg_rule = QgsRuleBasedRenderer.Rule(
                svg_marker, 0, 10000,
                QgsExpression.createFieldEqualityExpression('a', rule),
                rule
            )
            if rule in g_obs_rule_descs:
                svg_rule.setLabel(g_obs_rule_descs[rule])
                svg_rule.setDescription('{}: {}'.format(
                    rule,
                    g_obs_rule_descs[rule]
                ))
            # add rule
            g_obs_rootrule.appendChild(svg_rule)
            rendering_pass_idx -= 1
        g_obs_rootrule.appendChild(
            QgsRuleBasedRenderer.Rule(
                QgsMarkerSymbol.createSimple(
                    {
                        'name': 'circle',
                        'color': '#0000b2',
                        'outline_color': '#0000b2',
                        'size': '1'
                    }
                ),
                0, 10000, 'ELSE', 'Autres'
            )
        )
        g_obs.setRenderer(QgsRuleBasedRenderer(g_obs_rootrule))
        feedback.pushInfo('Project has been setup')
        return {}
예제 #17
0
    def test_joined_layers_conversion(self):
        v1 = QgsVectorLayer(
            "Point?field=id:integer&field=b_id:integer&field=c_id:integer&field=name:string",
            "A", "memory")
        self.assertEqual(v1.isValid(), True)
        v2 = QgsVectorLayer(
            "Point?field=id:integer&field=bname:string&field=bfield:integer",
            "B", "memory")
        self.assertEqual(v2.isValid(), True)
        v3 = QgsVectorLayer("Point?field=id:integer&field=cname:string", "C",
                            "memory")
        self.assertEqual(v3.isValid(), True)
        tl1 = QgsVectorLayer(
            "NoGeometry?field=id:integer&field=e_id:integer&field=0name:string",
            "D", "memory")
        self.assertEqual(tl1.isValid(), True)
        tl2 = QgsVectorLayer("NoGeometry?field=id:integer&field=ena me:string",
                             "E", "memory")
        self.assertEqual(tl2.isValid(), True)
        QgsProject.instance().addMapLayers([v1, v2, v3, tl1, tl2])
        joinInfo = QgsVectorLayerJoinInfo()
        joinInfo.setTargetFieldName("b_id")
        joinInfo.setJoinLayer(v2)
        joinInfo.setJoinFieldName("id")
        #joinInfo.setPrefix("B_")
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 6)

        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(
            df.query(),
            'SELECT t.geometry, t.rowid AS uid, t."id", t."b_id", t."c_id", t."name", j1."bname" AS "B_bname", j1."bfield" AS "B_bfield" FROM "{}" AS t LEFT JOIN "{}" AS j1 ON t."b_id"=j1."id"'
            .format(v1.id(), v2.id()))

        # with a field subset
        v1.removeJoin(v2.id())
        joinInfo.setJoinFieldNamesSubset(["bname"])
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 5)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(
            df.query(),
            'SELECT t.geometry, t.rowid AS uid, t."id", t."b_id", t."c_id", t."name", j1."bname" AS "B_bname" FROM "{}" AS t LEFT JOIN "{}" AS j1 ON t."b_id"=j1."id"'
            .format(v1.id(), v2.id()))
        joinInfo.setJoinFieldNamesSubset(None)

        # add a table prefix to the join
        v1.removeJoin(v2.id())
        joinInfo.setPrefix("BB_")
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 6)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(
            df.query(),
            'SELECT t.geometry, t.rowid AS uid, t."id", t."b_id", t."c_id", t."name", j1."bname" AS "BB_bname", j1."bfield" AS "BB_bfield" FROM "{}" AS t LEFT JOIN "{}" AS j1 ON t."b_id"=j1."id"'
            .format(v1.id(), v2.id()))
        joinInfo.setPrefix("")
        v1.removeJoin(v2.id())
        v1.addJoin(joinInfo)

        # add another join
        joinInfo2 = QgsVectorLayerJoinInfo()
        joinInfo2.setTargetFieldName("c_id")
        joinInfo2.setJoinLayer(v3)
        joinInfo2.setJoinFieldName("id")
        v1.addJoin(joinInfo2)
        self.assertEqual(len(v1.fields()), 7)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(df.query(), (
            'SELECT t.geometry, t.rowid AS uid, t."id", t."b_id", t."c_id", t."name", j1."bname" AS "B_bname", j1."bfield" AS "B_bfield", j2."cname" AS "C_cname" FROM "{}" AS t '
            + 'LEFT JOIN "{}" AS j1 ON t."b_id"=j1."id" ' +
            'LEFT JOIN "{}" AS j2 ON t."c_id"=j2."id"').format(
                v1.id(), v2.id(), v3.id()))

        # test NoGeometry joined layers with field names starting with a digit or containing white spaces
        joinInfo3 = QgsVectorLayerJoinInfo()
        joinInfo3.setTargetFieldName("e_id")
        joinInfo3.setJoinLayer(tl2)
        joinInfo3.setJoinFieldName("id")
        tl1.addJoin(joinInfo3)
        self.assertEqual(len(tl1.fields()), 4)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(tl1)
        self.assertEqual(
            df.query(),
            'SELECT t.rowid AS uid, t."id", t."e_id", t."0name", j1."ena me" AS "E_ena me" FROM "{}" AS t LEFT JOIN "{}" AS j1 ON t."e_id"=j1."id"'
            .format(tl1.id(), tl2.id()))

        QgsProject.instance().removeMapLayers(
            [v1.id(), v2.id(), v3.id(),
             tl1.id(), tl2.id()])
예제 #18
0
    def add_joined_layer(
            source_layer: Union[FeatureLayer, StandaloneTable],  # pylint: disable=too-many-branches
            input_file,
            base_layer: QgsVectorLayer,
            context: Context):
        """
        Adds joined layers
        """
        if not source_layer.join:
            return None

        if isinstance(source_layer.join, MemoryRelationshipClassName):
            if isinstance(source_layer.join.origin_name, RelQueryTableName):
                if context.unsupported_object_callback:
                    context.unsupported_object_callback(
                        '{}: Nested joins are not supported in QGIS'.format(
                            context.layer_name),
                        level=Context.CRITICAL)

                return None

            join_info = QgsVectorLayerJoinInfo()

            join_info.setJoinFieldName(source_layer.join.origin_primary_key)
            join_info.setTargetFieldName(source_layer.join.origin_foreign_key)

            base, _ = os.path.split(input_file)

            source_layer_props = DatasetNameConverter.convert(
                name=source_layer.join.destination_name,
                base=base,
                crs=QgsCoordinateReferenceSystem(),
                context=context)
            context.layer_type_hint = source_layer_props.wkb_type

            name = 'join'
            if hasattr(source_layer.join.destination_name, 'name'):
                name = source_layer.join.destination_name.name
                join_info.setPrefix(name + '.')

            if Qgis.QGIS_VERSION_INT >= 30800:
                opts = QgsVectorLayer.LayerOptions()
                if source_layer_props.wkb_type is not None:
                    opts.fallbackWkbType = source_layer_props.wkb_type

                vl = QgsVectorLayer(source_layer_props.uri, name,
                                    source_layer_props.provider, opts)
            else:
                vl = QgsVectorLayer(source_layer_props.uri, name,
                                    source_layer_props.provider)
            if not vl.isValid() and Qgis.QGIS_VERSION_INT < 30600:
                if source_layer_props.provider == 'ogr' and not os.path.exists(
                        source_layer_props.file_name
                ) and context.invalid_layer_resolver:
                    res = context.invalid_layer_resolver(
                        source_layer.join.name, source_layer_props.uri,
                        source_layer_props.wkb_type)
                    source_layer_props.uri = res.uri
                    source_layer_props.provider = res.providerKey

                vl = QgsVectorLayer(source_layer_props.uri, 'join',
                                    source_layer_props.provider)

            # todo layer name
            vl.setRenderer(QgsNullSymbolRenderer())

            try:
                vl.setFlags(vl.flags() | QgsMapLayer.Private)
            except AttributeError:
                pass

            join_info.setJoinLayer(vl)
            base_layer.addJoin(join_info)

            return vl

        else:
            if context.unsupported_object_callback:
                context.unsupported_object_callback(
                    '{}: Join layers of type {} are not yet supported'.format(
                        context.layer_name,
                        source_layer.join.__class__.__name__),
                    level=Context.CRITICAL)

            return None
예제 #19
0
    def run(self):
        project_id = self.settings.value("project/id")
        epsg = self.settings.value("project/epsg")

        locale = QSettings().value('locale/userLocale')[
            0:2]  # this is for multilingual legends

        # If locale is different to frence or italian, german will be used.
        # Otherwise we get into troubles with the legends, e.g. locale = "en"
        # but
        # there is no english legend (qml file).
        if locale == "fr":
            pass
        elif locale == "it":
            pass
        else:
            locale = "de"

        if not project_id:
            self.message_bar.pushCritical(
                "Error",
                _translate("VeriSO_V+D_FP2", "project_id not set", None))
            return

        QApplication.setOverrideCursor(Qt.WaitCursor)
        try:
            group = _translate("VeriSO_V+D_FP2", "FixpunkteKategorie2", None)
            group += " (" + str(project_id) + ")"

            # Lagefixpunkte 2

            layer = {
                "type": "postgres",
                "title": _translate("VeriSO_V+D_FP2", "LFP2 Nachführung",
                                    None),
                "featuretype": "fixpunktekategorie2_lfp2nachfuehrung",
                "geom": "perimeter",
                "key": "ogc_fid",
                "sql": "",
                "readonly": True,
                "group": group
            }

            # Visibility and if legend and/or groupd should be collapsed can
            # be set with parameters in the self.layer_loader.load()
            # method:
            # load(layer, visibility=True, collapsed_legend=False,
            # collapsed_group=False)
            vlayer_lfp2_nf = self.layer_loader.load(layer, False, True)

            layer = {
                "type": "postgres",
                "title": _translate("VeriSO_V+D_FP2", "LFP2", None),
                "featuretype": "fixpunktekategorie2_lfp2",
                "geom": "geometrie",
                "key": "ogc_fid",
                "sql": "",
                "readonly": True,
                "group": group,
                "style": "fixpunkte/lfp2.qml"
            }

            vlayer_lfp2 = self.layer_loader.load(layer)

            # Join two layers (lfp2 and lfp2nachfuehrung)
            lfp2_field = "entstehung"
            lfp2_nf_field = "ogc_fid"
            join_obj = QgsVectorLayerJoinInfo()
            join_obj.setJoinLayerId(vlayer_lfp2_nf.id())
            join_obj.setJoinFieldName(lfp2_nf_field)
            join_obj.setTargetFieldName(lfp2_field)
            join_obj.setUsingMemoryCache(True)
            join_obj.setPrefix("lfp2_nf_")
            vlayer_lfp2.addJoin(join_obj)

            # This is how WMS layer work.
            layer = {
                "type": "wms",
                "title": _translate("VeriSO_V+D_FP2", "LFP2 Schweiz (WMS)",
                                    None),
                "url": "http://wms.geo.admin.ch/",
                "layers": "ch.swisstopo.fixpunkte-lfp2",
                "format": "image/png",
                "crs": "EPSG:" + str(epsg),
                "group": group
            }

            vlayer = self.layer_loader.load(layer, False, True)

            # Höhenfixpunkte 2
            layer = {
                "type": "postgres",
                "title": _translate("VeriSO_V+D_FP2", "HFP2 Nachführung",
                                    None),
                "featuretype": "fixpunktekategorie2_hfp2nachfuehrung",
                "geom": "perimeter",
                "key": "ogc_fid",
                "sql": "",
                "readonly": True,
                "group": group
            }

            vlayer_hfp2_nf = self.layer_loader.load(layer, False, True)

            layer = {
                "type": "postgres",
                "title": _translate("VeriSO_V+D_FP2", "HFP2", None),
                "featuretype": "fixpunktekategorie2_hfp2",
                "geom": "geometrie",
                "key": "ogc_fid",
                "sql": "",
                "readonly": True,
                "group": group,
                "style": "fixpunkte/hfp2.qml"
            }

            vlayer_hfp2 = self.layer_loader.load(layer)

            # Join two layers (hfp2 and hfp2nachfuehrung)
            hfp2_field = "entstehung"
            hfp2_nf_field = "ogc_fid"
            join_obj = QgsVectorLayerJoinInfo()
            join_obj.setJoinLayerId(vlayer_hfp2_nf.id())
            join_obj.setJoinFieldName(hfp2_nf_field)
            join_obj.setTargetFieldName(hfp2_field)
            join_obj.setUsingMemoryCache(True)
            join_obj.setPrefix("hfp2_nf_")
            vlayer_hfp2.addJoin(join_obj)

            layer = {
                "type": "wms",
                "title": _translate("VeriSO_V+D_FP2", "HFP2 Schweiz (WMS)",
                                    None),
                "url": "http://wms.geo.admin.ch/",
                "layers": "ch.swisstopo.fixpunkte-hfp2",
                "format": "image/png",
                "crs": "EPSG:" + str(epsg),
                "group": group
            }

            vlayer = self.layer_loader.load(layer, False, True)

            # Business as usual: Gemeindegrenzen
            layer = {
                "type": "postgres",
                "title": _translate("VeriSO_V+D_FP2", "Gemeindegrenze", None),
                "featuretype": "gemeindegrenzen_gemeindegrenze",
                "geom": "geometrie",
                "key": "ogc_fid",
                "sql": "",
                "readonly": True,
                "group": group,
                "style": "global_qml/gemeindegrenze/gemgre_strichliert.qml"
            }

            gemgrelayer = self.layer_loader.load(layer)

            # Change map extent.
            # Bug (?) in QGIS: http://hub.qgis.org/issues/10980
            # Closed for the lack of feedback. Upsi...
            # Still a problem? (sz / 2015-04-12)
            if gemgrelayer:
                rect = gemgrelayer.extent()
                rect.scale(5)
                self.iface.mapCanvas().setExtent(rect)
                self.iface.mapCanvas().refresh()
                # Sometimes it does make much more sense
                # to zoom to maximal extent:
                # self.iface.mapCanvas().zoomToFullExtent()

        except Exception:
            QApplication.restoreOverrideCursor()
            exc_type, exc_value, exc_traceback = sys.exc_info()
            self.message_bar.pushMessage(
                "Error",
                str(traceback.format_exc(exc_traceback)),
                level=Qgis.Critical,
                duration=0)
        QApplication.restoreOverrideCursor()
예제 #20
0
    def testJoinedFieldIsEditableRole(self):
        layer = QgsVectorLayer("Point?field=id_a:integer", "addfeat", "memory")
        layer2 = QgsVectorLayer("Point?field=id_b:integer&field=value_b",
                                "addfeat", "memory")
        QgsProject.instance().addMapLayers([layer, layer2])

        # editable join
        join_info = QgsVectorLayerJoinInfo()
        join_info.setTargetFieldName("id_a")
        join_info.setJoinLayer(layer2)
        join_info.setJoinFieldName("id_b")
        join_info.setPrefix("B_")
        join_info.setEditable(True)
        join_info.setUpsertOnEdit(True)
        layer.addJoin(join_info)

        m = QgsFieldModel()
        m.setLayer(layer)

        self.assertIsNone(
            m.data(m.indexFromName('id_a'),
                   QgsFieldModel.JoinedFieldIsEditable))
        self.assertTrue(
            m.data(m.indexFromName('B_value_b'),
                   QgsFieldModel.JoinedFieldIsEditable))
        self.assertIsNone(
            m.data(m.indexFromName('an expression'),
                   QgsFieldModel.JoinedFieldIsEditable))
        self.assertIsNone(
            m.data(m.indexFromName(None), QgsFieldModel.JoinedFieldIsEditable))
        m.setAllowExpression(True)
        m.setExpression('an expression')
        self.assertIsNone(
            m.data(m.indexFromName('an expression'),
                   QgsFieldModel.JoinedFieldIsEditable))
        m.setAllowEmptyFieldName(True)
        self.assertIsNone(
            m.data(m.indexFromName(None), QgsFieldModel.JoinedFieldIsEditable))

        proxy_m = QgsFieldProxyModel()
        proxy_m.setFilters(QgsFieldProxyModel.AllTypes
                           | QgsFieldProxyModel.HideReadOnly)
        proxy_m.sourceFieldModel().setLayer(layer)
        self.assertEqual(proxy_m.rowCount(), 2)
        self.assertEqual(proxy_m.data(proxy_m.index(0, 0)), 'id_a')
        self.assertEqual(proxy_m.data(proxy_m.index(1, 0)), 'B_value_b')

        # not editable join
        layer3 = QgsVectorLayer("Point?field=id_a:integer", "addfeat",
                                "memory")
        QgsProject.instance().addMapLayers([layer3])
        join_info = QgsVectorLayerJoinInfo()
        join_info.setTargetFieldName("id_a")
        join_info.setJoinLayer(layer2)
        join_info.setJoinFieldName("id_b")
        join_info.setPrefix("B_")
        join_info.setEditable(False)

        layer3.addJoin(join_info)
        m = QgsFieldModel()
        m.setLayer(layer3)

        self.assertIsNone(
            m.data(m.indexFromName('id_a'),
                   QgsFieldModel.JoinedFieldIsEditable))
        self.assertFalse(
            m.data(m.indexFromName('B_value_b'),
                   QgsFieldModel.JoinedFieldIsEditable))
        self.assertIsNone(
            m.data(m.indexFromName('an expression'),
                   QgsFieldModel.JoinedFieldIsEditable))
        self.assertIsNone(
            m.data(m.indexFromName(None), QgsFieldModel.JoinedFieldIsEditable))
        m.setAllowExpression(True)
        m.setExpression('an expression')
        self.assertIsNone(
            m.data(m.indexFromName('an expression'),
                   QgsFieldModel.JoinedFieldIsEditable))
        m.setAllowEmptyFieldName(True)
        self.assertIsNone(
            m.data(m.indexFromName(None), QgsFieldModel.JoinedFieldIsEditable))

        proxy_m = QgsFieldProxyModel()
        proxy_m.sourceFieldModel().setLayer(layer3)
        proxy_m.setFilters(QgsFieldProxyModel.AllTypes
                           | QgsFieldProxyModel.HideReadOnly)
        self.assertEqual(proxy_m.rowCount(), 1)
        self.assertEqual(proxy_m.data(proxy_m.index(0, 0)), 'id_a')
예제 #21
0
    def test_joined_layers_conversion(self):
        v1 = QgsVectorLayer("Point?field=id:integer&field=b_id:integer&field=c_id:integer&field=name:string", "A", "memory")
        self.assertEqual(v1.isValid(), True)
        v2 = QgsVectorLayer("Point?field=id:integer&field=bname:string&field=bfield:integer", "B", "memory")
        self.assertEqual(v2.isValid(), True)
        v3 = QgsVectorLayer("Point?field=id:integer&field=cname:string", "C", "memory")
        self.assertEqual(v3.isValid(), True)
        tl1 = QgsVectorLayer("NoGeometry?field=id:integer&field=e_id:integer&field=0name:string", "D", "memory")
        self.assertEqual(tl1.isValid(), True)
        tl2 = QgsVectorLayer("NoGeometry?field=id:integer&field=ena me:string", "E", "memory")
        self.assertEqual(tl2.isValid(), True)
        QgsProject.instance().addMapLayers([v1, v2, v3, tl1, tl2])
        joinInfo = QgsVectorLayerJoinInfo()
        joinInfo.setTargetFieldName("b_id")
        joinInfo.setJoinLayer(v2)
        joinInfo.setJoinFieldName("id")
        #joinInfo.setPrefix("B_")
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 6)

        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(df.query(), 'SELECT t.geometry, t.rowid AS uid, t."id", t."b_id", t."c_id", t."name", j1."bname" AS "B_bname", j1."bfield" AS "B_bfield" FROM "{}" AS t LEFT JOIN "{}" AS j1 ON t."b_id"=j1."id"'.format(v1.id(), v2.id()))

        # with a field subset
        v1.removeJoin(v2.id())
        joinInfo.setJoinFieldNamesSubset(["bname"])
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 5)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(df.query(), 'SELECT t.geometry, t.rowid AS uid, t."id", t."b_id", t."c_id", t."name", j1."bname" AS "B_bname" FROM "{}" AS t LEFT JOIN "{}" AS j1 ON t."b_id"=j1."id"'.format(v1.id(), v2.id()))
        joinInfo.setJoinFieldNamesSubset(None)

        # add a table prefix to the join
        v1.removeJoin(v2.id())
        joinInfo.setPrefix("BB_")
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 6)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(df.query(), 'SELECT t.geometry, t.rowid AS uid, t."id", t."b_id", t."c_id", t."name", j1."bname" AS "BB_bname", j1."bfield" AS "BB_bfield" FROM "{}" AS t LEFT JOIN "{}" AS j1 ON t."b_id"=j1."id"'.format(v1.id(), v2.id()))
        joinInfo.setPrefix("")
        v1.removeJoin(v2.id())
        v1.addJoin(joinInfo)

        # add another join
        joinInfo2 = QgsVectorLayerJoinInfo()
        joinInfo2.setTargetFieldName("c_id")
        joinInfo2.setJoinLayer(v3)
        joinInfo2.setJoinFieldName("id")
        v1.addJoin(joinInfo2)
        self.assertEqual(len(v1.fields()), 7)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(df.query(), ('SELECT t.geometry, t.rowid AS uid, t."id", t."b_id", t."c_id", t."name", j1."bname" AS "B_bname", j1."bfield" AS "B_bfield", j2."cname" AS "C_cname" FROM "{}" AS t '
                                      + 'LEFT JOIN "{}" AS j1 ON t."b_id"=j1."id" '
                                      + 'LEFT JOIN "{}" AS j2 ON t."c_id"=j2."id"').format(v1.id(), v2.id(), v3.id()))

        # test NoGeometry joined layers with field names starting with a digit or containing white spaces
        joinInfo3 = QgsVectorLayerJoinInfo()
        joinInfo3.setTargetFieldName("e_id")
        joinInfo3.setJoinLayer(tl2)
        joinInfo3.setJoinFieldName("id")
        tl1.addJoin(joinInfo3)
        self.assertEqual(len(tl1.fields()), 4)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(tl1)
        self.assertEqual(df.query(), 'SELECT t.rowid AS uid, t."id", t."e_id", t."0name", j1."ena me" AS "E_ena me" FROM "{}" AS t LEFT JOIN "{}" AS j1 ON t."e_id"=j1."id"'.format(tl1.id(), tl2.id()))

        QgsProject.instance().removeMapLayers([v1.id(), v2.id(), v3.id(), tl1.id(), tl2.id()])
    def fusionnerJointure(self, cheminCompletParcelle, jointureChoisie):
        """ Selon les tables déja ouverte dans le projet : ouverture si necessaire des différents cas de délimiteurs
            Jointure par QGIS """
        # Vérification du projet ouverte
        monProjet = QgsProject.instance()
        if monProjet.fileName() == None or monProjet.fileName() == "":
            monPrint("Projet en cours de création", T_WAR)
        else:
            monPrint("Projet ouvert {}".format(monProjet.fileName()))

        root = monProjet.layerTreeRoot()
        # Création du groupe jointure_date
        dateMaintenant = datetime.now()
        nomGroupe = MonParcellaire_JOI + " du " + dateMaintenant.strftime(
            "%d %b à %Hh%M:%S")
        temporaireGroupe = QgsLayerTreeGroup(nomGroupe)
        # Positionner en haut de root
        root.addChildNode(temporaireGroupe)
        nouveauGroupe = temporaireGroupe.clone()
        root.insertChildNode(0, nouveauGroupe)
        root.removeChildNode(temporaireGroupe)

        # Ouverture du vecteur parcelle
        parcelle = QgsVectorLayer(
            cheminCompletParcelle,
            MonParcellaire_PAR + SEP_U + MonParcellaire_JOI, 'ogr')
        monProjet.addMapLayer(parcelle, False)
        nouveauGroupe.addLayer(parcelle)

        # Recherche delimiteur
        delimiteur, csv, nomCsv = self.rechercherDelimiteurJointure(
            jointureChoisie, "No Pandas")
        nomCourtJointure = os.path.basename(jointureChoisie)

        monPrint(
            "Délimiteur identifié {0} pour {1}".format(delimiteur,
                                                       nomCourtJointure), T_OK)
        monProjet.addMapLayer(csv, False)
        nouveauGroupe.addLayer(csv)

        # Jointure
        attributsSelectionnes = self.AttributsAJoindre_listWidget.selectedItems(
        )
        attributsAJoindre = []
        for positionAttribut in range(len(attributsSelectionnes)):
            attributsAJoindre.append(
                str(self.AttributsAJoindre_listWidget.selectedItems()
                    [positionAttribut].text()))
        #monPrint( "Attributs à joindre {}".format( attributsAJoindre))
        # Liste des champs dans csv
        nomColonnes, _ = self.lireAttributsJointure(jointureChoisie)
        attributsAJoindreOrdonne = []
        for col in nomColonnes:
            if col in attributsAJoindre:
                if col != MonParcellaireNomAttribut:
                    attributsAJoindreOrdonne.append(col)
        #monPrint( "Attributs à joindre ordonné {}".format( attributsAJoindreOrdonne))

        champVecteur = MonParcellaireNomAttribut
        maJointure = QgsVectorLayerJoinInfo()
        champCsv = self.AttributJointure_comboBox.currentText()
        maJointure.setJoinFieldName(champCsv)
        maJointure.setTargetFieldName(champVecteur)
        maJointure.setUsingMemoryCache(True)
        maJointure.setPrefix("")
        maJointure.setJoinLayer(csv)
        # Récupérer les champs de jointure
        maJointure.setJoinFieldNamesSubset(attributsAJoindreOrdonne)
        parcelle.addJoin(maJointure)
        return jointureChoisie, attributsAJoindreOrdonne
예제 #23
0
def join_field(input_table,
               join_table,
               field_to_calc,
               field_to_copy,
               joinfield_input_table,
               joinfield_join_table,
               inner_join=False):
    """Veld overnemen uit andere tabel o.b.v. tablejoin.
       Het veld wat gevuld moet worden (field_to_calc) moet al wel bestaan en wordt in deze functie alleen gevuld.
       Vul "pk" in bij joinfield_join_table om de primary key te laten bepalen of kies een ander veld"""
    # voorbeeld: join_field(input_table="", join_table="", field_to_calc="", field_to_copy="", joinfield_input_table="", joinfield_join_table="")
    if 1 == 1:

        print_log(
            "joining field {} from {}...".format(
                field_to_calc, os.path.basename(join_table.name())), "d")

        input_table.selectByIds([])
        # add join old way qgis 2
        ## joinObject = QgsVectorJoinInfo()
        ## joinObject.joinLayerId = join_table.id()
        ## joinObject.joinFieldName = joinfield_join_table
        ## joinObject.joinFieldName = joinfield_join_table
        ## joinObject.targetFieldName = joinfield_input_table
        # add join qgis 3
        joinObject = QgsVectorLayerJoinInfo()  # old: QgsVectorJoinInfo()
        joinObject.setJoinLayer(join_table)
        joinObject.setJoinFieldName(joinfield_join_table)
        joinObject.setTargetFieldName(joinfield_input_table)
        if not input_table.addJoin(joinObject):
            print_log("join failed!", "w")
        # calculate field
        context = QgsExpressionContext()
        scope = QgsExpressionContextScope()
        context.appendScope(scope)
        e = QgsExpression('"{}_{}"'.format(join_table.name(), field_to_copy))
        ##e.prepare(input_table.fields()) # qgis 2
        print_log(
            "expression = {}".format('"{}_{}"'.format(join_table.name(),
                                                      field_to_copy)), "d")

        idx_field_to_copy = input_table.fields().indexFromName('{}_{}'.format(
            join_table.name(), field_to_copy))
        if idx_field_to_copy == -1:
            print_log(
                "[{}] is leeg omdat [{}] ontbreekt in kaartlaag '{}'.".format(
                    field_to_calc, field_to_copy, join_table.name()), "w")
        idx_joinfield_join_table = join_table.fields().indexFromName(
            joinfield_join_table)
        if idx_joinfield_join_table == -1:
            print_log(
                "join_field [{}] ontbreekt in {}. table join mislukt.".format(
                    joinfield_join_table, join_table.name()), "w")
        input_table.startEditing()
        idx = input_table.fields().indexFromName(field_to_calc)
        if idx == -1:
            print_log(
                "field_to_calculate [{}] niet gevonden in kaartlaag '{}'.".
                format(field_to_calc, input_table.name()), "w")
        if inner_join:
            print_log("inner_join = True", 'd')
            s_expr = '"{}_{}" IS NOT NULL'.format(join_table.name(),
                                                  field_to_copy)
            print_log(s_expr, 'd')
            expr = QgsExpression(s_expr)
            it = input_table.getFeatures(
                QgsFeatureRequest(expr))  # iterator object
            input_table.selectByIds([i.id() for i in it])
            features = input_table.selectedFeatures()
        else:
            features = input_table.getFeatures()
        for f in features:
            scope.setFeature(f)
            f[idx] = e.evaluate(context)  # qgis 2: e.evaluate(f)
            input_table.updateFeature(f)
        input_table.commitChanges()

        input_table.removeJoin(joinObject.joinLayerId())
예제 #24
0
    def run(self):
        project_id = self.settings.value("project/id")
        epsg = self.settings.value("project/epsg")
        self.project_dir = self.settings.value("project/projectdir")
        self.project_id = self.settings.value("project/id")

        locale = QSettings().value('locale/userLocale')[
            0:2]  # this is for multilingual legends

        # If locale is different to frence or italian, german will be used.
        # Otherwise we get into troubles with the legends, e.g. locale = "en"
        # but
        # there is no english legend (qml file).
        if locale == "fr":
            pass
        elif locale == "it":
            pass
        else:
            locale = "de"

        if not project_id:
            self.message_bar.pushCritical("Error",
                                          _translate("VeriSO_V+D_FP3",
                                                     "project_id not set",
                                                     None))
            return

        QApplication.setOverrideCursor(Qt.WaitCursor)
        try:
            group = _translate("VeriSO_V+D_FP3", "FixpunkteKategorie3", None)
            group += " (" + str(project_id) + ")"

            layer = {
                "type": "postgres",
                "title": _translate("VeriSO_V+D_FP3", "Toleranzstufen",
                                    None),
                "featuretype": "tseinteilung_toleranzstufe",
                "geom": "geometrie", "key": "ogc_fid", "sql": "",
                "readonly": True, "group": group,
                "style": "tseinteilung/toleranzstufe_" + locale + ".qml"
                }

            # Visibility and if legend and/or groupd should be collapsed can
            # be set with parameters in the self.layer_loader.load()
            # method:
            # load(layer, visibility=True, collapsed_legend=False,
            # collapsed_group=False)
            vlayer = self.layer_loader.load(layer)

            layer = {
                "type": "postgres",
                "title": _translate("VeriSO_V+D_FP3", "LFP3 Nachführung",
                                    None),
                "featuretype": "fixpunktekategorie3_lfp3nachfuehrung",
                "geom": "perimeter", "key": "ogc_fid", "sql": "",
                "readonly": True, "group": group
                }

            vlayer_lfp3_nf = self.layer_loader.load(layer, False, True)

            layer = {
                "type": "postgres",
                "title": _translate("VeriSO_V+D_FP3", "LFP3", None),
                "featuretype": "fixpunktekategorie3_lfp3", "geom": "geometrie",
                "key": "ogc_fid", "sql": "", "readonly": True, "group": group,
                "style": "fixpunkte/lfp3_" + locale + ".qml"
                }

            vlayer_lfp3 = self.layer_loader.load(layer)

            # Join two layers (lfp3 and lfp3nachfuehrung)
            lfp3_field = "entstehung"
            lfp3_nf_field = "ogc_fid"
            join_obj = QgsVectorLayerJoinInfo()
            join_obj.setJoinLayerId(vlayer_lfp3_nf.id())
            join_obj.setJoinFieldName(lfp3_nf_field)
            join_obj.setTargetFieldName(lfp3_field)
            join_obj.setUsingMemoryCache(True)
            join_obj.setPrefix("lfp3_nf_")
            vlayer_lfp3.addJoin(join_obj)

            layer = {
                "type": "postgres", "title": _translate("VeriSO_V+D_FP3",
                                                        "LFP3 ausserhalb "
                                                        "Gemeinde",
                                                        None),
                "featuretype": "t_lfp3_ausserhalb_gemeinde",
                "geom": "geometrie", "key": "ogc_fid", "sql": "",
                "readonly": True, "group": group,
                "style": "fixpunkte/lfp3ausserhalb.qml"
                }

            vlayer = self.layer_loader.load(layer)

            layer = {
                "type": "postgres",
                "title": _translate("VeriSO_V+D_FP3", "LFP3 pro TS", None),
                "featuretype": "t_lfp3_pro_ts", "key": "ogc_fid", "sql": "",
                "readonly": True, "group": group
                }

            vlayer_lfp3_pro_ts = self.layer_loader.load(layer)

            layer = {
                "type": "postgres",
                "title": _translate("VeriSO_V+D_FP3", "Gemeindegrenze",
                                    None),
                "featuretype": "gemeindegrenzen_gemeindegrenze",
                "geom": "geometrie", "key": "ogc_fid", "sql": "",
                "readonly": True, "group": group,
                "style": "global_qml/gemeindegrenze/gemgre_strichliert.qml"
                }

            gemgrelayer = self.layer_loader.load(layer)

            # Change map extent.
            # Bug (?) in QGIS: http://hub.qgis.org/issues/10980
            # Closed for the lack of feedback. Upsi...
            # Still a problem? (sz / 2015-04-12)
            # sz / 2015-04-20:
            # Aaaah: still a problem. Some really strange combination of
            # checked/unchecked-order-of-layers-thing?
            # If wms is addes after gemgre then is scales (rect.scale(5))?!
            # So it seems that the last added layer HAS TO BE unchecked?
            # No not exactly. Only if a wms is added before?
            # rect.scale(5) has no effect?

            # I reopened the ticket / 2015-04-20 / sz

            if gemgrelayer:
                rect = gemgrelayer.extent()
                rect.scale(5)
                self.iface.mapCanvas().setExtent(rect)
                self.iface.mapCanvas().refresh()
                # Sometimes it does make much more sense
            # to zoom to maximal extent:
            # self.iface.mapCanvas().zoomToFullExtent()

            self.export_to_excel(vlayer_lfp3_pro_ts)

        except Exception:
            QApplication.restoreOverrideCursor()
            exc_type, exc_value, exc_traceback = sys.exc_info()
            self.message_bar.pushMessage("Error", str(
                traceback.format_exc(exc_traceback)),
                level=Qgis.Critical,
                duration=0)
        QApplication.restoreOverrideCursor()
예제 #25
0
    def test_field_is_read_only(self):
        """
        Test fieldIsReadOnly
        """
        layer = createLayerWithOnePoint()
        # layer is not editable => all fields are read only
        self.assertTrue(QgsVectorLayerUtils.fieldIsReadOnly(layer, 0))
        self.assertTrue(QgsVectorLayerUtils.fieldIsReadOnly(layer, 1))

        layer.startEditing()
        self.assertFalse(QgsVectorLayerUtils.fieldIsReadOnly(layer, 0))
        self.assertFalse(QgsVectorLayerUtils.fieldIsReadOnly(layer, 1))

        field = QgsField('test', QVariant.String)
        layer.addAttribute(field)
        self.assertFalse(QgsVectorLayerUtils.fieldIsReadOnly(layer, 0))
        self.assertFalse(QgsVectorLayerUtils.fieldIsReadOnly(layer, 1))
        self.assertFalse(QgsVectorLayerUtils.fieldIsReadOnly(layer, 2))

        # simulate read-only field from provider
        field = QgsField('test2', QVariant.String)
        field.setReadOnly(True)
        layer.addAttribute(field)
        self.assertFalse(QgsVectorLayerUtils.fieldIsReadOnly(layer, 0))
        self.assertFalse(QgsVectorLayerUtils.fieldIsReadOnly(layer, 1))
        self.assertFalse(QgsVectorLayerUtils.fieldIsReadOnly(layer, 2))
        self.assertTrue(QgsVectorLayerUtils.fieldIsReadOnly(layer, 3))

        layer.rollBack()
        layer.startEditing()

        # edit form config specifies read only
        form_config = layer.editFormConfig()
        form_config.setReadOnly(1, True)
        layer.setEditFormConfig(form_config)
        self.assertFalse(QgsVectorLayerUtils.fieldIsReadOnly(layer, 0))
        self.assertTrue(QgsVectorLayerUtils.fieldIsReadOnly(layer, 1))
        form_config.setReadOnly(1, False)
        layer.setEditFormConfig(form_config)
        self.assertFalse(QgsVectorLayerUtils.fieldIsReadOnly(layer, 0))
        self.assertFalse(QgsVectorLayerUtils.fieldIsReadOnly(layer, 1))

        # joined field
        layer2 = QgsVectorLayer(
            "Point?field=fldtxt2:string&field=fldint:integer", "addfeat",
            "memory")
        join_info = QgsVectorLayerJoinInfo()
        join_info.setJoinLayer(layer2)
        join_info.setJoinFieldName('fldint')
        join_info.setTargetFieldName('fldint')
        join_info.setUsingMemoryCache(True)
        layer.addJoin(join_info)
        layer.updateFields()

        self.assertEqual([f.name() for f in layer.fields()],
                         ['fldtxt', 'fldint', 'addfeat_fldtxt2'])
        self.assertFalse(QgsVectorLayerUtils.fieldIsReadOnly(layer, 0))
        self.assertFalse(QgsVectorLayerUtils.fieldIsReadOnly(layer, 1))
        # join layer is not editable
        self.assertTrue(QgsVectorLayerUtils.fieldIsReadOnly(layer, 2))

        # make join editable
        layer.removeJoin(layer2.id())
        join_info.setEditable(True)
        layer.addJoin(join_info)
        layer.updateFields()
        self.assertEqual([f.name() for f in layer.fields()],
                         ['fldtxt', 'fldint', 'addfeat_fldtxt2'])

        # should still be read only -- the join layer itself is not editable
        self.assertTrue(QgsVectorLayerUtils.fieldIsReadOnly(layer, 2))

        layer2.startEditing()
        self.assertFalse(QgsVectorLayerUtils.fieldIsReadOnly(layer, 2))

        # but now we set a property on the join layer which blocks editing for the feature...
        form_config = layer2.editFormConfig()
        form_config.setReadOnly(0, True)
        layer2.setEditFormConfig(form_config)
        # should now be read only -- the joined layer edit form config prohibits edits
        self.assertTrue(QgsVectorLayerUtils.fieldIsReadOnly(layer, 2))