QGIS API Documentation  2.99.0-Master (314842d)
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 "qgisgui.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 
55 
56  if ( renderer )
57  {
59  }
60  if ( !mRenderer )
61  {
62  mRenderer = new QgsPointDisplacementRenderer();
63  }
64 
65  blockAllSignals( true );
66 
67  mPlacementComboBox->addItem( tr( "Ring" ), QgsPointDisplacementRenderer::Ring );
68  mPlacementComboBox->addItem( tr( "Concentric rings" ), QgsPointDisplacementRenderer::ConcentricRings );
69 
70  //insert attributes into combo box
71  if ( layer )
72  {
73  Q_FOREACH ( const QgsField &f, layer->fields() )
74  {
75  mLabelFieldComboBox->addItem( f.name() );
76  }
77  mLabelFieldComboBox->addItem( tr( "None" ) );
78 
79  QString currentLabelAttribute = mRenderer->labelAttributeName();
80  if ( !currentLabelAttribute.isEmpty() )
81  {
82  mLabelFieldComboBox->setCurrentIndex( mLabelFieldComboBox->findText( currentLabelAttribute ) );
83  }
84  else
85  {
86  mLabelFieldComboBox->setCurrentIndex( mLabelFieldComboBox->findText( tr( "None" ) ) );
87  }
88  }
89 
90  //insert possible renderer types
92  QStringList::const_iterator it = rendererList.constBegin();
93  for ( ; it != rendererList.constEnd(); ++it )
94  {
95  if ( *it != QLatin1String( "pointDisplacement" ) && *it != QLatin1String( "pointCluster" ) && *it != QLatin1String( "heatmapRenderer" ) )
96  {
98  mRendererComboBox->addItem( m->icon(), m->visibleName(), *it );
99  }
100  }
101 
102  mCircleColorButton->setColorDialogTitle( tr( "Select color" ) );
103  mCircleColorButton->setContext( QStringLiteral( "symbology" ) );
104  mCircleColorButton->setAllowAlpha( true );
105  mCircleColorButton->setShowNoColor( true );
106  mCircleColorButton->setNoColorString( tr( "No stroke" ) );
107  mLabelColorButton->setContext( QStringLiteral( "symbology" ) );
108  mLabelColorButton->setColorDialogTitle( tr( "Select color" ) );
109  mLabelColorButton->setAllowAlpha( true );
110 
111  mCircleWidthSpinBox->setValue( mRenderer->circleWidth() );
112  mCircleColorButton->setColor( mRenderer->circleColor() );
113  mLabelColorButton->setColor( mRenderer->labelColor() );
114  mCircleModificationSpinBox->setClearValue( 0.0 );
115  mCircleModificationSpinBox->setValue( mRenderer->circleRadiusAddition() );
116  mDistanceSpinBox->setValue( mRenderer->tolerance() );
117  mDistanceUnitWidget->setUnit( mRenderer->toleranceUnit() );
118  mDistanceUnitWidget->setMapUnitScale( mRenderer->toleranceMapUnitScale() );
119 
120  mPlacementComboBox->setCurrentIndex( mPlacementComboBox->findData( mRenderer->placement() ) );
121 
122  //scale dependent labeling
123  mMaxScaleDenominatorEdit->setText( QString::number( mRenderer->maxLabelScaleDenominator() ) );
124  mMaxScaleDenominatorEdit->setValidator( new QDoubleValidator( mMaxScaleDenominatorEdit ) );
125  if ( mRenderer->maxLabelScaleDenominator() > 0 )
126  {
127  mScaleDependentLabelsCheckBox->setCheckState( Qt::Checked );
128  }
129  else
130  {
131  mScaleDependentLabelsCheckBox->setCheckState( Qt::Unchecked );
132  mMaxScaleDenominatorEdit->setEnabled( false );
133  }
134 
135 
136  blockAllSignals( false );
137 
138  //set the appropriate renderer dialog
139  if ( mRenderer->embeddedRenderer() )
140  {
141  QString rendererName = mRenderer->embeddedRenderer()->type();
142  int rendererIndex = mRendererComboBox->findData( rendererName );
143  if ( rendererIndex != -1 )
144  {
145  mRendererComboBox->setCurrentIndex( rendererIndex );
146  on_mRendererComboBox_currentIndexChanged( rendererIndex );
147  }
148  }
149 
150  updateCenterIcon();
151 }
152 
154 {
155  delete mRenderer;
156 }
157 
159 {
160  return mRenderer;
161 }
162 
164 {
166  if ( mDistanceUnitWidget )
167  mDistanceUnitWidget->setMapCanvas( context.mapCanvas() );
168 }
169 
170 void QgsPointDisplacementRendererWidget::on_mLabelFieldComboBox_currentIndexChanged( const QString &text )
171 {
172  if ( mRenderer )
173  {
174  if ( text == tr( "None" ) )
175  {
176  mRenderer->setLabelAttributeName( QLatin1String( "" ) );
177  }
178  else
179  {
180  mRenderer->setLabelAttributeName( text );
181  }
182  emit widgetChanged();
183  }
184 }
185 
186 void QgsPointDisplacementRendererWidget::on_mRendererComboBox_currentIndexChanged( int index )
187 {
188  QString rendererId = mRendererComboBox->itemData( index ).toString();
190  if ( m )
191  {
192  // unfortunately renderer conversion is only available through the creation of a widget...
193  QgsRendererWidget *tempRenderWidget = m->createRendererWidget( mLayer, mStyle, mRenderer->embeddedRenderer()->clone() );
194  mRenderer->setEmbeddedRenderer( tempRenderWidget->renderer()->clone() );
195  delete tempRenderWidget;
196  emit widgetChanged();
197  }
198 }
199 
200 void QgsPointDisplacementRendererWidget::on_mPlacementComboBox_currentIndexChanged( int index )
201 {
202  if ( !mRenderer )
203  return;
204 
205  mRenderer->setPlacement( ( QgsPointDisplacementRenderer::Placement )mPlacementComboBox->itemData( index ).toInt() );
206  emit widgetChanged();
207 }
208 
209 void QgsPointDisplacementRendererWidget::on_mRendererSettingsButton_clicked()
210 {
211  if ( !mRenderer )
212  return;
213 
215  if ( m )
216  {
218  w->setPanelTitle( tr( "Renderer settings" ) );
219 
221 
225  QList< QgsExpressionContextScope > scopes = context.additionalExpressionContextScopes();
226  scopes << scope;
227  context.setAdditionalExpressionContextScopes( scopes );
228  w->setContext( context );
229 
230  connect( w, SIGNAL( widgetChanged() ), this, SLOT( updateRendererFromWidget() ) );
231  openPanel( w );
232  }
233 }
234 
235 void QgsPointDisplacementRendererWidget::on_mLabelFontButton_clicked()
236 {
237  if ( !mRenderer )
238  {
239  return;
240  }
241 
242  bool ok;
243  QFont newFont = QgisGui::getFont( ok, mRenderer->labelFont(), tr( "Label Font" ) );
244  if ( ok )
245  {
246  mRenderer->setLabelFont( newFont );
247  emit widgetChanged();
248  }
249 }
250 
251 void QgsPointDisplacementRendererWidget::on_mCircleWidthSpinBox_valueChanged( double d )
252 {
253  if ( mRenderer )
254  {
255  mRenderer->setCircleWidth( d );
256  emit widgetChanged();
257  }
258 }
259 
260 void QgsPointDisplacementRendererWidget::on_mCircleColorButton_colorChanged( const QColor &newColor )
261 {
262  if ( !mRenderer )
263  {
264  return;
265  }
266 
267  mRenderer->setCircleColor( newColor );
268  emit widgetChanged();
269 }
270 
271 void QgsPointDisplacementRendererWidget::on_mLabelColorButton_colorChanged( const QColor &newColor )
272 {
273  if ( !mRenderer )
274  {
275  return;
276  }
277 
278  mRenderer->setLabelColor( newColor );
279  emit widgetChanged();
280 }
281 
282 void QgsPointDisplacementRendererWidget::on_mCircleModificationSpinBox_valueChanged( double d )
283 {
284  if ( !mRenderer )
285  {
286  return;
287  }
288 
289  mRenderer->setCircleRadiusAddition( d );
290  emit widgetChanged();
291 }
292 
293 void QgsPointDisplacementRendererWidget::on_mDistanceSpinBox_valueChanged( double d )
294 {
295  if ( mRenderer )
296  {
297  mRenderer->setTolerance( d );
298  emit widgetChanged();
299  }
300 }
301 
302 void QgsPointDisplacementRendererWidget::on_mDistanceUnitWidget_changed()
303 {
304  if ( mRenderer )
305  {
306  mRenderer->setToleranceUnit( mDistanceUnitWidget->unit() );
307  mRenderer->setToleranceMapUnitScale( mDistanceUnitWidget->getMapUnitScale() );
308  emit widgetChanged();
309  }
310 }
311 
312 void QgsPointDisplacementRendererWidget::on_mScaleDependentLabelsCheckBox_stateChanged( int state )
313 {
314  if ( state == Qt::Unchecked )
315  {
316  mMaxScaleDenominatorEdit->setText( QStringLiteral( "-1" ) );
317  mMaxScaleDenominatorEdit->setEnabled( false );
318  }
319  else
320  {
321  mMaxScaleDenominatorEdit->setEnabled( true );
322  }
323 }
324 
325 void QgsPointDisplacementRendererWidget::on_mMaxScaleDenominatorEdit_textChanged( const QString &text )
326 {
327  if ( !mRenderer )
328  {
329  return;
330  }
331 
332  bool ok;
333  double scaleDenominator = text.toDouble( &ok );
334  if ( ok )
335  {
336  mRenderer->setMaxLabelScaleDenominator( scaleDenominator );
337  emit widgetChanged();
338  }
339 }
340 
341 void QgsPointDisplacementRendererWidget::blockAllSignals( bool block )
342 {
343  mLabelFieldComboBox->blockSignals( block );
344  mLabelFontButton->blockSignals( block );
345  mCircleWidthSpinBox->blockSignals( block );
346  mCircleColorButton->blockSignals( block );
347  mRendererComboBox->blockSignals( block );
348  mLabelColorButton->blockSignals( block );
349  mCircleModificationSpinBox->blockSignals( block );
350  mScaleDependentLabelsCheckBox->blockSignals( block );
351  mMaxScaleDenominatorEdit->blockSignals( block );
352  mCenterSymbolPushButton->blockSignals( block );
353  mDistanceSpinBox->blockSignals( block );
354  mDistanceUnitWidget->blockSignals( block );
355  mPlacementComboBox->blockSignals( block );
356 }
357 
358 void QgsPointDisplacementRendererWidget::on_mCenterSymbolPushButton_clicked()
359 {
360  if ( !mRenderer || !mRenderer->centerSymbol() )
361  {
362  return;
363  }
364  QgsMarkerSymbol *markerSymbol = mRenderer->centerSymbol()->clone();
366  dlg->setPanelTitle( tr( "Center symbol" ) );
367 
369 
373  QList< QgsExpressionContextScope > scopes = context.additionalExpressionContextScopes();
374  scopes << scope;
375  context.setAdditionalExpressionContextScopes( scopes );
376  dlg->setContext( context );
377 
378  connect( dlg, SIGNAL( widgetChanged() ), this, SLOT( updateCenterSymbolFromWidget() ) );
379  connect( dlg, &QgsPanelWidget::panelAccepted, this, &QgsPointDisplacementRendererWidget::cleanUpSymbolSelector );
380  openPanel( dlg );
381 }
382 
383 void QgsPointDisplacementRendererWidget::updateCenterSymbolFromWidget()
384 {
385  QgsSymbolSelectorWidget *dlg = qobject_cast<QgsSymbolSelectorWidget *>( sender() );
386  QgsSymbol *symbol = dlg->symbol()->clone();
387  mRenderer->setCenterSymbol( static_cast< QgsMarkerSymbol * >( symbol ) );
388  updateCenterIcon();
389  emit widgetChanged();
390 }
391 
392 void QgsPointDisplacementRendererWidget::cleanUpSymbolSelector( QgsPanelWidget *container )
393 {
394  if ( container )
395  {
396  QgsSymbolSelectorWidget *dlg = qobject_cast<QgsSymbolSelectorWidget *>( container );
397  delete dlg->symbol();
398  }
399 }
400 
401 void QgsPointDisplacementRendererWidget::updateRendererFromWidget()
402 {
403  QgsRendererWidget *w = qobject_cast<QgsRendererWidget *>( sender() );
404  if ( !w )
405  return;
406 
407  mRenderer->setEmbeddedRenderer( w->renderer()->clone() );
408  emit widgetChanged();
409 }
410 
411 void QgsPointDisplacementRendererWidget::updateCenterIcon()
412 {
413  QgsMarkerSymbol *symbol = mRenderer->centerSymbol();
414  if ( !symbol )
415  {
416  return;
417  }
418  QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( symbol, mCenterSymbolPushButton->iconSize() );
419  mCenterSymbolPushButton->setIcon( icon );
420 }
421 
422 void QgsPointDisplacementRendererWidget::setupBlankUi( const QString &layerName )
423 {
424  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 );
425  QVBoxLayout *layout = new QVBoxLayout( this );
426  layout->setContentsMargins( 0, 0, 0, 0 );
427  layout->addWidget( label );
428 }
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.
static unsigned index
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)...
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:53
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.
QFont getFont(bool &ok, const QFont &initial, const QString &title)
Show font selection dialog.
Definition: qgisgui.cpp:192
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.
QString labelAttributeName() const
Returns the attribute name used for labeling points, or an empty string if no labeling will be done b...
QList< RenderUnit > RenderUnitList
List of render units.
Definition: qgsunittypes.h:145
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.
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:50
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
QgsFields fields() const
Returns the list of fields of this layer.
QgsWkbTypes::Type wkbType() const
Returns the WKBType or WKBUnknown in case of error.
QFont labelFont() const
Returns the font used for labeling points.
QString type() const
Definition: qgsrenderer.h:93
static QIcon symbolPreviewIcon(QgsSymbol *symbol, QSize size, int padding=0)
Returns an icon preview for a color ramp.
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.
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 setPlacement(Placement placement)
Sets the placement method used for dispersing the points.
Symbol selector widget that cna be used to select and build a symbol.
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:45
void setMaxLabelScaleDenominator(double denominator)
Sets the maximum scale at which points should be labeled by the 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.
Place points in a single ring around group.
double maxLabelScaleDenominator() const
Returns the denominator for the maximum scale at which points should be labeled by the renderer...
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.
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.
QString name
Read property of QString layerName.
Definition: qgsmaplayer.h:56
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:1474
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)