mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
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:
parent
fbc5e0fc8e
commit
94e1d5e52e
@ -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 );
|
||||
|
||||
};
|
||||
|
@ -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 );
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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 );
|
||||
|
@ -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 );
|
||||
|
@ -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 );
|
||||
|
@ -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)
|
||||
|
176
tests/src/python/test_qgsrendererv2.py
Normal file
176
tests/src/python/test_qgsrendererv2.py
Normal 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()
|
Loading…
x
Reference in New Issue
Block a user