QGIS API Documentation  2.99.0-Master (53aba61)
qgspointdisplacementrendererwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspointdisplacementrendererwidget.cpp
3  --------------------------------------
4  begin : January 26, 2010
5  copyright : (C) 2010 by Marco Hugentobler
6  email : marco at hugis dot net
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 "qgsfields.h"
22 #include "qgsstyle.h"
24 #include "qgssymbollayerutils.h"
25 #include "qgsvectorlayer.h"
26 #include "qgsguiutils.h"
27 
29 {
30  return new QgsPointDisplacementRendererWidget( layer, style, renderer );
31 }
32 
34  : QgsRendererWidget( layer, style )
35 
36 {
37  if ( !layer )
38  {
39  return;
40  }
41 
42  //the renderer only applies to point vector layers
43  if ( layer->wkbType() != QgsWkbTypes::Point && layer->wkbType() != QgsWkbTypes::Point25D )
44  {
45  //setup blank dialog
46  mRenderer = nullptr;
47  setupBlankUi( layer->name() );
48  return;
49  }
50  setupUi( this );
51  this->layout()->setContentsMargins( 0, 0, 0, 0 );
52 
53  mLabelFontButton->setMode( QgsFontButton::ModeQFont );
56  mCenterSymbolToolButton->setSymbolType( QgsSymbol::Marker );
57 
58  if ( renderer )
59  {
61  }
62  if ( !mRenderer )
63  {
64  mRenderer = new QgsPointDisplacementRenderer();
65  }
66 
67  blockAllSignals( true );
68 
69  mPlacementComboBox->addItem( tr( "Ring" ), QgsPointDisplacementRenderer::Ring );
70  mPlacementComboBox->addItem( tr( "Concentric rings" ), QgsPointDisplacementRenderer::ConcentricRings );
71 
72  //insert attributes into combo box
73  if ( layer )
74  {
75  const QgsFields layerFields = layer->fields();
76  for ( const QgsField &f : layerFields )
77  {
78  mLabelFieldComboBox->addItem( f.name() );
79  }
80  mLabelFieldComboBox->addItem( tr( "None" ) );
81 
82  QString currentLabelAttribute = mRenderer->labelAttributeName();
83  if ( !currentLabelAttribute.isEmpty() )
84  {
85  mLabelFieldComboBox->setCurrentIndex( mLabelFieldComboBox->findText( currentLabelAttribute ) );
86  }
87  else
88  {
89  mLabelFieldComboBox->setCurrentIndex( mLabelFieldComboBox->findText( tr( "None" ) ) );
90  }
91  }
92 
93  //insert possible renderer types
95  QStringList::const_iterator it = rendererList.constBegin();
96  for ( ; it != rendererList.constEnd(); ++it )
97  {
98  if ( *it != QLatin1String( "pointDisplacement" ) && *it != QLatin1String( "pointCluster" ) && *it != QLatin1String( "heatmapRenderer" ) )
99  {
101  mRendererComboBox->addItem( m->icon(), m->visibleName(), *it );
102  }
103  }
104 
105  mCircleColorButton->setColorDialogTitle( tr( "Select Color" ) );
106  mCircleColorButton->setContext( QStringLiteral( "symbology" ) );
107  mCircleColorButton->setAllowOpacity( true );
108  mCircleColorButton->setShowNoColor( true );
109  mCircleColorButton->setNoColorString( tr( "No stroke" ) );
110  mLabelColorButton->setContext( QStringLiteral( "symbology" ) );
111  mLabelColorButton->setColorDialogTitle( tr( "Select Color" ) );
112  mLabelColorButton->setAllowOpacity( true );
113 
114  mCircleWidthSpinBox->setValue( mRenderer->circleWidth() );
115  mCircleColorButton->setColor( mRenderer->circleColor() );
116  mLabelColorButton->setColor( mRenderer->labelColor() );
117  mLabelFontButton->setCurrentFont( mRenderer->labelFont() );
118  mCircleModificationSpinBox->setClearValue( 0.0 );
119  mCircleModificationSpinBox->setValue( mRenderer->circleRadiusAddition() );
120  mDistanceSpinBox->setValue( mRenderer->tolerance() );
121  mDistanceUnitWidget->setUnit( mRenderer->toleranceUnit() );
122  mDistanceUnitWidget->setMapUnitScale( mRenderer->toleranceMapUnitScale() );
123  mCenterSymbolToolButton->setSymbol( mRenderer->centerSymbol()->clone() );
124 
125  mPlacementComboBox->setCurrentIndex( mPlacementComboBox->findData( mRenderer->placement() ) );
126 
127  //scale dependent labeling
128  mMinLabelScaleWidget->setScale( std::max( mRenderer->minimumLabelScale(), 0.0 ) );
129  if ( mRenderer->minimumLabelScale() > 0 )
130  {
131  mScaleDependentLabelsCheckBox->setCheckState( Qt::Checked );
132  }
133  else
134  {
135  mScaleDependentLabelsCheckBox->setCheckState( Qt::Unchecked );
136  mMinLabelScaleWidget->setEnabled( false );
137  }
138 
139 
140  blockAllSignals( false );
141 
142  //set the appropriate renderer dialog
143  if ( mRenderer->embeddedRenderer() )
144  {
145  QString rendererName = mRenderer->embeddedRenderer()->type();
146  int rendererIndex = mRendererComboBox->findData( rendererName );
147  if ( rendererIndex != -1 )
148  {
149  mRendererComboBox->setCurrentIndex( rendererIndex );
150  on_mRendererComboBox_currentIndexChanged( rendererIndex );
151  }
152  }
153 
154  connect( mMinLabelScaleWidget, &QgsScaleWidget::scaleChanged, this, &QgsPointDisplacementRendererWidget::minLabelScaleChanged );
155  connect( mLabelFontButton, &QgsFontButton::changed, this, &QgsPointDisplacementRendererWidget::labelFontChanged );
156  connect( mCenterSymbolToolButton, &QgsSymbolButton::changed, this, &QgsPointDisplacementRendererWidget::centerSymbolChanged );
157  mCenterSymbolToolButton->setDialogTitle( tr( "Center symbol" ) );
158  mCenterSymbolToolButton->setLayer( mLayer );
159  mCenterSymbolToolButton->registerExpressionContextGenerator( this );
160 }
161 
163 {
164  delete mRenderer;
165 }
166 
168 {
169  return mRenderer;
170 }
171 
173 {
175  if ( mDistanceUnitWidget )
176  mDistanceUnitWidget->setMapCanvas( context.mapCanvas() );
177  if ( mMinLabelScaleWidget )
178  {
179  mMinLabelScaleWidget->setMapCanvas( context.mapCanvas() );
180  mMinLabelScaleWidget->setShowCurrentScaleButton( true );
181  }
182  if ( mCenterSymbolToolButton )
183  {
184  mCenterSymbolToolButton->setMapCanvas( context.mapCanvas() );
185  }
186 }
187 
189 {
191  if ( mContext.expressionContext() )
192  context = *mContext.expressionContext();
193  else
198  QList< QgsExpressionContextScope > scopes = mContext.additionalExpressionContextScopes();
199  scopes << scope;
200  Q_FOREACH ( const QgsExpressionContextScope &s, scopes )
201  {
202  context << new QgsExpressionContextScope( s );
203  }
204  return context;
205 }
206 
207 void QgsPointDisplacementRendererWidget::on_mLabelFieldComboBox_currentIndexChanged( const QString &text )
208 {
209  if ( mRenderer )
210  {
211  if ( text == tr( "None" ) )
212  {
213  mRenderer->setLabelAttributeName( QLatin1String( "" ) );
214  }
215  else
216  {
217  mRenderer->setLabelAttributeName( text );
218  }
219  emit widgetChanged();
220  }
221 }
222 
223 void QgsPointDisplacementRendererWidget::on_mRendererComboBox_currentIndexChanged( int index )
224 {
225  QString rendererId = mRendererComboBox->itemData( index ).toString();
227  if ( m )
228  {
229  // unfortunately renderer conversion is only available through the creation of a widget...
230  QgsRendererWidget *tempRenderWidget = m->createRendererWidget( mLayer, mStyle, mRenderer->embeddedRenderer()->clone() );
231  mRenderer->setEmbeddedRenderer( tempRenderWidget->renderer()->clone() );
232  delete tempRenderWidget;
233  emit widgetChanged();
234  }
235 }
236 
237 void QgsPointDisplacementRendererWidget::on_mPlacementComboBox_currentIndexChanged( int index )
238 {
239  if ( !mRenderer )
240  return;
241 
242  mRenderer->setPlacement( ( QgsPointDisplacementRenderer::Placement )mPlacementComboBox->itemData( index ).toInt() );
243  emit widgetChanged();
244 }
245 
246 void QgsPointDisplacementRendererWidget::on_mRendererSettingsButton_clicked()
247 {
248  if ( !mRenderer )
249  return;
250 
252  if ( m )
253  {
255  w->setPanelTitle( tr( "Renderer settings" ) );
256 
258 
262  QList< QgsExpressionContextScope > scopes = context.additionalExpressionContextScopes();
263  scopes << scope;
264  context.setAdditionalExpressionContextScopes( scopes );
265  w->setContext( context );
266 
267  connect( w, &QgsPanelWidget::widgetChanged, this, &QgsPointDisplacementRendererWidget::updateRendererFromWidget );
268  openPanel( w );
269  }
270 }
271 
272 void QgsPointDisplacementRendererWidget::labelFontChanged()
273 {
274  if ( !mRenderer )
275  {
276  return;
277  }
278 
279  mRenderer->setLabelFont( mLabelFontButton->currentFont() );
280  emit widgetChanged();
281 }
282 
283 void QgsPointDisplacementRendererWidget::on_mCircleWidthSpinBox_valueChanged( double d )
284 {
285  if ( mRenderer )
286  {
287  mRenderer->setCircleWidth( d );
288  emit widgetChanged();
289  }
290 }
291 
292 void QgsPointDisplacementRendererWidget::on_mCircleColorButton_colorChanged( const QColor &newColor )
293 {
294  if ( !mRenderer )
295  {
296  return;
297  }
298 
299  mRenderer->setCircleColor( newColor );
300  emit widgetChanged();
301 }
302 
303 void QgsPointDisplacementRendererWidget::on_mLabelColorButton_colorChanged( const QColor &newColor )
304 {
305  if ( !mRenderer )
306  {
307  return;
308  }
309 
310  mRenderer->setLabelColor( newColor );
311  emit widgetChanged();
312 }
313 
314 void QgsPointDisplacementRendererWidget::on_mCircleModificationSpinBox_valueChanged( double d )
315 {
316  if ( !mRenderer )
317  {
318  return;
319  }
320 
321  mRenderer->setCircleRadiusAddition( d );
322  emit widgetChanged();
323 }
324 
325 void QgsPointDisplacementRendererWidget::on_mDistanceSpinBox_valueChanged( double d )
326 {
327  if ( mRenderer )
328  {
329  mRenderer->setTolerance( d );
330  emit widgetChanged();
331  }
332 }
333 
334 void QgsPointDisplacementRendererWidget::on_mDistanceUnitWidget_changed()
335 {
336  if ( mRenderer )
337  {
338  mRenderer->setToleranceUnit( mDistanceUnitWidget->unit() );
339  mRenderer->setToleranceMapUnitScale( mDistanceUnitWidget->getMapUnitScale() );
340  emit widgetChanged();
341  }
342 }
343 
344 void QgsPointDisplacementRendererWidget::on_mScaleDependentLabelsCheckBox_stateChanged( int state )
345 {
346  if ( state == Qt::Unchecked )
347  {
348  mMinLabelScaleWidget->setScale( 0 );
349  mMinLabelScaleWidget->setEnabled( false );
350  }
351  else
352  {
353  mMinLabelScaleWidget->setEnabled( true );
354  }
355 }
356 
357 void QgsPointDisplacementRendererWidget::minLabelScaleChanged( double scale )
358 {
359  if ( !mRenderer )
360  {
361  return;
362  }
363 
364  mRenderer->setMinimumLabelScale( scale );
365  emit widgetChanged();
366 }
367 
368 void QgsPointDisplacementRendererWidget::blockAllSignals( bool block )
369 {
370  mLabelFieldComboBox->blockSignals( block );
371  mLabelFontButton->blockSignals( block );
372  mCircleWidthSpinBox->blockSignals( block );
373  mCircleColorButton->blockSignals( block );
374  mRendererComboBox->blockSignals( block );
375  mLabelColorButton->blockSignals( block );
376  mCircleModificationSpinBox->blockSignals( block );
377  mScaleDependentLabelsCheckBox->blockSignals( block );
378  mMinLabelScaleWidget->blockSignals( block );
379  mCenterSymbolToolButton->blockSignals( block );
380  mDistanceSpinBox->blockSignals( block );
381  mDistanceUnitWidget->blockSignals( block );
382  mPlacementComboBox->blockSignals( block );
383 }
384 
385 void QgsPointDisplacementRendererWidget::centerSymbolChanged()
386 {
387  mRenderer->setCenterSymbol( mCenterSymbolToolButton->clonedSymbol< QgsMarkerSymbol >() );
388  emit widgetChanged();
389 }
390 
391 void QgsPointDisplacementRendererWidget::updateRendererFromWidget()
392 {
393  QgsRendererWidget *w = qobject_cast<QgsRendererWidget *>( sender() );
394  if ( !w )
395  return;
396 
397  mRenderer->setEmbeddedRenderer( w->renderer()->clone() );
398  emit widgetChanged();
399 }
400 
401 void QgsPointDisplacementRendererWidget::setupBlankUi( const QString &layerName )
402 {
403  QLabel *label = new QLabel( tr( "The point displacement renderer only applies to (single) point layers. \n'%1' is not a point layer and cannot be displayed by the point displacement renderer" ).arg( layerName ), this );
404  QVBoxLayout *layout = new QVBoxLayout( this );
405  layout->setContentsMargins( 0, 0, 0, 0 );
406  layout->addWidget( label );
407 }
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
static const QString EXPR_CLUSTER_COLOR
Inbuilt variable name for cluster color variable.
Meters value as Map units.
Definition: qgsunittypes.h:107
Single variable definition for use within a QgsExpressionContextScope.
QList< QgsExpressionContextScope * > globalProjectAtlasMapLayerScopes(const QgsMapLayer *layer) const
Returns list of scopes: global, project, atlas, map, layer.
Placement
Placement methods for dispersing points.
virtual QgsFeatureRenderer * renderer()=0
return pointer to the renderer (no transfer of ownership)
QgsMarkerSymbol * centerSymbol()
Returns the symbol for the center of a displacement group (but not ownership of the symbol)...
double minimumLabelScale() const
Returns the minimum map scale (i.e.
virtual void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the renderer widget is shown, e.g., the associated map canvas and expressio...
virtual QgsRendererWidget * createRendererWidget(QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *oldRenderer)
Return 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...
Base class for renderer settings widgets.
void setLabelFont(const QFont &font)
Sets the font used for labeling points.
void setTolerance(double distance)
Sets the tolerance distance for grouping points.
QgsVectorLayer * mLayer
void setLabelColor(const QColor &color)
Sets the color to use for for labeling points.
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.
double circleRadiusAddition() const
Returns the factor for increasing the ring size of displacement groups.
Container of fields for a vector layer.
Definition: qgsfields.h:41
QStringList renderersList(QgsRendererAbstractMetadata::LayerTypes layerTypes=QgsRendererAbstractMetadata::All) const
Returns a list of available renderers.
void scaleChanged(double scale)
Emitted when user has finished editing/selecting a new scale.
QString labelAttributeName() const
Returns the attribute name used for labeling points, or an empty string if no labeling will be done b...
void setCenterSymbol(QgsMarkerSymbol *symbol)
Sets the center symbol for a displacement group.
QList< QgsUnitTypes::RenderUnit > RenderUnitList
List of render units.
Definition: qgsunittypes.h:171
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
QgsUnitTypes::RenderUnit toleranceUnit() const
Returns the units for the tolerance distance.
QFont labelFont() const
Returns the font used for labeling points.
QString type() const
Definition: qgsrenderer.h:124
QgsFields fields() const override
Returns the list of fields of this layer.
Contains settings which reflect the context in which a symbol (or renderer) widget is shown...
Compatible with point layers.
void setCircleColor(const QColor &color)
Sets the color used for drawing the displacement group circle.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsWkbTypes::Type wkbType() const override
Returns the WKBType or WKBUnknown in case of error.
points (e.g., for font sizes)
Definition: qgsunittypes.h:105
void setLabelAttributeName(const QString &name)
Sets the attribute name for labeling points.
QColor circleColor() const
Returns the color used for drawing the displacement group circle.
Place points in concentric rings around group.
QgsRendererAbstractMetadata * rendererMetadata(const QString &rendererName)
Returns the metadata for a specified renderer.
void changed()
Emitted when the widget&#39;s text format settings are changed.
void setPlacement(Placement placement)
Sets the placement method used for dispersing the points.
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:46
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.
Place points in a single ring around group.
A renderer that automatically displaces points with the same geographic location. ...
QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
Marker symbol.
Definition: qgssymbol.h:84
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.
void setMinimumLabelScale(double scale)
Sets the minimum map scale (i.e.
Stores metadata about one renderer class.
static const QString EXPR_CLUSTER_SIZE
Inbuilt variable name for cluster size variable.
Configure font settings for use with QFont objects.
Definition: qgsfontbutton.h:57
QString name
Definition: qgsmaplayer.h:58
QgsFeatureRenderer * renderer() override
return pointer to the renderer (no transfer of ownership)
void appendScopes(const QList< QgsExpressionContextScope *> &scopes)
Appends a list of scopes to the end of the context.
void setContext(const QgsSymbolWidgetContext &context) override
Sets the context in which the renderer widget is shown, e.g., the associated map canvas and expressio...
Placement placement() const
Returns the placement method used for dispersing the points.
void setCircleRadiusAddition(double distance)
Sets a factor for increasing the ring size of displacement groups.
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 QgsRendererWidget * create(QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *renderer)
static QgsPointDisplacementRenderer * convertFromRenderer(const QgsFeatureRenderer *renderer)
Creates a QgsPointDisplacementRenderer from an existing renderer.
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
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.
virtual QgsMarkerSymbol * clone() const override
Get a deep copy of this symbol.
Definition: qgssymbol.cpp:1503
void setCircleWidth(double width)
Sets the line width for the displacement group circle.
QColor labelColor() const
Returns the color used for for labeling points.
QList< QgsExpressionContextScope > additionalExpressionContextScopes() const
Returns the list of additional expression context scopes to show as available within the layer...
double circleWidth() const
Returns the line width for the displacement group circle in mm.
QgsPointDisplacementRendererWidget(QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *renderer)