QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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#include "qgsmarkersymbol.h"
29
31{
32 return new QgsPointDisplacementRendererWidget( layer, style, renderer );
33}
34
36 : QgsRendererWidget( layer, style )
37
38{
39 if ( !layer )
40 {
41 return;
42 }
43
44 //the renderer only applies to point vector layers
46 {
47 //setup blank dialog
48 mRenderer = nullptr;
49 setupBlankUi( layer->name() );
50 return;
51 }
52 setupUi( this );
53 connect( mLabelFieldComboBox, &QComboBox::currentTextChanged, this, &QgsPointDisplacementRendererWidget::mLabelFieldComboBox_currentIndexChanged );
54 connect( mRendererComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointDisplacementRendererWidget::mRendererComboBox_currentIndexChanged );
55 connect( mPlacementComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointDisplacementRendererWidget::mPlacementComboBox_currentIndexChanged );
56 connect( mCircleWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsPointDisplacementRendererWidget::mCircleWidthSpinBox_valueChanged );
57 connect( mCircleColorButton, &QgsColorButton::colorChanged, this, &QgsPointDisplacementRendererWidget::mCircleColorButton_colorChanged );
58 connect( mDistanceSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsPointDisplacementRendererWidget::mDistanceSpinBox_valueChanged );
59 connect( mDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointDisplacementRendererWidget::mDistanceUnitWidget_changed );
60 connect( mLabelColorButton, &QgsColorButton::colorChanged, this, &QgsPointDisplacementRendererWidget::mLabelColorButton_colorChanged );
61 connect( mCircleModificationSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsPointDisplacementRendererWidget::mCircleModificationSpinBox_valueChanged );
62 connect( mLabelDistanceFactorSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsPointDisplacementRendererWidget::mLabelDistanceFactorSpinBox_valueChanged );
63 connect( mScaleDependentLabelsCheckBox, &QCheckBox::stateChanged, this, &QgsPointDisplacementRendererWidget::mScaleDependentLabelsCheckBox_stateChanged );
64 connect( mRendererSettingsButton, &QPushButton::clicked, this, &QgsPointDisplacementRendererWidget::mRendererSettingsButton_clicked );
65 this->layout()->setContentsMargins( 0, 0, 0, 0 );
66
67 mLabelFontButton->setMode( QgsFontButton::ModeQFont );
70 mCenterSymbolToolButton->setSymbolType( Qgis::SymbolType::Marker );
71
72 if ( renderer )
73 {
75 }
76 if ( !mRenderer )
77 {
78 mRenderer = std::make_unique< QgsPointDisplacementRenderer >();
79 if ( renderer )
80 renderer->copyRendererData( mRenderer.get() );
81 }
82
83 blockAllSignals( true );
84
85 mPlacementComboBox->addItem( tr( "Ring" ), QgsPointDisplacementRenderer::Ring );
86 mPlacementComboBox->addItem( tr( "Concentric Rings" ), QgsPointDisplacementRenderer::ConcentricRings );
87 mPlacementComboBox->addItem( tr( "Grid" ), QgsPointDisplacementRenderer::Grid );
88
89 //insert attributes into combo box
90 if ( layer )
91 {
92 const QgsFields layerFields = layer->fields();
93 for ( const QgsField &f : layerFields )
94 {
95 mLabelFieldComboBox->addItem( f.name() );
96 }
97 mLabelFieldComboBox->addItem( tr( "None" ) );
98
99 const QString currentLabelAttribute = mRenderer->labelAttributeName();
100 if ( !currentLabelAttribute.isEmpty() )
101 {
102 mLabelFieldComboBox->setCurrentIndex( mLabelFieldComboBox->findText( currentLabelAttribute ) );
103 }
104 else
105 {
106 mLabelFieldComboBox->setCurrentIndex( mLabelFieldComboBox->findText( tr( "None" ) ) );
107 }
108 }
109
110 //insert possible renderer types
112 QStringList::const_iterator it = rendererList.constBegin();
113 for ( ; it != rendererList.constEnd(); ++it )
114 {
115 if ( *it != QLatin1String( "pointDisplacement" ) && *it != QLatin1String( "pointCluster" ) && *it != QLatin1String( "heatmapRenderer" ) )
116 {
118 mRendererComboBox->addItem( m->icon(), m->visibleName(), *it );
119 }
120 }
121
122 mCircleColorButton->setColorDialogTitle( tr( "Select Color" ) );
123 mCircleColorButton->setContext( QStringLiteral( "symbology" ) );
124 mCircleColorButton->setAllowOpacity( true );
125 mCircleColorButton->setShowNoColor( true );
126 mCircleColorButton->setNoColorString( tr( "Transparent Stroke" ) );
127 mLabelColorButton->setContext( QStringLiteral( "symbology" ) );
128 mLabelColorButton->setColorDialogTitle( tr( "Select Color" ) );
129 mLabelColorButton->setAllowOpacity( true );
130
131 mCircleWidthSpinBox->setValue( mRenderer->circleWidth() );
132 mCircleColorButton->setColor( mRenderer->circleColor() );
133 mLabelColorButton->setColor( mRenderer->labelColor() );
134 mLabelFontButton->setCurrentFont( mRenderer->labelFont() );
135 mCircleModificationSpinBox->setClearValue( 0.0 );
136 mCircleModificationSpinBox->setValue( mRenderer->circleRadiusAddition() );
137 mLabelDistanceFactorSpinBox->setClearValue( 0.5 );
138 mLabelDistanceFactorSpinBox->setValue( mRenderer->labelDistanceFactor() );
139 mDistanceSpinBox->setValue( mRenderer->tolerance() );
140 mDistanceUnitWidget->setUnit( mRenderer->toleranceUnit() );
141 mDistanceUnitWidget->setMapUnitScale( mRenderer->toleranceMapUnitScale() );
142 mCenterSymbolToolButton->setSymbol( mRenderer->centerSymbol()->clone() );
143
144 mPlacementComboBox->setCurrentIndex( mPlacementComboBox->findData( mRenderer->placement() ) );
145
146 //scale dependent labeling
147 mMinLabelScaleWidget->setScale( std::max( mRenderer->minimumLabelScale(), 0.0 ) );
148 if ( mRenderer->minimumLabelScale() > 0 )
149 {
150 mScaleDependentLabelsCheckBox->setCheckState( Qt::Checked );
151 }
152 else
153 {
154 mScaleDependentLabelsCheckBox->setCheckState( Qt::Unchecked );
155 mMinLabelScaleWidget->setEnabled( false );
156 }
157
158
159 blockAllSignals( false );
160
161 //set the appropriate renderer dialog
162 if ( mRenderer->embeddedRenderer() )
163 {
164 const QString rendererName = mRenderer->embeddedRenderer()->type();
165 const int rendererIndex = mRendererComboBox->findData( rendererName );
166 if ( rendererIndex != -1 )
167 {
168 mRendererComboBox->setCurrentIndex( rendererIndex );
169 mRendererComboBox_currentIndexChanged( rendererIndex );
170 }
171 }
172
173 connect( mMinLabelScaleWidget, &QgsScaleWidget::scaleChanged, this, &QgsPointDisplacementRendererWidget::minLabelScaleChanged );
174 connect( mLabelFontButton, &QgsFontButton::changed, this, &QgsPointDisplacementRendererWidget::labelFontChanged );
175 connect( mCenterSymbolToolButton, &QgsSymbolButton::changed, this, &QgsPointDisplacementRendererWidget::centerSymbolChanged );
176 mCenterSymbolToolButton->setDialogTitle( tr( "Center symbol" ) );
177 mCenterSymbolToolButton->setLayer( mLayer );
178 mCenterSymbolToolButton->registerExpressionContextGenerator( this );
179}
180
182
184{
185 return mRenderer.get();
186}
187
189{
191 if ( mDistanceUnitWidget )
192 mDistanceUnitWidget->setMapCanvas( context.mapCanvas() );
193 if ( mMinLabelScaleWidget )
194 {
195 mMinLabelScaleWidget->setMapCanvas( context.mapCanvas() );
196 mMinLabelScaleWidget->setShowCurrentScaleButton( true );
197 }
198 if ( mCenterSymbolToolButton )
199 {
200 mCenterSymbolToolButton->setMapCanvas( context.mapCanvas() );
201 mCenterSymbolToolButton->setMessageBar( context.messageBar() );
202 }
203}
204
206{
208 if ( auto *lExpressionContext = mContext.expressionContext() )
209 context = *lExpressionContext;
210 else
215 QList< QgsExpressionContextScope > scopes = mContext.additionalExpressionContextScopes();
216 scopes << scope;
217 const auto constScopes = scopes;
218 for ( const QgsExpressionContextScope &s : constScopes )
219 {
221 }
222 return context;
223}
224
225void QgsPointDisplacementRendererWidget::mLabelFieldComboBox_currentIndexChanged( const QString &text )
226{
227 if ( mRenderer )
228 {
229 if ( text == tr( "None" ) )
230 {
231 mRenderer->setLabelAttributeName( QString() );
232 }
233 else
234 {
235 mRenderer->setLabelAttributeName( text );
236 }
237 emit widgetChanged();
238 }
239}
240
241void QgsPointDisplacementRendererWidget::mRendererComboBox_currentIndexChanged( int index )
242{
243 const QString rendererId = mRendererComboBox->itemData( index ).toString();
245 if ( m )
246 {
247 // unfortunately renderer conversion is only available through the creation of a widget...
248 const std::unique_ptr< QgsFeatureRenderer> oldRenderer( mRenderer->embeddedRenderer()->clone() );
249 QgsRendererWidget *tempRenderWidget = m->createRendererWidget( mLayer, mStyle, oldRenderer.get() );
250 mRenderer->setEmbeddedRenderer( tempRenderWidget->renderer()->clone() );
251 delete tempRenderWidget;
252 emit widgetChanged();
253 }
254}
255
256void QgsPointDisplacementRendererWidget::mPlacementComboBox_currentIndexChanged( int index )
257{
258 if ( !mRenderer )
259 return;
260
261 mRenderer->setPlacement( ( QgsPointDisplacementRenderer::Placement )mPlacementComboBox->itemData( index ).toInt() );
262 emit widgetChanged();
263}
264
265void QgsPointDisplacementRendererWidget::mRendererSettingsButton_clicked()
266{
267 if ( !mRenderer )
268 return;
269
270 QgsRendererAbstractMetadata *m = QgsApplication::rendererRegistry()->rendererMetadata( mRenderer->embeddedRenderer()->type() );
271 if ( m )
272 {
273 QgsRendererWidget *w = m->createRendererWidget( mLayer, mStyle, mRenderer->embeddedRenderer()->clone() );
274 w->setPanelTitle( tr( "Renderer Settings" ) );
275
277
281 QList< QgsExpressionContextScope > scopes = context.additionalExpressionContextScopes();
282 scopes << scope;
285 w->setContext( context );
286
287 connect( w, &QgsPanelWidget::widgetChanged, this, &QgsPointDisplacementRendererWidget::updateRendererFromWidget );
288 openPanel( w );
289 }
290}
291
292void QgsPointDisplacementRendererWidget::labelFontChanged()
293{
294 if ( !mRenderer )
295 {
296 return;
297 }
298
299 mRenderer->setLabelFont( mLabelFontButton->currentFont() );
300 emit widgetChanged();
301}
302
303void QgsPointDisplacementRendererWidget::mCircleWidthSpinBox_valueChanged( double d )
304{
305 if ( mRenderer )
306 {
307 mRenderer->setCircleWidth( d );
308 emit widgetChanged();
309 }
310}
311
312void QgsPointDisplacementRendererWidget::mCircleColorButton_colorChanged( const QColor &newColor )
313{
314 if ( !mRenderer )
315 {
316 return;
317 }
318
319 mRenderer->setCircleColor( newColor );
320 emit widgetChanged();
321}
322
323void QgsPointDisplacementRendererWidget::mLabelColorButton_colorChanged( const QColor &newColor )
324{
325 if ( !mRenderer )
326 {
327 return;
328 }
329
330 mRenderer->setLabelColor( newColor );
331 emit widgetChanged();
332}
333
334void QgsPointDisplacementRendererWidget::mCircleModificationSpinBox_valueChanged( double d )
335{
336 if ( !mRenderer )
337 {
338 return;
339 }
340
341 mRenderer->setCircleRadiusAddition( d );
342 emit widgetChanged();
343}
344
345void QgsPointDisplacementRendererWidget::mLabelDistanceFactorSpinBox_valueChanged( double d )
346{
347 if ( !mRenderer )
348 {
349 return;
350 }
351
352 mRenderer->setLabelDistanceFactor( d );
353 emit widgetChanged();
354}
355
356void QgsPointDisplacementRendererWidget::mDistanceSpinBox_valueChanged( double d )
357{
358 if ( mRenderer )
359 {
360 mRenderer->setTolerance( d );
361 emit widgetChanged();
362 }
363}
364
365void QgsPointDisplacementRendererWidget::mDistanceUnitWidget_changed()
366{
367 if ( mRenderer )
368 {
369 mRenderer->setToleranceUnit( mDistanceUnitWidget->unit() );
370 mRenderer->setToleranceMapUnitScale( mDistanceUnitWidget->getMapUnitScale() );
371 emit widgetChanged();
372 }
373}
374
375void QgsPointDisplacementRendererWidget::mScaleDependentLabelsCheckBox_stateChanged( int state )
376{
377 if ( state == Qt::Unchecked )
378 {
379 mMinLabelScaleWidget->setScale( 0 );
380 mMinLabelScaleWidget->setEnabled( false );
381 }
382 else
383 {
384 mMinLabelScaleWidget->setEnabled( true );
385 }
386}
387
388void QgsPointDisplacementRendererWidget::minLabelScaleChanged( double scale )
389{
390 if ( !mRenderer )
391 {
392 return;
393 }
394
395 mRenderer->setMinimumLabelScale( scale );
396 emit widgetChanged();
397}
398
399void QgsPointDisplacementRendererWidget::blockAllSignals( bool block )
400{
401 mLabelFieldComboBox->blockSignals( block );
402 mLabelFontButton->blockSignals( block );
403 mCircleWidthSpinBox->blockSignals( block );
404 mCircleColorButton->blockSignals( block );
405 mRendererComboBox->blockSignals( block );
406 mLabelColorButton->blockSignals( block );
407 mCircleModificationSpinBox->blockSignals( block );
408 mLabelDistanceFactorSpinBox->blockSignals( block );
409 mScaleDependentLabelsCheckBox->blockSignals( block );
410 mMinLabelScaleWidget->blockSignals( block );
411 mCenterSymbolToolButton->blockSignals( block );
412 mDistanceSpinBox->blockSignals( block );
413 mDistanceUnitWidget->blockSignals( block );
414 mPlacementComboBox->blockSignals( block );
415}
416
417void QgsPointDisplacementRendererWidget::centerSymbolChanged()
418{
419 mRenderer->setCenterSymbol( mCenterSymbolToolButton->clonedSymbol< QgsMarkerSymbol >() );
420 emit widgetChanged();
421}
422
423void QgsPointDisplacementRendererWidget::updateRendererFromWidget()
424{
425 QgsRendererWidget *w = qobject_cast<QgsRendererWidget *>( sender() );
426 if ( !w )
427 return;
428
429 mRenderer->setEmbeddedRenderer( w->renderer()->clone() );
430 emit widgetChanged();
431}
432
433void QgsPointDisplacementRendererWidget::setupBlankUi( const QString &layerName )
434{
435 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 );
436 QVBoxLayout *layout = new QVBoxLayout( this );
437 layout->setContentsMargins( 0, 0, 0, 0 );
438 layout->addWidget( label );
439}
@ 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:52
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:51
Container of fields for a vector layer.
Definition: qgsfields.h:45
@ ModeQFont
Configure font settings for use with QFont objects.
Definition: qgsfontbutton.h:63
void changed()
Emitted when the widget's text format settings are changed.
QString name
Definition: qgsmaplayer.h:76
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.
QList< QgsUnitTypes::RenderUnit > RenderUnitList
List of render units.
Definition: qgsunittypes.h:240
@ RenderMetersInMapUnits
Meters value as Map units.
Definition: qgsunittypes.h:176
@ RenderPoints
Points (e.g., for font sizes)
Definition: qgsunittypes.h:173
@ RenderPixels
Pixels.
Definition: qgsunittypes.h:171
@ RenderInches
Inches.
Definition: qgsunittypes.h:174
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:169
@ RenderMapUnits
Map units.
Definition: qgsunittypes.h:170
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
static GeometryType geometryType(Type type) SIP_HOLDGIL
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:968
Single variable definition for use within a QgsExpressionContextScope.