Fix crash when using inverted polygons with heatmap renderer

Add methods to QgsRendererV2AbstractMetadata and QgsRendererV2Registry
to control renderer compatiblity by layer type. Should make it
easier to avoid this recurring bug popping up again in future.

Also add unit tests for QgsRendererV2Registry

Fix #14968
This commit is contained in:
Nyall Dawson 2016-06-07 13:28:14 +10:00
parent fbc5e0fc8e
commit 94e1d5e52e
8 changed files with 340 additions and 32 deletions

View File

@ -13,6 +13,19 @@ class QgsRendererV2AbstractMetadata
%End
public:
//! Layer types the renderer is compatible with
//! @note added in QGIS 2.16
enum LayerType
{
PointLayer, //!< Compatible with point layers
LineLayer, //!< Compatible with line layers
PolygonLayer, //!< Compatible with polygon layers
All, //!< Compatible with all vector layers
};
typedef QFlags<QgsRendererV2AbstractMetadata::LayerType> LayerTypes;
QgsRendererV2AbstractMetadata( const QString& name, const QString& visibleName, const QIcon& icon = QIcon() );
virtual ~QgsRendererV2AbstractMetadata();
@ -22,6 +35,11 @@ class QgsRendererV2AbstractMetadata
QIcon icon() const;
void setIcon( const QIcon& icon );
/** Returns flags indicating the types of layer the renderer is compatible with.
* @note added in QGIS 2.16
*/
virtual QgsRendererV2AbstractMetadata::LayerTypes compatibleLayerTypes() const;
/** Return new instance of the renderer given the DOM element. Returns NULL on error.
* Pure virtual function: must be implemented in derived classes. */
virtual QgsFeatureRendererV2* createRenderer( QDomElement& elem ) = 0 /Factory/;
@ -37,6 +55,8 @@ class QgsRendererV2AbstractMetadata
virtual QgsFeatureRendererV2* createRendererFromSld( QDomElement& elem, QGis::GeometryType geomType ) /Factory/;
};
QFlags<QgsRendererV2AbstractMetadata::LayerType> operator|(QgsRendererV2AbstractMetadata::LayerType f1, QFlags<QgsRendererV2AbstractMetadata::LayerType> f2);
/**
Convenience metadata class that uses static functions to create renderer and its widget.
*/
@ -55,15 +75,19 @@ class QgsRendererV2Metadata : QgsRendererV2AbstractMetadata
// QgsFeatureRendererV2* (*)( QDomElement&, QGis::GeometryType geomType ) createFromSldFunction() const;
// void setWidgetFunction( QgsRendererV2WidgetFunc f );
virtual QgsRendererV2AbstractMetadata::LayerTypes compatibleLayerTypes() const;
private:
QgsRendererV2Metadata(); // pretend this is private
};
/**
Registry of renderers.
This is a singleton, renderers can be added / removed at any time
/** \ingroup core
* \class QgsRendererV2Registry
* \brief Registry of renderers.
*
* This is a singleton, renderers can be added / removed at any time
*/
class QgsRendererV2Registry
{
%TypeHeaderCode
@ -72,19 +96,33 @@ class QgsRendererV2Registry
public:
//! Returns a pointer to the QgsRendererV2Registry singleton
static QgsRendererV2Registry* instance();
//! add a renderer to registry. Takes ownership of the metadata object.
//! Adds a renderer to the registry. Takes ownership of the metadata object.
//! @param metadata renderer metadata
//! @returns true if renderer was added successfully, or false if renderer could not
//! be added (eg a renderer with a duplicate name already exists)
bool addRenderer( QgsRendererV2AbstractMetadata* metadata /Transfer/ );
//! remove renderer from registry
//! Removes a renderer from registry.
//! @param rendererName name of renderer to remove from registry
//! @returns true if renderer was sucessfully removed, or false if matching
//! renderer could not be found
bool removeRenderer( const QString& rendererName );
//! get metadata for particular renderer. Returns NULL if not found in registry.
//! Returns the metadata for a specified renderer. Returns NULL if a matching
//! renderer was not found in the registry.
QgsRendererV2AbstractMetadata* rendererMetadata( const QString& rendererName );
//! return a list of available renderers
QStringList renderersList();
//! Returns a list of available renderers.
//! @param layerTypes flags to filter the renderers by compatible layer types
QStringList renderersList( QgsRendererV2AbstractMetadata::LayerTypes layerTypes = QgsRendererV2AbstractMetadata::All ) const;
//! Returns a list of available renderers which are compatible with a specified layer.
//! @param layer vector layer
//! @note added in QGIS 2.16
QStringList renderersList( const QgsVectorLayer* layer ) const;
protected:
//! protected constructor
@ -93,5 +131,6 @@ class QgsRendererV2Registry
private:
QgsRendererV2Registry( const QgsRendererV2Registry& rh );
//QgsRendererV2Registry& operator=( const QgsRendererV2Registry& rh );
};

