QGIS API Documentation 3.99.0-Master (26c88405ac0)
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
17#include "qgis.h"
18#include "qgsapplication.h"
19#include "qgsfontbutton.h"
20#include "qgslogger.h"
25#include "qgspointcloudlayer.h"
30#include "qgsproject.h"
31#include "qgsprojectutils.h"
32#include "qgsstyle.h"
34#include "qgstextformatwidget.h"
35#include "qgsvirtualpointcloudprovider.h"
36
37#include "moc_qgspointcloudrendererpropertieswidget.cpp"
38
39static bool initPointCloudRenderer( const QString &name, QgsPointCloudRendererWidgetFunc f, const QString &iconName = QString() )
40{
42 if ( !rendererAbstractMetadata )
43 return false;
44 QgsPointCloudRendererMetadata *rendererMetadata = dynamic_cast<QgsPointCloudRendererMetadata *>( rendererAbstractMetadata );
45 if ( !rendererMetadata )
46 return false;
47
48 rendererMetadata->setWidgetFunction( f );
49
50 if ( !iconName.isEmpty() )
51 {
52 rendererMetadata->setIcon( QgsApplication::getThemeIcon( iconName ) );
53 }
54
55 QgsDebugMsgLevel( "Set for " + name, 2 );
56 return true;
57}
58
59void QgsPointCloudRendererPropertiesWidget::initRendererWidgetFunctions()
60{
61 static bool sInitialized = false;
62 if ( sInitialized )
63 return;
64
65 initPointCloudRenderer( QStringLiteral( "extent" ), QgsPointCloudExtentRendererWidget::create, QStringLiteral( "styleicons/pointcloudextent.svg" ) );
66 initPointCloudRenderer( QStringLiteral( "rgb" ), QgsPointCloudRgbRendererWidget::create, QStringLiteral( "styleicons/multibandcolor.svg" ) );
67 initPointCloudRenderer( QStringLiteral( "ramp" ), QgsPointCloudAttributeByRampRendererWidget::create, QStringLiteral( "styleicons/singlebandpseudocolor.svg" ) );
68 initPointCloudRenderer( QStringLiteral( "classified" ), QgsPointCloudClassifiedRendererWidget::create, QStringLiteral( "styleicons/paletted.svg" ) );
69
70 sInitialized = true;
71}
72
74 : QgsMapLayerConfigWidget( layer, nullptr, parent )
75 , mLayer( layer )
76 , mStyle( style )
77{
78 setupUi( this );
79
80 layout()->setContentsMargins( 0, 0, 0, 0 );
81
82 // initialize registry's widget functions
83 initRendererWidgetFunctions();
84
86 const QStringList renderers = reg->renderersList();
87 for ( const QString &name : renderers )
88 {
90 cboRenderers->addItem( m->icon(), m->visibleName(), name );
91 }
92
93 cboRenderers->setCurrentIndex( -1 ); // set no current renderer
94
95 mPointStyleComboBox->addItem( tr( "Square" ), QVariant::fromValue( Qgis::PointCloudSymbol::Square ) );
96 mPointStyleComboBox->addItem( tr( "Circle" ), QVariant::fromValue( Qgis::PointCloudSymbol::Circle ) );
97
98 connect( cboRenderers, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRendererPropertiesWidget::rendererChanged );
99
100 connect( mBlendModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
101 connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
102
104
105 connect( mPointSizeSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
106 connect( mPointSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
107
108 mDrawOrderComboBox->addItem( tr( "Default" ), QVariant::fromValue( Qgis::PointCloudDrawOrder::Default ) );
109 mDrawOrderComboBox->addItem( tr( "Bottom to Top" ), QVariant::fromValue( Qgis::PointCloudDrawOrder::BottomToTop ) );
110 mDrawOrderComboBox->addItem( tr( "Top to Bottom" ), QVariant::fromValue( Qgis::PointCloudDrawOrder::TopToBottom ) );
111
113 mMaxErrorSpinBox->setClearValue( 0.3 );
114
115 mHorizontalTriangleThresholdSpinBox->setClearValue( 5.0 );
117
118 connect( mMaxErrorSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
119 connect( mMaxErrorUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
120
121 connect( mPointStyleComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
122 connect( mDrawOrderComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
123
124 connect( mTriangulateGroupBox, &QGroupBox::toggled, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
125 connect( mHorizontalTriangleCheckBox, &QCheckBox::clicked, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
126 connect( mHorizontalTriangleThresholdSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
127 connect( mHorizontalTriangleUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
128
129 // show virtual point cloud options only when vpc layer is selected
130 if ( !mLayer->dataProvider()->subIndexes().isEmpty() )
131 {
132 mLabelOptions->setDialogTitle( tr( "Customize label text" ) );
133 mLabelOptions->setText( tr( "Label format" ) );
134 connect( mLabels, &QCheckBox::stateChanged, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
135 connect( mLabelOptions, &QgsFontButton::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
136 mZoomOutOptions->addItem( tr( "Show Extents Only" ), QVariant::fromValue( Qgis::PointCloudZoomOutRenderBehavior::RenderExtents ) );
137
138 if ( const QgsVirtualPointCloudProvider *vpcProvider = dynamic_cast<QgsVirtualPointCloudProvider *>( mLayer->dataProvider() ) )
139 {
140 if ( vpcProvider->overview() )
141 {
142 mZoomOutOptions->addItem( tr( "Show Overview Only" ), QVariant::fromValue( Qgis::PointCloudZoomOutRenderBehavior::RenderOverview ) );
143 mZoomOutOptions->addItem( tr( "Show Extents Over Overview" ), QVariant::fromValue( Qgis::PointCloudZoomOutRenderBehavior::RenderOverviewAndExtents ) );
144 }
145 }
146 else
147 {
148 mZoomOutOptions->setEnabled( false );
149 }
150
151 connect( mZoomOutOptions, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this]( int ) {
152 switch ( mZoomOutOptions->currentData().value<Qgis::PointCloudZoomOutRenderBehavior>() )
153 {
155 mLabels->setEnabled( false );
156 mLabelOptions->setEnabled( false );
157 break;
160 mLabels->setEnabled( true );
161 mLabelOptions->setEnabled( true );
162 }
163 emitWidgetChanged();
164 } );
165 }
166 else
167 {
168 mVpcGroupBox->setVisible( false );
169 }
170
171 syncToLayer( layer );
172}
173
175{
176 mMapCanvas = context.mapCanvas();
177 mMessageBar = context.messageBar();
178 if ( mActiveWidget )
179 {
180 mActiveWidget->setContext( context );
181 }
182}
183
185{
186 mLayer = qobject_cast<QgsPointCloudLayer *>( layer );
187
188 mBlockChangedSignal = true;
189 mOpacityWidget->setOpacity( mLayer->opacity() );
190 mBlendModeComboBox->setShowClippingModes( QgsProjectUtils::layerIsContainedInGroupLayer( QgsProject::instance(), mLayer ) );
191 mBlendModeComboBox->setBlendMode( mLayer->blendMode() );
192
193 if ( mLayer->renderer() )
194 {
195 // set current renderer from layer
196 const QString rendererName = mLayer->renderer()->type();
197
198 const int rendererIdx = cboRenderers->findData( rendererName );
199 if ( cboRenderers->currentIndex() != rendererIdx )
200 {
201 cboRenderers->setCurrentIndex( rendererIdx );
202 }
203 else
204 {
205 rendererChanged();
206 }
207
208 // no renderer found... this mustn't happen
209 Q_ASSERT( rendererIdx != -1 && "there must be a renderer!" );
210
211 mPointSizeSpinBox->setValue( mLayer->renderer()->pointSize() );
212 mPointSizeUnitWidget->setUnit( mLayer->renderer()->pointSizeUnit() );
213 mPointSizeUnitWidget->setMapUnitScale( mLayer->renderer()->pointSizeMapUnitScale() );
214
215 mPointStyleComboBox->setCurrentIndex( mPointStyleComboBox->findData( QVariant::fromValue( mLayer->renderer()->pointSymbol() ) ) );
216 mDrawOrderComboBox->setCurrentIndex( mDrawOrderComboBox->findData( QVariant::fromValue( mLayer->renderer()->drawOrder2d() ) ) );
217
218 mMaxErrorSpinBox->setValue( mLayer->renderer()->maximumScreenError() );
219 mMaxErrorUnitWidget->setUnit( mLayer->renderer()->maximumScreenErrorUnit() );
220
221 mTriangulateGroupBox->setChecked( mLayer->renderer()->renderAsTriangles() );
222 mHorizontalTriangleCheckBox->setChecked( mLayer->renderer()->horizontalTriangleFilter() );
223 mHorizontalTriangleThresholdSpinBox->setValue( mLayer->renderer()->horizontalTriangleFilterThreshold() );
224 mHorizontalTriangleUnitWidget->setUnit( mLayer->renderer()->horizontalTriangleFilterUnit() );
225
226 if ( !mLayer->dataProvider()->subIndexes().isEmpty() )
227 {
228 mLabels->setChecked( mLayer->renderer()->showLabels() );
229 mLabelOptions->setTextFormat( mLayer->renderer()->labelTextFormat() );
230 mZoomOutOptions->setCurrentIndex( mZoomOutOptions->findData( QVariant::fromValue( mLayer->renderer()->zoomOutBehavior() ) ) );
231 switch ( mLayer->renderer()->zoomOutBehavior() )
232 {
234 mLabels->setEnabled( false );
235 mLabelOptions->setEnabled( false );
236 break;
237 default:
238 mLabels->setEnabled( true );
239 mLabelOptions->setEnabled( true );
240 }
241 }
242 }
243
244 mBlockChangedSignal = false;
245}
246
248{
249 if ( mActiveWidget )
250 mActiveWidget->setDockMode( dockMode );
252}
253
255{
256 mLayer->setOpacity( mOpacityWidget->opacity() );
257 mLayer->setBlendMode( mBlendModeComboBox->blendMode() );
258
259 if ( mActiveWidget )
260 mLayer->setRenderer( mActiveWidget->renderer() );
261 else if ( !cboRenderers->currentData().toString().isEmpty() )
262 {
263 QDomElement elem;
264 if ( QgsPointCloudRendererAbstractMetadata *metadata = QgsApplication::pointCloudRendererRegistry()->rendererMetadata( cboRenderers->currentData().toString() ) )
265 {
266 mLayer->setRenderer( metadata->createRenderer( elem, QgsReadWriteContext() ) );
267 }
268 }
269
270 mLayer->renderer()->setPointSize( mPointSizeSpinBox->value() );
271 mLayer->renderer()->setPointSizeUnit( mPointSizeUnitWidget->unit() );
272 mLayer->renderer()->setPointSizeMapUnitScale( mPointSizeUnitWidget->getMapUnitScale() );
273
274 mLayer->renderer()->setPointSymbol( mPointStyleComboBox->currentData().value<Qgis::PointCloudSymbol>() );
275
276 mLayer->renderer()->setMaximumScreenError( mMaxErrorSpinBox->value() );
277 mLayer->renderer()->setMaximumScreenErrorUnit( mMaxErrorUnitWidget->unit() );
278 mLayer->renderer()->setDrawOrder2d( mDrawOrderComboBox->currentData().value<Qgis::PointCloudDrawOrder>() );
279
280 mLayer->renderer()->setRenderAsTriangles( mTriangulateGroupBox->isChecked() );
281 mLayer->renderer()->setHorizontalTriangleFilter( mHorizontalTriangleCheckBox->isChecked() );
282 mLayer->renderer()->setHorizontalTriangleFilterThreshold( mHorizontalTriangleThresholdSpinBox->value() );
283 mLayer->renderer()->setHorizontalTriangleFilterUnit( mHorizontalTriangleUnitWidget->unit() );
284
285 mLayer->renderer()->setShowLabels( mLabels->isChecked() );
286 mLayer->renderer()->setLabelTextFormat( mLabelOptions->textFormat() );
287 mLayer->renderer()->setZoomOutBehavior( mZoomOutOptions->currentData().value<Qgis::PointCloudZoomOutRenderBehavior>() );
288}
289
290void QgsPointCloudRendererPropertiesWidget::rendererChanged()
291{
292 if ( cboRenderers->currentIndex() == -1 )
293 {
294 QgsDebugError( QStringLiteral( "No current item -- this should never happen!" ) );
295 return;
296 }
297
298 const QString rendererName = cboRenderers->currentData().toString();
299
300 //Retrieve the previous renderer: from the old active widget if possible, otherwise from the layer
301 std::unique_ptr<QgsPointCloudRenderer> oldRenderer;
302 std::unique_ptr<QgsPointCloudRenderer> newRenderer;
303 if ( mActiveWidget )
304 newRenderer.reset( mActiveWidget->renderer() );
305
306 if ( newRenderer )
307 {
308 oldRenderer = std::move( newRenderer );
309 }
310 else
311 {
312 oldRenderer.reset( mLayer->renderer()->clone() );
313 }
314
315 // get rid of old active widget (if any)
316 if ( mActiveWidget )
317 {
318 stackedWidget->removeWidget( mActiveWidget );
319
320 delete mActiveWidget;
321 mActiveWidget = nullptr;
322 }
323
324 QgsPointCloudRendererWidget *widget = nullptr;
325 QgsPointCloudRendererAbstractMetadata *rendererMetadata = QgsApplication::pointCloudRendererRegistry()->rendererMetadata( rendererName );
326 if ( rendererMetadata )
327 widget = rendererMetadata->createRendererWidget( mLayer, mStyle, oldRenderer.get() );
328 oldRenderer.reset();
329
330 if ( widget )
331 {
332 // instantiate the widget and set as active
333 mActiveWidget = widget;
334 stackedWidget->addWidget( mActiveWidget );
335 stackedWidget->setCurrentWidget( mActiveWidget );
336
337 if ( mMapCanvas || mMessageBar )
338 {
339 QgsSymbolWidgetContext context;
340 context.setMapCanvas( mMapCanvas );
341 context.setMessageBar( mMessageBar );
342 mActiveWidget->setContext( context );
343 }
344
347 widget->setDockMode( dockMode() );
348 }
349 else
350 {
351 // set default "no edit widget available" page
352 stackedWidget->setCurrentWidget( pageNoWidget );
353 }
354 emitWidgetChanged();
355}
356
357void QgsPointCloudRendererPropertiesWidget::emitWidgetChanged()
358{
359 if ( !mBlockChangedSignal )
360 emit widgetChanged();
361}
PointCloudSymbol
Rendering symbols for point cloud points.
Definition qgis.h:4246
@ Circle
Renders points as circles.
Definition qgis.h:4248
@ Square
Renders points as squares.
Definition qgis.h:4247
PointCloudDrawOrder
Pointcloud rendering order for 2d views.
Definition qgis.h:4258
@ BottomToTop
Draw points with larger Z values last.
Definition qgis.h:4260
@ Default
Draw points in the order they are stored.
Definition qgis.h:4259
@ TopToBottom
Draw points with larger Z values first.
Definition qgis.h:4261
PointCloudZoomOutRenderBehavior
Point cloud zoom out options.
Definition qgis.h:6085
@ RenderOverviewAndExtents
Render point cloud extents over overview point cloud.
Definition qgis.h:6088
@ RenderExtents
Render only point cloud extents when zoomed out.
Definition qgis.h:6086
@ RenderOverview
Render overview point cloud when zoomed out.
Definition qgis.h:6087
@ 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
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.
QgsMapLayerConfigWidget(QgsMapLayer *layer, QgsMapCanvas *canvas, QWidget *parent=nullptr)
A panel widget that can be shown in the map style dock.
Base class for all map layer types.
Definition qgsmaplayer.h:80
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 ...
bool dockMode() const
Returns the dock mode state.
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.
Represents a map layer supporting display of point clouds.
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)
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.
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.
A container for the context for various read/write operations on objects.
A database of saved style entities, including symbols, color ramps, text formats and others.
Definition qgsstyle.h:88
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:61
#define QgsDebugError(str)
Definition qgslogger.h:57
QgsPointCloudRendererWidget *(* QgsPointCloudRendererWidgetFunc)(QgsPointCloudLayer *, QgsStyle *, QgsPointCloudRenderer *)