QgsRendererRangeV2.symbol() dumps QGIS

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

QgsRendererRangeV2.symbol() dumps QGIS

Tom Chadwin
The line:

symbol = range.symbol()

where range is (I trust) a QgsRendererRangeV2 is dumping QGIS for me. Does anyone know what circumstances can result in this? Fuller code snippet:

elif isinstance(renderer, QgsGraduatedSymbolRendererV2):
    classAttribute = renderer.classAttribute()
    attrValue = feat.attribute(classAttribute)
    ranges = renderer.ranges()
    for range in ranges:
        if (attrValue >= range.lowerValue() and
                attrValue <= range.upperValue()):
            symbol = range.symbol()
Reply | Threaded
Open this post in threaded view
|

Re: QgsRendererRangeV2.symbol() dumps QGIS

Tom Chadwin
Wait, do I need startRender() and stopRender() for this as well?
Reply | Threaded
Open this post in threaded view
|

Re: QgsRendererRangeV2.symbol() dumps QGIS

Tom Chadwin
No, it's not that. I already have startRender() and stopRender() either side of the code block above. Can anyone explain the crash?
Reply | Threaded
Open this post in threaded view
|

Re: QgsRendererRangeV2.symbol() dumps QGIS

Tom Chadwin
Here's a fuller code snippet.

# cleanedLayer is a memory layer with the extra fields added for height, roof, colour, and wall colour
# i is the original layer
# canvas is obviously iface.mapCanvas()

fields = cleanedLayer.pendingFields()
renderer = i.rendererV2()
renderContext = QgsRenderContext.fromMapSettings(
        canvas.mapSettings())
feats = i.getFeatures()
context = QgsExpressionContext()
context.appendScope(QgsExpressionContextUtils.layerScope(i))
expression = QgsExpression('eval(@qgis_25d_height)')
heightField = fields.indexFromName("height")
wallField = fields.indexFromName("wallColor")
roofField = fields.indexFromName("roofColor")
renderer.startRender(renderContext, fields)
cleanedLayer.startEditing()
for feat in feats:
    context.setFeature(feat)
    height = expression.evaluate(context)
    if isinstance(renderer, QgsCategorizedSymbolRendererV2):
        classAttribute = renderer.classAttribute()
        attrValue = feat.attribute(classAttribute)
        catIndex = renderer.categoryIndexForValue(attrValue)
        categories = renderer.categories()
        symbol = categories[catIndex].symbol()
    elif isinstance(renderer, QgsGraduatedSymbolRendererV2):
        classAttribute = renderer.classAttribute()
        attrValue = feat.attribute(classAttribute)
        ranges = renderer.ranges()
        for range in ranges:
            if (attrValue >= range.lowerValue() and
                    attrValue <= range.upperValue()):
                symbol = range.symbol()
    else:
        symbol = renderer.symbolForFeature2(feat, renderContext)

As I say, this works for single symbol and categorized renderers, but dumps QGIS for graduated renderers, crashing on the line:

symbol = range.symbol()

What's the cause?
Reply | Threaded
Open this post in threaded view
|

Re: QgsRendererRangeV2.symbol() dumps QGIS

Tom Chadwin
I'm not sure how, but that line is no longer crashing. However, I am now getting a crash on a subsequent line:

wallColor = symbol.symbolLayer(1).subSymbol().color().name()

What is interesting is that it crashes not immediately, but on the third feature it loops to in "for feat in feats". Simplified code snippet:

for feat in feats:
    classAttribute = renderer.classAttribute()
    attrValue = feat.attribute(classAttribute)
    ranges = renderer.ranges()
    for range in ranges:
        if (attrValue >= range.lowerValue() and attrValue <= range.upperValue()):
            symbol = range.symbol()
    wallColor = symbol.symbolLayer(1).subSymbol().color().name()

What could cause that last line to crash for some features but not others?
Reply | Threaded
Open this post in threaded view
|

Re: QgsRendererRangeV2.symbol() dumps QGIS

Nyall Dawson
On 14 March 2016 at 23:08, Tom Chadwin <[hidden email]> wrote:

> I'm not sure how, but that line is no longer crashing. However, I am now
> getting a crash on a subsequent line:
>
> wallColor = symbol.symbolLayer(1).subSymbol().color().name()
>
> What is interesting is that it crashes not immediately, but on the third
> feature it loops to in "for feat in feats". Simplified code snippet:
>
> for feat in feats:
>     classAttribute = renderer.classAttribute()
>     attrValue = feat.attribute(classAttribute)
>     ranges = renderer.ranges()
>     for range in ranges:
>         if (attrValue >= range.lowerValue() and attrValue <=
> range.upperValue()):
>             symbol = range.symbol()
>     wallColor = symbol.symbolLayer(1).subSymbol().color().name()
>
> What could cause that last line to crash for some features but not others?

I think symbol is probably getting deleted by the renderer. I'd try
making a copy of it, eg

symbol = QgsSymbolV2( range.symbol() )

Nyall


>
>
>
> --
> View this message in context: http://osgeo-org.1560.x6.nabble.com/QgsRendererRangeV2-symbol-dumps-QGIS-tp5255977p5256206.html
> Sent from the Quantum GIS - Developer mailing list archive at Nabble.com.
> _______________________________________________
> Qgis-developer mailing list
> [hidden email]
> List info: http://lists.osgeo.org/mailman/listinfo/qgis-developer
> Unsubscribe: http://lists.osgeo.org/mailman/listinfo/qgis-developer
_______________________________________________
Qgis-developer mailing list
[hidden email]
List info: http://lists.osgeo.org/mailman/listinfo/qgis-developer
Unsubscribe: http://lists.osgeo.org/mailman/listinfo/qgis-developer
Reply | Threaded
Open this post in threaded view
|

Re: QgsRendererRangeV2.symbol() dumps QGIS

Tom Chadwin
@Nyall You're completely right. Thanks so much! Couldn't use your method precisely (throws "TypeError: qgis._core.QgsSymbolV2 represents a C++ abstract class and cannot be instantiated"). However, this did the trick:

symbol = range.symbol().clone()

Thanks again, and sorry about all the questions on the mailing list. I absolutely don't mean to flood.