QGIS API Documentation  3.6.0-Noosa (5873452)
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 #include "qgsapplication.h"
28 
30 {
31  return new QgsPointDisplacementRendererWidget( 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( mLabelFieldComboBox, static_cast<void ( QComboBox::* )( const QString & )>( &QComboBox::currentIndexChanged ), this, &QgsPointDisplacementRendererWidget::mLabelFieldComboBox_currentIndexChanged );
53  connect( mRendererComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointDisplacementRendererWidget::mRendererComboBox_currentIndexChanged );
54  connect( mPlacementComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointDisplacementRendererWidget::mPlacementComboBox_currentIndexChanged );
55  connect( mCircleWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsPointDisplacementRendererWidget::mCircleWidthSpinBox_valueChanged );
56  connect( mCircleColorButton, &QgsColorButton::colorChanged, this, &QgsPointDisplacementRendererWidget::mCircleColorButton_colorChanged );
57  connect( mDistanceSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsPointDisplacementRendererWidget::mDistanceSpinBox_valueChanged );
58  connect( mDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointDisplacementRendererWidget::mDistanceUnitWidget_changed );
59  connect( mLabelColorButton, &QgsColorButton::colorChanged, this, &QgsPointDisplacementRendererWidget::mLabelColorButton_colorChanged );
60  connect( mCircleModificationSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsPointDisplacementRendererWidget::mCircleModificationSpinBox_valueChanged );
61  connect( mScaleDependentLabelsCheckBox, &QCheckBox::stateChanged, this, &QgsPointDisplacementRendererWidget::mScaleDependentLabelsCheckBox_stateChanged );
62  connect( mRendererSettingsButton, &QPushButton::clicked, this, &QgsPointDisplacementRendererWidget::mRendererSettingsButton_clicked );
63  this->layout()->setContentsMargins( 0, 0, 0, 0 );
64 
65  mLabelFontButton->setMode( QgsFontButton::ModeQFont );
68  mCenterSymbolToolButton->setSymbolType( QgsSymbol::Marker );
69 
70  if ( renderer )
71  {
73  }
74  if ( !mRenderer )
75  {
76  mRenderer = new QgsPointDisplacementRenderer();
77  }
78 
79  blockAllSignals( true );
80 
81  mPlacementComboBox->addItem( tr( "Ring" ), QgsPointDisplacementRenderer::Ring );
82  mPlacementComboBox->addItem( tr( "Concentric rings" ), QgsPointDisplacementRenderer::ConcentricRings );
83  mPlacementComboBox->addItem( tr( "Grid" ), QgsPointDisplacementRenderer::Grid );
84 
85  //insert attributes into combo box
86  if ( layer )
87  {
88  const QgsFields layerFields = layer->fields();
89  for ( const QgsField &f : layerFields )
90  {
91  mLabelFieldComboBox->addItem( f.name() );
92  }
93  mLabelFieldComboBox->addItem( tr( "None" ) );
94 
95  QString currentLabelAttribute = mRenderer->labelAttributeName();
96  if ( !currentLabelAttribute.isEmpty() )
97  {
98  mLabelFieldComboBox->setCurrentIndex( mLabelFieldComboBox->findText( currentLabelAttribute ) );
99  }
100  else
101  {
102  mLabelFieldComboBox->setCurrentIndex( mLabelFieldComboBox->findText( tr( "None" ) ) );
103  }
104  }
105 
106  //insert possible renderer types
108  QStringList::const_iterator it = rendererList.constBegin();
109  for ( ; it != rendererList.constEnd(); ++it )
110  {
111  if ( *it != QLatin1String( "pointDisplacement" ) && *it != QLatin1String( "pointCluster" ) && *it != QLatin1String( "heatmapRenderer" ) )
112  {
114  mRendererComboBox->addItem( m->icon(), m->visibleName(), *it );
115  }
116  }
117 
118  mCircleColorButton->setColorDialogTitle( tr( "Select Color" ) );
119  mCircleColorButton->setContext( QStringLiteral( "symbology" ) );
120  mCircleColorButton->setAllowOpacity( true );
121  mCircleColorButton->setShowNoColor( true );
122  mCircleColorButton->setNoColorString( tr( "Transparent Stroke" ) );
123  mLabelColorButton->setContext( QStringLiteral( "symbology" ) );
124  mLabelColorButton->setColorDialogTitle( tr( "Select Color" ) );
125  mLabelColorButton->setAllowOpacity( true );
126 
127  mCircleWidthSpinBox->setValue( mRenderer->circleWidth() );
128  mCircleColorButton->setColor( mRenderer->circleColor() );
129  mLabelColorButton->setColor( mRenderer->labelColor() );
130  mLabelFontButton->setCurrentFont( mRenderer->labelFont() );
131  mCircleModificationSpinBox->setClearValue( 0.0 );
132  mCircleModificationSpinBox->setValue( mRenderer->circleRadiusAddition() );
133  mDistanceSpinBox->setValue( mRenderer->tolerance() );
134  mDistanceUnitWidget->setUnit( mRenderer->toleranceUnit() );
135  mDistanceUnitWidget->setMapUnitScale( mRenderer->toleranceMapUnitScale() );
136  mCenterSymbolToolButton->setSymbol( mRenderer->centerSymbol()->clone() );
137 
138  mPlacementComboBox->setCurrentIndex( mPlacementComboBox->findData( mRenderer->placement() ) );
139 
140  //scale dependent labeling
141  mMinLabelScaleWidget->setScale( std::max( mRenderer->minimumLabelScale(), 0.0 ) );
142  if ( mRenderer->minimumLabelScale() > 0 )
143  {
144  mScaleDependentLabelsCheckBox->setCheckState( Qt::Checked );
145  }
146  else
147  {
148  mScaleDependentLabelsCheckBox->setCheckState( Qt::Unchecked );
149  mMinLabelScaleWidget->setEnabled( false );
150  }
151 
152 
153  blockAllSignals( false );
154 
155  //set the appropriate renderer dialog
156  if ( mRenderer->embeddedRenderer() )
157  {
158  QString rendererName = mRenderer->embeddedRenderer()->type();
159  int rendererIndex = mRendererComboBox->findData( rendererName );
160  if ( rendererIndex != -1 )
161  {
162  mRendererComboBox->setCurrentIndex( rendererIndex );
163  mRendererComboBox_currentIndexChanged( rendererIndex );
164  }
165  }
166 
167  connect( mMinLabelScaleWidget, &QgsScaleWidget::scaleChanged, this, &QgsPointDisplacementRendererWidget::minLabelScaleChanged );
168  connect( mLabelFontButton, &QgsFontButton::changed, this, &QgsPointDisplacementRendererWidget::labelFontChanged );
169  connect( mCenterSymbolToolButton, &QgsSymbolButton::changed, this, &QgsPointDisplacementRendererWidget::centerSymbolChanged );
170  mCenterSymbolToolButton->setDialogTitle( tr( "Center symbol" ) );
171  mCenterSymbolToolButton->setLayer( mLayer );
172  mCenterSymbolToolButton->registerExpressionContextGenerator( this );
173 }
174 
176 {
177  delete mRenderer;
178 }
179 
181 {
182  return mRenderer;
183 }
184 
186 {
188  if ( mDistanceUnitWidget )
189  mDistanceUnitWidget->setMapCanvas( context.mapCanvas() );
190  if ( mMinLabelScaleWidget )
191  {
192  mMinLabelScaleWidget->setMapCanvas( context.mapCanvas() );
193  mMinLabelScaleWidget->setShowCurrentScaleButton( true );
194  }
195  if ( mCenterSymbolToolButton )
196  {
197  mCenterSymbolToolButton->setMapCanvas( context.mapCanvas() );
198  mCenterSymbolToolButton->setMessageBar( context.messageBar() );
199  }
200 }
201 
203 {
205  if ( mContext.expressionContext() )
206  context = *mContext.expressionContext();
207  else
212  QList< QgsExpressionContextScope > scopes = mContext.additionalExpressionContextScopes();
213  scopes << scope;
214  Q_FOREACH ( const QgsExpressionContextScope &s, scopes )
215  {
216  context << new QgsExpressionContextScope( s );
217  }
218  return context;
219 }
220 
221 void QgsPointDisplacementRendererWidget::mLabelFieldComboBox_currentIndexChanged( const QString &text )
222 {
223  if ( mRenderer )
224  {
225  if ( text == tr( "None" ) )
226  {
227  mRenderer->setLabelAttributeName( QString() );
228  }
229  else
230  {
231  mRenderer->setLabelAttributeName( text );
232  }
233  emit widgetChanged();
234  }
235 }
236 
237 void QgsPointDisplacementRendererWidget::mRendererComboBox_currentIndexChanged( int index )
238 {
239  QString rendererId = mRendererComboBox->itemData( index ).toString();
241  if ( m )
242  {
243  // unfortunately renderer conversion is only available through the creation of a widget...
244  QgsRendererWidget *tempRenderWidget = m->createRendererWidget( mLayer, mStyle, mRenderer->embeddedRenderer()->clone() );
245  mRenderer->setEmbeddedRenderer( tempRenderWidget->renderer()->clone() );
246  delete tempRenderWidget;
247  emit widgetChanged();
248  }
249 }
250 
251 void QgsPointDisplacementRendererWidget::mPlacementComboBox_currentIndexChanged( int index )
252 {
253  if ( !mRenderer )
254  return;
255 
256  mRenderer->setPlacement( ( QgsPointDisplacementRenderer::Placement )mPlacementComboBox->itemData( index ).toInt() );
257  emit widgetChanged();
258 }
259 
260 void QgsPointDisplacementRendererWidget::mRendererSettingsButton_clicked()
261 {
262  if ( !mRenderer )
263  return;
264 
266  if ( m )
267  {
269  w->setPanelTitle( tr( "Renderer Settings" ) );
270 
272 
276  QList< QgsExpressionContextScope > scopes = context.additionalExpressionContextScopes();
277  scopes << scope;
278  context.setAdditionalExpressionContextScopes( scopes );
279  w->setContext( context );
280 
281  connect( w, &QgsPanelWidget::widgetChanged, this, &QgsPointDisplacementRendererWidget::updateRendererFromWidget );
282  openPanel( w );
283  }
284 }
285 
286 void QgsPointDisplacementRendererWidget::labelFontChanged()
287 {
288  if ( !mRenderer )
289  {
290  return;
291  }
292 
293  mRenderer->setLabelFont( mLabelFontButton->currentFont() );
294  emit widgetChanged();
295 }
296 
297 void QgsPointDisplacementRendererWidget::mCircleWidthSpinBox_valueChanged( double d )
298 {
299  if ( mRenderer )
300  {
301  mRenderer->setCircleWidth( d );
302  emit widgetChanged();
303  }
304 }
305 
306 void QgsPointDisplacementRendererWidget::mCircleColorButton_colorChanged( const QColor &newColor )
307 {
308  if ( !mRenderer )
309  {
310  return;
311  }
312 
313  mRenderer->setCircleColor( newColor );
314  emit widgetChanged();
315 }
316 
317 void QgsPointDisplacementRendererWidget::mLabelColorButton_colorChanged( const QColor &newColor )
318 {
319  if ( !mRenderer )
320  {
321  return;
322  }
323 
324  mRenderer->setLabelColor( newColor );
325  emit widgetChanged();
326 }
327 
328 void QgsPointDisplacementRendererWidget::mCircleModificationSpinBox_valueChanged( double d )
329 {
330  if ( !mRenderer )
331  {
332  return;
333  }
334 
335  mRenderer->setCircleRadiusAddition( d );
336  emit widgetChanged();
337 }
338 
339 void QgsPointDisplacementRendererWidget::mDistanceSpinBox_valueChanged( double d )
340 {
341  if ( mRenderer )
342  {
343  mRenderer->setTolerance( d );
344  emit widgetChanged();
345  }
346 }
347 
348 void QgsPointDisplacementRendererWidget::mDistanceUnitWidget_changed()
349 {
350  if ( mRenderer )
351  {
352  mRenderer->setToleranceUnit( mDistanceUnitWidget->unit() );
353  mRenderer->setToleranceMapUnitScale( mDistanceUnitWidget->getMapUnitScale() );
354  emit widgetChanged();
355  }
356 }
357 
358 void QgsPointDisplacementRendererWidget::mScaleDependentLabelsCheckBox_stateChanged( int state )
359 {
360  if ( state == Qt::Unchecked )
361  {
362  mMinLabelScaleWidget->setScale( 0 );
363  mMinLabelScaleWidget->setEnabled( false );
364  }
365  else
366  {
367  mMinLabelScaleWidget->setEnabled( true );
368  }
369 }
370 
371 void QgsPointDisplacementRendererWidget::minLabelScaleChanged( double scale )
372 {
373  if ( !mRenderer )
374  {
375  return;
376  }
377 
378  mRenderer->setMinimumLabelScale( scale );
379  emit widgetChanged();
380 }
381 
382 void QgsPointDisplacementRendererWidget::blockAllSignals( bool block )
383 {
384  mLabelFieldComboBox->blockSignals( block );
385  mLabelFontButton->blockSignals( block );
386  mCircleWidthSpinBox->blockSignals( block );
387  mCircleColorButton->blockSignals( block );
388  mRendererComboBox->blockSignals( block );
389  mLabelColorButton->blockSignals( block );
390  mCircleModificationSpinBox->blockSignals( block );
391  mScaleDependentLabelsCheckBox->blockSignals( block );
392  mMinLabelScaleWidget->blockSignals( block );
393  mCenterSymbolToolButton->blockSignals( block );
394  mDistanceSpinBox->blockSignals( block );
395  mDistanceUnitWidget->blockSignals( block );
396  mPlacementComboBox->blockSignals( block );
397 }
398 
399 void QgsPointDisplacementRendererWidget::centerSymbolChanged()
400 {
401  mRenderer->setCenterSymbol( mCenterSymbolToolButton->clonedSymbol< QgsMarkerSymbol >() );
402  emit widgetChanged();
403 }
404 
405 void QgsPointDisplacementRendererWidget::updateRendererFromWidget()
406 {
407  QgsRendererWidget *w = qobject_cast<QgsRendererWidget *>( sender() );
408  if ( !w )
409  return;
410 
411  mRenderer->setEmbeddedRenderer( w->renderer()->clone() );
412  emit widgetChanged();
413 }
414 
415 void QgsPointDisplacementRendererWidget::setupBlankUi( const QString &layerName )
416 {
417  QLabel *label = new QLabel( tr( "The point displacement renderer only applies to (single) point layers. \n'%1' is not a (single) point layer and cannot be displayed by the point displacement renderer." ).arg( layerName ), this );
418  QVBoxLayout *layout = new QVBoxLayout( this );
419  layout->setContentsMargins( 0, 0, 0, 0 );
420  layout->addWidget( label );
421 }
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:120
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.
Place points in a grid around group.
virtual QgsFeatureRenderer * renderer()=0
Returns 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)
Returns new instance of settings widget for the renderer.
static bool isMultiType(Type type)
Returns true if the WKB type is a multi type.
Definition: qgswkbtypes.h:559
QgsSymbolWidgetContext context() const
Returns the context in which the renderer widget is shown, e.g., the associated map canvas and expres...
QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
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:42
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: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:732
QFont labelFont() const
Returns the font used for labeling points.
QString type() const
Definition: qgsrenderer.h:129
QgsFields fields() const FINAL
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...
static GeometryType geometryType(Type type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:665
points (e.g., for font sizes)
Definition: qgsunittypes.h:118
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:48
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. ...
void colorChanged(const QColor &color)
Is emitted whenever a new color is set for the button.
QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
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.
void setMinimumLabelScale(double scale)
Sets the minimum map scale (i.e.
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.
Configure font settings for use with QFont objects.
Definition: qgsfontbutton.h:57
QString name
Definition: qgsmaplayer.h:68
QgsFeatureRenderer * renderer() override
Returns 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.
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:1585
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)