Skip to content

Commit

Permalink
Create new "Embedded Symbol" renderer
Browse files Browse the repository at this point in the history
This renderer will draw features using their embedded feature symbology
  • Loading branch information
nyalldawson committed Mar 6, 2021
1 parent 4dd6a89 commit 50082a3
Show file tree
Hide file tree
Showing 13 changed files with 406 additions and 0 deletions.
@@ -0,0 +1,75 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/symbology/qgsembeddedsymbolrenderer.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/


class QgsEmbeddedSymbolRenderer : QgsFeatureRenderer
{
%Docstring

A vector feature renderer which uses embedded feature symbology to render per-feature
symbols.

This renderer can be used for vector layers with a data provider which supports the
:py:class:`QgsVectorDataProvider`.FeatureSymbology capability, where the dataset has embedded information
on how each feature should be rendered.

.. versionadded:: 3.20
%End

%TypeHeaderCode
#include "qgsembeddedsymbolrenderer.h"
%End
public:

QgsEmbeddedSymbolRenderer();
%Docstring
Constructor for QgsEmbeddedSymbolRenderer.
%End
~QgsEmbeddedSymbolRenderer();

virtual QgsSymbol *symbolForFeature( const QgsFeature &feature, QgsRenderContext &context ) const;

virtual QgsSymbol *originalSymbolForFeature( const QgsFeature &feature, QgsRenderContext &context ) const;

virtual void startRender( QgsRenderContext &context, const QgsFields &fields );

virtual bool renderFeature( const QgsFeature &feature, QgsRenderContext &context, int layer = -1, bool selected = false, bool drawVertexMarker = false ) throw( QgsCsException );

virtual void stopRender( QgsRenderContext &context );

virtual QSet<QString> usedAttributes( const QgsRenderContext &context ) const;

virtual bool usesEmbeddedSymbols() const;

virtual QgsEmbeddedSymbolRenderer *clone() const /Factory/;

virtual QgsFeatureRenderer::Capabilities capabilities();

virtual QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context );


static QgsFeatureRenderer *create( QDomElement &element, const QgsReadWriteContext &context ) /Factory/;
%Docstring
Creates a new embedded symbol renderer from an XML ``element``, using the supplied read/write ``context``.

The caller takes ownership of the returned renderer.
%End

private:
QgsEmbeddedSymbolRenderer( const QgsEmbeddedSymbolRenderer & );
QgsEmbeddedSymbolRenderer &operator=( const QgsEmbeddedSymbolRenderer & );
};


