QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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 "qgsvectorlayer.h"
25#include "qgsapplication.h"
26#include "qgsmarkersymbol.h"
27
29{
30 return new QgsPointDisplacementRendererWidget( layer, style, renderer );
31}
32
34 : QgsRendererWidget( layer, style )
35
36{
37 if ( !layer )
38 {
39 return;
40 }
41
42 //the renderer only applies to point vector layers
44 {
45 //setup blank dialog
46 mRenderer = nullptr;
47 setupBlankUi( layer->name() );
48 return;
49 }
50 setupUi( this );
51 connect( mLabelFieldComboBox, &QComboBox::currentTextChanged, this, &QgsPointDisplacementRendererWidget::mLabelFieldComboBox_currentIndexChanged );
52 connect( mRendererComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointDisplacementRendererWidget::mRendererComboBox_currentIndexChanged );
53 connect( mPlacementComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointDisplacementRendererWidget::mPlacementComboBox_currentIndexChanged );
54 connect( mCircleWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsPointDisplacementRendererWidget::mCircleWidthSpinBox_valueChanged );
55 connect( mCircleColorButton, &QgsColorButton::colorChanged, this, &QgsPointDisplacementRendererWidget::mCircleColorButton_colorChanged );
56 connect( mDistanceSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsPointDisplacementRendererWidget::mDistanceSpinBox_valueChanged );
57 connect( mDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointDisplacementRendererWidget::mDistanceUnitWidget_changed );
58 connect( mLabelColorButton, &QgsColorButton::colorChanged, this, &QgsPointDisplacementRendererWidget::mLabelColorButton_colorChanged );
59 connect( mCircleModificationSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsPointDisplacementRendererWidget::mCircleModificationSpinBox_valueChanged );
60 connect( mLabelDistanceFactorSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsPointDisplacementRendererWidget::mLabelDistanceFactorSpinBox_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( Qgis::SymbolType::Marker );
69
70 if ( renderer )
71 {
73 }
74 if ( !mRenderer )
75 {
76 mRenderer = std::make_unique< QgsPointDisplacementRenderer >();
77 if ( renderer )
78 renderer->copyRendererData( mRenderer.get() );
79 }
80
81 blockAllSignals( true );
82
83 mPlacementComboBox->addItem( tr( "Ring" ), QgsPointDisplacementRenderer::Ring );
84 mPlacementComboBox->addItem( tr( "Concentric Rings" ), QgsPointDisplacementRenderer::ConcentricRings );
85 mPlacementComboBox->addItem( tr( "Grid" ), QgsPointDisplacementRenderer::Grid );
86
87 //insert attributes into combo box
88 if ( layer )
89 {
90 const QgsFields layerFields = layer->fields();
91 for ( const QgsField &f : layerFields )
92 {
93 mLabelFieldComboBox->addItem( f.name() );
94 }
95 mLabelFieldComboBox->addItem( tr( "None" ) );
96
97 const QString currentLabelAttribute = mRenderer->labelAttributeName();
98 if ( !currentLabelAttribute.isEmpty() )
99 {
100 mLabelFieldComboBox->setCurrentIndex( mLabelFieldComboBox->findText( currentLabelAttribute ) );
101 }
102 else
103 {
104 mLabelFieldComboBox->setCurrentIndex( mLabelFieldComboBox->findText( tr( "None" ) ) );
105 }
106 }
107
108 //insert possible renderer types
110 QStringList::const_iterator it = rendererList.constBegin();
111 for ( ; it != rendererList.constEnd(); ++it )
112 {
113 if ( *it != QLatin1String( "pointDisplacement" ) && *it != QLatin1String( "pointCluster" ) && *it != QLatin1String( "heatmapRenderer" ) )
114 {
116 mRendererComboBox->addItem( m->icon(), m->visibleName(), *it );
117 }
118 }
119
120 mCircleColorButton->setColorDialogTitle( tr( "Select Color" ) );
121 mCircleColorButton->setContext( QStringLiteral( "symbology" ) );
122 mCircleColorButton->setAllowOpacity( true );
123 mCircleColorButton->setShowNoColor( true );
124 mCircleColorButton->setNoColorString( tr( "Transparent Stroke" ) );
125 mLabelColorButton->setContext( QStringLiteral( "symbology" ) );
126 mLabelColorButton->setColorDialogTitle( tr( "Select Color" ) );
127 mLabelColorButton->setAllowOpacity( true );
128
129 mCircleWidthSpinBox->setValue( mRenderer->circleWidth() );
130 mCircleColorButton->setColor( mRenderer->circleColor() );
131 mLabelColorButton->setColor( mRenderer->labelColor() );
132 mLabelFontButton->setCurrentFont( mRenderer->labelFont() );
133 mCircleModificationSpinBox->setClearValue( 0.0 );
134 mCircleModificationSpinBox->setValue( mRenderer->circleRadiusAddition() );
135 mLabelDistanceFactorSpinBox->setClearValue( 0.5 );
136 mLabelDistanceFactorSpinBox->setValue( mRenderer->labelDistanceFactor() );
137 mDistanceSpinBox->setValue( mRenderer->tolerance() );
138 mDistanceUnitWidget->setUnit( mRenderer->toleranceUnit() );
139 mDistanceUnitWidget->setMapUnitScale( mRenderer->toleranceMapUnitScale() );
140 mCenterSymbolToolButton->setSymbol( mRenderer->centerSymbol()->clone() );
141
142 mPlacementComboBox->setCurrentIndex( mPlacementComboBox->findData( mRenderer->placement() ) );
143
144 //scale dependent labeling
145 mMinLabelScaleWidget->setScale( std::max( mRenderer->minimumLabelScale(), 0.0 ) );
146 if ( mRenderer->minimumLabelScale() > 0 )
147 {
148 mScaleDependentLabelsCheckBox->setCheckState( Qt::Checked );
149 }
150 else
151 {
152 mScaleDependentLabelsCheckBox->setCheckState( Qt::Unchecked );
153 mMinLabelScaleWidget->setEnabled( false );
154 }
155
156
157 blockAllSignals( false );
158
159 //set the appropriate renderer dialog
160 if ( mRenderer->embeddedRenderer() )
161 {
162 const QString rendererName = mRenderer->embeddedRenderer()->type();
163 const int rendererIndex = mRendererComboBox->findData( rendererName );
164 if ( rendererIndex != -1 )
165 {
166 mRendererComboBox->setCurrentIndex( rendererIndex );
167 mRendererComboBox_currentIndexChanged( rendererIndex );
168 }
169 }
170
171 connect( mMinLabelScaleWidget, &QgsScaleWidget::scaleChanged, this, &QgsPointDisplacementRendererWidget::minLabelScaleChanged );
172 connect( mLabelFontButton, &QgsFontButton::changed, this, &QgsPointDisplacementRendererWidget::labelFontChanged );
173 connect( mCenterSymbolToolButton, &QgsSymbolButton::changed, this, &QgsPointDisplacementRendererWidget::centerSymbolChanged );
174 mCenterSymbolToolButton->setDialogTitle( tr( "Center symbol" ) );
175 mCenterSymbolToolButton->setLayer( mLayer );
176 mCenterSymbolToolButton->registerExpressionContextGenerator( this );
177}
178
180
182{
183 return mRenderer.get();
184}
185
187{
189 if ( mDistanceUnitWidget )
190 mDistanceUnitWidget->setMapCanvas( context.mapCanvas() );
191 if ( mMinLabelScaleWidget )
192 {
193 mMinLabelScaleWidget->setMapCanvas( context.mapCanvas() );
194 mMinLabelScaleWidget->setShowCurrentScaleButton( true );
195 }
196 if ( mCenterSymbolToolButton )
197 {
198 mCenterSymbolToolButton->setMapCanvas( context.mapCanvas() );
199 mCenterSymbolToolButton->setMessageBar( context.messageBar() );
200 }
201}
202
204{
206 if ( auto *lExpressionContext = mContext.expressionContext() )
207 context = *lExpressionContext;
208 else
213 QList< QgsExpressionContextScope > scopes = mContext.additionalExpressionContextScopes();
214 scopes << scope;
215 const auto constScopes = scopes;
216 for ( const QgsExpressionContextScope &s : constScopes )
217 {
219 }
220 return context;
221}
222
223void QgsPointDisplacementRendererWidget::mLabelFieldComboBox_currentIndexChanged( const QString &text )
224{
225 if ( mRenderer )
226 {
227 if ( text == tr( "None" ) )
228 {
229 mRenderer->setLabelAttributeName( QString() );
230 }
231 else
232 {
233 mRenderer->setLabelAttributeName( text );
234 }
235 emit widgetChanged();
236 }
237}
238
239void QgsPointDisplacementRendererWidget::mRendererComboBox_currentIndexChanged( int index )
240{
241 const QString rendererId = mRendererComboBox->itemData( index ).toString();
243 if ( m )
244 {
245 // unfortunately renderer conversion is only available through the creation of a widget...
246 const std::unique_ptr< QgsFeatureRenderer> oldRenderer( mRenderer->embeddedRenderer()->clone() );
247 QgsRendererWidget *tempRenderWidget = m->createRendererWidget( mLayer, mStyle, oldRenderer.get() );
248 mRenderer->setEmbeddedRenderer( tempRenderWidget->renderer()->clone() );
249 delete tempRenderWidget;
250 emit widgetChanged();
251 }
252}
253
254void QgsPointDisplacementRendererWidget::mPlacementComboBox_currentIndexChanged( int index )
255{
256 if ( !mRenderer )
257 return;
258
259 mRenderer->setPlacement( ( QgsPointDisplacementRenderer::Placement )mPlacementComboBox->itemData( index ).toInt() );
260 emit widgetChanged();
261}
262
263void QgsPointDisplacementRendererWidget::mRendererSettingsButton_clicked()
264{
265 if ( !mRenderer )
266 return;
267
268 QgsRendererAbstractMetadata *m = QgsApplication::rendererRegistry()->rendererMetadata( mRenderer->embeddedRenderer()->type() );
269 if ( m )
270 {
271 QgsRendererWidget *w = m->createRendererWidget( mLayer, mStyle, mRenderer->embeddedRenderer()->clone() );
272 w->setPanelTitle( tr( "Renderer Settings" ) );
273
275
279 QList< QgsExpressionContextScope > scopes = context.additionalExpressionContextScopes();
280 scopes << scope;
283 w->setContext( context );
284
285 connect( w, &QgsPanelWidget::widgetChanged, this, &QgsPointDisplacementRendererWidget::updateRendererFromWidget );
286 openPanel( w );
287 }
288}
289
290void QgsPointDisplacementRendererWidget::labelFontChanged()
291{
292 if ( !mRenderer )
293 {
294 return;
295 }
296
297 mRenderer->setLabelFont( mLabelFontButton->currentFont() );
298 emit widgetChanged();
299}
300
301void QgsPointDisplacementRendererWidget::mCircleWidthSpinBox_valueChanged( double d )
302{
303 if ( mRenderer )
304 {
305 mRenderer->setCircleWidth( d );
306 emit widgetChanged();
307 }
308}
309
310void QgsPointDisplacementRendererWidget::mCircleColorButton_colorChanged( const QColor &newColor )
311{
312 if ( !mRenderer )
313 {
314 return;
315 }
316
317 mRenderer->setCircleColor( newColor );
318 emit widgetChanged();
319}
320
321void QgsPointDisplacementRendererWidget::mLabelColorButton_colorChanged( const QColor &newColor )
322{
323 if ( !mRenderer )
324 {
325 return;
326 }
327
328 mRenderer->setLabelColor( newColor );
329 emit widgetChanged();
330}
331
332void QgsPointDisplacementRendererWidget::mCircleModificationSpinBox_valueChanged( double d )
333{
334 if ( !mRenderer )
335 {
336 return;
337 }
338
339 mRenderer->setCircleRadiusAddition( d );
340 emit widgetChanged();
341}
342
343void QgsPointDisplacementRendererWidget::mLabelDistanceFactorSpinBox_valueChanged( double d )
344{
345 if ( !mRenderer )
346 {
347 return;
348 }
349
350 mRenderer->setLabelDistanceFactor( d );
351 emit widgetChanged();
352}
353
354void QgsPointDisplacementRendererWidget::mDistanceSpinBox_valueChanged( double d )
355{
356 if ( mRenderer )
357 {
358 mRenderer->setTolerance( d );
359 emit widgetChanged();
360 }
361}
362
363void QgsPointDisplacementRendererWidget::mDistanceUnitWidget_changed()
364{
365 if ( mRenderer )
366 {
367 mRenderer->setToleranceUnit( mDistanceUnitWidget->unit() );
368 mRenderer->setToleranceMapUnitScale( mDistanceUnitWidget->getMapUnitScale() );
369 emit widgetChanged();
370 }
371}
372
373void QgsPointDisplacementRendererWidget::mScaleDependentLabelsCheckBox_stateChanged( int state )
374{
375 if ( state == Qt::Unchecked )
376 {
377 mMinLabelScaleWidget->setScale( 0 );
378 mMinLabelScaleWidget->setEnabled( false );
379 }
380 else
381 {
382 mMinLabelScaleWidget->setEnabled( true );
383 }
384}
385
386void QgsPointDisplacementRendererWidget::minLabelScaleChanged( double scale )
387{
388 if ( !mRenderer )
389 {
390 return;
391 }
392
393 mRenderer->setMinimumLabelScale( scale );
394 emit widgetChanged();
395}
396
397void QgsPointDisplacementRendererWidget::blockAllSignals( bool block )
398{
399 mLabelFieldComboBox->blockSignals( block );
400 mLabelFontButton->blockSignals( block );
401 mCircleWidthSpinBox->blockSignals( block );
402 mCircleColorButton->blockSignals( block );
403 mRendererComboBox->blockSignals( block );
404 mLabelColorButton->blockSignals( block );
405 mCircleModificationSpinBox->blockSignals( block );
406 mLabelDistanceFactorSpinBox->blockSignals( block );
407 mScaleDependentLabelsCheckBox->blockSignals( block );
408 mMinLabelScaleWidget->blockSignals( block );
409 mCenterSymbolToolButton->blockSignals( block );
410 mDistanceSpinBox->blockSignals( block );
411 mDistanceUnitWidget->blockSignals( block );
412 mPlacementComboBox->blockSignals( block );
413}
414
415void QgsPointDisplacementRendererWidget::centerSymbolChanged()
416{
417 mRenderer->setCenterSymbol( mCenterSymbolToolButton->clonedSymbol< QgsMarkerSymbol >() );
418 emit widgetChanged();
419}
420
421void QgsPointDisplacementRendererWidget::updateRendererFromWidget()
422{
423 QgsRendererWidget *w = qobject_cast<QgsRendererWidget *>( sender() );
424 if ( !w )
425 return;
426
427 mRenderer->setEmbeddedRenderer( w->renderer()->clone() );
428 emit widgetChanged();
429}
430
431void QgsPointDisplacementRendererWidget::setupBlankUi( const QString &layerName )
432{
433 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 );
434 QVBoxLayout *layout = new QVBoxLayout( this );
435 layout->setContentsMargins( 0, 0, 0, 0 );
436 layout->addWidget( label );
437}
@ Millimeters
Millimeters.
@ Points
Points (e.g., for font sizes)
@ MapUnits
Map units.
@ MetersInMapUnits
Meters value as Map units.
@ Marker
Marker symbol.
static QgsRendererRegistry * rendererRegistry()
Returns the application's renderer registry, used for managing vector layer renderers.
void colorChanged(const QColor &color)
Emitted whenever a new color is set for the button.
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
static const QString EXPR_CLUSTER_SIZE
Inbuilt variable name for cluster size variable.
static const QString EXPR_CLUSTER_COLOR
Inbuilt variable name for cluster color variable.
void copyRendererData(QgsFeatureRenderer *destRenderer) const
Clones generic renderer data to another renderer.
Definition: qgsrenderer.cpp:46
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:53
Container of fields for a vector layer.
Definition: qgsfields.h:45
@ ModeQFont
Configure font settings for use with QFont objects.
Definition: qgsfontbutton.h:62
void changed()
Emitted when the widget's text format settings are changed.
QString name
Definition: qgsmaplayer.h:78
A marker symbol type, for rendering Point and MultiPoint geometries.
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
void widgetChanged()
Emitted when the widget state changes.
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
QgsFeatureRenderer * renderer() override
Returns 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...
QgsPointDisplacementRendererWidget(QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *renderer)
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
static QgsRendererWidget * create(QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *renderer)
Placement
Placement methods for dispersing points.
@ ConcentricRings
Place points in concentric rings around group.
@ Ring
Place points in a single ring around group.
@ Grid
Place points in a grid around group.
static QgsPointDisplacementRenderer * convertFromRenderer(const QgsFeatureRenderer *renderer)
Creates a QgsPointDisplacementRenderer from an existing renderer.
Stores metadata about one renderer class.
@ PointLayer
Compatible with point layers.
QIcon icon() const
Returns an icon representing the renderer.
QString visibleName() const
Returns a friendly display name of the renderer.
virtual QgsRendererWidget * createRendererWidget(QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *oldRenderer)
Returns new instance of settings widget for the renderer.
QStringList renderersList(QgsRendererAbstractMetadata::LayerTypes layerTypes=QgsRendererAbstractMetadata::All) const
Returns a list of available renderers.
QgsRendererAbstractMetadata * rendererMetadata(const QString &rendererName)
Returns the metadata for a specified renderer.
Base class for renderer settings widgets.
QgsSymbolWidgetContext mContext
Context in which widget is shown.
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 QgsFeatureRenderer * renderer()=0
Returns pointer to the renderer (no transfer of ownership)
virtual void disableSymbolLevels()
Disables symbol level modification on the widget.
QgsSymbolWidgetContext context() const
Returns the context in which the renderer widget is shown, e.g., the associated map canvas and expres...
QgsVectorLayer * mLayer
void scaleChanged(double scale)
Emitted when user has finished editing/selecting a new scale.
void changed()
Emitted when the symbol's settings are changed.
Contains settings which reflect the context in which a symbol (or renderer) widget is shown,...
QList< QgsExpressionContextScope > additionalExpressionContextScopes() const
Returns the list of additional expression context scopes to show as available within the layer.
QList< QgsExpressionContextScope * > globalProjectAtlasMapLayerScopes(const QgsMapLayer *layer) const
Returns list of scopes: global, project, atlas, map, layer.
void setAdditionalExpressionContextScopes(const QList< QgsExpressionContextScope > &scopes)
Sets a list of additional expression context scopes to show as available within the layer.
QgsExpressionContext * expressionContext() const
Returns the expression context used for the widget, if set.
QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
QgsMessageBar * messageBar() const
Returns the message bar associated with the widget.
Represents a vector layer which manages a vector based data sets.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Q_INVOKABLE Qgis::WkbType wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:862
Single variable definition for use within a QgsExpressionContextScope.