View File

@ -24,6 +24,7 @@
#include "qgsheatmaprenderer.h"
#include "qgs25drenderer.h"
#include "qgsnullsymbolrenderer.h"
#include "qgsvectorlayer.h"
QgsRendererV2Registry::QgsRendererV2Registry()
{
@ -52,20 +53,32 @@ QgsRendererV2Registry::QgsRendererV2Registry()
addRenderer( new QgsRendererV2Metadata( "pointDisplacement",
QObject::tr( "Point displacement" ),
QgsPointDisplacementRenderer::create ) );
QgsPointDisplacementRenderer::create,
QIcon(),
nullptr,
QgsRendererV2AbstractMetadata::PointLayer ) );
addRenderer( new QgsRendererV2Metadata( "invertedPolygonRenderer",
QObject::tr( "Inverted polygons" ),
QgsInvertedPolygonRenderer::create ) );
QgsInvertedPolygonRenderer::create,
QIcon(),
nullptr,
QgsRendererV2AbstractMetadata::PolygonLayer ) );
addRenderer( new QgsRendererV2Metadata( "heatmapRenderer",
QObject::tr( "Heatmap" ),
QgsHeatmapRenderer::create ) );
QgsHeatmapRenderer::create,
QIcon(),
nullptr,
QgsRendererV2AbstractMetadata::PointLayer ) );
addRenderer( new QgsRendererV2Metadata( "25dRenderer",
QObject::tr( "2.5 D" ),
Qgs25DRenderer::create ) );
Qgs25DRenderer::create,
QIcon(),
nullptr,
QgsRendererV2AbstractMetadata::PolygonLayer ) );
}
QgsRendererV2Registry::~QgsRendererV2Registry()
@ -108,7 +121,39 @@ QgsRendererV2AbstractMetadata* QgsRendererV2Registry::rendererMetadata( const QS
QgsRendererV2Metadata::~QgsRendererV2Metadata() {}
QStringList QgsRendererV2Registry::renderersList()
QStringList QgsRendererV2Registry::renderersList( QgsRendererV2AbstractMetadata::LayerTypes layerTypes ) const
{
return mRenderersOrder;
QStringList renderers;
Q_FOREACH ( const QString& renderer, mRenderersOrder )
{
if ( mRenderers.value( renderer )->compatibleLayerTypes() & layerTypes )
renderers << renderer;
}
return renderers;
}
QStringList QgsRendererV2Registry::renderersList( const QgsVectorLayer* layer ) const
{
QgsRendererV2AbstractMetadata::LayerType layerType = QgsRendererV2AbstractMetadata::All;
switch ( layer->geometryType() )
{
case QGis::Point:
layerType = QgsRendererV2AbstractMetadata::PointLayer;
break;
case QGis::Line:
layerType = QgsRendererV2AbstractMetadata::LineLayer;
break;
case QGis::Polygon:
layerType = QgsRendererV2AbstractMetadata::PolygonLayer;
break;
case QGis::UnknownGeometry:
case QGis::NoGeometry:
break;
}
return renderersList( layerType );
}

View File

@ -36,6 +36,18 @@ class QgsRendererV2Widget;
class CORE_EXPORT QgsRendererV2AbstractMetadata
{
public:
//! Layer types the renderer is compatible with
//! @note added in QGIS 2.16
enum LayerType
{
PointLayer = 1, //!< Compatible with point layers
LineLayer = 2, //!< Compatible with line layers
PolygonLayer = 4, //!< Compatible with polygon layers
All = PointLayer | LineLayer | PolygonLayer, //!< Compatible with all vector layers
};
Q_DECLARE_FLAGS( LayerTypes, LayerType )
QgsRendererV2AbstractMetadata( const QString& name, const QString& visibleName, const QIcon& icon = QIcon() )
: mName( name )
, mVisibleName( visibleName )
@ -49,6 +61,11 @@ class CORE_EXPORT QgsRendererV2AbstractMetadata
QIcon icon() const { return mIcon; }
void setIcon( const QIcon& icon ) { mIcon = icon; }
/** Returns flags indicating the types of layer the renderer is compatible with.
* @note added in QGIS 2.16
*/
virtual LayerTypes compatibleLayerTypes() const { return All; }
/** Return new instance of the renderer given the DOM element. Returns NULL on error.
* Pure virtual function: must be implemented in derived classes. */
virtual QgsFeatureRendererV2* createRenderer( QDomElement& elem ) = 0;
@ -75,6 +92,9 @@ class CORE_EXPORT QgsRendererV2AbstractMetadata
};
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsRendererV2AbstractMetadata::LayerTypes )
typedef QgsFeatureRendererV2*( *QgsRendererV2CreateFunc )( QDomElement& );
typedef QgsRendererV2Widget*( *QgsRendererV2WidgetFunc )( QgsVectorLayer*, QgsStyleV2*, QgsFeatureRendererV2* );
typedef QgsFeatureRendererV2*( *QgsRendererV2CreateFromSldFunc )( QDomElement&, QGis::GeometryType geomType );
@ -92,11 +112,13 @@ class CORE_EXPORT QgsRendererV2Metadata : public QgsRendererV2AbstractMetadata
const QString& visibleName,
QgsRendererV2CreateFunc pfCreate,
const QIcon& icon = QIcon(),
QgsRendererV2WidgetFunc pfWidget = nullptr )
QgsRendererV2WidgetFunc pfWidget = nullptr,
QgsRendererV2AbstractMetadata::LayerTypes layerTypes = QgsRendererV2AbstractMetadata::All )
: QgsRendererV2AbstractMetadata( name, visibleName, icon )
, mCreateFunc( pfCreate )
, mWidgetFunc( pfWidget )
, mCreateFromSldFunc( nullptr )
, mLayerTypes( layerTypes )
{}
//! @note not available in python bindings
@ -105,11 +127,13 @@ class CORE_EXPORT QgsRendererV2Metadata : public QgsRendererV2AbstractMetadata
QgsRendererV2CreateFunc pfCreate,
QgsRendererV2CreateFromSldFunc pfCreateFromSld,
const QIcon& icon = QIcon(),
QgsRendererV2WidgetFunc pfWidget = nullptr )
QgsRendererV2WidgetFunc pfWidget = nullptr,
QgsRendererV2AbstractMetadata::LayerTypes layerTypes = QgsRendererV2AbstractMetadata::All )
: QgsRendererV2AbstractMetadata( name, visibleName, icon )
, mCreateFunc( pfCreate )
, mWidgetFunc( pfWidget )
, mCreateFromSldFunc( pfCreateFromSld )
, mLayerTypes( layerTypes )
{}
virtual ~QgsRendererV2Metadata();
@ -130,6 +154,8 @@ class CORE_EXPORT QgsRendererV2Metadata : public QgsRendererV2AbstractMetadata
//! @note not available in python bindings
void setWidgetFunction( QgsRendererV2WidgetFunc f ) { mWidgetFunc = f; }
virtual QgsRendererV2AbstractMetadata::LayerTypes compatibleLayerTypes() const override { return mLayerTypes; }
protected:
//! pointer to function that creates an instance of the renderer when loading project / style
QgsRendererV2CreateFunc mCreateFunc;
@ -137,39 +163,61 @@ class CORE_EXPORT QgsRendererV2Metadata : public QgsRendererV2AbstractMetadata
QgsRendererV2WidgetFunc mWidgetFunc;
//! pointer to function that creates an instance of the renderer from SLD
QgsRendererV2CreateFromSldFunc mCreateFromSldFunc;
private:
QgsRendererV2AbstractMetadata::LayerTypes mLayerTypes;
};
/**
Registry of renderers.
This is a singleton, renderers can be added / removed at any time
/** \ingroup core
* \class QgsRendererV2Registry
* \brief Registry of renderers.
*
* This is a singleton, renderers can be added / removed at any time
*/
class CORE_EXPORT QgsRendererV2Registry
{
public:
//! Returns a pointer to the QgsRendererV2Registry singleton
static QgsRendererV2Registry* instance();
//! add a renderer to registry. Takes ownership of the metadata object.
//! Adds a renderer to the registry. Takes ownership of the metadata object.
//! @param metadata renderer metadata
//! @returns true if renderer was added successfully, or false if renderer could not
//! be added (eg a renderer with a duplicate name already exists)
bool addRenderer( QgsRendererV2AbstractMetadata* metadata );
//! remove renderer from registry
//! Removes a renderer from registry.
//! @param rendererName name of renderer to remove from registry
//! @returns true if renderer was sucessfully removed, or false if matching
//! renderer could not be found
bool removeRenderer( const QString& rendererName );
//! get metadata for particular renderer. Returns NULL if not found in registry.
//! Returns the metadata for a specified renderer. Returns NULL if a matching
//! renderer was not found in the registry.
QgsRendererV2AbstractMetadata* rendererMetadata( const QString& rendererName );
//! return a list of available renderers
QStringList renderersList();
//! Returns a list of available renderers.
//! @param layerTypes flags to filter the renderers by compatible layer types
QStringList renderersList( QgsRendererV2AbstractMetadata::LayerTypes layerTypes = QgsRendererV2AbstractMetadata::All ) const;
//! Returns a list of available renderers which are compatible with a specified layer.
//! @param layer vector layer
//! @note added in QGIS 2.16
QStringList renderersList( const QgsVectorLayer* layer ) const;
protected:
//! protected constructor
QgsRendererV2Registry();
~QgsRendererV2Registry();
//! Map of name to renderer
QMap<QString, QgsRendererV2AbstractMetadata*> mRenderers;
//! list to keep order in which renderers have been added
//! List of renderers, maintained in the order that they have been added
QStringList mRenderersOrder;
private:

View File

@ -69,14 +69,13 @@ QgsInvertedPolygonRendererWidget::QgsInvertedPolygonRendererWidget( QgsVectorLay
int currentEmbeddedIdx = 0;
//insert possible renderer types
QStringList rendererList = QgsRendererV2Registry::instance()->renderersList();
QStringList rendererList = QgsRendererV2Registry::instance()->renderersList( QgsRendererV2AbstractMetadata::PolygonLayer );
QStringList::const_iterator it = rendererList.constBegin();
int idx = 0;
mRendererComboBox->blockSignals( true );
for ( ; it != rendererList.constEnd(); ++it, ++idx )
{
if (( *it != "invertedPolygonRenderer" ) && //< an inverted renderer cannot contain another inverted renderer
( *it != "pointDisplacement" ) ) //< an inverted renderer can only contain a polygon renderer
if ( *it != "invertedPolygonRenderer" ) //< an inverted renderer cannot contain another inverted renderer
{
QgsRendererV2AbstractMetadata* m = QgsRendererV2Registry::instance()->rendererMetadata( *it );
mRendererComboBox->addItem( m->icon(), m->visibleName(), /* data */ *it );

View File

@ -87,11 +87,11 @@ QgsPointDisplacementRendererWidget::QgsPointDisplacementRendererWidget( QgsVecto
}
//insert possible renderer types
QStringList rendererList = QgsRendererV2Registry::instance()->renderersList();
QStringList rendererList = QgsRendererV2Registry::instance()->renderersList( QgsRendererV2AbstractMetadata::PointLayer );
QStringList::const_iterator it = rendererList.constBegin();
for ( ; it != rendererList.constEnd(); ++it )
{
if ( *it != "pointDisplacement" && *it != "heatmapRenderer" && *it != "invertedPolygonRenderer" )
if ( *it != "pointDisplacement" )
{
QgsRendererV2AbstractMetadata* m = QgsRendererV2Registry::instance()->rendererMetadata( *it );
mRendererComboBox->addItem( m->icon(), m->visibleName(), *it );

View File

@ -100,7 +100,7 @@ QgsRendererV2PropertiesDialog::QgsRendererV2PropertiesDialog( QgsVectorLayer* la
_initRendererWidgetFunctions();
QgsRendererV2Registry* reg = QgsRendererV2Registry::instance();
QStringList renderers = reg->renderersList();
QStringList renderers = reg->renderersList( mLayer );
Q_FOREACH ( const QString& name, renderers )
{
QgsRendererV2AbstractMetadata* m = reg->rendererMetadata( name );

View File

@ -68,6 +68,7 @@ ADD_PYTHON_TEST(PyQgsRasterLayer test_qgsrasterlayer.py)
ADD_PYTHON_TEST(PyQgsRectangle test_qgsrectangle.py)
ADD_PYTHON_TEST(PyQgsRelation test_qgsrelation.py)
ADD_PYTHON_TEST(PyQgsRelationManager test_qgsrelationmanager.py)
ADD_PYTHON_TEST(PyQgsRendererV2 test_qgsrendererv2.py)
ADD_PYTHON_TEST(PyQgsRulebasedRenderer test_qgsrulebasedrenderer.py)
ADD_PYTHON_TEST(PyQgsSingleSymbolRenderer test_qgssinglesymbolrenderer.py)
ADD_PYTHON_TEST(PyQgsShapefileProvider test_provider_shapefile.py)

View File

@ -0,0 +1,176 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsFeatureRendererV2.
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
"""
__author__ = 'Nyall Dawson'
__date__ = '07/06/2016'
__copyright__ = 'Copyright 2016, The QGIS Project'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
import qgis # NOQA
from qgis.core import (QgsFeatureRendererV2,
QgsRendererV2AbstractMetadata,
QgsRendererV2Registry,
QgsVectorLayer
)
from qgis.testing import start_app, unittest
start_app()
def createReferencingLayer():
layer = QgsVectorLayer("Point?field=fldtxt:string&field=foreignkey:integer",
"referencinglayer", "memory")
pr = layer.dataProvider()
f1 = QgsFeature()
f1.setFields(layer.pendingFields())
f1.setAttributes(["test1", 123])
f1.setGeometry(QgsGeometry.fromPoint(QgsPoint(100, 200)))
f2 = QgsFeature()
f2.setFields(layer.pendingFields())
f2.setAttributes(["test2", 123])
f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(101, 201)))
assert pr.addFeatures([f1, f2])
return layer
class TestRenderer(QgsRendererV2AbstractMetadata):
def __init__(self, name, layerTypes=QgsRendererV2AbstractMetadata.All):
QgsRendererV2AbstractMetadata.__init__(self, name, "Test Renderer")
self.types = layerTypes
def compatibleLayerTypes(self):
return self.types
def createRenderer(self, elem):
return None
def clearRegistry():
# clear registry to start with
for r in QgsRendererV2Registry.instance().renderersList():
if r == 'singleSymbol':
continue
QgsRendererV2Registry.instance().removeRenderer(r)
class TestQgsRendererV2Registry(unittest.TestCase):
def testInstance(self):
""" test retrieving global instance """
self.assertTrue(QgsRendererV2Registry.instance())
# instance should be initially populated with some default renderers
self.assertTrue('singleSymbol' in QgsRendererV2Registry.instance().renderersList())
# register a renderer to the singleton, to test that the same instance is always returned
self.assertFalse('test' in QgsRendererV2Registry.instance().renderersList())
self.assertTrue(QgsRendererV2Registry.instance().addRenderer(TestRenderer('test')))
self.assertTrue('test' in QgsRendererV2Registry.instance().renderersList())
def testAddRenderer(self):
""" test adding renderers to registry """
clearRegistry()
# add a renderer
self.assertTrue(QgsRendererV2Registry.instance().addRenderer(TestRenderer('test2')))
self.assertTrue('test2' in QgsRendererV2Registry.instance().renderersList())
# try adding it again - should be rejected due to duplicate name
self.assertFalse(QgsRendererV2Registry.instance().addRenderer(TestRenderer('test2')))
self.assertTrue('test2' in QgsRendererV2Registry.instance().renderersList())
def testRemoveRenderer(self):
""" test removing renderers from registry """
clearRegistry()
# try removing non-existant renderer
self.assertFalse(QgsRendererV2Registry.instance().removeRenderer('test3'))
# now add it
self.assertTrue(QgsRendererV2Registry.instance().addRenderer(TestRenderer('test3')))
self.assertTrue('test3' in QgsRendererV2Registry.instance().renderersList())
# try removing it again - should be ok this time
self.assertTrue(QgsRendererV2Registry.instance().removeRenderer('test3'))
self.assertFalse('test3' in QgsRendererV2Registry.instance().renderersList())
# try removing it again - should be false since already removed
self.assertFalse(QgsRendererV2Registry.instance().removeRenderer('test3'))
def testRetrieveRenderer(self):
""" test retrieving renderer by name """
clearRegistry()
# try non-existant renderer
self.assertFalse(QgsRendererV2Registry.instance().rendererMetadata('test4'))
# now add it
r = TestRenderer('test4')
self.assertTrue(QgsRendererV2Registry.instance().addRenderer(r))
# try retrieving it
result = QgsRendererV2Registry.instance().rendererMetadata('test4')
self.assertTrue(result)
self.assertEqual(result.name(), 'test4')
def testRenderersList(self):
""" test getting list of renderers from registry """
clearRegistry()
self.assertEqual(QgsRendererV2Registry.instance().renderersList(), ['singleSymbol'])
# add some renderers
r1 = TestRenderer('test1', QgsRendererV2AbstractMetadata.PointLayer)
self.assertTrue(QgsRendererV2Registry.instance().addRenderer(r1))
r2 = TestRenderer('test2', QgsRendererV2AbstractMetadata.LineLayer)
self.assertTrue(QgsRendererV2Registry.instance().addRenderer(r2))
r3 = TestRenderer('test3', QgsRendererV2AbstractMetadata.PolygonLayer)
self.assertTrue(QgsRendererV2Registry.instance().addRenderer(r3))
r4 = TestRenderer('test4', QgsRendererV2AbstractMetadata.PointLayer | QgsRendererV2AbstractMetadata.LineLayer)
self.assertTrue(QgsRendererV2Registry.instance().addRenderer(r4))
self.assertEqual(QgsRendererV2Registry.instance().renderersList(), ['singleSymbol', 'test1', 'test2', 'test3', 'test4'])
# test subsets
self.assertEqual(QgsRendererV2Registry.instance().renderersList(QgsRendererV2AbstractMetadata.PointLayer), ['singleSymbol', 'test1', 'test4'])
self.assertEqual(QgsRendererV2Registry.instance().renderersList(QgsRendererV2AbstractMetadata.LineLayer), ['singleSymbol', 'test2', 'test4'])
self.assertEqual(QgsRendererV2Registry.instance().renderersList(QgsRendererV2AbstractMetadata.PolygonLayer), ['singleSymbol', 'test3'])
self.assertEqual(QgsRendererV2Registry.instance().renderersList(QgsRendererV2AbstractMetadata.LineLayer | QgsRendererV2AbstractMetadata.PolygonLayer), ['singleSymbol', 'test2', 'test3', 'test4'])
def testRenderersByLayerType(self):
""" test retrieving compatible renderers by layer type """
clearRegistry()
# add some renderers
r1 = TestRenderer('test1', QgsRendererV2AbstractMetadata.PointLayer)
self.assertTrue(QgsRendererV2Registry.instance().addRenderer(r1))
r2 = TestRenderer('test2', QgsRendererV2AbstractMetadata.LineLayer)
self.assertTrue(QgsRendererV2Registry.instance().addRenderer(r2))
r3 = TestRenderer('test3', QgsRendererV2AbstractMetadata.PolygonLayer)
self.assertTrue(QgsRendererV2Registry.instance().addRenderer(r3))
r4 = TestRenderer('test4', QgsRendererV2AbstractMetadata.PointLayer | QgsRendererV2AbstractMetadata.LineLayer)
self.assertTrue(QgsRendererV2Registry.instance().addRenderer(r4))
# make some layers
point_layer = QgsVectorLayer("Point?field=fldtxt:string",
"pointlayer", "memory")
line_layer = QgsVectorLayer("LineString?field=fldtxt:string",
"linelayer", "memory")
polygon_layer = QgsVectorLayer("Polygon?field=fldtxt:string",
"polylayer", "memory")
# test subsets
self.assertEqual(QgsRendererV2Registry.instance().renderersList(point_layer), ['singleSymbol', 'test1', 'test4'])
self.assertEqual(QgsRendererV2Registry.instance().renderersList(line_layer), ['singleSymbol', 'test2', 'test4'])
self.assertEqual(QgsRendererV2Registry.instance().renderersList(polygon_layer), ['singleSymbol', 'test3'])
if __name__ == '__main__':
unittest.main()