/************************************************************************
* This file has been generated automatically from *
* *
* src/core/symbology/qgsembeddedsymbolrenderer.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
2 changes: 2 additions & 0 deletions python/core/auto_generated/symbology/qgsrenderer.sip.in
Expand Up @@ -75,6 +75,8 @@ class QgsFeatureRenderer
sipType = sipType_Qgs25DRenderer;
else if ( type == QLatin1String( "nullSymbol" ) )
sipType = sipType_QgsNullSymbolRenderer;
else if ( type == QLatin1String( "embeddedSymbol" ) )
sipType = sipType_QgsEmbeddedSymbolRenderer;
else
sipType = 0;
%End
Expand Down
1 change: 1 addition & 0 deletions python/core/core_auto.sip
Expand Up @@ -559,6 +559,7 @@
%Include auto_generated/symbology/qgscolorbrewerpalette.sip
%Include auto_generated/symbology/qgscptcityarchive.sip
%Include auto_generated/symbology/qgsellipsesymbollayer.sip
%Include auto_generated/symbology/qgsembeddedsymbolrenderer.sip
%Include auto_generated/symbology/qgsfeaturerenderergenerator.sip
%Include auto_generated/symbology/qgsfillsymbollayer.sip
%Include auto_generated/symbology/qgsgeometrygeneratorsymbollayer.sip
Expand Down
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Expand Up @@ -45,6 +45,7 @@ set(QGIS_CORE_SRCS
symbology/qgscolorbrewerpalette.cpp
symbology/qgscptcityarchive.cpp
symbology/qgsellipsesymbollayer.cpp
symbology/qgsembeddedsymbolrenderer.cpp
symbology/qgsfeaturerenderergenerator.cpp
symbology/qgsfillsymbollayer.cpp
symbology/qgsgeometrygeneratorsymbollayer.cpp
Expand Down Expand Up @@ -1505,6 +1506,7 @@ set(QGIS_CORE_HDRS
symbology/qgscolorbrewerpalette.h
symbology/qgscptcityarchive.h
symbology/qgsellipsesymbollayer.h
symbology/qgsembeddedsymbolrenderer.h
symbology/qgsfeaturerenderergenerator.h
symbology/qgsfillsymbollayer.h
symbology/qgsgeometrygeneratorsymbollayer.h
Expand Down
113 changes: 113 additions & 0 deletions src/core/symbology/qgsembeddedsymbolrenderer.cpp
@@ -0,0 +1,113 @@
/***************************************************************************
qgsembeddedsymbolrenderer.cpp
---------------------
begin : March 2021
copyright : (C) 2021 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 "qgsembeddedsymbolrenderer.h"
#include "qgspainteffectregistry.h"

QgsEmbeddedSymbolRenderer::QgsEmbeddedSymbolRenderer()
: QgsFeatureRenderer( QStringLiteral( "embeddedSymbol" ) )
{
}

QgsEmbeddedSymbolRenderer::~QgsEmbeddedSymbolRenderer() = default;

QgsSymbol *QgsEmbeddedSymbolRenderer::symbolForFeature( const QgsFeature &feature, QgsRenderContext & ) const
{
return const_cast< QgsSymbol * >( feature.embeddedSymbol() );
}

QgsSymbol *QgsEmbeddedSymbolRenderer::originalSymbolForFeature( const QgsFeature &feature, QgsRenderContext &context ) const
{
Q_UNUSED( context )
return const_cast< QgsSymbol * >( feature.embeddedSymbol() );
}

void QgsEmbeddedSymbolRenderer::startRender( QgsRenderContext &context, const QgsFields &fields )
{
QgsFeatureRenderer::startRender( context, fields );
}

bool QgsEmbeddedSymbolRenderer::renderFeature( const QgsFeature &feature, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker )
{
if ( const QgsSymbol *symbol = feature.embeddedSymbol() )
{
std::unique_ptr< QgsSymbol > clone( symbol->clone() );

clone->startRender( context );
renderFeatureWithSymbol( feature, clone.get(), context, layer, selected, drawVertexMarker );
clone->stopRender( context );
return true;
}
else
{
return false;
}
return true;
}

void QgsEmbeddedSymbolRenderer::stopRender( QgsRenderContext &context )
{
QgsFeatureRenderer::stopRender( context );
}

QSet<QString> QgsEmbeddedSymbolRenderer::usedAttributes( const QgsRenderContext & ) const
{
return QSet<QString>();
}

bool QgsEmbeddedSymbolRenderer::usesEmbeddedSymbols() const
{
return true;
}

QgsEmbeddedSymbolRenderer *QgsEmbeddedSymbolRenderer::clone() const
{
QgsEmbeddedSymbolRenderer *r = new QgsEmbeddedSymbolRenderer();
r->setUsingSymbolLevels( usingSymbolLevels() );
copyRendererData( r );
return r;
}

QgsFeatureRenderer::Capabilities QgsEmbeddedSymbolRenderer::capabilities()
{
return SymbolLevels;
}

QgsFeatureRenderer *QgsEmbeddedSymbolRenderer::create( QDomElement &, const QgsReadWriteContext & )
{
QgsEmbeddedSymbolRenderer *r = new QgsEmbeddedSymbolRenderer();
return r;
}

QDomElement QgsEmbeddedSymbolRenderer::save( QDomDocument &doc, const QgsReadWriteContext & )
{
QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
rendererElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "embeddedSymbol" ) );
rendererElem.setAttribute( QStringLiteral( "symbollevels" ), ( mUsingSymbolLevels ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ) );
rendererElem.setAttribute( QStringLiteral( "forceraster" ), ( mForceRaster ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ) );

if ( mPaintEffect && !QgsPaintEffectRegistry::isDefaultStack( mPaintEffect ) )
mPaintEffect->saveProperties( doc, rendererElem );

if ( !mOrderBy.isEmpty() )
{
QDomElement orderBy = doc.createElement( QStringLiteral( "orderby" ) );
mOrderBy.save( orderBy );
rendererElem.appendChild( orderBy );
}
rendererElem.setAttribute( QStringLiteral( "enableorderby" ), ( mOrderByEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ) );

return rendererElem;
}
72 changes: 72 additions & 0 deletions src/core/symbology/qgsembeddedsymbolrenderer.h
@@ -0,0 +1,72 @@
/***************************************************************************
qgsembeddedsymbolrenderer.h
---------------------
begin : March 2021
copyright : (C) 2021 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 QGSEMBEDDEDSYMBOLRENDERER_H
#define QGSEMBEDDEDSYMBOLRENDERER_H

#include "qgis_core.h"
#include "qgis.h"
#include "qgsrenderer.h"

/**
* \ingroup core
* \class QgsEmbeddedSymbolRenderer
*
* \brief A vector feature renderer which uses embedded feature symbology to render per-feature
* symbols.
*
* This renderer can be used for vector layers with a data provider which supports the
* QgsVectorDataProvider::FeatureSymbology capability, where the dataset has embedded information
* on how each feature should be rendered.
*
* \since QGIS 3.20
*/
class CORE_EXPORT QgsEmbeddedSymbolRenderer : public QgsFeatureRenderer
{
public:

/**
* Constructor for QgsEmbeddedSymbolRenderer.
*/
QgsEmbeddedSymbolRenderer();
~QgsEmbeddedSymbolRenderer() override;

QgsSymbol *symbolForFeature( const QgsFeature &feature, QgsRenderContext &context ) const override;
QgsSymbol *originalSymbolForFeature( const QgsFeature &feature, QgsRenderContext &context ) const override;
void startRender( QgsRenderContext &context, const QgsFields &fields ) override;
bool renderFeature( const QgsFeature &feature, QgsRenderContext &context, int layer = -1, bool selected = false, bool drawVertexMarker = false ) SIP_THROW( QgsCsException ) override;
void stopRender( QgsRenderContext &context ) override;
QSet<QString> usedAttributes( const QgsRenderContext &context ) const override;
bool usesEmbeddedSymbols() const override;
QgsEmbeddedSymbolRenderer *clone() const override SIP_FACTORY;
QgsFeatureRenderer::Capabilities capabilities() override;
QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) override;

