QGIS API Documentation  3.24.2-Tisler (13c1a02865)
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 #include "qgsproject.h"
32 #include "qgsprojectutils.h"
33 
34 static bool _initRenderer( const QString &name, QgsPointCloudRendererWidgetFunc f, const QString &iconName = QString() )
35 {
37  if ( !rendererAbstractMetadata )
38  return false;
39  QgsPointCloudRendererMetadata *rendererMetadata = dynamic_cast<QgsPointCloudRendererMetadata *>( rendererAbstractMetadata );
40  if ( !rendererMetadata )
41  return false;
42 
43  rendererMetadata->setWidgetFunction( f );
44 
45  if ( !iconName.isEmpty() )
46  {
47  rendererMetadata->setIcon( QgsApplication::getThemeIcon( iconName ) );
48  }
49 
50  QgsDebugMsgLevel( "Set for " + name, 2 );
51  return true;
52 }
53 
54 static void _initRendererWidgetFunctions()
55 {
56  static bool sInitialized = false;
57  if ( sInitialized )
58  return;
59 
60  _initRenderer( QStringLiteral( "extent" ), QgsPointCloudExtentRendererWidget::create, QStringLiteral( "styleicons/pointcloudextent.svg" ) );
61  _initRenderer( QStringLiteral( "rgb" ), QgsPointCloudRgbRendererWidget::create, QStringLiteral( "styleicons/multibandcolor.svg" ) );
62  _initRenderer( QStringLiteral( "ramp" ), QgsPointCloudAttributeByRampRendererWidget::create, QStringLiteral( "styleicons/singlebandpseudocolor.svg" ) );
63  _initRenderer( QStringLiteral( "classified" ), QgsPointCloudClassifiedRendererWidget::create, QStringLiteral( "styleicons/paletted.svg" ) );
64 
65  sInitialized = true;
66 }
67 
69  : QgsMapLayerConfigWidget( layer, nullptr, parent )
70  , mLayer( layer )
71  , mStyle( style )
72 {
73  setupUi( this );
74 
75  layout()->setContentsMargins( 0, 0, 0, 0 );
76 
77  // initialize registry's widget functions
78  _initRendererWidgetFunctions();
79 
81  const QStringList renderers = reg->renderersList();
82  for ( const QString &name : renderers )
83  {
85  cboRenderers->addItem( m->icon(), m->visibleName(), name );
86  }
87 
88  cboRenderers->setCurrentIndex( -1 ); // set no current renderer
89 
90  mPointStyleComboBox->addItem( tr( "Square" ), QgsPointCloudRenderer::Square );
91  mPointStyleComboBox->addItem( tr( "Circle" ), QgsPointCloudRenderer::Circle );
92 
93  connect( cboRenderers, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRendererPropertiesWidget::rendererChanged );
94 
95  connect( mBlendModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
96  connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
97 
100 
101  connect( mPointSizeSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
102  connect( mPointSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
103 
104  mDrawOrderComboBox->addItem( tr( "Default" ), static_cast< int >( QgsPointCloudRenderer::DrawOrder::Default ) );
105  mDrawOrderComboBox->addItem( tr( "Bottom to Top" ), static_cast< int >( QgsPointCloudRenderer::DrawOrder::BottomToTop ) );
106  mDrawOrderComboBox->addItem( tr( "Top to Bottom" ), static_cast< int >( QgsPointCloudRenderer::DrawOrder::TopToBottom ) );
107 
110  mMaxErrorSpinBox->setClearValue( 0.3 );
111 
112  connect( mMaxErrorSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
113  connect( mMaxErrorUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
114 
115  connect( mPointStyleComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
116  connect( mDrawOrderComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged );
117  syncToLayer( layer );
118 }
119 
121 {
122  mMapCanvas = context.mapCanvas();
123  mMessageBar = context.messageBar();
124  if ( mActiveWidget )
125  {
126  mActiveWidget->setContext( context );
127  }
128 }
129 
131 {
132  mLayer = qobject_cast< QgsPointCloudLayer * >( layer );
133 
134  mBlockChangedSignal = true;
135  mOpacityWidget->setOpacity( mLayer->opacity() );
136  mBlendModeComboBox->setShowClippingModes( QgsProjectUtils::layerIsContainedInGroupLayer( QgsProject::instance(), mLayer ) );
137  mBlendModeComboBox->setBlendMode( mLayer->blendMode() );
138 
139  if ( mLayer->renderer() )
140  {
141  // set current renderer from layer
142  const QString rendererName = mLayer->renderer()->type();
143 
144  const int rendererIdx = cboRenderers->findData( rendererName );
145  cboRenderers->setCurrentIndex( rendererIdx );
146 
147  // no renderer found... this mustn't happen
148  Q_ASSERT( rendererIdx != -1 && "there must be a renderer!" );
149 
150  mPointSizeSpinBox->setValue( mLayer->renderer()->pointSize() );
151  mPointSizeUnitWidget->setUnit( mLayer->renderer()->pointSizeUnit() );
152  mPointSizeUnitWidget->setMapUnitScale( mLayer->renderer()->pointSizeMapUnitScale() );
153 
154  mPointStyleComboBox->setCurrentIndex( mPointStyleComboBox->findData( mLayer->renderer()->pointSymbol() ) );
155  mDrawOrderComboBox->setCurrentIndex( mDrawOrderComboBox->findData( static_cast< int >( mLayer->renderer()->drawOrder2d() ) ) );
156 
157  mMaxErrorSpinBox->setValue( mLayer->renderer()->maximumScreenError() );
158  mMaxErrorUnitWidget->setUnit( mLayer->renderer()->maximumScreenErrorUnit() );
159  }
160 
161  mBlockChangedSignal = false;
162 }
163 
165 {
166  if ( mActiveWidget )
167  mActiveWidget->setDockMode( dockMode );
169 }
170 
172 {
173  mLayer->setOpacity( mOpacityWidget->opacity() );
174  mLayer->setBlendMode( mBlendModeComboBox->blendMode() );
175 
176  if ( mActiveWidget )
177  mLayer->setRenderer( mActiveWidget->renderer() );
178  else if ( !cboRenderers->currentData().toString().isEmpty() )
179  {
180  QDomElement elem;
181  mLayer->setRenderer( QgsApplication::pointCloudRendererRegistry()->rendererMetadata( cboRenderers->currentData().toString() )->createRenderer( elem, QgsReadWriteContext() ) );
182  }
183 
184  mLayer->renderer()->setPointSize( mPointSizeSpinBox->value() );
185  mLayer->renderer()->setPointSizeUnit( mPointSizeUnitWidget->unit() );
186  mLayer->renderer()->setPointSizeMapUnitScale( mPointSizeUnitWidget->getMapUnitScale() );
187 
188  mLayer->renderer()->setPointSymbol( static_cast< QgsPointCloudRenderer::PointSymbol >( mPointStyleComboBox->currentData().toInt() ) );
189 
190  mLayer->renderer()->setMaximumScreenError( mMaxErrorSpinBox->value() );
191  mLayer->renderer()->setMaximumScreenErrorUnit( mMaxErrorUnitWidget->unit() );
192  mLayer->renderer()->setDrawOrder2d( static_cast< QgsPointCloudRenderer::DrawOrder >( mDrawOrderComboBox->currentData().toInt() ) );
193 }
194 
195 void QgsPointCloudRendererPropertiesWidget::rendererChanged()
196 {
197  if ( cboRenderers->currentIndex() == -1 )
198  {
199  QgsDebugMsg( QStringLiteral( "No current item -- this should never happen!" ) );
200  return;
201  }
202 
203  const QString rendererName = cboRenderers->currentData().toString();
204 
205  //Retrieve the previous renderer: from the old active widget if possible, otherwise from the layer
206  std::unique_ptr< QgsPointCloudRenderer > oldRenderer;
207  std::unique_ptr< QgsPointCloudRenderer > newRenderer;
208  if ( mActiveWidget )
209  newRenderer.reset( mActiveWidget->renderer() );
210 
211  if ( newRenderer )
212  {
213  oldRenderer = std::move( newRenderer );
214  }
215  else
216  {
217  oldRenderer.reset( mLayer->renderer()->clone() );
218  }
219 
220  // get rid of old active widget (if any)
221  if ( mActiveWidget )
222  {
223  stackedWidget->removeWidget( mActiveWidget );
224 
225  delete mActiveWidget;
226  mActiveWidget = nullptr;
227  }
228 
229  QgsPointCloudRendererWidget *widget = nullptr;
231  if ( rendererMetadata )
232  widget = rendererMetadata->createRendererWidget( mLayer, mStyle, oldRenderer.get() );
233  oldRenderer.reset();
234 
235  if ( widget )
236  {
237  // instantiate the widget and set as active
238  mActiveWidget = widget;
239  stackedWidget->addWidget( mActiveWidget );
240  stackedWidget->setCurrentWidget( mActiveWidget );
241 
242  if ( mMapCanvas || mMessageBar )
243  {
244  QgsSymbolWidgetContext context;
245  context.setMapCanvas( mMapCanvas );
246  context.setMessageBar( mMessageBar );
247  mActiveWidget->setContext( context );
248  }
249 
252  widget->setDockMode( dockMode() );
253  }
254  else
255  {
256  // set default "no edit widget available" page
257  stackedWidget->setCurrentWidget( pageNoWidget );
258  }
259  emitWidgetChanged();
260 }
261 
262 void QgsPointCloudRendererPropertiesWidget::emitWidgetChanged()
263 {
264  if ( !mBlockChangedSignal )
265  emit widgetChanged();
266 }
267 
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:73
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:82
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.
DrawOrder
Pointcloud rendering order for 2d views /since QGIS 3.24.
@ 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.
PointSymbol pointSymbol() const
Returns the symbol used by the renderer for drawing points.
DrawOrder drawOrder2d() const
Returns the drawing order 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.
void setDrawOrder2d(DrawOrder order)
Sets the drawing order used by the renderer for drawing points.
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:470
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 *)