QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
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
19#include "moc_qgspointdisplacementrendererwidget.cpp"
21#include "qgsrendererregistry.h"
22#include "qgsfields.h"
23#include "qgsstyle.h"
25#include "qgsvectorlayer.h"
26#include "qgsapplication.h"
27#include "qgsmarkersymbol.h"
28
33
35 : QgsRendererWidget( layer, style )
36
37{
38 if ( !layer )
39 {
40 return;
41 }
42
43 //the renderer only applies to point vector layers
45 {
46 //setup blank dialog
47 mRenderer = nullptr;
48 setupBlankUi( layer->name() );
49 return;
50 }
51 setupUi( this );
52 connect( mLabelFieldComboBox, &QComboBox::currentTextChanged, this, &QgsPointDisplacementRendererWidget::mLabelFieldComboBox_currentIndexChanged );
53 connect( mRendererComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointDisplacementRendererWidget::mRendererComboBox_currentIndexChanged );
54 connect( mPlacementComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointDisplacementRendererWidget::mPlacementComboBox_currentIndexChanged );
55 connect( mCircleWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointDisplacementRendererWidget::mCircleWidthSpinBox_valueChanged );
56 connect( mCircleColorButton, &QgsColorButton::colorChanged, this, &QgsPointDisplacementRendererWidget::mCircleColorButton_colorChanged );
57 connect( mDistanceSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointDisplacementRendererWidget::mDistanceSpinBox_valueChanged );
58 connect( mDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointDisplacementRendererWidget::mDistanceUnitWidget_changed );
59 connect( mLabelColorButton, &QgsColorButton::colorChanged, this, &QgsPointDisplacementRendererWidget::mLabelColorButton_colorChanged );
60 connect( mCircleModificationSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointDisplacementRendererWidget::mCircleModificationSpinBox_valueChanged );
61 connect( mLabelDistanceFactorSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointDisplacementRendererWidget::mLabelDistanceFactorSpinBox_valueChanged );
62 connect( mScaleDependentLabelsCheckBox, &QCheckBox::stateChanged, this, &QgsPointDisplacementRendererWidget::mScaleDependentLabelsCheckBox_stateChanged );
63 connect( mRendererSettingsButton, &QPushButton::clicked, this, &QgsPointDisplacementRendererWidget::mRendererSettingsButton_clicked );
64 this->layout()->setContentsMargins( 0, 0, 0, 0 );
65
66 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
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 for ( const QgsExpressionContextScope &s : std::as_const( scopes ) )
216 {
218 }
219 return context;
220}
221
222void QgsPointDisplacementRendererWidget::mLabelFieldComboBox_currentIndexChanged( const QString &text )
223{
224 if ( mRenderer )
225 {
226 if ( text == tr( "None" ) )
227 {
228 mRenderer->setLabelAttributeName( QString() );
229 }
230 else
231 {
232 mRenderer->setLabelAttributeName( text );
233 }
234 emit widgetChanged();
235 }
236}
237
238void QgsPointDisplacementRendererWidget::mRendererComboBox_currentIndexChanged( int index )
239{
240 const QString rendererId = mRendererComboBox->itemData( index ).toString();
242 if ( m )
243 {
244 // unfortunately renderer conversion is only available through the creation of a widget...
245 const std::unique_ptr<QgsFeatureRenderer> oldRenderer( mRenderer->embeddedRenderer()->clone() );
246 QgsRendererWidget *tempRenderWidget = m->createRendererWidget( mLayer, mStyle, oldRenderer.get() );
247 mRenderer->setEmbeddedRenderer( tempRenderWidget->renderer()->clone() );
248 delete tempRenderWidget;
249 emit widgetChanged();
250 }
251}
252
253void QgsPointDisplacementRendererWidget::mPlacementComboBox_currentIndexChanged( int index )
254{
255 if ( !mRenderer )
256 return;
257
258 mRenderer->setPlacement( ( QgsPointDisplacementRenderer::Placement ) mPlacementComboBox->itemData( index ).toInt() );
259 emit widgetChanged();
260}
261
262void QgsPointDisplacementRendererWidget::mRendererSettingsButton_clicked()
263{
264 if ( !mRenderer )
265 return;
266
267 QgsRendererAbstractMetadata *m = QgsApplication::rendererRegistry()->rendererMetadata( mRenderer->embeddedRenderer()->type() );
268 if ( m )
269 {
270 QgsRendererWidget *w = m->createRendererWidget( mLayer, mStyle, mRenderer->embeddedRenderer()->clone() );
271 w->setPanelTitle( tr( "Renderer Settings" ) );
272
274
278 QList<QgsExpressionContextScope> scopes = context.additionalExpressionContextScopes();
279 scopes << scope;
282 w->setContext( context );
283
284 connect( w, &QgsPanelWidget::widgetChanged, this, &QgsPointDisplacementRendererWidget::updateRendererFromWidget );
285 openPanel( w );
286 }
287}
288
289void QgsPointDisplacementRendererWidget::labelFontChanged()
290{
291 if ( !mRenderer )
292 {
293 return;
294 }
295
296 mRenderer->setLabelFont( mLabelFontButton->currentFont() );
297 emit widgetChanged();
298}
299
300void QgsPointDisplacementRendererWidget::mCircleWidthSpinBox_valueChanged( double d )
301{
302 if ( mRenderer )
303 {
304 mRenderer->setCircleWidth( d );
305 emit widgetChanged();
306 }
307}
308
309void QgsPointDisplacementRendererWidget::mCircleColorButton_colorChanged( const QColor &newColor )
310{
311 if ( !mRenderer )
312 {
313 return;
314 }
315
316 mRenderer->setCircleColor( newColor );
317 emit widgetChanged();
318}
319
320void QgsPointDisplacementRendererWidget::mLabelColorButton_colorChanged( const QColor &newColor )
321{
322 if ( !mRenderer )
323 {
324 return;
325 }
326
327 mRenderer->setLabelColor( newColor );
328 emit widgetChanged();
329}
330
331void QgsPointDisplacementRendererWidget::mCircleModificationSpinBox_valueChanged( double d )
332{
333 if ( !mRenderer )
334 {
335 return;
336 }
337
338 mRenderer->setCircleRadiusAddition( d );
339 emit widgetChanged();
340}
341
342void QgsPointDisplacementRendererWidget::mLabelDistanceFactorSpinBox_valueChanged( double d )
343{
344 if ( !mRenderer )
345 {
346 return;
347 }
348
349 mRenderer->setLabelDistanceFactor( d );
350 emit widgetChanged();
351}
352
353void QgsPointDisplacementRendererWidget::mDistanceSpinBox_valueChanged( double d )
354{
355 if ( mRenderer )
356 {
357 mRenderer->setTolerance( d );
358 emit widgetChanged();
359 }
360}
361
362void QgsPointDisplacementRendererWidget::mDistanceUnitWidget_changed()
363{
364 if ( mRenderer )
365 {
366 mRenderer->setToleranceUnit( mDistanceUnitWidget->unit() );
367 mRenderer->setToleranceMapUnitScale( mDistanceUnitWidget->getMapUnitScale() );
368 emit widgetChanged();
369 }
370}
371
372void QgsPointDisplacementRendererWidget::mScaleDependentLabelsCheckBox_stateChanged( int state )
373{
374 if ( state == Qt::Unchecked )
375 {
376 mMinLabelScaleWidget->setScale( 0 );
377 mMinLabelScaleWidget->setEnabled( false );
378 }
379 else
380 {
381 mMinLabelScaleWidget->setEnabled( true );
382 }
383}
384
385void QgsPointDisplacementRendererWidget::minLabelScaleChanged( double scale )
386{
387 if ( !mRenderer )
388 {
389 return;
390 }
391
392 mRenderer->setMinimumLabelScale( scale );
393 emit widgetChanged();
394}
395
396void QgsPointDisplacementRendererWidget::blockAllSignals( bool block )
397{
398 mLabelFieldComboBox->blockSignals( block );
399 mLabelFontButton->blockSignals( block );
400 mCircleWidthSpinBox->blockSignals( block );
401 mCircleColorButton->blockSignals( block );
402 mRendererComboBox->blockSignals( block );
403 mLabelColorButton->blockSignals( block );
404 mCircleModificationSpinBox->blockSignals( block );
405 mLabelDistanceFactorSpinBox->blockSignals( block );
406 mScaleDependentLabelsCheckBox->blockSignals( block );
407 mMinLabelScaleWidget->blockSignals( block );
408 mCenterSymbolToolButton->blockSignals( block );
409 mDistanceSpinBox->blockSignals( block );
410 mDistanceUnitWidget->blockSignals( block );
411 mPlacementComboBox->blockSignals( block );
412}
413
414void QgsPointDisplacementRendererWidget::centerSymbolChanged()
415{
416 mRenderer->setCenterSymbol( mCenterSymbolToolButton->clonedSymbol<QgsMarkerSymbol>() );
417 emit widgetChanged();
418}
419
420void QgsPointDisplacementRendererWidget::updateRendererFromWidget()
421{
422 QgsRendererWidget *w = qobject_cast<QgsRendererWidget *>( sender() );
423 if ( !w )
424 return;
425
426 mRenderer->setEmbeddedRenderer( w->renderer()->clone() );
427 emit widgetChanged();
428}
429
430void QgsPointDisplacementRendererWidget::setupBlankUi( const QString &layerName )
431{
432 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 );
433 QVBoxLayout *layout = new QVBoxLayout( this );
434 layout->setContentsMargins( 0, 0, 0, 0 );
435 layout->addWidget( label );
436}
@ 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.
Abstract base class for all 2D vector feature renderers.
void copyRendererData(QgsFeatureRenderer *destRenderer) const
Clones generic renderer data to another renderer.
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:46
@ ModeQFont
Configure font settings for use with QFont objects.
void changed()
Emitted when the widget's text format settings are changed.
QString name
Definition qgsmaplayer.h:80
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.
void changed()
Emitted when the selected unit is changed, or the definition of the map unit scale is changed.
Represents a vector layer which manages a vector based data sets.
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...
Single variable definition for use within a QgsExpressionContextScope.