/**
* Creates a new embedded symbol renderer from an XML \a element, using the supplied read/write \a context.
*
* The caller takes ownership of the returned renderer.
*/
static QgsFeatureRenderer *create( QDomElement &element, const QgsReadWriteContext &context ) SIP_FACTORY;

private:
#ifdef SIP_RUN
QgsEmbeddedSymbolRenderer( const QgsEmbeddedSymbolRenderer & );
QgsEmbeddedSymbolRenderer &operator=( const QgsEmbeddedSymbolRenderer & );
#endif

};


#endif // QGSEMBEDDEDSYMBOLRENDERER_H
2 changes: 2 additions & 0 deletions src/core/symbology/qgsrenderer.h
Expand Up @@ -127,6 +127,8 @@ class CORE_EXPORT QgsFeatureRenderer
sipType = sipType_Qgs25DRenderer;
else if ( type == QLatin1String( "nullSymbol" ) )
sipType = sipType_QgsNullSymbolRenderer;
else if ( type == QLatin1String( "embeddedSymbol" ) )
sipType = sipType_QgsEmbeddedSymbolRenderer;
else
sipType = 0;
SIP_END
Expand Down
5 changes: 5 additions & 0 deletions src/core/symbology/qgsrendererregistry.cpp
Expand Up @@ -25,6 +25,7 @@
#include "qgsmergedfeaturerenderer.h"
#include "qgsheatmaprenderer.h"
#include "qgs25drenderer.h"
#include "qgsembeddedsymbolrenderer.h"
#include "qgsnullsymbolrenderer.h"
#include "qgsvectorlayer.h"

Expand Down Expand Up @@ -95,6 +96,10 @@ QgsRendererRegistry::QgsRendererRegistry()
QIcon(),
nullptr,
QgsRendererAbstractMetadata::PolygonLayer ) );

addRenderer( new QgsRendererMetadata( QStringLiteral( "embeddedSymbol" ),
QObject::tr( "Embedded Symbols" ),
QgsEmbeddedSymbolRenderer::create ) );
}

QgsRendererRegistry::~QgsRendererRegistry()
Expand Down
1 change: 1 addition & 0 deletions tests/src/python/CMakeLists.txt
Expand Up @@ -71,6 +71,7 @@ ADD_PYTHON_TEST(PyQgsDistanceArea test_qgsdistancearea.py)
ADD_PYTHON_TEST(PyQgsEditFormConfig test_qgseditformconfig.py)
ADD_PYTHON_TEST(PyQgsEditWidgets test_qgseditwidgets.py)
ADD_PYTHON_TEST(PyQgsEllipsoidUtils test_qgsellipsoidutils.py)
ADD_PYTHON_TEST(PyQgsEmbeddedSymbolRenderer test_qgsembeddedsymbolrenderer.py)
ADD_PYTHON_TEST(PyQgsEncodingSelectionDialog test_qgsencodingselectiondialog.py)
ADD_PYTHON_TEST(PyQgsExifTools test_qgsexiftools.py)
ADD_PYTHON_TEST(PyQgsExpression test_qgsexpression.py)
Expand Down

0 comments on commit 50082a3

Please sign in to comment.