Category Archives: pyqgis

Today I wanna share a solution for a problem we faced during the implementation of a tool for our QGIS plugin, DsgTools. The tool in question captures the signal featureAdded to get access to the newly created features for a particular QgsVectorLayer and change their attributes.

But, during our code testing we found a major problem. During the edition, when the undo button was pressed QGIS crashed big time!

By studing the link above and some other related, we have discovered that our function connected to featureAdded was messing things up, but why? Sure, we have learned some “kludges” or like some might say “McGyver Programming Stunts” to solve the problem, but what is the magic that happens when a user finishes adding a feature in QGIS? We need to understand that in order to code in an elegant way!

First of all, featureAdded() is triggered:

self.iface.actionAddFeature().trigger()

This triggers QgsMapToolAddFeature::addFeature which does the following

Ok, on one hand I want to manipulate feature’s attributes when they are added, but on the other hand, if I try to do so, I’ll mess up the undo stack. How should we proceed? What if I only peep while QGIS does its magic and then I barge in and do my own stuff? So I have to have one slot connected to featureAdded signal just to let me know which features should I visit on the editBuffer and another slot connected to editCommandEnded signal, so that I am sure that the undoStack is properly built allowing me to revisit the added features to change its attributes.

Have you ever needed to explode multi geometry layer into a single geometry layer, using in each new geometry the attributes of the original multi one? If you were working with FME, for instance, you basically would just use the transformer Deaggregator. Let’s learn how to solve this problem with python and QGIS!

The following code snippet teaches you how to work with QgsVectorLayers, it’s attributes and how to manipulate geometries.

from qgis.core import QgsVectorLayer, QgsFeature, QgsMapLayerRegistry
#fill in your input layer name. In this example, our inputLyrName is input_layer
inputLyrName = 'input_layer'
inputLyr = QgsMapLayerRegistry.instance().mapLayersByName(inputLyrName)[0]
#fill in your output layer name. In this example, our outputLyrName is output_layer
outputName = 'output_layer'
outputLyr = QgsMapLayerRegistry.instance().mapLayersByName(outputLyrName)[0]
#tests type of output: if it is a multi parted geometry or
#a single parted geometry
if outputLyr.wkbType() in [QGis.WKBPoint, QGis.WKBLineString, QGis.WKBPolygon]:
isMulti = False
else:
isMulti = True
outputLyr.startEditing()
addList = []
for feat in inputLyr.getFeatures():
#gets all parts of geometry as an individual single geometry
parts = feat.geometry().asGeometryCollection()
#checks if it isMulti, if it is, convert each
#part in geometryCollection to multi
if isMulti:
for part in parts:
part.convertToMultiType()
#for each part, get original set of attribute and create a new feat
#with this set
for i in range(0,len(parts)):
#new feature constructor. newFeat has all atributes of feat
newFeat = QgsFeature(feat)
#set geometry with part
newFeat.setGeometry(parts[i])
#get field id and get defaultValue from provider
idx = newFeat.fieldNameIndex('id')
newFeat.setAttribute(idx,provider.defaultValue(idx))
addList.append(newFeat)
outputLyr.addFeatures(addList,True)
outputLyr.commitChanges()

We all know that GRASS is a great GIS software. Combined with QGIS it is even more great!

Using GRASS from within QGIS is very useful to deal with daily GIS problems. Everyone that works with geospatial data knows how annoying is to clean up geometries full of errors. The manual process demands lots of time and we can always forget something in the end. Do this kind of job automatically is faster and safer.

Let’s se how to do this using pyqgis. Imagine that we have a database layer like this:

A good way to clean problems like those shown above and at the same time solve snapping problems is to use the following tools in v.clean.advanced provided by GRASS: