QGIS API Documentation  3.8.0-Zanzibar (11aff65)
qgspointclusterrendererwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspointclusterrendererwidget.cpp
3  ---------------------------------
4  begin : February 2016
5  copyright : (C) 2016 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
20 #include "qgsrendererregistry.h"
21 #include "qgsfield.h"
22 #include "qgsstyle.h"
24 #include "qgssymbollayerutils.h"
25 #include "qgsvectorlayer.h"
26 #include "qgsguiutils.h"
27 #include "qgsapplication.h"
28 
30 {
31  return new QgsPointClusterRendererWidget( layer, style, renderer );
32 }
33 
35  : QgsRendererWidget( layer, style )
36 
37 {
38  if ( !layer )
39  {
40  return;
41  }
42 
43  //the renderer only applies to point vector layers
45  {
46  //setup blank dialog
47  mRenderer = nullptr;
48  setupBlankUi( layer->name() );
49  return;
50  }
51  setupUi( this );
52  connect( mRendererComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointClusterRendererWidget::mRendererComboBox_currentIndexChanged );
53  connect( mDistanceSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsPointClusterRendererWidget::mDistanceSpinBox_valueChanged );
54  connect( mDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointClusterRendererWidget::mDistanceUnitWidget_changed );
55  connect( mRendererSettingsButton, &QPushButton::clicked, this, &QgsPointClusterRendererWidget::mRendererSettingsButton_clicked );
56  this->layout()->setContentsMargins( 0, 0, 0, 0 );
57 
60 
61  mCenterSymbolToolButton->setSymbolType( QgsSymbol::Marker );
62 
63  if ( renderer )
64  {
65  mRenderer = QgsPointClusterRenderer::convertFromRenderer( renderer );
66  }
67  if ( !mRenderer )
68  {
69  mRenderer = new QgsPointClusterRenderer();
70  }
71 
72  blockAllSignals( true );
73 
74  //insert possible renderer types
76  QStringList::const_iterator it = rendererList.constBegin();
77  for ( ; it != rendererList.constEnd(); ++it )
78  {
79  if ( *it != QLatin1String( "pointDisplacement" ) && *it != QLatin1String( "pointCluster" ) && *it != QLatin1String( "heatmapRenderer" ) )
80  {
82  mRendererComboBox->addItem( m->icon(), m->visibleName(), *it );
83  }
84  }
85 
86  mDistanceSpinBox->setValue( mRenderer->tolerance() );
87  mDistanceUnitWidget->setUnit( mRenderer->toleranceUnit() );
88  mDistanceUnitWidget->setMapUnitScale( mRenderer->toleranceMapUnitScale() );
89  mCenterSymbolToolButton->setSymbol( mRenderer->clusterSymbol()->clone() );
90 
91  blockAllSignals( false );
92 
93  //set the appropriate renderer dialog
94  if ( mRenderer->embeddedRenderer() )
95  {
96  QString rendererName = mRenderer->embeddedRenderer()->type();
97  int rendererIndex = mRendererComboBox->findData( rendererName );
98  if ( rendererIndex != -1 )
99  {
100  mRendererComboBox->setCurrentIndex( rendererIndex );
101  mRendererComboBox_currentIndexChanged( rendererIndex );
102  }
103  }
104 
105  connect( mCenterSymbolToolButton, &QgsSymbolButton::changed, this, &QgsPointClusterRendererWidget::centerSymbolChanged );
106  mCenterSymbolToolButton->setDialogTitle( tr( "Cluster symbol" ) );
107  mCenterSymbolToolButton->setLayer( mLayer );
108  mCenterSymbolToolButton->registerExpressionContextGenerator( this );
109 }
110 
112 {
113  delete mRenderer;
114 }
115 
117 {
118  return mRenderer;
119 }
120 
122 {
124  if ( mDistanceUnitWidget )
125  mDistanceUnitWidget->setMapCanvas( context.mapCanvas() );
126  if ( mCenterSymbolToolButton )
127  {
128  mCenterSymbolToolButton->setMapCanvas( context.mapCanvas() );
129  mCenterSymbolToolButton->setMessageBar( context.messageBar() );
130  }
131 }
132 
133 void QgsPointClusterRendererWidget::mRendererComboBox_currentIndexChanged( int index )
134 {
135  QString rendererId = mRendererComboBox->itemData( index ).toString();
137  if ( m )
138  {
139  // unfortunately renderer conversion is only available through the creation of a widget...
140  QgsRendererWidget *tempRenderWidget = m->createRendererWidget( mLayer, mStyle, mRenderer->embeddedRenderer()->clone() );
141  mRenderer->setEmbeddedRenderer( tempRenderWidget->renderer()->clone() );
142  delete tempRenderWidget;
143  }
144  emit widgetChanged();
145 }
146 
147 void QgsPointClusterRendererWidget::mRendererSettingsButton_clicked()
148 {
149  if ( !mRenderer )
150  return;
151 
153  if ( m )
154  {
156  w->setPanelTitle( tr( "Renderer Settings" ) );
157 
161  QList< QgsExpressionContextScope > scopes = mContext.additionalExpressionContextScopes();
162  scopes << scope;
164  context.setAdditionalExpressionContextScopes( scopes );
165  w->setContext( context );
166  connect( w, &QgsPanelWidget::widgetChanged, this, &QgsPointClusterRendererWidget::updateRendererFromWidget );
167  w->setDockMode( this->dockMode() );
168  openPanel( w );
169  }
170 }
171 
172 void QgsPointClusterRendererWidget::mDistanceSpinBox_valueChanged( double d )
173 {
174  if ( mRenderer )
175  {
176  mRenderer->setTolerance( d );
177  }
178  emit widgetChanged();
179 }
180 
181 void QgsPointClusterRendererWidget::mDistanceUnitWidget_changed()
182 {
183  if ( mRenderer )
184  {
185  mRenderer->setToleranceUnit( mDistanceUnitWidget->unit() );
186  mRenderer->setToleranceMapUnitScale( mDistanceUnitWidget->getMapUnitScale() );
187  }
188  emit widgetChanged();
189 }
190 
191 void QgsPointClusterRendererWidget::blockAllSignals( bool block )
192 {
193  mRendererComboBox->blockSignals( block );
194  mCenterSymbolToolButton->blockSignals( block );
195  mDistanceSpinBox->blockSignals( block );
196  mDistanceUnitWidget->blockSignals( block );
197 }
198 
200 {
202  if ( mContext.expressionContext() )
203  context = *mContext.expressionContext();
204  else
209  QList< QgsExpressionContextScope > scopes = mContext.additionalExpressionContextScopes();
210  scopes << scope;
211  const auto constScopes = scopes;
212  for ( const QgsExpressionContextScope &s : constScopes )
213  {
214  context << new QgsExpressionContextScope( s );
215  }
216  return context;
217 }
218 
219 void QgsPointClusterRendererWidget::centerSymbolChanged()
220 {
221  mRenderer->setClusterSymbol( mCenterSymbolToolButton->clonedSymbol< QgsMarkerSymbol >() );
222  emit widgetChanged();
223 }
224 
225 void QgsPointClusterRendererWidget::updateRendererFromWidget()
226 {
227  QgsRendererWidget *w = qobject_cast<QgsRendererWidget *>( sender() );
228  if ( !w )
229  return;
230 
231  mRenderer->setEmbeddedRenderer( w->renderer()->clone() );
232  emit widgetChanged();
233 }
234 
235 void QgsPointClusterRendererWidget::setupBlankUi( const QString &layerName )
236 {
237  QGridLayout *layout = new QGridLayout( this );
238  QLabel *label = new QLabel( tr( "The point cluster renderer only applies to (single) point layers. \n'%1' is not a (single) point layer and cannot be displayed by the point cluster renderer." ).arg( layerName ), this );
239  layout->addWidget( label );
240 }
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
static const QString EXPR_CLUSTER_COLOR
Inbuilt variable name for cluster color variable.
Single variable definition for use within a QgsExpressionContextScope.
QList< QgsExpressionContextScope * > globalProjectAtlasMapLayerScopes(const QgsMapLayer *layer) const
Returns list of scopes: global, project, atlas, map, layer.
virtual QgsFeatureRenderer * renderer()=0
Returns pointer to the renderer (no transfer of ownership)
virtual void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the renderer widget is shown, e.g., the associated map canvas and expressio...
bool dockMode()
Returns the dock mode state.
void setClusterSymbol(QgsMarkerSymbol *symbol)
Sets the symbol for rendering clustered groups.
virtual QgsRendererWidget * createRendererWidget(QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *oldRenderer)
Returns new instance of settings widget for the renderer.
QgsSymbolWidgetContext context() const
Returns the context in which the renderer widget is shown, e.g., the associated map canvas and expres...
void setContext(const QgsSymbolWidgetContext &context) override
Sets the context in which the renderer widget is shown, e.g., the associated map canvas and expressio...
QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
Base class for renderer settings widgets.
QgsMarkerSymbol * clusterSymbol()
Returns the symbol used for rendering clustered groups (but not ownership of the symbol).
void setTolerance(double distance)
Sets the tolerance distance for grouping points.
QgsVectorLayer * mLayer
void setToleranceMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the distance tolerance.
void setToleranceUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the tolerance distance.
void changed()
Emitted when the symbol&#39;s settings are changed.
QStringList renderersList(QgsRendererAbstractMetadata::LayerTypes layerTypes=QgsRendererAbstractMetadata::All) const
Returns a list of available renderers.
QList< QgsUnitTypes::RenderUnit > RenderUnitList
List of render units.
Definition: qgsunittypes.h:184
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
QgsUnitTypes::RenderUnit toleranceUnit() const
Returns the units for the tolerance distance.
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:766
virtual void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs...
static QgsPointClusterRenderer * convertFromRenderer(const QgsFeatureRenderer *renderer)
Creates a QgsPointClusterRenderer from an existing renderer.
QString type() const
Definition: qgsrenderer.h:129
Contains settings which reflect the context in which a symbol (or renderer) widget is shown...
Compatible with point layers.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
A renderer that automatically clusters points with the same geographic position.
QgsRendererAbstractMetadata * rendererMetadata(const QString &rendererName)
Returns the metadata for a specified renderer.
Single scope for storing variables and functions for use within a QgsExpressionContext.
void setAdditionalExpressionContextScopes(const QList< QgsExpressionContextScope > &scopes)
Sets a list of additional expression context scopes to show as available within the layer...
void widgetChanged()
Emitted when the widget state changes.
double tolerance() const
Returns the tolerance distance for grouping points.
const QgsMapUnitScale & toleranceMapUnitScale() const
Returns the map unit scale object for the distance tolerance.
QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Marker symbol.
Definition: qgssymbol.h:85
const QgsFeatureRenderer * embeddedRenderer() const override
Returns the current embedded renderer (subrenderer) for this feature renderer.
QgsExpressionContext * expressionContext() const
Returns the expression context used for the widget, if set.
QgsSymbolWidgetContext mContext
Context in which widget is shown.
QgsPointClusterRendererWidget(QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *renderer)
Constructor for QgsPointClusterRendererWidget.
Points (e.g., for font sizes)
Definition: qgsunittypes.h:117
Stores metadata about one renderer class.
QgsMessageBar * messageBar() const
Returns the message bar associated with the widget.
static const QString EXPR_CLUSTER_SIZE
Inbuilt variable name for cluster size variable.
QString name
Definition: qgsmaplayer.h:82
void appendScopes(const QList< QgsExpressionContextScope *> &scopes)
Appends a list of scopes to the end of the context.
void setEmbeddedRenderer(QgsFeatureRenderer *r) override
Sets an embedded renderer (subrenderer) for this feature renderer.
Represents a vector layer which manages a vector based data sets.
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:430
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
QgsFeatureRenderer * renderer() override
Returns pointer to the renderer (no transfer of ownership)
static QgsRendererRegistry * rendererRegistry()
Returns the application&#39;s renderer registry, used for managing vector layer renderers.
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:1641
static QgsRendererWidget * create(QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *renderer)
Returns a new QgsPointClusterRendererWidget.
QList< QgsExpressionContextScope > additionalExpressionContextScopes() const
Returns the list of additional expression context scopes to show as available within the layer...