Skip to content

Commit

Permalink
Add widget for Embedded Symbols renderer
Browse files Browse the repository at this point in the history
Allows users to control the default symbol used for features without
embedded styles
  • Loading branch information
nyalldawson committed Mar 6, 2021
1 parent 031e2b0 commit 5245430
Show file tree
Hide file tree
Showing 10 changed files with 344 additions and 0 deletions.
Expand Up @@ -79,6 +79,13 @@ Ownership of ``symbol`` is transferred to the renderer.
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

static QgsEmbeddedSymbolRenderer *convertFromRenderer( const QgsFeatureRenderer *renderer ) /Factory/;
%Docstring
Creates a QgsEmbeddedSymbolRenderer from an existing ``renderer``.

:return: a new renderer if the conversion was possible, otherwise ``None``.
%End

private:
Expand Down
@@ -0,0 +1,58 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/symbology/qgsembeddedsymbolrendererwidget.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/



class QgsEmbeddedSymbolRendererWidget : QgsRendererWidget, QgsExpressionContextGenerator
{
%Docstring
A widget used represent options of a :py:class:`QgsEmbeddedSymbolRenderer`

.. versionadded:: 3.20
%End

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

static QgsRendererWidget *create( QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *renderer ) /Factory/;
%Docstring
Static creation method

:param layer: the layer where this renderer is applied
:param style:
:param renderer: the merged feature renderer (will not take ownership)
%End

QgsEmbeddedSymbolRendererWidget( QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *renderer );
%Docstring
Constructor

:param layer: the layer where this renderer is applied
:param style:
:param renderer: the merged feature renderer (will not take ownership)
%End

virtual QgsFeatureRenderer *renderer();

virtual void setContext( const QgsSymbolWidgetContext &context );

virtual QgsExpressionContext createExpressionContext() const;


};


/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/symbology/qgsembeddedsymbolrendererwidget.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
1 change: 1 addition & 0 deletions python/gui/gui_auto.sip
Expand Up @@ -390,6 +390,7 @@
%Include auto_generated/symbology/qgsdashspacedialog.sip
%Include auto_generated/symbology/qgsdatadefinedsizelegendwidget.sip
%Include auto_generated/symbology/qgsellipsesymbollayerwidget.sip
%Include auto_generated/symbology/qgsembeddedsymbolrendererwidget.sip
%Include auto_generated/symbology/qgsgraduatedhistogramwidget.sip
%Include auto_generated/symbology/qgsgraduatedsymbolrendererwidget.sip
%Include auto_generated/symbology/qgsheatmaprendererwidget.sip
Expand Down
18 changes: 18 additions & 0 deletions src/core/symbology/qgsembeddedsymbolrenderer.cpp
Expand Up @@ -16,6 +16,7 @@
#include "qgsembeddedsymbolrenderer.h"
#include "qgspainteffectregistry.h"
#include "qgssymbollayerutils.h"
#include "qgssinglesymbolrenderer.h"

QgsEmbeddedSymbolRenderer::QgsEmbeddedSymbolRenderer( QgsSymbol *defaultSymbol )
: QgsFeatureRenderer( QStringLiteral( "embeddedSymbol" ) )
Expand Down Expand Up @@ -114,6 +115,23 @@ QgsFeatureRenderer *QgsEmbeddedSymbolRenderer::create( QDomElement &element, con
return r;
}

QgsEmbeddedSymbolRenderer *QgsEmbeddedSymbolRenderer::convertFromRenderer( const QgsFeatureRenderer *renderer )
{
if ( renderer->type() == QLatin1String( "embeddedSymbol" ) )
{
return dynamic_cast<QgsEmbeddedSymbolRenderer *>( renderer->clone() );
}
else if ( renderer->type() == QLatin1String( "singleSymbol" ) )
{
std::unique_ptr< QgsEmbeddedSymbolRenderer > symbolRenderer = std::make_unique< QgsEmbeddedSymbolRenderer >( static_cast< const QgsSingleSymbolRenderer * >( renderer )->symbol()->clone() );
return symbolRenderer.release();
}
else
{
return nullptr;
}
}

QDomElement QgsEmbeddedSymbolRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context )
{
QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
Expand Down
6 changes: 6 additions & 0 deletions src/core/symbology/qgsembeddedsymbolrenderer.h
Expand Up @@ -79,6 +79,12 @@ class CORE_EXPORT QgsEmbeddedSymbolRenderer : public QgsFeatureRenderer
*/
static QgsFeatureRenderer *create( QDomElement &element, const QgsReadWriteContext &context ) SIP_FACTORY;

/**
* Creates a QgsEmbeddedSymbolRenderer from an existing \a renderer.
* \returns a new renderer if the conversion was possible, otherwise NULLPTR.
*/
static QgsEmbeddedSymbolRenderer *convertFromRenderer( const QgsFeatureRenderer *renderer ) SIP_FACTORY;

private:
#ifdef SIP_RUN
QgsEmbeddedSymbolRenderer( const QgsEmbeddedSymbolRenderer & );
Expand Down
2 changes: 2 additions & 0 deletions src/gui/CMakeLists.txt
Expand Up @@ -38,6 +38,7 @@ set(QGIS_GUI_SRCS
symbology/qgsdashspacedialog.cpp
symbology/qgsdatadefinedsizelegendwidget.cpp
symbology/qgsellipsesymbollayerwidget.cpp
symbology/qgsembeddedsymbolrendererwidget.cpp
symbology/qgsgraduatedhistogramwidget.cpp
symbology/qgsgraduatedsymbolrendererwidget.cpp
symbology/qgsheatmaprendererwidget.cpp
Expand Down Expand Up @@ -1193,6 +1194,7 @@ set(QGIS_GUI_HDRS
symbology/qgsdashspacedialog.h
symbology/qgsdatadefinedsizelegendwidget.h
symbology/qgsellipsesymbollayerwidget.h
symbology/qgsembeddedsymbolrendererwidget.h
symbology/qgsgraduatedhistogramwidget.h
symbology/qgsgraduatedsymbolrendererwidget.h
symbology/qgsheatmaprendererwidget.h
Expand Down
112 changes: 112 additions & 0 deletions src/gui/symbology/qgsembeddedsymbolrendererwidget.cpp
@@ -0,0 +1,112 @@
/***************************************************************************
qgsembeddedsymbolrendererwidget.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 "qgsembeddedsymbolrendererwidget.h"
#include "qgsembeddedsymbolrenderer.h"
#include "qgsrendererregistry.h"

#include "qgssymbol.h"

#include "qgslogger.h"
#include "qgsvectorlayer.h"
#include "qgsapplication.h"

QgsRendererWidget *QgsEmbeddedSymbolRendererWidget::create( QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *renderer )
{
return new QgsEmbeddedSymbolRendererWidget( layer, style, renderer );
}

QgsEmbeddedSymbolRendererWidget::QgsEmbeddedSymbolRendererWidget( QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *renderer )
: QgsRendererWidget( layer, style )
{
if ( !layer )
{
return;
}

QgsWkbTypes::GeometryType type = QgsWkbTypes::geometryType( layer->wkbType() );

// the renderer only applies to layers with providers supporting embedded symbols
if ( !( layer->dataProvider()->capabilities() & QgsVectorDataProvider::FeatureSymbology ) )
{
//setup blank dialog
mRenderer.reset( nullptr );
QGridLayout *layout = new QGridLayout( this );
QLabel *label = new QLabel( tr( "The embedded symbols renderer can only be used with layers\n"
"containing embedded styling information.\n\n"
"'%1' does not contain embedded styling and cannot be displayed." )
.arg( layer->name() ), this );
this->setLayout( layout );
layout->addWidget( label );
return;
}
setupUi( this );

mDefaultSymbolToolButton->setSymbolType( QgsSymbol::symbolTypeForGeometryType( type ) );

// try to recognize the previous renderer
// (null renderer means "no previous renderer")
if ( renderer )
{
mRenderer.reset( QgsEmbeddedSymbolRenderer::convertFromRenderer( renderer ) );
}
if ( ! mRenderer )
{
// use default embedded renderer
mRenderer.reset( new QgsEmbeddedSymbolRenderer( QgsSymbol::defaultSymbol( type ) ) );
}

mDefaultSymbolToolButton->setSymbol( mRenderer->defaultSymbol()->clone() );
mDefaultSymbolToolButton->setDialogTitle( tr( "Default symbol" ) );
mDefaultSymbolToolButton->setLayer( mLayer );
mDefaultSymbolToolButton->registerExpressionContextGenerator( this );

connect( mDefaultSymbolToolButton, &QgsSymbolButton::changed, this, [ = ]
{
mRenderer->setDefaultSymbol( mDefaultSymbolToolButton->symbol()->clone() );
emit widgetChanged();
} );
}

QgsFeatureRenderer *QgsEmbeddedSymbolRendererWidget::renderer()
{
return mRenderer.get();
}

void QgsEmbeddedSymbolRendererWidget::setContext( const QgsSymbolWidgetContext &context )
{
QgsRendererWidget::setContext( context );
if ( mDefaultSymbolToolButton )
{
mDefaultSymbolToolButton->setMapCanvas( context.mapCanvas() );
mDefaultSymbolToolButton->setMessageBar( context.messageBar() );
}
}

QgsExpressionContext QgsEmbeddedSymbolRendererWidget::createExpressionContext() const
{
QgsExpressionContext context;
if ( QgsExpressionContext *expressionContext = mContext.expressionContext() )
context = *expressionContext;
else
context.appendScopes( mContext.globalProjectAtlasMapLayerScopes( mLayer ) );

const QList< QgsExpressionContextScope > scopes = mContext.additionalExpressionContextScopes();
for ( const QgsExpressionContextScope &s : scopes )
{
context << new QgsExpressionContextScope( s );
}
return context;
}

65 changes: 65 additions & 0 deletions src/gui/symbology/qgsembeddedsymbolrendererwidget.h
@@ -0,0 +1,65 @@
/***************************************************************************
qgsembeddedsymbolrendererwidget.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 QGSEMBEDDEDSYMBOLRENDERERWIDGET_H
#define QGSEMBEDDEDSYMBOLRENDERERWIDGET_H

#include "ui_qgsembeddedsymbolrendererwidgetbase.h"
#include "qgis_sip.h"
#include "qgsembeddedsymbolrenderer.h"
#include "qgsrendererwidget.h"
#include "qgis_gui.h"

class QMenu;

/**
* \ingroup gui
* \brief A widget used represent options of a QgsEmbeddedSymbolRenderer
*
* \since QGIS 3.20
*/
class GUI_EXPORT QgsEmbeddedSymbolRendererWidget : public QgsRendererWidget, public QgsExpressionContextGenerator, private Ui::QgsEmbeddedSymbolRendererWidgetBase
{
Q_OBJECT

public:

/**
* Static creation method
* \param layer the layer where this renderer is applied
* \param style
* \param renderer the merged feature renderer (will not take ownership)
*/
static QgsRendererWidget *create( QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *renderer ) SIP_FACTORY;

/**
* Constructor
* \param layer the layer where this renderer is applied
* \param style
* \param renderer the merged feature renderer (will not take ownership)
*/
QgsEmbeddedSymbolRendererWidget( QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *renderer );

QgsFeatureRenderer *renderer() override;
void setContext( const QgsSymbolWidgetContext &context ) override;
QgsExpressionContext createExpressionContext() const override;

private:
//! The renderer
std::unique_ptr<QgsEmbeddedSymbolRenderer> mRenderer;

};


#endif // QGSEMBEDDEDSYMBOLRENDERERWIDGET_H
2 changes: 2 additions & 0 deletions src/gui/symbology/qgsrendererpropertiesdialog.cpp
Expand Up @@ -29,6 +29,7 @@
#include "qgsheatmaprendererwidget.h"
#include "qgs25drendererwidget.h"
#include "qgsnullsymbolrendererwidget.h"
#include "qgsembeddedsymbolrendererwidget.h"
#include "qgspanelwidget.h"
#include "qgspainteffect.h"

Expand Down Expand Up @@ -78,6 +79,7 @@ static void _initRendererWidgetFunctions()
_initRenderer( QStringLiteral( "heatmapRenderer" ), QgsHeatmapRendererWidget::create, QStringLiteral( "rendererHeatmapSymbol.svg" ) );
_initRenderer( QStringLiteral( "25dRenderer" ), Qgs25DRendererWidget::create, QStringLiteral( "renderer25dSymbol.svg" ) );
_initRenderer( QStringLiteral( "nullSymbol" ), QgsNullSymbolRendererWidget::create, QStringLiteral( "rendererNullSymbol.svg" ) );
_initRenderer( QStringLiteral( "embeddedSymbol" ), QgsEmbeddedSymbolRendererWidget::create );
sInitialized = true;
}

Expand Down

0 comments on commit 5245430

Please sign in to comment.