From d464f862903184e94e01e4963e82e337efc4a388 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Wed, 6 Apr 2016 19:25:00 +1000 Subject: [PATCH] [FEATURE] Null ("No symbol") renderer Using this renderer no symbol will be drawn for features, but labeling, diagrams and other non-symbol parts will still be shown. Selections can still be made on the layer in the canvas and selected features will be rendered with a default symbol. Features being edited will also be shown. This is intended as a handy shortcut for layers which you only want to show labels or diagrams for, and avoids the need to render symbols with totally transparent fill/border to achieve this. (fix #12131) --- ci/travis/linux/qt5/blacklist.txt | 1 + images/images.qrc | 1 + images/themes/default/rendererNullSymbol.svg | 84 ++++++++++++ python/core/core.sip | 1 + .../symbology-ng/qgsnullsymbolrenderer.sip | 46 +++++++ python/core/symbology-ng/qgsrendererv2.sip | 2 + python/gui/gui.sip | 1 + .../qgsnullsymbolrendererwidget.sip | 24 ++++ src/core/CMakeLists.txt | 2 + .../symbology-ng/qgsnullsymbolrenderer.cpp | 125 ++++++++++++++++++ src/core/symbology-ng/qgsnullsymbolrenderer.h | 71 ++++++++++ .../symbology-ng/qgsrendererv2registry.cpp | 5 + src/gui/CMakeLists.txt | 2 + .../qgsnullsymbolrendererwidget.cpp | 52 ++++++++ .../qgsnullsymbolrendererwidget.h | 55 ++++++++ .../qgsrendererv2propertiesdialog.cpp | 2 + tests/src/python/CMakeLists.txt | 1 + .../src/python/test_qgsnullsymbolrenderer.py | 91 +++++++++++++ .../expected_nullrenderer_render.png | Bin 0 -> 957 bytes .../expected_nullrenderer_selected.png | Bin 0 -> 3467 bytes 20 files changed, 566 insertions(+) create mode 100644 images/themes/default/rendererNullSymbol.svg create mode 100644 python/core/symbology-ng/qgsnullsymbolrenderer.sip create mode 100644 python/gui/symbology-ng/qgsnullsymbolrendererwidget.sip create mode 100644 src/core/symbology-ng/qgsnullsymbolrenderer.cpp create mode 100644 src/core/symbology-ng/qgsnullsymbolrenderer.h create mode 100644 src/gui/symbology-ng/qgsnullsymbolrendererwidget.cpp create mode 100644 src/gui/symbology-ng/qgsnullsymbolrendererwidget.h create mode 100644 tests/src/python/test_qgsnullsymbolrenderer.py create mode 100644 tests/testdata/control_images/null_renderer/expected_nullrenderer_render/expected_nullrenderer_render.png create mode 100644 tests/testdata/control_images/null_renderer/expected_nullrenderer_selected/expected_nullrenderer_selected.png diff --git a/ci/travis/linux/qt5/blacklist.txt b/ci/travis/linux/qt5/blacklist.txt index ad1ebbb70f1..141337081c4 100755 --- a/ci/travis/linux/qt5/blacklist.txt +++ b/ci/travis/linux/qt5/blacklist.txt @@ -36,6 +36,7 @@ PyQgsLocalServer PyQgsMapUnitScale PyQgsMemoryProvider PyQgsNetworkContentFetcher +PyQgsNullSymbolRenderer PyQgsPalLabelingBase PyQgsPalLabelingCanvas PyQgsPalLabelingComposer diff --git a/images/images.qrc b/images/images.qrc index ec039a49f8a..14581cb72c4 100644 --- a/images/images.qrc +++ b/images/images.qrc @@ -486,6 +486,7 @@ themes/default/rendererCategorizedSymbol.svg themes/default/rendererGraduatedSymbol.png themes/default/rendererGraduatedSymbol.svg + themes/default/rendererNullSymbol.svg themes/default/rendererSingleSymbol.png themes/default/rendererSingleSymbol.svg themes/default/rendererRuleBasedSymbol.svg diff --git a/images/themes/default/rendererNullSymbol.svg b/images/themes/default/rendererNullSymbol.svg new file mode 100644 index 00000000000..c54fed8af19 --- /dev/null +++ b/images/themes/default/rendererNullSymbol.svg @@ -0,0 +1,84 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/python/core/core.sip b/python/core/core.sip index 0c6a082ebe8..2e967f08022 100644 --- a/python/core/core.sip +++ b/python/core/core.sip @@ -289,6 +289,7 @@ %Include symbology-ng/qgsheatmaprenderer.sip %Include symbology-ng/qgsinvertedpolygonrenderer.sip %Include symbology-ng/qgslegendsymbolitemv2.sip +%Include symbology-ng/qgsnullsymbolrenderer.sip %Include symbology-ng/qgspointdisplacementrenderer.sip %Include symbology-ng/qgsrendererv2.sip %Include symbology-ng/qgsrendererv2registry.sip diff --git a/python/core/symbology-ng/qgsnullsymbolrenderer.sip b/python/core/symbology-ng/qgsnullsymbolrenderer.sip new file mode 100644 index 00000000000..ac9f8321e91 --- /dev/null +++ b/python/core/symbology-ng/qgsnullsymbolrenderer.sip @@ -0,0 +1,46 @@ +/** \ingroup core + * \class QgsNullSymbolRenderer + * \brief Null symbol renderer. Renderer which draws no symbols for features by default, but allows for labeling + * and diagrams for the layer. Selected features will also be drawn with a default symbol. + * \note Added in version 2.16 + */ + +class QgsNullSymbolRenderer : QgsFeatureRendererV2 +{ +%TypeHeaderCode +#include +%End + public: + + QgsNullSymbolRenderer(); + + virtual ~QgsNullSymbolRenderer(); + + virtual QgsSymbolV2* symbolForFeature( QgsFeature& feature, QgsRenderContext& context ); + virtual QgsSymbolV2* originalSymbolForFeature( QgsFeature& feature, QgsRenderContext& context ); + + virtual bool renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer = -1, bool selected = false, bool drawVertexMarker = false ); + virtual void startRender( QgsRenderContext& context, const QgsFields& fields ); + virtual void stopRender( QgsRenderContext& context ); + virtual bool willRenderFeature( QgsFeature& feat, QgsRenderContext& context ); + + virtual QList usedAttributes(); + virtual QString dump() const; + virtual QgsFeatureRendererV2* clone() const /Factory/; + virtual QgsSymbolV2List symbols( QgsRenderContext& context ) /PyName=symbols2/; + + /** Creates a null renderer from XML element. + * @param element DOM element + * @returns new null symbol renderer + */ + static QgsFeatureRendererV2* create( QDomElement& element ) /Factory/; + + virtual QDomElement save( QDomDocument& doc ); + + /** Creates a QgsNullSymbolRenderer from an existing renderer. + * @param renderer renderer to convert from + * @returns a new renderer if the conversion was possible, otherwise nullptr. + */ + static QgsNullSymbolRenderer* convertFromRenderer( const QgsFeatureRendererV2 *renderer ) /Factory/; + +}; diff --git a/python/core/symbology-ng/qgsrendererv2.sip b/python/core/symbology-ng/qgsrendererv2.sip index 58916a96e3e..e36ffb8dba4 100644 --- a/python/core/symbology-ng/qgsrendererv2.sip +++ b/python/core/symbology-ng/qgsrendererv2.sip @@ -50,6 +50,8 @@ class QgsFeatureRendererV2 sipType = sipType_QgsPointDisplacementRenderer; else if (sipCpp->type() == "25dRenderer") sipType = sipType_Qgs25DRenderer; + else if (sipCpp->type() == "nullSymbol") + sipType = sipType_QgsNullSymbolRenderer; else sipType = 0; %End diff --git a/python/gui/gui.sip b/python/gui/gui.sip index fad5130ad6e..e8ed80558c4 100644 --- a/python/gui/gui.sip +++ b/python/gui/gui.sip @@ -208,6 +208,7 @@ %Include symbology-ng/qgsheatmaprendererwidget.sip %Include symbology-ng/qgsinvertedpolygonrendererwidget.sip %Include symbology-ng/qgslayerpropertieswidget.sip +%Include symbology-ng/qgsnullsymbolrendererwidget.sip %Include symbology-ng/qgspenstylecombobox.sip %Include symbology-ng/qgspointdisplacementrendererwidget.sip %Include symbology-ng/qgsrendererv2propertiesdialog.sip diff --git a/python/gui/symbology-ng/qgsnullsymbolrendererwidget.sip b/python/gui/symbology-ng/qgsnullsymbolrendererwidget.sip new file mode 100644 index 00000000000..3a2668f951e --- /dev/null +++ b/python/gui/symbology-ng/qgsnullsymbolrendererwidget.sip @@ -0,0 +1,24 @@ +/** \ingroup gui + * \class QgsNullSymbolRendererWidget + * \brief Blank widget for customising QgsNullSymbolRenderer. + * \note Added in version 2.16 + */ + +class QgsNullSymbolRendererWidget : QgsRendererV2Widget +{ +%TypeHeaderCode +#include +%End + + public: + + //! Creates a new QgsNullSymbolRendererWidget object + static QgsRendererV2Widget* create( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer ) /Factory/; + + //! Constructor for QgsNullSymbolRendererWidget + QgsNullSymbolRendererWidget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer ); + ~QgsNullSymbolRendererWidget(); + + //! Returns a pointer to the configured renderer + virtual QgsFeatureRendererV2* renderer(); +}; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 26111dc6a6b..5d199f3eb46 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -28,6 +28,7 @@ SET(QGIS_CORE_SRCS symbology-ng/qgslegendsymbolitemv2.cpp symbology-ng/qgslinesymbollayerv2.cpp symbology-ng/qgsmarkersymbollayerv2.cpp + symbology-ng/qgsnullsymbolrenderer.cpp symbology-ng/qgspointdisplacementrenderer.cpp symbology-ng/qgsrendererv2.cpp symbology-ng/qgsrendererv2registry.cpp @@ -796,6 +797,7 @@ SET(QGIS_CORE_HDRS symbology-ng/qgssinglesymbolrendererv2.h symbology-ng/qgsheatmaprenderer.h symbology-ng/qgsinvertedpolygonrenderer.h + symbology-ng/qgsnullsymbolrenderer.h symbology-ng/qgssymbollayerv2.h symbology-ng/qgssymbollayerv2registry.h symbology-ng/qgssymbollayerv2utils.h diff --git a/src/core/symbology-ng/qgsnullsymbolrenderer.cpp b/src/core/symbology-ng/qgsnullsymbolrenderer.cpp new file mode 100644 index 00000000000..0182120def4 --- /dev/null +++ b/src/core/symbology-ng/qgsnullsymbolrenderer.cpp @@ -0,0 +1,125 @@ +/*************************************************************************** + qgsnullsymbolrenderer.cpp + --------------------- + begin : November 2014 + copyright : (C) 2014 by Nyall Dawson + email : nyall dot dawson at gmail dot com + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "qgsnullsymbolrenderer.h" +#include "qgssymbolv2.h" + +#include +#include + +QgsNullSymbolRenderer::QgsNullSymbolRenderer() + : QgsFeatureRendererV2( "nullSymbol" ) +{ +} + +QgsNullSymbolRenderer::~QgsNullSymbolRenderer() +{ +} + +QgsSymbolV2* QgsNullSymbolRenderer::symbolForFeature( QgsFeature& , QgsRenderContext& ) +{ + return nullptr; +} + +QgsSymbolV2* QgsNullSymbolRenderer::originalSymbolForFeature( QgsFeature&, QgsRenderContext& ) +{ + return nullptr; +} + +bool QgsNullSymbolRenderer::renderFeature( QgsFeature &feature, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker ) +{ + //render selected features or features being edited only + if ( !selected && !drawVertexMarker ) + { + return true; + } + + if ( !feature.constGeometry() || + feature.constGeometry()->type() == QGis::NoGeometry || + feature.constGeometry()->type() == QGis::UnknownGeometry ) + return true; + + if ( mSymbol.isNull() ) + { + //create default symbol + mSymbol.reset( QgsSymbolV2::defaultSymbol( feature.constGeometry()->type() ) ); + mSymbol->startRender( context ); + } + + mSymbol->renderFeature( feature, context, layer, selected, drawVertexMarker, mCurrentVertexMarkerType, mCurrentVertexMarkerSize ); + + return true; +} + +void QgsNullSymbolRenderer::startRender( QgsRenderContext& context, const QgsFields& fields ) +{ + Q_UNUSED( context ); + Q_UNUSED( fields ); +} + +void QgsNullSymbolRenderer::stopRender( QgsRenderContext& context ) +{ + if ( mSymbol.data() ) + { + mSymbol->stopRender( context ); + } +} + +bool QgsNullSymbolRenderer::willRenderFeature( QgsFeature&, QgsRenderContext& ) +{ + //return true for every feature - so they are still selectable + return true; +} + +QList QgsNullSymbolRenderer::usedAttributes() +{ + return QList(); +} + +QString QgsNullSymbolRenderer::dump() const +{ + return QString( "NULL" ); +} + +QgsFeatureRendererV2* QgsNullSymbolRenderer::clone() const +{ + QgsNullSymbolRenderer* r = new QgsNullSymbolRenderer(); + return r; +} + +QgsSymbolV2List QgsNullSymbolRenderer::symbols( QgsRenderContext& ) +{ + return QgsSymbolV2List(); +} + +QgsFeatureRendererV2* QgsNullSymbolRenderer::create( QDomElement& element ) +{ + Q_UNUSED( element ); + QgsNullSymbolRenderer* r = new QgsNullSymbolRenderer(); + return r; +} + +QDomElement QgsNullSymbolRenderer::save( QDomDocument& doc ) +{ + QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME ); + rendererElem.setAttribute( "type", "nullSymbol" ); + return rendererElem; +} + +QgsNullSymbolRenderer* QgsNullSymbolRenderer::convertFromRenderer( const QgsFeatureRendererV2 *renderer ) +{ + Q_UNUSED( renderer ); + return new QgsNullSymbolRenderer(); +} diff --git a/src/core/symbology-ng/qgsnullsymbolrenderer.h b/src/core/symbology-ng/qgsnullsymbolrenderer.h new file mode 100644 index 00000000000..4442c1b2434 --- /dev/null +++ b/src/core/symbology-ng/qgsnullsymbolrenderer.h @@ -0,0 +1,71 @@ +/*************************************************************************** + qgsnullsymbolrenderer.h + --------------------- + begin : November 2014 + copyright : (C) 2014 by Nyall Dawson + email : nyall dot dawson at gmail dot com + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef QGSNULLSYMBOLRENDERER_H +#define QGSNULLSYMBOLRENDERER_H + +#include "qgis.h" +#include "qgsrendererv2.h" +#include "qgssymbolv2.h" + +/** \ingroup core + * \class QgsNullSymbolRenderer + * \brief Null symbol renderer. Renderer which draws no symbols for features by default, but allows for labeling + * and diagrams for the layer. Selected features will also be drawn with a default symbol. + * \note Added in version 2.16 + */ + +class CORE_EXPORT QgsNullSymbolRenderer : public QgsFeatureRendererV2 +{ + public: + + QgsNullSymbolRenderer(); + + virtual ~QgsNullSymbolRenderer(); + + virtual QgsSymbolV2* symbolForFeature( QgsFeature& feature, QgsRenderContext& context ) override; + virtual QgsSymbolV2* originalSymbolForFeature( QgsFeature& feature, QgsRenderContext& context ) override; + + virtual bool renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer = -1, bool selected = false, bool drawVertexMarker = false ) override; + virtual void startRender( QgsRenderContext& context, const QgsFields& fields ) override; + virtual void stopRender( QgsRenderContext& context ) override; + virtual bool willRenderFeature( QgsFeature& feat, QgsRenderContext& context ) override; + + virtual QList usedAttributes() override; + virtual QString dump() const override; + virtual QgsFeatureRendererV2* clone() const override; + virtual QgsSymbolV2List symbols( QgsRenderContext& context ) override; + + /** Creates a null renderer from XML element. + * @param element DOM element + * @returns new null symbol renderer + */ + static QgsFeatureRendererV2* create( QDomElement& element ); + + virtual QDomElement save( QDomDocument& doc ) override; + + /** Creates a QgsNullSymbolRenderer from an existing renderer. + * @param renderer renderer to convert from + * @returns a new renderer if the conversion was possible, otherwise nullptr. + */ + static QgsNullSymbolRenderer* convertFromRenderer( const QgsFeatureRendererV2 *renderer ); + + private: + + //! Symbol to use for rendering selected features + QScopedPointer mSymbol; + +}; + +#endif // QGSNULLSYMBOLRENDERER_H diff --git a/src/core/symbology-ng/qgsrendererv2registry.cpp b/src/core/symbology-ng/qgsrendererv2registry.cpp index 2a99e29ba5f..0cfd820de01 100644 --- a/src/core/symbology-ng/qgsrendererv2registry.cpp +++ b/src/core/symbology-ng/qgsrendererv2registry.cpp @@ -23,6 +23,7 @@ #include "qgsinvertedpolygonrenderer.h" #include "qgsheatmaprenderer.h" #include "qgs25drenderer.h" +#include "qgsnullsymbolrenderer.h" QgsRendererV2Registry::QgsRendererV2Registry() { @@ -61,6 +62,10 @@ QgsRendererV2Registry::QgsRendererV2Registry() addRenderer( new QgsRendererV2Metadata( "25dRenderer", QObject::tr( "2.5 D" ), Qgs25DRenderer::create ) ); + + addRenderer( new QgsRendererV2Metadata( "nullSymbol", + QObject::tr( "No Symbols" ), + QgsNullSymbolRenderer::create ) ); } QgsRendererV2Registry::~QgsRendererV2Registry() diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 4c350ed8bdb..a5837d62eca 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -22,6 +22,7 @@ SET(QGIS_GUI_SRCS symbology-ng/qgsheatmaprendererwidget.cpp symbology-ng/qgsinvertedpolygonrendererwidget.cpp symbology-ng/qgslayerpropertieswidget.cpp + symbology-ng/qgsnullsymbolrendererwidget.cpp symbology-ng/qgspenstylecombobox.cpp symbology-ng/qgspointdisplacementrendererwidget.cpp symbology-ng/qgsrendererv2propertiesdialog.cpp @@ -427,6 +428,7 @@ SET(QGIS_GUI_MOC_HDRS symbology-ng/qgsheatmaprendererwidget.h symbology-ng/qgsinvertedpolygonrendererwidget.h symbology-ng/qgslayerpropertieswidget.h + symbology-ng/qgsnullsymbolrendererwidget.h symbology-ng/qgspenstylecombobox.h symbology-ng/qgspointdisplacementrendererwidget.h symbology-ng/qgsrendererv2propertiesdialog.h diff --git a/src/gui/symbology-ng/qgsnullsymbolrendererwidget.cpp b/src/gui/symbology-ng/qgsnullsymbolrendererwidget.cpp new file mode 100644 index 00000000000..5c2c091d524 --- /dev/null +++ b/src/gui/symbology-ng/qgsnullsymbolrendererwidget.cpp @@ -0,0 +1,52 @@ +/*************************************************************************** + qgsnullsymbolrendererwidget.cpp + --------------------- + begin : November 2014 + copyright : (C) 2014 by Nyall Dawson + email : nyall dot dawson at gmail dot com + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#include "qgsnullsymbolrendererwidget.h" + +#include "qgsnullsymbolrenderer.h" +#include "qgssymbolv2.h" +#include +#include + +QgsRendererV2Widget* QgsNullSymbolRendererWidget::create( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer ) +{ + return new QgsNullSymbolRendererWidget( layer, style, renderer ); +} + +QgsNullSymbolRendererWidget::QgsNullSymbolRendererWidget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer ) + : QgsRendererV2Widget( layer, style ) +{ + if ( renderer ) + { + mRenderer = QgsNullSymbolRenderer::convertFromRenderer( renderer ); + } + if ( !mRenderer ) + { + mRenderer = new QgsNullSymbolRenderer(); + } + + QGridLayout* layout = new QGridLayout( this ); + QLabel* label = new QLabel( tr( "No symbols will be rendered for features in this layer." ) ); + layout->addWidget( label ); +} + +QgsNullSymbolRendererWidget::~QgsNullSymbolRendererWidget() +{ + delete mRenderer; +} + +QgsFeatureRendererV2* QgsNullSymbolRendererWidget::renderer() +{ + return mRenderer; +} diff --git a/src/gui/symbology-ng/qgsnullsymbolrendererwidget.h b/src/gui/symbology-ng/qgsnullsymbolrendererwidget.h new file mode 100644 index 00000000000..2f723370ed0 --- /dev/null +++ b/src/gui/symbology-ng/qgsnullsymbolrendererwidget.h @@ -0,0 +1,55 @@ +/*************************************************************************** + qgsnullsymbolrendererwidget.h + --------------------- + begin : November 2014 + copyright : (C) 2014 by Nyall Dawson + email : nyall dot dawson at gmail dot com + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef QGSNULLSYMBOLRENDERERWIDGET_H +#define QGSNULLSYMBOLRENDERERWIDGET_H + +#include "qgsrendererv2widget.h" + +class QgsNullSymbolRenderer; +class QgsSymbolV2SelectorDialog; + +class QMenu; + +/** \ingroup gui + * \class QgsNullSymbolRendererWidget + * \brief Blank widget for customising QgsNullSymbolRenderer. + * \note Added in version 2.16 + */ + +class GUI_EXPORT QgsNullSymbolRendererWidget : public QgsRendererV2Widget +{ + Q_OBJECT + + public: + + //! Creates a new QgsNullSymbolRendererWidget object + static QgsRendererV2Widget* create( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer ); + + //! Constructor for QgsNullSymbolRendererWidget + QgsNullSymbolRendererWidget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer ); + ~QgsNullSymbolRendererWidget(); + + //! Returns a pointer to the configured renderer + virtual QgsFeatureRendererV2* renderer(); + + protected: + + //! Renderer being configured by the widget + QgsNullSymbolRenderer* mRenderer; + +}; + + +#endif // QGSNULLSYMBOLRENDERERWIDGET_H diff --git a/src/gui/symbology-ng/qgsrendererv2propertiesdialog.cpp b/src/gui/symbology-ng/qgsrendererv2propertiesdialog.cpp index 25e3cb96b05..5cfb14b75e9 100644 --- a/src/gui/symbology-ng/qgsrendererv2propertiesdialog.cpp +++ b/src/gui/symbology-ng/qgsrendererv2propertiesdialog.cpp @@ -26,6 +26,7 @@ #include "qgsinvertedpolygonrendererwidget.h" #include "qgsheatmaprendererwidget.h" #include "qgs25drendererwidget.h" +#include "qgsnullsymbolrendererwidget.h" #include "qgsorderbydialog.h" #include "qgsapplication.h" @@ -73,6 +74,7 @@ static void _initRendererWidgetFunctions() _initRenderer( "invertedPolygonRenderer", QgsInvertedPolygonRendererWidget::create, "rendererInvertedSymbol.svg" ); _initRenderer( "heatmapRenderer", QgsHeatmapRendererWidget::create, "rendererHeatmapSymbol.svg" ); _initRenderer( "25dRenderer", Qgs25DRendererWidget::create, "renderer25dSymbol.svg" ); + _initRenderer( "nullSymbol", QgsNullSymbolRendererWidget::create, "rendererNullSymbol.svg" ); initialized = true; } diff --git a/tests/src/python/CMakeLists.txt b/tests/src/python/CMakeLists.txt index 909c2e53c7a..ce20be61148 100644 --- a/tests/src/python/CMakeLists.txt +++ b/tests/src/python/CMakeLists.txt @@ -44,6 +44,7 @@ ADD_PYTHON_TEST(PyQgsGraduatedSymbolRendererV2 test_qgsgraduatedsymbolrendererv2 ADD_PYTHON_TEST(PyQgsMapUnitScale test_qgsmapunitscale.py) ADD_PYTHON_TEST(PyQgsMemoryProvider test_provider_memory.py) ADD_PYTHON_TEST(PyQgsNetworkContentFetcher test_qgsnetworkcontentfetcher.py) +ADD_PYTHON_TEST(PyQgsNullSymbolRenderer test_qgsnullsymbolrenderer.py) ADD_PYTHON_TEST(PyQgsPalLabelingBase test_qgspallabeling_base.py) ADD_PYTHON_TEST(PyQgsPalLabelingCanvas test_qgspallabeling_canvas.py) ADD_PYTHON_TEST(PyQgsPalLabelingComposer test_qgspallabeling_composer.py) diff --git a/tests/src/python/test_qgsnullsymbolrenderer.py b/tests/src/python/test_qgsnullsymbolrenderer.py new file mode 100644 index 00000000000..a2305abed41 --- /dev/null +++ b/tests/src/python/test_qgsnullsymbolrenderer.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** + test_qgsnullsymbolrenderer.py + ----------------------------- + Date : April 2016 + Copyright : (C) 2016 by Nyall Dawson + Email : nyall dot dawson at gmail dot com +*************************************************************************** +* * +* 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__ = 'April 2016' +__copyright__ = '(C) 2016, Nyall Dawson' +# This will get replaced with a git SHA1 when you do a git archive +__revision__ = '$Format:%H$' + +import qgis # NOQA + +import os + +from PyQt.QtCore import QSize + +from qgis.core import (QgsVectorLayer, + QgsMapLayerRegistry, + QgsRectangle, + QgsMultiRenderChecker, + QgsNullSymbolRenderer, + QgsFeatureRequest + ) +from qgis.testing import start_app, unittest +from qgis.testing.mocked import get_iface +from utilities import unitTestDataPath + +# Convenience instances in case you may need them +# not used in this test +start_app() +TEST_DATA_DIR = unitTestDataPath() + + +class TestQgsNullSymbolRenderer(unittest.TestCase): + + def setUp(self): + self.iface = get_iface() + myShpFile = os.path.join(TEST_DATA_DIR, 'polys.shp') + self.layer = QgsVectorLayer(myShpFile, 'Polys', 'ogr') + QgsMapLayerRegistry.instance().addMapLayer(self.layer) + + self.renderer = QgsNullSymbolRenderer() + self.layer.setRendererV2(self.renderer) + + rendered_layers = [self.layer.id()] + self.mapsettings = self.iface.mapCanvas().mapSettings() + self.mapsettings.setOutputSize(QSize(400, 400)) + self.mapsettings.setOutputDpi(96) + self.mapsettings.setExtent(QgsRectangle(-163, 22, -70, 52)) + self.mapsettings.setLayers(rendered_layers) + + def tearDown(self): + QgsMapLayerRegistry.instance().removeAllMapLayers() + + def testRender(self): + # test no features are rendered + renderchecker = QgsMultiRenderChecker() + renderchecker.setMapSettings(self.mapsettings) + renderchecker.setControlPathPrefix('null_renderer') + renderchecker.setControlName('expected_nullrenderer_render') + result = renderchecker.runTest('nullrenderer_render') + assert result + + def testSelected(self): + # select a feature and render + self.layer.select([1, 2, 3]) + renderchecker = QgsMultiRenderChecker() + renderchecker.setMapSettings(self.mapsettings) + renderchecker.setControlPathPrefix('null_renderer') + renderchecker.setControlName('expected_nullrenderer_selected') + result = renderchecker.runTest('nullrenderer_selected') + assert result + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/testdata/control_images/null_renderer/expected_nullrenderer_render/expected_nullrenderer_render.png b/tests/testdata/control_images/null_renderer/expected_nullrenderer_render/expected_nullrenderer_render.png new file mode 100644 index 0000000000000000000000000000000000000000..6d6735a21d3223a90cfc649deda0ebc851a6594e GIT binary patch literal 957 zcmeAS@N?(olHy`uVBq!ia0y~yU|a&k5*%zm5n-1mYaqpz|H(?D8gCb z5n0T@z}*SLjOHg#uLTOSmw5WRvOi#9W0X_knh|5fz`*R~>EaktaqI0>M_vX44u*|} z|CyfUdQ~*?2wn2pasKG=9Tv=RUS literal 0 HcmV?d00001 diff --git a/tests/testdata/control_images/null_renderer/expected_nullrenderer_selected/expected_nullrenderer_selected.png b/tests/testdata/control_images/null_renderer/expected_nullrenderer_selected/expected_nullrenderer_selected.png new file mode 100644 index 0000000000000000000000000000000000000000..442a9faba3ab08b577d24c9db19353ced38784d4 GIT binary patch literal 3467 zcmdT{c{CL48dsK5mZFjrzDo+B%piLzG0B>JOKHen$QT-Ye40v@D6-2oleKJvF-RfH zn9O7uGh?}!iLno+G0fcQ{(H~&$NkQC|G4Mr@y2f{&?rU#}4g!U;4NoxA!@DxviuAA6LPApR(;UnPq-kA^y`LwukRqZ2(RU*

C-_Ve(! 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 Is#pBK0FR(H@&Et; literal 0 HcmV?d00001