0

I am updating a plugin for QGIS 1.8 to QGIS 2.x. I have the code below.

  1. The setAttributeMap does not exist anymore. I have replaced it with fet.setAttributes and it seems to work.

  2. When using fet.setAttributes({0:QVariant(fid}), I get the error:

PyQt4.QtCore.QVariant represents a mapped type and cannot be instantiated.

I have tried to just remove the QVariant() and used fet.setAttributes({0:fid}), but then I get the error:

TypeError: QgsFeature.setAttributes(list-of-attributes): argument 1 has unexpected type 'dict'

The code worked well with 1.8, so what can I do to replace QVariant or setAttributeMap? I think it could be something with changing setAttributeMap to setAttributes

vl = QgsVectorLayer("MultiLineString", layerName, "memory")
pr = vl.dataProvider()
vl.startEditing()
pr.addAttributes([QgsField("id", QVariant.Int)])
fet = QgsFeature()
addRange = northRange * math.tan(abs(math.radians(bearing)))
noPoints = ((eastRange + addRange) / projEast) + 1
for i in range(0,int(math.ceil(noPoints)), 1):
    fet.setGeometry( QgsGeometry.fromMultiPolyline( [[ QgsPoint(minE + offset + (projEast * i) ,minN), QgsPoint(minE + offset + (projEast * i) - addRange,maxN) ]] ))
    fet.setAttributeMap({0:QVariant(fid)})
    pr.addFeatures( [ fet ] )
    fid = fid + 1
vl.commitChanges()
QgsMapLayerRegistry.instance().addMapLayer(vl)

I have change my code to:

vl = QgsVectorLayer("MultiLineString", layerName, "memory")
pr = vl.dataProvider()
vl.startEditing()
pr.addAttributes([QgsField("id", QVariant.Int)])
fet = QgsFeature()
fields = vl.pendingFields()
fet.setFields( fields, True )
addRange = northRange * math.tan(abs(math.radians(bearing)))
noPoints = ((eastRange + addRange) / projEast) + 1
for i in range(0,int(math.ceil(noPoints)), 1):
    fet.setGeometry( QgsGeometry.fromMultiPolyline( [[ QgsPoint(minE + offset + (projEast * i) ,minN), QgsPoint(minE + offset + (projEast * i) - addRange,maxN) ]] ))
    fet['id'] = fid
    pr.addFeatures( [ fet ] )
    fid = fid + 1
vl.commitChanges()
QgsMapLayerRegistry.instance().addMapLayer(vl)

but I still need to make an attribute named 'id' I guess before it works. If I use the setAttributes function it includes a QVariant which I am not allowed to do!

Or is it me who does not understand.


This is the final code, and it is working:

vl = QgsVectorLayer("MultiLineString", layerName, "memory")
vl.startEditing()
vl.addAttribute(QgsField("id", QVariant.Int))
fet = QgsFeature()
fields = vl.pendingFields()
fet.setFields( fields, True )
addRange = northRange * math.tan(abs(math.radians(bearing)))
noPoints = ((eastRange + addRange) / projEast) + 1
for i in range(0,int(math.ceil(noPoints)), 1):
    fet.setGeometry( QgsGeometry.fromMultiPolyline( [[ QgsPoint(minE + offset + (projEast * i) ,minN), QgsPoint(minE + offset + (projEast * i) - addRange,maxN) ]] ))
    fet['id'] = fid
    vl.addFeatures( [ fet ] )
    fid = fid + 1
vl.commitChanges()
QgsMapLayerRegistry.instance().addMapLayer(vl)
1

1 Answer 1

0

You can still use QVariant but don't use it as a type.

E.g. the following is still fine:

from PyQt4.QtCore import QVariant
vl.startEditing()
vl.addAttribute(QgsField("id", QVariant.Int))

However, it is no longer required (and no longer allowed) to use QVariant as a datatype. This means, instead of QVariant(fid) you should just use fid. You already have posted a link to the relevant section in the API changes.

The API also changed in terms of vector layer handling, which can be confused with the changes concerning QVariant but it's a different pair of shoes.

The relevant code for this is:

fet = QgsFeature()
fields = vl.pendingFields()
fet.setFields( fields, True )
fet['id'] = 42

And a minor note:

  • If you directly work on the dataprovider ( pr.addFeatures(), pr.addAttributes()) there is no need to toggle layer editing ( vl.startEditing(), vl.commitChanges()). If you want an undo stack, use the QgsVectorLayer methods instead of the QgsVectorDataProvider methods (i.e. by using vl.[method] instead of pr.[method]. If you work directly on the dataprovider, another caveat is, that events (updated features...) may not be propagated properly and lead to inconsistencies in the representation (attribute table...). TL;DR: Use vl.addFeature() instead of pr.addFeatures()
7
  • Thanks for the explanation. It helped a bit. Although the fet.initFields( fields, True ) is not possible. It gives the error: 'AttributeError: 'QgsFeature' object has no attribute 'initFields''.
    – Toke
    Commented Apr 8, 2014 at 11:04
  • sorry, it is setFields(). My mistake. Commented Apr 8, 2014 at 11:06
  • I have added my new code at the top, but I can not make the `fet['id'] = 42' work.
    – Toke
    Commented Apr 8, 2014 at 11:36
  • You will still need to add a field to the layer. Either use pr.addAttributes() and a subsequent vl.updateFields() or vl.addAttribute() Commented Apr 8, 2014 at 11:53
  • I can still not make it work. I have added the pr.addAttributes in my code at the top, but I still do not understand how to add an attribute. I can not make vl.updateFields() or vl.addAttribute().
    – Toke
    Commented Apr 9, 2014 at 5:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.