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()])
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()])
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 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 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 test_field_editability_depends_on_feature(self): """ Test QgsVectorLayerUtils.fieldEditabilityDependsOnFeature """ layer = createLayerWithOnePoint() # not joined fields, so answer should be False self.assertFalse( QgsVectorLayerUtils.fieldEditabilityDependsOnFeature(layer, 0)) self.assertFalse( QgsVectorLayerUtils.fieldEditabilityDependsOnFeature(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.fieldEditabilityDependsOnFeature(layer, 0)) self.assertFalse( QgsVectorLayerUtils.fieldEditabilityDependsOnFeature(layer, 1)) # join layer is not editable => regardless of the feature, the field will always be read-only self.assertFalse( QgsVectorLayerUtils.fieldEditabilityDependsOnFeature(layer, 2)) # make join editable layer.removeJoin(layer2.id()) join_info.setEditable(True) join_info.setUpsertOnEdit(True) layer.addJoin(join_info) layer.updateFields() self.assertEqual([f.name() for f in layer.fields()], ['fldtxt', 'fldint', 'addfeat_fldtxt2']) # has upsert on edit => regardless of feature, we can create the join target to make the field editable self.assertFalse( QgsVectorLayerUtils.fieldEditabilityDependsOnFeature(layer, 2)) layer.removeJoin(layer2.id()) join_info.setEditable(True) join_info.setUpsertOnEdit(False) layer.addJoin(join_info) layer.updateFields() self.assertEqual([f.name() for f in layer.fields()], ['fldtxt', 'fldint', 'addfeat_fldtxt2']) # No upsert on edit => depending on feature, we either can edit the field or not, depending on whether # the join target feature already exists or not self.assertTrue( QgsVectorLayerUtils.fieldEditabilityDependsOnFeature(layer, 2))
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))
def join(self): # join the shp layer to the excel layer, non cached # TODO: Ignore if already joined? shpLayer = layer_from_name(self.shpName) jinfo = QgsVectorLayerJoinInfo() jinfo.setJoinFieldName(self.excelKeyName) jinfo.setTargetFieldName(self.shpKeyName) jinfo.setJoinLayerId(layer_from_name(self.excelName).id()) jinfo.setUsingMemoryCache(False) jinfo.setPrefix('') for jinfo2 in shpLayer.vectorJoins(): if jinfo2 == jinfo: info("Join already exists. Will not create it again") return info("Adding join between master and slave layers") shpLayer.addJoin(jinfo)
def buildJoin(self, originalLyr, originalLyrFieldName, joinnedLyr, joinLyrFieldName, startEdit=False): """ 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) if startEdit: joinnedLyr.startEditing() joinObject.setJoinLayer(joinnedLyr) # joinObject.setJoinFieldNamesSubset([]) joinObject.setUpsertOnEdit(True) #set to enable edit on original lyr joinObject.setCascadedDelete(True) joinObject.setDynamicFormEnabled(True) joinObject.setEditable(True) joinObject.setUsingMemoryCache(True) originalLyr.addJoin(joinObject)
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_FP1", "project_id not set", None)) return QApplication.setOverrideCursor(Qt.WaitCursor) try: group = _translate("VeriSO_V+D_FP1", "FixpunkteKategorie1", None) group += " (" + str(project_id) + ")" # Lagefixpunkte 1 layer = { "type": "postgres", "title": _translate("VeriSO_V+D_FP1", "LFP1 Nachführung", None), "featuretype": "fixpunktekategorie1_lfp1nachfuehrung", "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_lfp1_nf = self.layer_loader.load(layer, False, True) layer = { "type": "postgres", "title": _translate("VeriSO_V+D_FP1", "LFP1", None), "featuretype": "fixpunktekategorie1_lfp1", "geom": "geometrie", "key": "ogc_fid", "sql": "", "readonly": True, "group": group, "style": "fixpunkte/lfp2.qml" } vlayer_lfp1 = self.layer_loader.load(layer) # Join two layers (lfp1 and lfp1nachfuehrung) lfp1_field = "entstehung" lfp1_nf_field = "ogc_fid" join_obj = QgsVectorLayerJoinInfo() join_obj.setJoinLayerId(vlayer_lfp1_nf.id()) join_obj.setJoinFieldName(lfp1_nf_field) join_obj.setTargetFieldName(lfp1_field) join_obj.setUsingMemoryCache(True) join_obj.setPrefix("lfp1_nf_") vlayer_lfp1.addJoin(join_obj) # This is how WMS layer work. layer = { "type": "wms", "title": _translate("VeriSO_V+D_FP1", "LFP1 Schweiz (WMS)", None), "url": "http://wms.geo.admin.ch/", "layers": "ch.swisstopo.fixpunkte-lfp1", "format": "image/png", "crs": "EPSG:" + str(epsg), "group": group } vlayer = self.layer_loader.load(layer, False, True) # Höhenfixpunkte 1 layer = { "type": "postgres", "title": _translate("VeriSO_V+D_FP1", "HFP1 Nachführung", None), "featuretype": "fixpunktekategorie1_hfp1nachfuehrung", "geom": "perimeter", "key": "ogc_fid", "sql": "", "readonly": True, "group": group } vlayer_hfp1_nf = self.layer_loader.load(layer, False, True) layer = { "type": "postgres", "title": _translate("VeriSO_V+D_FP1", "HFP1", None), "featuretype": "fixpunktekategorie1_hfp1", "geom": "geometrie", "key": "ogc_fid", "sql": "", "readonly": True, "group": group, "style": "fixpunkte/hfp2.qml" } vlayer_hfp1 = self.layer_loader.load(layer) # Join two layers (hfp1 and hfp1nachfuehrung) hfp1_field = "entstehung" hfp1_nf_field = "ogc_fid" join_obj = QgsVectorLayerJoinInfo() join_obj.setJoinLayerId(vlayer_hfp1_nf.id()) join_obj.setJoinFieldName(hfp1_nf_field) join_obj.setTargetFieldName(hfp1_field) join_obj.setUsingMemoryCache(True) join_obj.setPrefix("hfp1_nf_") vlayer_hfp1.addJoin(join_obj) layer = { "type": "wms", "title": _translate("VeriSO_V+D_FP1", "HFP1 Schweiz (WMS)", None), "url": "http://wms.geo.admin.ch/", "layers": "ch.swisstopo.fixpunkte-hfp1", "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_FP1", "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()
def field_join(t_layer, s_layer, t_field, s_field): joinObject = QgsVectorLayerJoinInfo() joinObject.setJoinFieldName(s_field) joinObject.setTargetFieldName(t_field) joinObject.setJoinLayerId(s_layer.id()) joinObject.setUsingMemoryCache(True) joinObject.setJoinLayer(s_layer) t_layer.addJoin(joinObject)
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 {}