QGIS API Documentation  2.99.0-Master (0cba29c)
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  , mRenderer( nullptr )
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 
57  if ( renderer )
58  {
60  }
61  if ( !mRenderer )
62  {
63  mRenderer = new QgsPointDisplacementRenderer();
64  }
65 
66  blockAllSignals( true );
67 
68  mPlacementComboBox->addItem( tr( "Ring" ), QgsPointDisplacementRenderer::Ring );
69  mPlacementComboBox->addItem( tr( "Concentric rings" ), QgsPointDisplacementRenderer::ConcentricRings );
70 
71  //insert attributes into combo box
72  if ( layer )
73  {
74  Q_FOREACH ( const QgsField &f, layer->fields() )
75  {
76  mLabelFieldComboBox->addItem( f.name() );
77  }
78  mLabelFieldComboBox->addItem( tr( "None" ) );
79 
80  QString currentLabelAttribute = mRenderer->labelAttributeName();
81  if ( !currentLabelAttribute.isEmpty() )
82  {
83  mLabelFieldComboBox->setCurrentIndex( mLabelFieldComboBox->findText( currentLabelAttribute ) );
84  }
85  else
86  {
87  mLabelFieldComboBox->setCurrentIndex( mLabelFieldComboBox->findText( tr( "None" ) ) );
88  }
89  }
90 
91  //insert possible renderer types
93  QStringList::const_iterator it = rendererList.constBegin();
94  for ( ; it != rendererList.constEnd(); ++it )
95  {
96  if ( *it != QLatin1String( "pointDisplacement" ) && *it != QLatin1String( "pointCluster" ) && *it != QLatin1String( "heatmapRenderer" ) )
97  {
99  mRendererComboBox->addItem( m->icon(), m->visibleName(), *it );
100  }
101  }
102 
103  mCircleColorButton->setColorDialogTitle( tr( "Select color" ) );
104  mCircleColorButton->setContext( QStringLiteral( "symbology" ) );
105  mCircleColorButton->setAllowOpacity( true );
106  mCircleColorButton->setShowNoColor( true );
107  mCircleColorButton->setNoColorString( tr( "No stroke" ) );
108  mLabelColorButton->setContext( QStringLiteral( "symbology" ) );
109  mLabelColorButton->setColorDialogTitle( tr( "Select color" ) );
110  mLabelColorButton->setAllowOpacity( true );
111 
112  mCircleWidthSpinBox->setValue( mRenderer->circleWidth() );
113  mCircleColorButton->setColor( mRenderer->circleColor() );
114  mLabelColorButton->setColor( mRenderer->labelColor() );
115  mLabelFontButton->setCurrentFont( mRenderer->labelFont() );
116  mCircleModificationSpinBox->setClearValue( 0.0 );
117  mCircleModificationSpinBox->setValue( mRenderer->circleRadiusAddition() );
118  mDistanceSpinBox->setValue( mRenderer->tolerance() );
119  mDistanceUnitWidget->setUnit( mRenderer->toleranceUnit() );
120  mDistanceUnitWidget->setMapUnitScale( mRenderer->toleranceMapUnitScale() );
121 
122  mPlacementComboBox->setCurrentIndex( mPlacementComboBox->findData( mRenderer->placement() ) );
123 
124  //scale dependent labeling
125  mMinLabelScaleWidget->setScale( qMax( mRenderer->minimumLabelScale(), 0.0 ) );
126  if ( mRenderer->minimumLabelScale() > 0 )
127  {
128  mScaleDependentLabelsCheckBox->setCheckState( Qt::Checked );
129  }
130  else
131  {
132  mScaleDependentLabelsCheckBox->setCheckState( Qt::Unchecked );
133  mMinLabelScaleWidget->setEnabled( false );
134  }
135 
136 
137  blockAllSignals( false );
138 
139  //set the appropriate renderer dialog
140  if ( mRenderer->embeddedRenderer() )
141  {
142  QString rendererName = mRenderer->embeddedRenderer()->type();
143  int rendererIndex = mRendererComboBox->findData( rendererName );
144  if ( rendererIndex != -1 )
145  {
146  mRendererComboBox->setCurrentIndex( rendererIndex );
147  on_mRendererComboBox_currentIndexChanged( rendererIndex );
148  }
149  }
150 
151  connect( mMinLabelScaleWidget, &QgsScaleWidget::scaleChanged, this, &QgsPointDisplacementRendererWidget::minLabelScaleChanged );
152  connect( mLabelFontButton, &QgsFontButton::changed, this, &QgsPointDisplacementRendererWidget::labelFontChanged );
153 
154  updateCenterIcon();
155 }
156 
158 {
159  delete mRenderer;
160 }
161 
163 {
164  return mRenderer;
165 }
166 
168 {
170  if ( mDistanceUnitWidget )
171  mDistanceUnitWidget->setMapCanvas( context.mapCanvas() );
172  if ( mMinLabelScaleWidget )
173  {
174  mMinLabelScaleWidget->setMapCanvas( context.mapCanvas() );
175  mMinLabelScaleWidget->setShowCurrentScaleButton( true );
176  }
177 }
178 
179 void QgsPointDisplacementRendererWidget::on_mLabelFieldComboBox_currentIndexChanged( const QString &text )
180 {
181  if ( mRenderer )
182  {
183  if ( text == tr( "None" ) )
184  {
185  mRenderer->setLabelAttributeName( QLatin1String( "" ) );
186  }
187  else
188  {
189  mRenderer->setLabelAttributeName( text );
190  }
191  emit widgetChanged();
192  }
193 }
194 
195 void QgsPointDisplacementRendererWidget::on_mRendererComboBox_currentIndexChanged( int index )
196 {
197  QString rendererId = mRendererComboBox->itemData( index ).toString();
199  if ( m )
200  {
201  // unfortunately renderer conversion is only available through the creation of a widget...
202  QgsRendererWidget *tempRenderWidget = m->createRendererWidget( mLayer, mStyle, mRenderer->embeddedRenderer()->clone() );
203  mRenderer->setEmbeddedRenderer( tempRenderWidget->renderer()->clone() );
204  delete tempRenderWidget;
205  emit widgetChanged();
206  }
207 }
208 
209 void QgsPointDisplacementRendererWidget::on_mPlacementComboBox_currentIndexChanged( int index )
210 {
211  if ( !mRenderer )
212  return;
213 
214  mRenderer->setPlacement( ( QgsPointDisplacementRenderer::Placement )mPlacementComboBox->itemData( index ).toInt() );
215  emit widgetChanged();
216 }
217 
218 void QgsPointDisplacementRendererWidget::on_mRendererSettingsButton_clicked()
219 {
220  if ( !mRenderer )
221  return;
222 
224  if ( m )
225  {
227  w->setPanelTitle( tr( "Renderer settings" ) );
228 
230 
234  QList< QgsExpressionContextScope > scopes = context.additionalExpressionContextScopes();
235  scopes << scope;
236  context.setAdditionalExpressionContextScopes( scopes );
237  w->setContext( context );
238 
239  connect( w, &QgsPanelWidget::widgetChanged, this, &QgsPointDisplacementRendererWidget::updateRendererFromWidget );
240  openPanel( w );
241  }
242 }
243 
244 void QgsPointDisplacementRendererWidget::labelFontChanged()
245 {
246  if ( !mRenderer )
247  {
248  return;
249  }
250 
251  mRenderer->setLabelFont( mLabelFontButton->currentFont() );
252  emit widgetChanged();
253 }
254 
255 void QgsPointDisplacementRendererWidget::on_mCircleWidthSpinBox_valueChanged( double d )
256 {
257  if ( mRenderer )
258  {
259  mRenderer->setCircleWidth( d );
260  emit widgetChanged();
261  }
262 }
263 
264 void QgsPointDisplacementRendererWidget::on_mCircleColorButton_colorChanged( const QColor &newColor )
265 {
266  if ( !mRenderer )
267  {
268  return;
269  }
270 
271  mRenderer->setCircleColor( newColor );
272  emit widgetChanged();
273 }
274 
275 void QgsPointDisplacementRendererWidget::on_mLabelColorButton_colorChanged( const QColor &newColor )
276 {
277  if ( !mRenderer )
278  {
279  return;
280  }
281 
282  mRenderer->setLabelColor( newColor );
283  emit widgetChanged();
284 }
285 
286 void QgsPointDisplacementRendererWidget::on_mCircleModificationSpinBox_valueChanged( double d )
287 {
288  if ( !mRenderer )
289  {
290  return;
291  }
292 
293  mRenderer->setCircleRadiusAddition( d );
294  emit widgetChanged();
295 }
296 
297 void QgsPointDisplacementRendererWidget::on_mDistanceSpinBox_valueChanged( double d )
298 {
299  if ( mRenderer )
300  {
301  mRenderer->setTolerance( d );
302  emit widgetChanged();
303  }
304 }
305 
306 void QgsPointDisplacementRendererWidget::on_mDistanceUnitWidget_changed()
307 {
308  if ( mRenderer )
309  {
310  mRenderer->setToleranceUnit( mDistanceUnitWidget->unit() );
311  mRenderer->setToleranceMapUnitScale( mDistanceUnitWidget->getMapUnitScale() );
312  emit widgetChanged();
313  }
314 }
315 
316 void QgsPointDisplacementRendererWidget::on_mScaleDependentLabelsCheckBox_stateChanged( int state )
317 {
318  if ( state == Qt::Unchecked )
319  {
320  mMinLabelScaleWidget->setScale( 0 );
321  mMinLabelScaleWidget->setEnabled( false );
322  }
323  else
324  {
325  mMinLabelScaleWidget->setEnabled( true );
326  }
327 }
328 
329 void QgsPointDisplacementRendererWidget::minLabelScaleChanged( double scale )
330 {
331  if ( !mRenderer )
332  {
333  return;
334  }
335 
336  mRenderer->setMinimumLabelScale( scale );
337  emit widgetChanged();
338 }
339 
340 void QgsPointDisplacementRendererWidget::blockAllSignals( bool block )
341 {
342  mLabelFieldComboBox->blockSignals( block );
343  mLabelFontButton->blockSignals( block );
344  mCircleWidthSpinBox->blockSignals( block );
345  mCircleColorButton->blockSignals( block );
346  mRendererComboBox->blockSignals( block );
347  mLabelColorButton->blockSignals( block );
348  mCircleModificationSpinBox->blockSignals( block );
349  mScaleDependentLabelsCheckBox->blockSignals( block );
350  mMinLabelScaleWidget->blockSignals( block );
351  mCenterSymbolPushButton->blockSignals( block );
352  mDistanceSpinBox->blockSignals( block );
353  mDistanceUnitWidget->blockSignals( block );
354  mPlacementComboBox->blockSignals( block );
355 }
356 
357 void QgsPointDisplacementRendererWidget::on_mCenterSymbolPushButton_clicked()
358 {
359  if ( !mRenderer || !mRenderer->centerSymbol() )
360  {
361  return;
362  }
363  QgsMarkerSymbol *markerSymbol = mRenderer->centerSymbol()->clone();
365  dlg->setPanelTitle( tr( "Center symbol" ) );
366 
368 
372  QList< QgsExpressionContextScope > scopes = context.additionalExpressionContextScopes();
373  scopes << scope;
374  context.setAdditionalExpressionContextScopes( scopes );
375  dlg->setContext( context );
376 
377  connect( dlg, &QgsPanelWidget::widgetChanged, this, &QgsPointDisplacementRendererWidget::updateCenterSymbolFromWidget );
378  connect( dlg, &QgsPanelWidget::panelAccepted, this, &QgsPointDisplacementRendererWidget::cleanUpSymbolSelector );
379  openPanel( dlg );
380 }
381 
382 void QgsPointDisplacementRendererWidget::updateCenterSymbolFromWidget()
383 {
384  QgsSymbolSelectorWidget *dlg = qobject_cast<QgsSymbolSelectorWidget *>( sender() );
385  QgsSymbol *symbol = dlg->symbol()->clone();
386  mRenderer->setCenterSymbol( static_cast< QgsMarkerSymbol * >( symbol ) );
387  updateCenterIcon();
388  emit widgetChanged();
389 }
390 
391 void QgsPointDisplacementRendererWidget::cleanUpSymbolSelector( QgsPanelWidget *container )
392 {
393  if ( container )
394  {
395  QgsSymbolSelectorWidget *dlg = qobject_cast<QgsSymbolSelectorWidget *>( container );
396  delete dlg->symbol();
397  }
398 }
399 
400 void QgsPointDisplacementRendererWidget::updateRendererFromWidget()
401 {
402  QgsRendererWidget *w = qobject_cast<QgsRendererWidget *>( sender() );
403  if ( !w )
404  return;
405 
406  mRenderer->setEmbeddedRenderer( w->renderer()->clone() );
407  emit widgetChanged();
408 }
409 
410 void QgsPointDisplacementRendererWidget::updateCenterIcon()
411 {
412  QgsMarkerSymbol *symbol = mRenderer->centerSymbol();
413  if ( !symbol )
414  {
415  return;
416  }
417  QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( symbol, mCenterSymbolPushButton->iconSize() );
418  mCenterSymbolPushButton->setIcon( icon );
419 }
420 
421 void QgsPointDisplacementRendererWidget::setupBlankUi( const QString &layerName )
422 {
423  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 );
424  QVBoxLayout *layout = new QVBoxLayout( this );
425  layout->setContentsMargins( 0, 0, 0, 0 );
426  layout->addWidget( label );
427 }
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.
Meters value as Map units.
Definition: qgsunittypes.h:104
Single variable definition for use within a QgsExpressionContextScope.
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...
QString name
Definition: qgsfield.h:54
virtual QgsRendererWidget * createRendererWidget(QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *oldRenderer)
Return new instance of settings widget for the renderer.
QgsSymbol * symbol()
Return the symbol that is currently active in the widget.
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.
double circleRadiusAddition() const
Returns the factor for increasing the ring size of displacement groups.
Base class for any widget that can be shown as a inline panel.
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 panelAccepted(QgsPanelWidget *panel)
Emitted when the panel is accepted by the user.
void setCenterSymbol(QgsMarkerSymbol *symbol)
Sets the center symbol for a displacement group.
QList< QgsUnitTypes::RenderUnit > RenderUnitList
List of render units.
Definition: qgsunittypes.h:166
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
QgsUnitTypes::RenderUnit toleranceUnit() const
Returns the units for the tolerance distance.
static QgsStyle * defaultStyle()
Returns default application-wide style.
Definition: qgsstyle.cpp:51
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
QFont labelFont() const
Returns the font used for labeling points.
QString type() const
Definition: qgsrenderer.h:124
static QIcon symbolPreviewIcon(QgsSymbol *symbol, QSize size, int padding=0)
Returns an icon preview for a color ramp.
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.
QgsWkbTypes::Type wkbType() const override
Returns the WKBType or WKBUnknown in case of error.
points (e.g., for font sizes)
Definition: qgsunittypes.h:102
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.
Symbol selector widget that can be used to select and build a symbol.
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.
const QgsFeatureRenderer * embeddedRenderer() const override
Returns the current embedded renderer (subrenderer) for this feature renderer.
QgsSymbolWidgetContext mContext
Context in which widget is shown.
void setMinimumLabelScale(double scale)
Sets the minimum map scale (i.e.
virtual QgsSymbol * clone() const =0
Get a deep copy of this symbol.
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:59
QString name
Definition: qgsmaplayer.h:58
QgsFeatureRenderer * renderer() override
return pointer to the renderer (no transfer of ownership)
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)