QGIS API Documentation 3.41.0-Master (3440c17df1d)
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 );
69 mCenterSymbolToolButton->setSymbolType( Qgis::SymbolType::Marker );
70
71 if ( renderer )
72 {
74 }
75 if ( !mRenderer )
76 {
77 mRenderer = std::make_unique< QgsPointDisplacementRenderer >();
78 if ( renderer )
79 renderer->copyRendererData( mRenderer.get() );
80 }
81
82 blockAllSignals( true );
83
84 mPlacementComboBox->addItem( tr( "Ring" ), QgsPointDisplacementRenderer::Ring );
85 mPlacementComboBox->addItem( tr( "Concentric Rings" ), QgsPointDisplacementRenderer::ConcentricRings );
86 mPlacementComboBox->addItem( tr( "Grid" ), QgsPointDisplacementRenderer::Grid );
87
88 //insert attributes into combo box
89 if ( layer )
90 {
91 const QgsFields layerFields = layer->fields();
92 for ( const QgsField &f : layerFields )
93 {
94 mLabelFieldComboBox->addItem( f.name() );
95 }
96 mLabelFieldComboBox->addItem( tr( "None" ) );
97
98 const QString currentLabelAttribute = mRenderer->labelAttributeName();
99 if ( !currentLabelAttribute.isEmpty() )
100 {
101 mLabelFieldComboBox->setCurrentIndex( mLabelFieldComboBox->findText( currentLabelAttribute ) );
102 }
103 else
104 {
105 mLabelFieldComboBox->setCurrentIndex( mLabelFieldComboBox->findText( tr( "None" ) ) );
106 }
107 }
108
109 //insert possible renderer types
111 QStringList::const_iterator it = rendererList.constBegin();
112 for ( ; it != rendererList.constEnd(); ++it )
113 {
114 if ( *it != QLatin1String( "pointDisplacement" ) && *it != QLatin1String( "pointCluster" ) && *it != QLatin1String( "heatmapRenderer" ) )
115 {
117 mRendererComboBox->addItem( m->icon(), m->visibleName(), *it );
118 }
119 }
120
121 mCircleColorButton->setColorDialogTitle( tr( "Select Color" ) );
122 mCircleColorButton->setContext( QStringLiteral( "symbology" ) );
123 mCircleColorButton->setAllowOpacity( true );
124 mCircleColorButton->setShowNoColor( true );
125 mCircleColorButton->setNoColorString( tr( "Transparent Stroke" ) );
126 mLabelColorButton->setContext( QStringLiteral( "symbology" ) );
127 mLabelColorButton->setColorDialogTitle( tr( "Select Color" ) );
128 mLabelColorButton->setAllowOpacity( true );
129
130 mCircleWidthSpinBox->setValue( mRenderer->circleWidth() );
131 mCircleColorButton->setColor( mRenderer->circleColor() );
132 mLabelColorButton->setColor( mRenderer->labelColor() );
133 mLabelFontButton->setCurrentFont( mRenderer->labelFont() );
134 mCircleModificationSpinBox->setClearValue( 0.0 );
135 mCircleModificationSpinBox->setValue( mRenderer->circleRadiusAddition() );
136 mLabelDistanceFactorSpinBox->setClearValue( 0.5 );
137 mLabelDistanceFactorSpinBox->setValue( mRenderer->labelDistanceFactor() );
138 mDistanceSpinBox->setValue( mRenderer->tolerance() );
139 mDistanceUnitWidget->setUnit( mRenderer->toleranceUnit() );
140 mDistanceUnitWidget->setMapUnitScale( mRenderer->toleranceMapUnitScale() );
141 mCenterSymbolToolButton->setSymbol( mRenderer->centerSymbol()->clone() );
142
143 mPlacementComboBox->setCurrentIndex( mPlacementComboBox->findData( mRenderer->placement() ) );
144
145 //scale dependent labeling
146 mMinLabelScaleWidget->setScale( std::max( mRenderer->minimumLabelScale(), 0.0 ) );
147 if ( mRenderer->minimumLabelScale() > 0 )
148 {
149 mScaleDependentLabelsCheckBox->setCheckState( Qt::Checked );
150 }
151 else
152 {
153 mScaleDependentLabelsCheckBox->setCheckState( Qt::Unchecked );
154 mMinLabelScaleWidget->setEnabled( false );
155 }
156
157
158 blockAllSignals( false );
159
160 //set the appropriate renderer dialog
161 if ( mRenderer->embeddedRenderer() )
162 {
163 const QString rendererName = mRenderer->embeddedRenderer()->type();
164 const int rendererIndex = mRendererComboBox->findData( rendererName );
165 if ( rendererIndex != -1 )
166 {
167 mRendererComboBox->setCurrentIndex( rendererIndex );
168 mRendererComboBox_currentIndexChanged( rendererIndex );
169 }
170 }
171
172 connect( mMinLabelScaleWidget, &QgsScaleWidget::scaleChanged, this, &QgsPointDisplacementRendererWidget::minLabelScaleChanged );
173 connect( mLabelFontButton, &QgsFontButton::changed, this, &QgsPointDisplacementRendererWidget::labelFontChanged );
174 connect( mCenterSymbolToolButton, &QgsSymbolButton::changed, this, &QgsPointDisplacementRendererWidget::centerSymbolChanged );
175 mCenterSymbolToolButton->setDialogTitle( tr( "Center symbol" ) );
176 mCenterSymbolToolButton->setLayer( mLayer );
177 mCenterSymbolToolButton->registerExpressionContextGenerator( this );
178}
179
181
186
188{
190 if ( mDistanceUnitWidget )
191 mDistanceUnitWidget->setMapCanvas( context.mapCanvas() );
192 if ( mMinLabelScaleWidget )
193 {
194 mMinLabelScaleWidget->setMapCanvas( context.mapCanvas() );
195 mMinLabelScaleWidget->setShowCurrentScaleButton( true );
196 }
197 if ( mCenterSymbolToolButton )
198 {
199 mCenterSymbolToolButton->setMapCanvas( context.mapCanvas() );
200 mCenterSymbolToolButton->setMessageBar( context.messageBar() );
201 }
202}
203
205{
207 if ( auto *lExpressionContext = mContext.expressionContext() )
208 context = *lExpressionContext;
209 else
214 QList< QgsExpressionContextScope > scopes = mContext.additionalExpressionContextScopes();
215 scopes << scope;
216 const auto constScopes = scopes;
217 for ( const QgsExpressionContextScope &s : constScopes )
218 {
220 }
221 return context;
222}
223
224void QgsPointDisplacementRendererWidget::mLabelFieldComboBox_currentIndexChanged( const QString &text )
225{
226 if ( mRenderer )
227 {
228 if ( text == tr( "None" ) )
229 {
230 mRenderer->setLabelAttributeName( QString() );
231 }
232 else
233 {
234 mRenderer->setLabelAttributeName( text );
235 }
236 emit widgetChanged();
237 }
238}
239
240void QgsPointDisplacementRendererWidget::mRendererComboBox_currentIndexChanged( int index )
241{
242 const QString rendererId = mRendererComboBox->itemData( index ).toString();
244 if ( m )
245 {
246 // unfortunately renderer conversion is only available through the creation of a widget...
247 const std::unique_ptr< QgsFeatureRenderer> oldRenderer( mRenderer->embeddedRenderer()->clone() );
248 QgsRendererWidget *tempRenderWidget = m->createRendererWidget( mLayer, mStyle, oldRenderer.get() );
249 mRenderer->setEmbeddedRenderer( tempRenderWidget->renderer()->clone() );
250 delete tempRenderWidget;
251 emit widgetChanged();
252 }
253}
254
255void QgsPointDisplacementRendererWidget::mPlacementComboBox_currentIndexChanged( int index )
256{
257 if ( !mRenderer )
258 return;
259
260 mRenderer->setPlacement( ( QgsPointDisplacementRenderer::Placement )mPlacementComboBox->itemData( index ).toInt() );
261 emit widgetChanged();
262}
263
264void QgsPointDisplacementRendererWidget::mRendererSettingsButton_clicked()
265{
266 if ( !mRenderer )
267 return;
268
269 QgsRendererAbstractMetadata *m = QgsApplication::rendererRegistry()->rendererMetadata( mRenderer->embeddedRenderer()->type() );
270 if ( m )
271 {
272 QgsRendererWidget *w = m->createRendererWidget( mLayer, mStyle, mRenderer->embeddedRenderer()->clone() );
273 w->setPanelTitle( tr( "Renderer Settings" ) );
274
276
280 QList< QgsExpressionContextScope > scopes = context.additionalExpressionContextScopes();
281 scopes << scope;
284 w->setContext( context );
285
286 connect( w, &QgsPanelWidget::widgetChanged, this, &QgsPointDisplacementRendererWidget::updateRendererFromWidget );
287 openPanel( w );
288 }
289}
290
291void QgsPointDisplacementRendererWidget::labelFontChanged()
292{
293 if ( !mRenderer )
294 {
295 return;
296 }
297
298 mRenderer->setLabelFont( mLabelFontButton->currentFont() );
299 emit widgetChanged();
300}
301
302void QgsPointDisplacementRendererWidget::mCircleWidthSpinBox_valueChanged( double d )
303{
304 if ( mRenderer )
305 {
306 mRenderer->setCircleWidth( d );
307 emit widgetChanged();
308 }
309}
310
311void QgsPointDisplacementRendererWidget::mCircleColorButton_colorChanged( const QColor &newColor )
312{
313 if ( !mRenderer )
314 {
315 return;
316 }
317
318 mRenderer->setCircleColor( newColor );
319 emit widgetChanged();
320}
321
322void QgsPointDisplacementRendererWidget::mLabelColorButton_colorChanged( const QColor &newColor )
323{
324 if ( !mRenderer )
325 {
326 return;
327 }
328
329 mRenderer->setLabelColor( newColor );
330 emit widgetChanged();
331}
332
333void QgsPointDisplacementRendererWidget::mCircleModificationSpinBox_valueChanged( double d )
334{
335 if ( !mRenderer )
336 {
337 return;
338 }
339
340 mRenderer->setCircleRadiusAddition( d );
341 emit widgetChanged();
342}
343
344void QgsPointDisplacementRendererWidget::mLabelDistanceFactorSpinBox_valueChanged( double d )
345{
346 if ( !mRenderer )
347 {
348 return;
349 }
350
351 mRenderer->setLabelDistanceFactor( d );
352 emit widgetChanged();
353}
354
355void QgsPointDisplacementRendererWidget::mDistanceSpinBox_valueChanged( double d )
356{
357 if ( mRenderer )
358 {
359 mRenderer->setTolerance( d );
360 emit widgetChanged();
361 }
362}
363
364void QgsPointDisplacementRendererWidget::mDistanceUnitWidget_changed()
365{
366 if ( mRenderer )
367 {
368 mRenderer->setToleranceUnit( mDistanceUnitWidget->unit() );
369 mRenderer->setToleranceMapUnitScale( mDistanceUnitWidget->getMapUnitScale() );
370 emit widgetChanged();
371 }
372}
373
374void QgsPointDisplacementRendererWidget::mScaleDependentLabelsCheckBox_stateChanged( int state )
375{
376 if ( state == Qt::Unchecked )
377 {
378 mMinLabelScaleWidget->setScale( 0 );
379 mMinLabelScaleWidget->setEnabled( false );
380 }
381 else
382 {
383 mMinLabelScaleWidget->setEnabled( true );
384 }
385}
386
387void QgsPointDisplacementRendererWidget::minLabelScaleChanged( double scale )
388{
389 if ( !mRenderer )
390 {
391 return;
392 }
393
394 mRenderer->setMinimumLabelScale( scale );
395 emit widgetChanged();
396}
397
398void QgsPointDisplacementRendererWidget::blockAllSignals( bool block )
399{
400 mLabelFieldComboBox->blockSignals( block );
401 mLabelFontButton->blockSignals( block );
402 mCircleWidthSpinBox->blockSignals( block );
403 mCircleColorButton->blockSignals( block );
404 mRendererComboBox->blockSignals( block );
405 mLabelColorButton->blockSignals( block );
406 mCircleModificationSpinBox->blockSignals( block );
407 mLabelDistanceFactorSpinBox->blockSignals( block );
408 mScaleDependentLabelsCheckBox->blockSignals( block );
409 mMinLabelScaleWidget->blockSignals( block );
410 mCenterSymbolToolButton->blockSignals( block );
411 mDistanceSpinBox->blockSignals( block );
412 mDistanceUnitWidget->blockSignals( block );
413 mPlacementComboBox->blockSignals( block );
414}
415
416void QgsPointDisplacementRendererWidget::centerSymbolChanged()
417{
418 mRenderer->setCenterSymbol( mCenterSymbolToolButton->clonedSymbol< QgsMarkerSymbol >() );
419 emit widgetChanged();
420}
421
422void QgsPointDisplacementRendererWidget::updateRendererFromWidget()
423{
424 QgsRendererWidget *w = qobject_cast<QgsRendererWidget *>( sender() );
425 if ( !w )
426 return;
427
428 mRenderer->setEmbeddedRenderer( w->renderer()->clone() );
429 emit widgetChanged();
430}
431
432void QgsPointDisplacementRendererWidget::setupBlankUi( const QString &layerName )
433{
434 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 );
435 QVBoxLayout *layout = new QVBoxLayout( this );
436 layout->setContentsMargins( 0, 0, 0, 0 );
437 layout->addWidget( label );
438}
@ 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.