QGIS API Documentation 3.99.0-Master (2fe06baccd8)
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
20#include "qgsapplication.h"
21#include "qgsfields.h"
22#include "qgsmarkersymbol.h"
24#include "qgsrendererregistry.h"
25#include "qgsstyle.h"
27#include "qgsvectorlayer.h"
28
29#include "moc_qgspointdisplacementrendererwidget.cpp"
30
35
37 : QgsRendererWidget( layer, style )
38
39{
40 if ( !layer )
41 {
42 return;
43 }
44
45 //the renderer only applies to point vector layers
47 {
48 //setup blank dialog
49 mRenderer = nullptr;
50 setupBlankUi( layer->name() );
51 return;
52 }
53 setupUi( this );
54 connect( mLabelFieldComboBox, &QComboBox::currentTextChanged, this, &QgsPointDisplacementRendererWidget::mLabelFieldComboBox_currentIndexChanged );
55 connect( mRendererComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointDisplacementRendererWidget::mRendererComboBox_currentIndexChanged );
56 connect( mPlacementComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointDisplacementRendererWidget::mPlacementComboBox_currentIndexChanged );
57 connect( mCircleWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointDisplacementRendererWidget::mCircleWidthSpinBox_valueChanged );
58 connect( mCircleColorButton, &QgsColorButton::colorChanged, this, &QgsPointDisplacementRendererWidget::mCircleColorButton_colorChanged );
59 connect( mDistanceSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointDisplacementRendererWidget::mDistanceSpinBox_valueChanged );
60 connect( mDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointDisplacementRendererWidget::mDistanceUnitWidget_changed );
61 connect( mLabelColorButton, &QgsColorButton::colorChanged, this, &QgsPointDisplacementRendererWidget::mLabelColorButton_colorChanged );
62 connect( mCircleModificationSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointDisplacementRendererWidget::mCircleModificationSpinBox_valueChanged );
63 connect( mLabelDistanceFactorSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointDisplacementRendererWidget::mLabelDistanceFactorSpinBox_valueChanged );
64 connect( mScaleDependentLabelsCheckBox, &QCheckBox::stateChanged, this, &QgsPointDisplacementRendererWidget::mScaleDependentLabelsCheckBox_stateChanged );
65 connect( mRendererSettingsButton, &QPushButton::clicked, this, &QgsPointDisplacementRendererWidget::mRendererSettingsButton_clicked );
66 this->layout()->setContentsMargins( 0, 0, 0, 0 );
67
68 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
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
211 context.appendScopes( mContext.globalProjectAtlasMapLayerScopes( mLayer ) );
215 QList<QgsExpressionContextScope> scopes = mContext.additionalExpressionContextScopes();
216 scopes << scope;
217 for ( const QgsExpressionContextScope &s : std::as_const( scopes ) )
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();
243 QgsRendererAbstractMetadata *m = QgsApplication::rendererRegistry()->rendererMetadata( rendererId );
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
275 QgsSymbolWidgetContext context = mContext;
276
277 QgsExpressionContextScope scope;
278 scope.addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_CLUSTER_COLOR, "", true ) );
279 scope.addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_CLUSTER_SIZE, 0, true ) );
280 QList<QgsExpressionContextScope> scopes = context.additionalExpressionContextScopes();
281 scopes << scope;
282 context.setAdditionalExpressionContextScopes( scopes );
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}
@ Point
Points.
Definition qgis.h:359
@ Millimeters
Millimeters.
Definition qgis.h:5184
@ Points
Points (e.g., for font sizes).
Definition qgis.h:5188
@ MapUnits
Map units.
Definition qgis.h:5185
@ Pixels
Pixels.
Definition qgis.h:5186
@ Inches
Inches.
Definition qgis.h:5189
@ MetersInMapUnits
Meters value as Map units.
Definition qgis.h:5191
@ Marker
Marker symbol.
Definition qgis.h:611
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.
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:54
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.
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.
QgsRendererWidget(QgsVectorLayer *layer, QgsStyle *style)
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.
A database of saved style entities, including symbols, color ramps, text formats and others.
Definition qgsstyle.h:88
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,...
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 dataset.
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.