QGIS API Documentation 3.41.0-Master (cea29feecf2)
Loading...
Searching...
No Matches
qgspointcloudrendererpropertieswidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgspointcloudrendererpropertieswidget.cpp
3 ---------------------
4 begin : November 2020
5 copyright : (C) 2020 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
16#include "moc_qgspointcloudrendererpropertieswidget.cpp"
17
18#include "qgis.h"
19#include "qgsapplication.h"
20#include "qgsfontbutton.h"
21#include "qgslogger.h"
26#include "qgspointcloudlayer.h"
31#include "qgsproject.h"
32#include "qgsprojectutils.h"
33#include "qgsstyle.h"
35#include "qgstextformatwidget.h"
36
37static bool initPointCloudRenderer( const QString &name, QgsPointCloudRendererWidgetFunc f, const QString &iconName = QString() )
38{
40 if ( !rendererAbstractMetadata )
41 return false;
42 QgsPointCloudRendererMetadata *rendererMetadata = dynamic_cast<QgsPointCloudRendererMetadata *>( rendererAbstractMetadata );
43 if ( !rendererMetadata )
44 return false;
45
46 rendererMetadata->setWidgetFunction( f );
47
48 if ( !iconName.isEmpty() )
49 {
50 rendererMetadata->setIcon( QgsApplication::getThemeIcon( iconName ) );
51 }
52
53 QgsDebugMsgLevel( "Set for " + name, 2 );
54 return true;
55}
56
57void QgsPointCloudRendererPropertiesWidget::initRendererWidgetFunctions()
58{
59 static bool sInitialized = false;
60 if ( sInitialized )
61 return;
62
63 initPointCloudRenderer( QStringLiteral( "extent" ), QgsPointCloudExtentRendererWidget::create, QStringLiteral( "styleicons/pointcloudextent.svg" ) );
64 initPointCloudRenderer( QStringLiteral( "rgb" ), QgsPointCloudRgbRendererWidget::create, QStringLiteral( "styleicons/multibandcolor.svg" ) );
65 initPointCloudRenderer( QStringLiteral( "ramp" ), QgsPointCloudAttributeByRampRendererWidget::create, QStringLiteral( "styleicons/singlebandpseudocolor.svg" ) );
66 initPointCloudRenderer( QStringLiteral( "classified" ), QgsPointCloudClassifiedRendererWidget::create, QStringLiteral( "styleicons/paletted.svg" ) );
67
68 sInitialized = true;
69}
70
72 : QgsMapLayerConfigWidget( layer, nullptr, parent )
73 , mLayer( layer )
74 , mStyle( style )
75{
76 setupUi( this );
77
78 layout()->setContentsMargins( 0, 0, 0, 0 );
79
80 // initialize registry's widget functions
81 initRendererWidgetFunctions();
82
84 const QStringList renderers = reg->renderersList();
85 for ( const QString &name : renderers )
86 {
88 cboRenderers->addItem( m->icon(), m->visibleName(), name );
89 }
90
91 cboRenderers->setCurrentIndex( -1 ); // set no current renderer
92
93 mPointStyleComboBox->addItem( tr( "Square" ), static_cast<int>( Qgis::PointCloudSymbol::Square ) );
94 mPointStyleComboBox->addItem( tr( "Circle" ), static_cast<int>( Qgis::PointCloudSymbol::Circle ) );
95
96 connect( cboRenderers, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRendererPropertiesWidget::rendererChanged );
97
98 connect( mBlendModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
99 connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
100
102
103 connect( mPointSizeSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
104 connect( mPointSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
105
106 mDrawOrderComboBox->addItem( tr( "Default" ), static_cast<int>( Qgis::PointCloudDrawOrder::Default ) );
107 mDrawOrderComboBox->addItem( tr( "Bottom to Top" ), static_cast<int>( Qgis::PointCloudDrawOrder::BottomToTop ) );
108 mDrawOrderComboBox->addItem( tr( "Top to Bottom" ), static_cast<int>( Qgis::PointCloudDrawOrder::TopToBottom ) );
109
111 mMaxErrorSpinBox->setClearValue( 0.3 );
112
113 mHorizontalTriangleThresholdSpinBox->setClearValue( 5.0 );
115
116 connect( mMaxErrorSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
117 connect( mMaxErrorUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
118
119 connect( mPointStyleComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
120 connect( mDrawOrderComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
121
122 connect( mTriangulateGroupBox, &QGroupBox::toggled, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
123 connect( mHorizontalTriangleCheckBox, &QCheckBox::clicked, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
124 connect( mHorizontalTriangleThresholdSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
125 connect( mHorizontalTriangleUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
126
127 // show label options only for virtual point clouds
128 bool showLabelOptions = !mLayer->dataProvider()->subIndexes().isEmpty();
129 mLabels->setVisible( showLabelOptions );
130 mLabelOptions->setVisible( showLabelOptions );
131 mLabelOptions->setDialogTitle( tr( "Customize label text" ) );
132 connect( mLabels, &QCheckBox::stateChanged, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
133 connect( mLabelOptions, &QgsFontButton::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
134
135 syncToLayer( layer );
136}
137
139{
140 mMapCanvas = context.mapCanvas();
141 mMessageBar = context.messageBar();
142 if ( mActiveWidget )
143 {
144 mActiveWidget->setContext( context );
145 }
146}
147
149{
150 mLayer = qobject_cast<QgsPointCloudLayer *>( layer );
151
152 mBlockChangedSignal = true;
153 mOpacityWidget->setOpacity( mLayer->opacity() );
154 mBlendModeComboBox->setShowClippingModes( QgsProjectUtils::layerIsContainedInGroupLayer( QgsProject::instance(), mLayer ) );
155 mBlendModeComboBox->setBlendMode( mLayer->blendMode() );
156
157 if ( mLayer->renderer() )
158 {
159 // set current renderer from layer
160 const QString rendererName = mLayer->renderer()->type();
161
162 const int rendererIdx = cboRenderers->findData( rendererName );
163 if ( cboRenderers->currentIndex() != rendererIdx )
164 {
165 cboRenderers->setCurrentIndex( rendererIdx );
166 }
167 else
168 {
169 rendererChanged();
170 }
171
172 // no renderer found... this mustn't happen
173 Q_ASSERT( rendererIdx != -1 && "there must be a renderer!" );
174
175 mPointSizeSpinBox->setValue( mLayer->renderer()->pointSize() );
176 mPointSizeUnitWidget->setUnit( mLayer->renderer()->pointSizeUnit() );
177 mPointSizeUnitWidget->setMapUnitScale( mLayer->renderer()->pointSizeMapUnitScale() );
178
179 mPointStyleComboBox->setCurrentIndex( mPointStyleComboBox->findData( static_cast<int>( mLayer->renderer()->pointSymbol() ) ) );
180 mDrawOrderComboBox->setCurrentIndex( mDrawOrderComboBox->findData( static_cast<int>( mLayer->renderer()->drawOrder2d() ) ) );
181
182 mMaxErrorSpinBox->setValue( mLayer->renderer()->maximumScreenError() );
183 mMaxErrorUnitWidget->setUnit( mLayer->renderer()->maximumScreenErrorUnit() );
184
185 mTriangulateGroupBox->setChecked( mLayer->renderer()->renderAsTriangles() );
186 mHorizontalTriangleCheckBox->setChecked( mLayer->renderer()->horizontalTriangleFilter() );
187 mHorizontalTriangleThresholdSpinBox->setValue( mLayer->renderer()->horizontalTriangleFilterThreshold() );
188 mHorizontalTriangleUnitWidget->setUnit( mLayer->renderer()->horizontalTriangleFilterUnit() );
189
190 if ( !mLayer->dataProvider()->subIndexes().isEmpty() )
191 {
192 mLabels->setChecked( mLayer->renderer()->showLabels() );
193 mLabelOptions->setTextFormat( mLayer->renderer()->labelTextFormat() );
194 }
195 }
196
197 mBlockChangedSignal = false;
198}
199
201{
202 if ( mActiveWidget )
203 mActiveWidget->setDockMode( dockMode );
205}
206
208{
209 mLayer->setOpacity( mOpacityWidget->opacity() );
210 mLayer->setBlendMode( mBlendModeComboBox->blendMode() );
211
212 if ( mActiveWidget )
213 mLayer->setRenderer( mActiveWidget->renderer() );
214 else if ( !cboRenderers->currentData().toString().isEmpty() )
215 {
216 QDomElement elem;
217 mLayer->setRenderer( QgsApplication::pointCloudRendererRegistry()->rendererMetadata( cboRenderers->currentData().toString() )->createRenderer( elem, QgsReadWriteContext() ) );
218 }
219
220 mLayer->renderer()->setPointSize( mPointSizeSpinBox->value() );
221 mLayer->renderer()->setPointSizeUnit( mPointSizeUnitWidget->unit() );
222 mLayer->renderer()->setPointSizeMapUnitScale( mPointSizeUnitWidget->getMapUnitScale() );
223
224 mLayer->renderer()->setPointSymbol( static_cast<Qgis::PointCloudSymbol>( mPointStyleComboBox->currentData().toInt() ) );
225
226 mLayer->renderer()->setMaximumScreenError( mMaxErrorSpinBox->value() );
227 mLayer->renderer()->setMaximumScreenErrorUnit( mMaxErrorUnitWidget->unit() );
228 mLayer->renderer()->setDrawOrder2d( static_cast<Qgis::PointCloudDrawOrder>( mDrawOrderComboBox->currentData().toInt() ) );
229
230 mLayer->renderer()->setRenderAsTriangles( mTriangulateGroupBox->isChecked() );
231 mLayer->renderer()->setHorizontalTriangleFilter( mHorizontalTriangleCheckBox->isChecked() );
232 mLayer->renderer()->setHorizontalTriangleFilterThreshold( mHorizontalTriangleThresholdSpinBox->value() );
233 mLayer->renderer()->setHorizontalTriangleFilterUnit( mHorizontalTriangleUnitWidget->unit() );
234
235 mLayer->renderer()->setShowLabels( mLabels->isChecked() );
236 mLayer->renderer()->setLabelTextFormat( mLabelOptions->textFormat() );
237}
238
239void QgsPointCloudRendererPropertiesWidget::rendererChanged()
240{
241 if ( cboRenderers->currentIndex() == -1 )
242 {
243 QgsDebugError( QStringLiteral( "No current item -- this should never happen!" ) );
244 return;
245 }
246
247 const QString rendererName = cboRenderers->currentData().toString();
248
249 //Retrieve the previous renderer: from the old active widget if possible, otherwise from the layer
250 std::unique_ptr<QgsPointCloudRenderer> oldRenderer;
251 std::unique_ptr<QgsPointCloudRenderer> newRenderer;
252 if ( mActiveWidget )
253 newRenderer.reset( mActiveWidget->renderer() );
254
255 if ( newRenderer )
256 {
257 oldRenderer = std::move( newRenderer );
258 }
259 else
260 {
261 oldRenderer.reset( mLayer->renderer()->clone() );
262 }
263
264 // get rid of old active widget (if any)
265 if ( mActiveWidget )
266 {
267 stackedWidget->removeWidget( mActiveWidget );
268
269 delete mActiveWidget;
270 mActiveWidget = nullptr;
271 }
272
273 QgsPointCloudRendererWidget *widget = nullptr;
275 if ( rendererMetadata )
276 widget = rendererMetadata->createRendererWidget( mLayer, mStyle, oldRenderer.get() );
277 oldRenderer.reset();
278
279 if ( widget )
280 {
281 // instantiate the widget and set as active
282 mActiveWidget = widget;
283 stackedWidget->addWidget( mActiveWidget );
284 stackedWidget->setCurrentWidget( mActiveWidget );
285
286 if ( mMapCanvas || mMessageBar )
287 {
289 context.setMapCanvas( mMapCanvas );
290 context.setMessageBar( mMessageBar );
291 mActiveWidget->setContext( context );
292 }
293
296 widget->setDockMode( dockMode() );
297 }
298 else
299 {
300 // set default "no edit widget available" page
301 stackedWidget->setCurrentWidget( pageNoWidget );
302 }
303 emitWidgetChanged();
304}
305
306void QgsPointCloudRendererPropertiesWidget::emitWidgetChanged()
307{
308 if ( !mBlockChangedSignal )
309 emit widgetChanged();
310}
PointCloudSymbol
Rendering symbols for point cloud points.
Definition qgis.h:3995
@ Circle
Renders points as circles.
@ Square
Renders points as squares.
PointCloudDrawOrder
Pointcloud rendering order for 2d views.
Definition qgis.h:4007
@ BottomToTop
Draw points with larger Z values last.
@ Default
Draw points in the order they are stored.
@ TopToBottom
Draw points with larger Z values first.
@ Millimeters
Millimeters.
@ Points
Points (e.g., for font sizes)
@ MapUnits
Map units.
@ MetersInMapUnits
Meters value as Map units.
static QgsPointCloudRendererRegistry * pointCloudRendererRegistry()
Returns the application's point cloud renderer registry, used for managing point cloud layer 2D rende...
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
void changed()
Emitted when the widget's text format settings are changed.
A panel widget that can be shown in the map style dock.
Base class for all map layer types.
Definition qgsmaplayer.h:76
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
virtual void setOpacity(double opacity)
Sets the opacity for the layer, where opacity is a value between 0 (totally transparent) and 1....
double opacity
Definition qgsmaplayer.h:88
void opacityChanged(double opacity)
Emitted when the opacity is changed in the widget, where opacity ranges from 0.0 (transparent) to 1....
void showPanel(QgsPanelWidget *panel)
Emit when you require a panel to be show in the interface.
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.
virtual void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
bool dockMode()
Returns the dock mode state.
virtual QVector< QgsPointCloudSubIndex > subIndexes()
Returns a list of sub indexes available if the provider supports multiple indexes,...
Represents a map layer supporting display of point clouds.
QgsPointCloudRenderer * renderer()
Returns the 2D renderer for the point cloud.
QgsPointCloudDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
void setRenderer(QgsPointCloudRenderer *renderer)
Sets the 2D renderer for the point cloud.
Stores metadata about one point cloud renderer class.
void setIcon(const QIcon &icon)
Sets an icon representing the renderer.
virtual QgsPointCloudRendererWidget * createRendererWidget(QgsPointCloudLayer *layer, QgsStyle *style, QgsPointCloudRenderer *oldRenderer)
Returns new instance of settings widget for the renderer.
Convenience metadata class that uses static functions to create point cloud renderer and its widget.
void setWidgetFunction(QgsPointCloudRendererWidgetFunc f)
QgsPointCloudRenderer * createRenderer(QDomElement &elem, const QgsReadWriteContext &context) override
Returns new instance of the renderer given the DOM element.
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the widget is shown, e.g., the associated map canvas and expression context...
QgsPointCloudRendererPropertiesWidget(QgsPointCloudLayer *layer, QgsStyle *style, QWidget *parent=nullptr)
Constructor for QgsPointCloudRendererPropertiesWidget, associated with the specified layer and style ...
void syncToLayer(QgsMapLayer *layer) final
Reset to original (vector layer) values.
void setDockMode(bool dockMode) final
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
Registry of 2D renderers for point clouds.
QgsPointCloudRendererAbstractMetadata * rendererMetadata(const QString &rendererName)
Returns the metadata for a specified renderer.
QStringList renderersList() const
Returns a list of available renderers.
Base class for point cloud 2D renderer settings widgets.
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 QgsPointCloudRenderer * renderer()=0
Returns a new instance of a renderer as defined by the settings in the widget.
bool renderAsTriangles() const
Returns whether points are triangulated to render solid surface.
void setMaximumScreenError(double error)
Sets the maximum screen error allowed when rendering the point cloud.
QgsTextFormat labelTextFormat() const
Returns the text format renderer is using for rendering labels.
void setMaximumScreenErrorUnit(Qgis::RenderUnit unit)
Sets the unit for the maximum screen error allowed when rendering the point cloud.
const QgsMapUnitScale & pointSizeMapUnitScale() const
Returns the map unit scale used for the point size.
void setPointSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale used for the point size.
void setPointSize(double size)
Sets the point size.
bool horizontalTriangleFilter() const
Returns whether large triangles will get rendered.
virtual QString type() const =0
Returns the identifier of the renderer type.
void setHorizontalTriangleFilterThreshold(double threshold)
Sets threshold for filtering of triangles.
void setHorizontalTriangleFilterUnit(Qgis::RenderUnit unit)
Sets units of the threshold for filtering of triangles.
bool showLabels() const
Returns whether the renderer shows file labels inside the extent rectangle.
virtual QgsPointCloudRenderer * clone() const =0
Create a deep copy of this renderer.
Qgis::RenderUnit maximumScreenErrorUnit() const
Returns the unit for the maximum screen error allowed when rendering the point cloud.
void setDrawOrder2d(Qgis::PointCloudDrawOrder order)
Sets the drawing order used by the renderer for drawing points.
void setPointSizeUnit(const Qgis::RenderUnit units)
Sets the units used for the point size.
Qgis::RenderUnit horizontalTriangleFilterUnit() const
Returns units of the threshold for filtering of triangles.
void setRenderAsTriangles(bool asTriangles)
Sets whether points are triangulated to render solid surface.
void setPointSymbol(Qgis::PointCloudSymbol symbol)
Sets the symbol used by the renderer for drawing points.
void setLabelTextFormat(const QgsTextFormat &textFormat)
Sets the text format renderers should use for rendering labels.
double maximumScreenError() const
Returns the maximum screen error allowed when rendering the point cloud.
void setShowLabels(const bool show)
Set whether the renderer should also render file labels inside extent.
Qgis::RenderUnit pointSizeUnit() const
Returns the units used for the point size.
double horizontalTriangleFilterThreshold() const
Returns threshold for filtering of triangles.
Qgis::PointCloudSymbol pointSymbol() const
Returns the symbol used by the renderer for drawing points.
Qgis::PointCloudDrawOrder drawOrder2d() const
Returns the drawing order used by the renderer for drawing points.
void setHorizontalTriangleFilter(bool enabled)
Sets whether large triangles will get rendered.
double pointSize() const
Returns the point size.
static bool layerIsContainedInGroupLayer(QgsProject *project, QgsMapLayer *layer)
Returns true if the specified layer is a child layer from any QgsGroupLayer in the given project.
static QgsProject * instance()
Returns the QgsProject singleton instance.
The class is used as a container of context for various read/write operations on other objects.
Contains settings which reflect the context in which a symbol (or renderer) widget is shown,...
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
void setMessageBar(QgsMessageBar *bar)
Sets the message bar associated with the widget.
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.
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:39
#define QgsDebugError(str)
Definition qgslogger.h:38
QgsPointCloudRendererWidget *(* QgsPointCloudRendererWidgetFunc)(QgsPointCloudLayer *, QgsStyle *, QgsPointCloudRenderer *)