QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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
17#include "qgis.h"
19#include "qgsapplication.h"
22#include "qgspointcloudlayer.h"
28#include "qgslogger.h"
29#include "qgsproject.h"
30#include "qgsprojectutils.h"
31
32static bool initPointCloudRenderer( const QString &name, QgsPointCloudRendererWidgetFunc f, const QString &iconName = QString() )
33{
35 if ( !rendererAbstractMetadata )
36 return false;
37 QgsPointCloudRendererMetadata *rendererMetadata = dynamic_cast<QgsPointCloudRendererMetadata *>( rendererAbstractMetadata );
38 if ( !rendererMetadata )
39 return false;
40
41 rendererMetadata->setWidgetFunction( f );
42
43 if ( !iconName.isEmpty() )
44 {
45 rendererMetadata->setIcon( QgsApplication::getThemeIcon( iconName ) );
46 }
47
48 QgsDebugMsgLevel( "Set for " + name, 2 );
49 return true;
50}
51
52void QgsPointCloudRendererPropertiesWidget::initRendererWidgetFunctions()
53{
54 static bool sInitialized = false;
55 if ( sInitialized )
56 return;
57
58 initPointCloudRenderer( QStringLiteral( "extent" ), QgsPointCloudExtentRendererWidget::create, QStringLiteral( "styleicons/pointcloudextent.svg" ) );
59 initPointCloudRenderer( QStringLiteral( "rgb" ), QgsPointCloudRgbRendererWidget::create, QStringLiteral( "styleicons/multibandcolor.svg" ) );
60 initPointCloudRenderer( QStringLiteral( "ramp" ), QgsPointCloudAttributeByRampRendererWidget::create, QStringLiteral( "styleicons/singlebandpseudocolor.svg" ) );
61 initPointCloudRenderer( QStringLiteral( "classified" ), QgsPointCloudClassifiedRendererWidget::create, QStringLiteral( "styleicons/paletted.svg" ) );
62
63 sInitialized = true;
64}
65
67 : QgsMapLayerConfigWidget( layer, nullptr, parent )
68 , mLayer( layer )
69 , mStyle( style )
70{
71 setupUi( this );
72
73 layout()->setContentsMargins( 0, 0, 0, 0 );
74
75 // initialize registry's widget functions
76 initRendererWidgetFunctions();
77
79 const QStringList renderers = reg->renderersList();
80 for ( const QString &name : renderers )
81 {
83 cboRenderers->addItem( m->icon(), m->visibleName(), name );
84 }
85
86 cboRenderers->setCurrentIndex( -1 ); // set no current renderer
87
88 mPointStyleComboBox->addItem( tr( "Square" ), static_cast< int >( Qgis::PointCloudSymbol::Square ) );
89 mPointStyleComboBox->addItem( tr( "Circle" ), static_cast< int >( Qgis::PointCloudSymbol::Circle ) );
90
91 connect( cboRenderers, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRendererPropertiesWidget::rendererChanged );
92
93 connect( mBlendModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
94 connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
95
96 mPointSizeUnitWidget->setUnits( {Qgis::RenderUnit::Millimeters,
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
110 mMaxErrorUnitWidget->setUnits( { Qgis::RenderUnit::Millimeters,
116 mMaxErrorSpinBox->setClearValue( 0.3 );
117
118 mHorizontalTriangleThresholdSpinBox->setClearValue( 5.0 );
119 mHorizontalTriangleUnitWidget->setUnits( { Qgis::RenderUnit::Millimeters,
125
126 connect( mMaxErrorSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
127 connect( mMaxErrorUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
128
129 connect( mPointStyleComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
130 connect( mDrawOrderComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
131
132 connect( mTriangulateGroupBox, &QGroupBox::toggled, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
133 connect( mHorizontalTriangleCheckBox, &QCheckBox::clicked, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
134 connect( mHorizontalTriangleThresholdSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
135 connect( mHorizontalTriangleUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
136
137 syncToLayer( layer );
138}
139
141{
142 mMapCanvas = context.mapCanvas();
143 mMessageBar = context.messageBar();
144 if ( mActiveWidget )
145 {
146 mActiveWidget->setContext( context );
147 }
148}
149
151{
152 mLayer = qobject_cast< QgsPointCloudLayer * >( layer );
153
154 mBlockChangedSignal = true;
155 mOpacityWidget->setOpacity( mLayer->opacity() );
156 mBlendModeComboBox->setShowClippingModes( QgsProjectUtils::layerIsContainedInGroupLayer( QgsProject::instance(), mLayer ) );
157 mBlendModeComboBox->setBlendMode( mLayer->blendMode() );
158
159 if ( mLayer->renderer() )
160 {
161 // set current renderer from layer
162 const QString rendererName = mLayer->renderer()->type();
163
164 const int rendererIdx = cboRenderers->findData( rendererName );
165 if ( cboRenderers->currentIndex() != rendererIdx )
166 {
167 cboRenderers->setCurrentIndex( rendererIdx );
168 }
169 else
170 {
171 rendererChanged();
172 }
173
174 // no renderer found... this mustn't happen
175 Q_ASSERT( rendererIdx != -1 && "there must be a renderer!" );
176
177 mPointSizeSpinBox->setValue( mLayer->renderer()->pointSize() );
178 mPointSizeUnitWidget->setUnit( mLayer->renderer()->pointSizeUnit() );
179 mPointSizeUnitWidget->setMapUnitScale( mLayer->renderer()->pointSizeMapUnitScale() );
180
181 mPointStyleComboBox->setCurrentIndex( mPointStyleComboBox->findData( static_cast< int >( mLayer->renderer()->pointSymbol() ) ) );
182 mDrawOrderComboBox->setCurrentIndex( mDrawOrderComboBox->findData( static_cast< int >( mLayer->renderer()->drawOrder2d() ) ) );
183
184 mMaxErrorSpinBox->setValue( mLayer->renderer()->maximumScreenError() );
185 mMaxErrorUnitWidget->setUnit( mLayer->renderer()->maximumScreenErrorUnit() );
186
187 mTriangulateGroupBox->setChecked( mLayer->renderer()->renderAsTriangles() );
188 mHorizontalTriangleCheckBox->setChecked( mLayer->renderer()->horizontalTriangleFilter() );
189 mHorizontalTriangleThresholdSpinBox->setValue( mLayer->renderer()->horizontalTriangleFilterThreshold() );
190 mHorizontalTriangleUnitWidget->setUnit( mLayer->renderer()->horizontalTriangleFilterUnit() );
191 }
192
193 mBlockChangedSignal = false;
194}
195
197{
198 if ( mActiveWidget )
199 mActiveWidget->setDockMode( dockMode );
201}
202
204{
205 mLayer->setOpacity( mOpacityWidget->opacity() );
206 mLayer->setBlendMode( mBlendModeComboBox->blendMode() );
207
208 if ( mActiveWidget )
209 mLayer->setRenderer( mActiveWidget->renderer() );
210 else if ( !cboRenderers->currentData().toString().isEmpty() )
211 {
212 QDomElement elem;
213 mLayer->setRenderer( QgsApplication::pointCloudRendererRegistry()->rendererMetadata( cboRenderers->currentData().toString() )->createRenderer( elem, QgsReadWriteContext() ) );
214 }
215
216 mLayer->renderer()->setPointSize( mPointSizeSpinBox->value() );
217 mLayer->renderer()->setPointSizeUnit( mPointSizeUnitWidget->unit() );
218 mLayer->renderer()->setPointSizeMapUnitScale( mPointSizeUnitWidget->getMapUnitScale() );
219
220 mLayer->renderer()->setPointSymbol( static_cast< Qgis::PointCloudSymbol >( mPointStyleComboBox->currentData().toInt() ) );
221
222 mLayer->renderer()->setMaximumScreenError( mMaxErrorSpinBox->value() );
223 mLayer->renderer()->setMaximumScreenErrorUnit( mMaxErrorUnitWidget->unit() );
224 mLayer->renderer()->setDrawOrder2d( static_cast< Qgis::PointCloudDrawOrder >( mDrawOrderComboBox->currentData().toInt() ) );
225
226 mLayer->renderer()->setRenderAsTriangles( mTriangulateGroupBox->isChecked() );
227 mLayer->renderer()->setHorizontalTriangleFilter( mHorizontalTriangleCheckBox->isChecked() );
228 mLayer->renderer()->setHorizontalTriangleFilterThreshold( mHorizontalTriangleThresholdSpinBox->value() );
229 mLayer->renderer()->setHorizontalTriangleFilterUnit( mHorizontalTriangleUnitWidget->unit() );
230}
231
232void QgsPointCloudRendererPropertiesWidget::rendererChanged()
233{
234 if ( cboRenderers->currentIndex() == -1 )
235 {
236 QgsDebugError( QStringLiteral( "No current item -- this should never happen!" ) );
237 return;
238 }
239
240 const QString rendererName = cboRenderers->currentData().toString();
241
242 //Retrieve the previous renderer: from the old active widget if possible, otherwise from the layer
243 std::unique_ptr< QgsPointCloudRenderer > oldRenderer;
244 std::unique_ptr< QgsPointCloudRenderer > newRenderer;
245 if ( mActiveWidget )
246 newRenderer.reset( mActiveWidget->renderer() );
247
248 if ( newRenderer )
249 {
250 oldRenderer = std::move( newRenderer );
251 }
252 else
253 {
254 oldRenderer.reset( mLayer->renderer()->clone() );
255 }
256
257 // get rid of old active widget (if any)
258 if ( mActiveWidget )
259 {
260 stackedWidget->removeWidget( mActiveWidget );
261
262 delete mActiveWidget;
263 mActiveWidget = nullptr;
264 }
265
266 QgsPointCloudRendererWidget *widget = nullptr;
268 if ( rendererMetadata )
269 widget = rendererMetadata->createRendererWidget( mLayer, mStyle, oldRenderer.get() );
270 oldRenderer.reset();
271
272 if ( widget )
273 {
274 // instantiate the widget and set as active
275 mActiveWidget = widget;
276 stackedWidget->addWidget( mActiveWidget );
277 stackedWidget->setCurrentWidget( mActiveWidget );
278
279 if ( mMapCanvas || mMessageBar )
280 {
282 context.setMapCanvas( mMapCanvas );
283 context.setMessageBar( mMessageBar );
284 mActiveWidget->setContext( context );
285 }
286
289 widget->setDockMode( dockMode() );
290 }
291 else
292 {
293 // set default "no edit widget available" page
294 stackedWidget->setCurrentWidget( pageNoWidget );
295 }
296 emitWidgetChanged();
297}
298
299void QgsPointCloudRendererPropertiesWidget::emitWidgetChanged()
300{
301 if ( !mBlockChangedSignal )
302 emit widgetChanged();
303}
304
PointCloudSymbol
Rendering symbols for point cloud points.
Definition: qgis.h:3488
@ Circle
Renders points as circles.
@ Square
Renders points as squares.
PointCloudDrawOrder
Pointcloud rendering order for 2d views.
Definition: qgis.h:3500
@ 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.
A panel widget that can be shown in the map style dock.
Base class for all map layer types.
Definition: qgsmaplayer.h:75
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:84
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.
Represents a map layer supporting display of point clouds.
QgsPointCloudRenderer * renderer()
Returns the 2D renderer for the point cloud.
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.
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.
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.
double maximumScreenError() const
Returns the maximum screen error allowed when rendering the point cloud.
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.
Definition: qgsproject.cpp:481
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.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugError(str)
Definition: qgslogger.h:38
QgsPointCloudRendererWidget *(* QgsPointCloudRendererWidgetFunc)(QgsPointCloudLayer *, QgsStyle *, QgsPointCloudRenderer *)