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