QGIS API Documentation  2.99.0-Master (5753576)
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 
54 
55  if ( renderer )
56  {
58  }
59  if ( !mRenderer )
60  {
61  mRenderer = new QgsPointDisplacementRenderer();
62  }
63 
64  blockAllSignals( true );
65 
66  mPlacementComboBox->addItem( tr( "Ring" ), QgsPointDisplacementRenderer::Ring );
67  mPlacementComboBox->addItem( tr( "Concentric rings" ), QgsPointDisplacementRenderer::ConcentricRings );
68 
69  //insert attributes into combo box
70  if ( layer )
71  {
72  Q_FOREACH ( const QgsField& f, layer->fields() )
73  {
74  mLabelFieldComboBox->addItem( f.name() );
75  }
76  mLabelFieldComboBox->addItem( tr( "None" ) );
77 
78  QString currentLabelAttribute = mRenderer->labelAttributeName();
79  if ( !currentLabelAttribute.isEmpty() )
80  {
81  mLabelFieldComboBox->setCurrentIndex( mLabelFieldComboBox->findText( currentLabelAttribute ) );
82  }
83  else
84  {
85  mLabelFieldComboBox->setCurrentIndex( mLabelFieldComboBox->findText( tr( "None" ) ) );
86  }
87  }
88 
89  //insert possible renderer types
91  QStringList::const_iterator it = rendererList.constBegin();
92  for ( ; it != rendererList.constEnd(); ++it )
93  {
94  if ( *it != QLatin1String( "pointDisplacement" ) && *it != QLatin1String( "pointCluster" ) && *it != QLatin1String( "heatmapRenderer" ) )
95  {
97  mRendererComboBox->addItem( m->icon(), m->visibleName(), *it );
98  }
99  }
100 
101  mCircleColorButton->setColorDialogTitle( tr( "Select color" ) );
102  mCircleColorButton->setContext( QStringLiteral( "symbology" ) );
103  mCircleColorButton->setAllowAlpha( true );
104  mCircleColorButton->setShowNoColor( true );
105  mCircleColorButton->setNoColorString( tr( "No outline" ) );
106  mLabelColorButton->setContext( QStringLiteral( "symbology" ) );
107  mLabelColorButton->setColorDialogTitle( tr( "Select color" ) );
108  mLabelColorButton->setAllowAlpha( true );
109 
110  mCircleWidthSpinBox->setValue( mRenderer->circleWidth() );
111  mCircleColorButton->setColor( mRenderer->circleColor() );
112  mLabelColorButton->setColor( mRenderer->labelColor() );
113  mCircleModificationSpinBox->setClearValue( 0.0 );
114  mCircleModificationSpinBox->setValue( mRenderer->circleRadiusAddition() );
115  mDistanceSpinBox->setValue( mRenderer->tolerance() );
116  mDistanceUnitWidget->setUnit( mRenderer->toleranceUnit() );
117  mDistanceUnitWidget->setMapUnitScale( mRenderer->toleranceMapUnitScale() );
118 
119  mPlacementComboBox->setCurrentIndex( mPlacementComboBox->findData( mRenderer->placement() ) );
120 
121  //scale dependent labeling
122  mMaxScaleDenominatorEdit->setText( QString::number( mRenderer->maxLabelScaleDenominator() ) );
123  mMaxScaleDenominatorEdit->setValidator( new QDoubleValidator( mMaxScaleDenominatorEdit ) );
124  if ( mRenderer->maxLabelScaleDenominator() > 0 )
125  {
126  mScaleDependentLabelsCheckBox->setCheckState( Qt::Checked );
127  }
128  else
129  {
130  mScaleDependentLabelsCheckBox->setCheckState( Qt::Unchecked );
131  mMaxScaleDenominatorEdit->setEnabled( false );
132  }
133 
134 
135  blockAllSignals( false );
136 
137  //set the appropriate renderer dialog
138  if ( mRenderer->embeddedRenderer() )
139  {
140  QString rendererName = mRenderer->embeddedRenderer()->type();
141  int rendererIndex = mRendererComboBox->findData( rendererName );
142  if ( rendererIndex != -1 )
143  {
144  mRendererComboBox->setCurrentIndex( rendererIndex );
145  on_mRendererComboBox_currentIndexChanged( rendererIndex );
146  }
147  }
148 
149  updateCenterIcon();
150 }
151 
153 {
154  delete mRenderer;
155 }
156 
158 {
159  return mRenderer;
160 }
161 
163 {
165  if ( mDistanceUnitWidget )
166  mDistanceUnitWidget->setMapCanvas( context.mapCanvas() );
167 }
168 
169 void QgsPointDisplacementRendererWidget::on_mLabelFieldComboBox_currentIndexChanged( const QString& text )
170 {
171  if ( mRenderer )
172  {
173  if ( text == tr( "None" ) )
174  {
175  mRenderer->setLabelAttributeName( QLatin1String( "" ) );
176  }
177  else
178  {
179  mRenderer->setLabelAttributeName( text );
180  }
181  emit widgetChanged();
182  }
183 }
184 
185 void QgsPointDisplacementRendererWidget::on_mRendererComboBox_currentIndexChanged( int index )
186 {
187  QString rendererId = mRendererComboBox->itemData( index ).toString();
189  if ( m )
190  {
191  // unfortunately renderer conversion is only available through the creation of a widget...
192  QgsRendererWidget* tempRenderWidget = m->createRendererWidget( mLayer, mStyle, mRenderer->embeddedRenderer()->clone() );
193  mRenderer->setEmbeddedRenderer( tempRenderWidget->renderer()->clone() );
194  delete tempRenderWidget;
195  emit widgetChanged();
196  }
197 }
198 
199 void QgsPointDisplacementRendererWidget::on_mPlacementComboBox_currentIndexChanged( int index )
200 {
201  if ( !mRenderer )
202  return;
203 
204  mRenderer->setPlacement(( QgsPointDisplacementRenderer::Placement )mPlacementComboBox->itemData( index ).toInt() );
205  emit widgetChanged();
206 }
207 
208 void QgsPointDisplacementRendererWidget::on_mRendererSettingsButton_clicked()
209 {
210  if ( !mRenderer )
211  return;
212 
214  if ( m )
215  {
217  w->setPanelTitle( tr( "Renderer settings" ) );
218 
220 
224  QList< QgsExpressionContextScope > scopes = context.additionalExpressionContextScopes();
225  scopes << scope;
226  context.setAdditionalExpressionContextScopes( scopes );
227  w->setContext( context );
228 
229  connect( w, SIGNAL( widgetChanged() ), this, SLOT( updateRendererFromWidget() ) );
230  openPanel( w );
231  }
232 }
233 
234 void QgsPointDisplacementRendererWidget::on_mLabelFontButton_clicked()
235 {
236  if ( !mRenderer )
237  {
238  return;
239  }
240 
241  bool ok;
242  QFont newFont = QgisGui::getFont( ok, mRenderer->labelFont(), tr( "Label Font" ) );
243  if ( ok )
244  {
245  mRenderer->setLabelFont( newFont );
246  emit widgetChanged();
247  }
248 }
249 
250 void QgsPointDisplacementRendererWidget::on_mCircleWidthSpinBox_valueChanged( double d )
251 {
252  if ( mRenderer )
253  {
254  mRenderer->setCircleWidth( d );
255  emit widgetChanged();
256  }
257 }
258 
259 void QgsPointDisplacementRendererWidget::on_mCircleColorButton_colorChanged( const QColor& newColor )
260 {
261  if ( !mRenderer )
262  {
263  return;
264  }
265 
266  mRenderer->setCircleColor( newColor );
267  emit widgetChanged();
268 }
269 
270 void QgsPointDisplacementRendererWidget::on_mLabelColorButton_colorChanged( const QColor& newColor )
271 {
272  if ( !mRenderer )
273  {
274  return;
275  }
276 
277  mRenderer->setLabelColor( newColor );
278  emit widgetChanged();
279 }
280 
281 void QgsPointDisplacementRendererWidget::on_mCircleModificationSpinBox_valueChanged( double d )
282 {
283  if ( !mRenderer )
284  {
285  return;
286  }
287 
288  mRenderer->setCircleRadiusAddition( d );
289  emit widgetChanged();
290 }
291 
292 void QgsPointDisplacementRendererWidget::on_mDistanceSpinBox_valueChanged( double d )
293 {
294  if ( mRenderer )
295  {
296  mRenderer->setTolerance( d );
297  emit widgetChanged();
298  }
299 }
300 
301 void QgsPointDisplacementRendererWidget::on_mDistanceUnitWidget_changed()
302 {
303  if ( mRenderer )
304  {
305  mRenderer->setToleranceUnit( mDistanceUnitWidget->unit() );
306  mRenderer->setToleranceMapUnitScale( mDistanceUnitWidget->getMapUnitScale() );
307  emit widgetChanged();
308  }
309 }
310 
311 void QgsPointDisplacementRendererWidget::on_mScaleDependentLabelsCheckBox_stateChanged( int state )
312 {
313  if ( state == Qt::Unchecked )
314  {
315  mMaxScaleDenominatorEdit->setText( QStringLiteral( "-1" ) );
316  mMaxScaleDenominatorEdit->setEnabled( false );
317  }
318  else
319  {
320  mMaxScaleDenominatorEdit->setEnabled( true );
321  }
322 }
323 
324 void QgsPointDisplacementRendererWidget::on_mMaxScaleDenominatorEdit_textChanged( const QString & text )
325 {
326  if ( !mRenderer )
327  {
328  return;
329  }
330 
331  bool ok;
332  double scaleDenominator = text.toDouble( &ok );
333  if ( ok )
334  {
335  mRenderer->setMaxLabelScaleDenominator( scaleDenominator );
336  emit widgetChanged();
337  }
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  mMaxScaleDenominatorEdit->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, SIGNAL( widgetChanged() ), this, SLOT( updateCenterSymbolFromWidget() ) );
378  connect( dlg, SIGNAL( panelAccepted( QgsPanelWidget* ) ), this, SLOT( cleanUpSymbolSelector( QgsPanelWidget* ) ) );
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.
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:104
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:52
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:99
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:54
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:1492
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)