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