QGIS API Documentation  3.21.0-Master (909859188c)
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"
20 #include "qgssymbolwidgetcontext.h"
22 #include "qgspointcloudlayer.h"
23 #include "qgspointcloudrenderer.h"
28 
30 #include "qgslogger.h"
31 
32 static bool _initRenderer( 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 
52 static void _initRendererWidgetFunctions()
53 {
54  static bool sInitialized = false;
55  if ( sInitialized )
56  return;
57 
58  _initRenderer( QStringLiteral( "extent" ), QgsPointCloudExtentRendererWidget::create, QStringLiteral( "styleicons/pointcloudextent.svg" ) );
59  _initRenderer( QStringLiteral( "rgb" ), QgsPointCloudRgbRendererWidget::create, QStringLiteral( "styleicons/multibandcolor.svg" ) );
60  _initRenderer( QStringLiteral( "ramp" ), QgsPointCloudAttributeByRampRendererWidget::create, QStringLiteral( "styleicons/singlebandpseudocolor.svg" ) );
61  _initRenderer( 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" ), QgsPointCloudRenderer::Square );
89  mPointStyleComboBox->addItem( tr( "Circle" ), QgsPointCloudRenderer::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 
98 
99  connect( mPointSizeSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
100  connect( mPointSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
101 
104  mMaxErrorSpinBox->setClearValue( 0.3 );
105 
106  connect( mMaxErrorSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
107  connect( mMaxErrorUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
108 
109  connect( mPointStyleComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
110 
111  syncToLayer( layer );
112 }
113 
115 {
116  mMapCanvas = context.mapCanvas();
117  mMessageBar = context.messageBar();
118  if ( mActiveWidget )
119  {
120  mActiveWidget->setContext( context );
121  }
122 }
123 
125 {
126  mLayer = qobject_cast< QgsPointCloudLayer * >( layer );
127 
128  mBlockChangedSignal = true;
129  mOpacityWidget->setOpacity( mLayer->opacity() );
130  mBlendModeComboBox->setBlendMode( mLayer->blendMode() );
131 
132  if ( mLayer->renderer() )
133  {
134  // set current renderer from layer
135  const QString rendererName = mLayer->renderer()->type();
136 
137  const int rendererIdx = cboRenderers->findData( rendererName );
138  cboRenderers->setCurrentIndex( rendererIdx );
139 
140  // no renderer found... this mustn't happen
141  Q_ASSERT( rendererIdx != -1 && "there must be a renderer!" );
142 
143  mPointSizeSpinBox->setValue( mLayer->renderer()->pointSize() );
144  mPointSizeUnitWidget->setUnit( mLayer->renderer()->pointSizeUnit() );
145  mPointSizeUnitWidget->setMapUnitScale( mLayer->renderer()->pointSizeMapUnitScale() );
146 
147  mPointStyleComboBox->setCurrentIndex( mPointStyleComboBox->findData( mLayer->renderer()->pointSymbol() ) );
148 
149  mMaxErrorSpinBox->setValue( mLayer->renderer()->maximumScreenError() );
150  mMaxErrorUnitWidget->setUnit( mLayer->renderer()->maximumScreenErrorUnit() );
151  }
152 
153  mBlockChangedSignal = false;
154 }
155 
157 {
158  if ( mActiveWidget )
159  mActiveWidget->setDockMode( dockMode );
161 }
162 
164 {
165  mLayer->setOpacity( mOpacityWidget->opacity() );
166  mLayer->setBlendMode( mBlendModeComboBox->blendMode() );
167 
168  if ( mActiveWidget )
169  mLayer->setRenderer( mActiveWidget->renderer() );
170  else if ( !cboRenderers->currentData().toString().isEmpty() )
171  {
172  QDomElement elem;
173  mLayer->setRenderer( QgsApplication::pointCloudRendererRegistry()->rendererMetadata( cboRenderers->currentData().toString() )->createRenderer( elem, QgsReadWriteContext() ) );
174  }
175 
176  mLayer->renderer()->setPointSize( mPointSizeSpinBox->value() );
177  mLayer->renderer()->setPointSizeUnit( mPointSizeUnitWidget->unit() );
178  mLayer->renderer()->setPointSizeMapUnitScale( mPointSizeUnitWidget->getMapUnitScale() );
179 
180  mLayer->renderer()->setPointSymbol( static_cast< QgsPointCloudRenderer::PointSymbol >( mPointStyleComboBox->currentData().toInt() ) );
181 
182  mLayer->renderer()->setMaximumScreenError( mMaxErrorSpinBox->value() );
183  mLayer->renderer()->setMaximumScreenErrorUnit( mMaxErrorUnitWidget->unit() );
184 }
185 
186 void QgsPointCloudRendererPropertiesWidget::rendererChanged()
187 {
188  if ( cboRenderers->currentIndex() == -1 )
189  {
190  QgsDebugMsg( QStringLiteral( "No current item -- this should never happen!" ) );
191  return;
192  }
193 
194  const QString rendererName = cboRenderers->currentData().toString();
195 
196  //Retrieve the previous renderer: from the old active widget if possible, otherwise from the layer
197  std::unique_ptr< QgsPointCloudRenderer > oldRenderer;
198  std::unique_ptr< QgsPointCloudRenderer > newRenderer;
199  if ( mActiveWidget )
200  newRenderer.reset( mActiveWidget->renderer() );
201 
202  if ( newRenderer )
203  {
204  oldRenderer = std::move( newRenderer );
205  }
206  else
207  {
208  oldRenderer.reset( mLayer->renderer()->clone() );
209  }
210 
211  // get rid of old active widget (if any)
212  if ( mActiveWidget )
213  {
214  stackedWidget->removeWidget( mActiveWidget );
215 
216  delete mActiveWidget;
217  mActiveWidget = nullptr;
218  }
219 
220  QgsPointCloudRendererWidget *widget = nullptr;
222  if ( rendererMetadata )
223  widget = rendererMetadata->createRendererWidget( mLayer, mStyle, oldRenderer.get() );
224  oldRenderer.reset();
225 
226  if ( widget )
227  {
228  // instantiate the widget and set as active
229  mActiveWidget = widget;
230  stackedWidget->addWidget( mActiveWidget );
231  stackedWidget->setCurrentWidget( mActiveWidget );
232 
233  if ( mMapCanvas || mMessageBar )
234  {
235  QgsSymbolWidgetContext context;
236  context.setMapCanvas( mMapCanvas );
237  context.setMessageBar( mMessageBar );
238  mActiveWidget->setContext( context );
239  }
240 
243  widget->setDockMode( dockMode() );
244  }
245  else
246  {
247  // set default "no edit widget available" page
248  stackedWidget->setCurrentWidget( pageNoWidget );
249  }
250  emitWidgetChanged();
251 }
252 
253 void QgsPointCloudRendererPropertiesWidget::emitWidgetChanged()
254 {
255  if ( !mBlockChangedSignal )
256  emit widgetChanged();
257 }
258 
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:72
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:81
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 setDockMode(bool dockMode) override
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
void syncToLayer(QgsMapLayer *layer) override
Reset to original (vector layer) values.
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 QgsPointCloudRenderer * renderer()=0
Returns a new instance of a renderer as defined by the settings in the widget.
virtual void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the renderer widget is shown, e.g., the associated map canvas and expressio...
const QgsMapUnitScale & pointSizeMapUnitScale() const
Returns the map unit scale used for the point size.
void setMaximumScreenError(double error)
Sets the maximum screen error allowed when rendering the point cloud.
void setPointSizeUnit(const QgsUnitTypes::RenderUnit units)
Sets the units used for the point size.
PointSymbol pointSymbol() const
Returns the symbol used by the renderer for drawing points.
void setPointSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale used for the point size.
virtual QgsPointCloudRenderer * clone() const =0
Create a deep copy of this renderer.
void setPointSize(double size)
Sets the point size.
PointSymbol
Rendering symbols for points.
@ Square
Renders points as squares.
@ Circle
Renders points as circles.
virtual QString type() const =0
Returns the identifier of the renderer type.
void setPointSymbol(PointSymbol symbol)
Sets the symbol used by the renderer for drawing points.
QgsUnitTypes::RenderUnit maximumScreenErrorUnit() const
Returns the unit for the maximum screen error allowed when rendering the point cloud.
QgsUnitTypes::RenderUnit pointSizeUnit() const
Returns the units used for the point size.
double maximumScreenError() const
Returns the maximum screen error allowed when rendering the point cloud.
void setMaximumScreenErrorUnit(QgsUnitTypes::RenderUnit unit)
Sets the unit for the maximum screen error allowed when rendering the point cloud.
double pointSize() const
Returns the point size.
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.
QList< QgsUnitTypes::RenderUnit > RenderUnitList
List of render units.
Definition: qgsunittypes.h:240
@ RenderMetersInMapUnits
Meters value as Map units.
Definition: qgsunittypes.h:176
@ RenderPoints
Points (e.g., for font sizes)
Definition: qgsunittypes.h:173
@ RenderPixels
Pixels.
Definition: qgsunittypes.h:171
@ RenderInches
Inches.
Definition: qgsunittypes.h:174
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:169
@ RenderMapUnits
Map units.
Definition: qgsunittypes.h:170
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsPointCloudRendererWidget *(* QgsPointCloudRendererWidgetFunc)(QgsPointCloudLayer *, QgsStyle *, QgsPointCloudRenderer *)