Skip to content

Commit

Permalink
[FEATURE] Null ("No symbol") renderer
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
nyalldawson committed Apr 6, 2016
1 parent 86ec27e commit d464f86
Show file tree
Hide file tree
Showing 20 changed files with 566 additions and 0 deletions.
1 change: 1 addition & 0 deletions ci/travis/linux/qt5/blacklist.txt
Expand Up @@ -36,6 +36,7 @@ PyQgsLocalServer
PyQgsMapUnitScale
PyQgsMemoryProvider
PyQgsNetworkContentFetcher
PyQgsNullSymbolRenderer
PyQgsPalLabelingBase
PyQgsPalLabelingCanvas
PyQgsPalLabelingComposer
Expand Down
1 change: 1 addition & 0 deletions images/images.qrc
Expand Up @@ -486,6 +486,7 @@
<file>themes/default/rendererCategorizedSymbol.svg</file>
<file>themes/default/rendererGraduatedSymbol.png</file>
<file>themes/default/rendererGraduatedSymbol.svg</file>
<file>themes/default/rendererNullSymbol.svg</file>
<file>themes/default/rendererSingleSymbol.png</file>
<file>themes/default/rendererSingleSymbol.svg</file>
<file>themes/default/rendererRuleBasedSymbol.svg</file>
Expand Down
84 changes: 84 additions & 0 deletions images/themes/default/rendererNullSymbol.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions python/core/core.sip
Expand Up @@ -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
Expand Down
46 changes: 46 additions & 0 deletions 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 <qgsnullsymbolrenderer.h>
%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<QString> 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/;

};
2 changes: 2 additions & 0 deletions python/core/symbology-ng/qgsrendererv2.sip
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions python/gui/gui.sip
Expand Up @@ -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
Expand Down
24 changes: 24 additions & 0 deletions 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 <qgsnullsymbolrendererwidget.h>
%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();
};
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
125 changes: 125 additions & 0 deletions 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 <QDomDocument>
#include <QDomElement>

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<QString> QgsNullSymbolRenderer::usedAttributes()
{
return QList<QString>();
}

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();
}

0 comments on commit d464f86

Please sign in to comment.