QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgssinglebandpseudocolorrendererwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssinglebandpseudocolorrendererwidget.cpp
3  ------------------------------------------
4  begin : February 2012
5  copyright : (C) 2012 by Marco Hugentobler
6  email : marco at sourcepole dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
20 #include "qgsrasterlayer.h"
21 #include "qgsrasterdataprovider.h"
22 #include "qgsrastershader.h"
23 #include "qgsrasterminmaxwidget.h"
24 #include "qgsdoublevalidator.h"
25 #include "qgstreewidgetitem.h"
26 #include "qgssettings.h"
27 #include "qgsmapcanvas.h"
28 #include "qgsguiutils.h"
29 
30 // for color ramps - todo add rasterStyle and refactor raster vs. vector ramps
31 #include "qgsstyle.h"
32 #include "qgscolorramp.h"
33 #include "qgscolorrampbutton.h"
34 #include "qgscolordialog.h"
35 
36 #include <QCursor>
37 #include <QPushButton>
38 #include <QInputDialog>
39 #include <QFileDialog>
40 #include <QMenu>
41 #include <QMessageBox>
42 #include <QTextStream>
43 #include <QTreeView>
44 
46  : QgsRasterRendererWidget( layer, extent )
47  , mMinMaxOrigin( 0 )
48 {
49  const QgsSettings settings;
50 
51  setupUi( this );
52 
53  mColorRampShaderWidget->initializeForUseWithRasterLayer();
54 
55  connect( mMinLineEdit, &QLineEdit::textChanged, this, &QgsSingleBandPseudoColorRendererWidget::mMinLineEdit_textChanged );
56  connect( mMaxLineEdit, &QLineEdit::textChanged, this, &QgsSingleBandPseudoColorRendererWidget::mMaxLineEdit_textChanged );
57  connect( mMinLineEdit, &QLineEdit::textEdited, this, &QgsSingleBandPseudoColorRendererWidget::mMinLineEdit_textEdited );
58  connect( mMaxLineEdit, &QLineEdit::textEdited, this, &QgsSingleBandPseudoColorRendererWidget::mMaxLineEdit_textEdited );
59 
60  if ( !mRasterLayer )
61  {
62  return;
63  }
64 
66  if ( !provider )
67  {
68  return;
69  }
70 
71  // Must be before adding items to mBandComboBox (signal)
72  mMinLineEdit->setValidator( new QgsDoubleValidator( mMinLineEdit ) );
73  mMaxLineEdit->setValidator( new QgsDoubleValidator( mMaxLineEdit ) );
74 
75  mMinMaxWidget = new QgsRasterMinMaxWidget( layer, this );
76  mMinMaxWidget->setExtent( extent );
77  mMinMaxWidget->setMapCanvas( mCanvas );
78 
79  QHBoxLayout *layout = new QHBoxLayout();
80  layout->setContentsMargins( 0, 0, 0, 0 );
81  mMinMaxContainerWidget->setLayout( layout );
82  layout->addWidget( mMinMaxWidget );
83 
84  mColorRampShaderWidget->setRasterDataProvider( provider );
85  mBandComboBox->setLayer( mRasterLayer );
86 
87  setFromRenderer( layer->renderer() );
88 
91 
92  // If there is currently no min/max, load default with user current default options
93  if ( mMinLineEdit->text().isEmpty() || mMaxLineEdit->text().isEmpty() )
94  {
95  QgsRasterMinMaxOrigin minMaxOrigin = mMinMaxWidget->minMaxOrigin();
96  if ( minMaxOrigin.limits() == QgsRasterMinMaxOrigin::None )
97  {
99  mMinMaxWidget->setFromMinMaxOrigin( minMaxOrigin );
100  }
101  mMinMaxWidget->doComputations();
102  }
103 
104  whileBlocking( mColorRampShaderWidget )->setMinimumMaximum( lineEditValue( mMinLineEdit ), lineEditValue( mMaxLineEdit ) );
105 
106  connect( mBandComboBox, &QgsRasterBandComboBox::bandChanged, this, &QgsSingleBandPseudoColorRendererWidget::bandChanged );
109 }
110 
112 {
113  QgsRasterShader *rasterShader = new QgsRasterShader();
114 
115  mColorRampShaderWidget->setMinimumMaximum( lineEditValue( mMinLineEdit ), lineEditValue( mMaxLineEdit ) );
116  mColorRampShaderWidget->setExtent( mMinMaxWidget->extent() );
117 
118  QgsColorRampShader *fcn = new QgsColorRampShader( mColorRampShaderWidget->shader() );
119  rasterShader->setRasterShaderFunction( fcn );
120 
121  const int bandNumber = mBandComboBox->currentBand();
123  renderer->setClassificationMin( lineEditValue( mMinLineEdit ) );
124  renderer->setClassificationMax( lineEditValue( mMaxLineEdit ) );
125  renderer->setMinMaxOrigin( mMinMaxWidget->minMaxOrigin() );
126  return renderer;
127 }
128 
130 {
131  mMinMaxWidget->doComputations();
132 }
133 
135 
137 {
139  mMinMaxWidget->setMapCanvas( canvas );
140  mColorRampShaderWidget->setExtent( mMinMaxWidget->extent() );
141 }
142 
144 {
145  const QgsSingleBandPseudoColorRenderer *pr = dynamic_cast<const QgsSingleBandPseudoColorRenderer *>( r );
146  if ( pr )
147  {
148  mBandComboBox->setBand( pr->band() );
149  mMinMaxWidget->setBands( QList< int >() << pr->band() );
150  mColorRampShaderWidget->setRasterBand( pr->band() );
151 
152  // need to set min/max properties here because if we use the raster shader below,
153  // we may set a new color ramp which needs to have min/max values defined.
154  setLineEditValue( mMinLineEdit, pr->classificationMin() );
155  setLineEditValue( mMaxLineEdit, pr->classificationMax() );
156  mMinMaxWidget->setFromMinMaxOrigin( pr->minMaxOrigin() );
157 
158  const QgsRasterShader *rasterShader = pr->shader();
159  if ( rasterShader )
160  {
161  const QgsColorRampShader *colorRampShader = dynamic_cast<const QgsColorRampShader *>( rasterShader->rasterShaderFunction() );
162  if ( colorRampShader )
163  {
164  mColorRampShaderWidget->setFromShader( *colorRampShader );
165  }
166  }
167  }
168  else
169  {
170  mMinMaxWidget->setBands( QList< int >() << mBandComboBox->currentBand() );
171  mColorRampShaderWidget->setRasterBand( mBandComboBox->currentBand() );
172  }
173 }
174 
175 void QgsSingleBandPseudoColorRendererWidget::bandChanged()
176 {
177  QList<int> bands;
178  bands.append( mBandComboBox->currentBand() );
179  mMinMaxWidget->setBands( bands );
180  mColorRampShaderWidget->setRasterBand( mBandComboBox->currentBand() );
181  mColorRampShaderWidget->classify();
182 }
183 
184 void QgsSingleBandPseudoColorRendererWidget::loadMinMax( int bandNo, double min, double max )
185 {
186  QgsDebugMsgLevel( QStringLiteral( "theBandNo = %1 min = %2 max = %3" ).arg( bandNo ).arg( min ).arg( max ), 2 );
187 
188  const QString oldMinTextvalue = mMinLineEdit->text();
189  const QString oldMaxTextvalue = mMaxLineEdit->text();
190 
191  if ( std::isnan( min ) )
192  {
193  whileBlocking( mMinLineEdit )->clear();
194  }
195  else
196  {
197  whileBlocking( mMinLineEdit )->setText( displayValueWithMaxPrecision( min ) );
198  }
199 
200  if ( std::isnan( max ) )
201  {
202  whileBlocking( mMaxLineEdit )->clear();
203  }
204  else
205  {
206  whileBlocking( mMaxLineEdit )->setText( displayValueWithMaxPrecision( max ) );
207  }
208 
209  // We compare old min and new min as text because QString::number keeps a fixed number of significant
210  // digits (default 6) and so loaded min/max will always differ from current one, which triggers a
211  // classification, and wipe out every user modification (see https://github.com/qgis/QGIS/issues/36172)
212  if ( mMinLineEdit->text() != oldMinTextvalue || mMaxLineEdit->text() != oldMaxTextvalue )
213  {
214  whileBlocking( mColorRampShaderWidget )->setRasterBand( bandNo );
215  whileBlocking( mColorRampShaderWidget )->setMinimumMaximumAndClassify( min, max );
216  }
217 }
218 
219 
221 {
222  whileBlocking( mMinLineEdit )->setText( displayValueWithMaxPrecision( min ) );
223  whileBlocking( mMaxLineEdit )->setText( displayValueWithMaxPrecision( max ) );
224  minMaxModified();
225 }
226 
227 
228 void QgsSingleBandPseudoColorRendererWidget::setLineEditValue( QLineEdit *lineEdit, double value )
229 {
230  QString s;
231  if ( !std::isnan( value ) )
232  {
233  s = displayValueWithMaxPrecision( value );
234  }
235  lineEdit->setText( s );
236 }
237 
238 double QgsSingleBandPseudoColorRendererWidget::lineEditValue( const QLineEdit *lineEdit ) const
239 {
240  if ( lineEdit->text().isEmpty() )
241  {
242  return std::numeric_limits<double>::quiet_NaN();
243  }
244 
245  return QgsDoubleValidator::toDouble( lineEdit->text() );
246 }
247 
248 void QgsSingleBandPseudoColorRendererWidget::mMinLineEdit_textEdited( const QString & )
249 {
250  minMaxModified();
251  whileBlocking( mColorRampShaderWidget )->setMinimumMaximumAndClassify( lineEditValue( mMinLineEdit ), lineEditValue( mMaxLineEdit ) );
252  emit widgetChanged();
253 }
254 
255 void QgsSingleBandPseudoColorRendererWidget::mMaxLineEdit_textEdited( const QString & )
256 {
257  minMaxModified();
258  whileBlocking( mColorRampShaderWidget )->setMinimumMaximumAndClassify( lineEditValue( mMinLineEdit ), lineEditValue( mMaxLineEdit ) );
259  emit widgetChanged();
260 }
261 
262 void QgsSingleBandPseudoColorRendererWidget::mMinLineEdit_textChanged( const QString & )
263 {
264  whileBlocking( mColorRampShaderWidget )->setMinimumMaximum( lineEditValue( mMinLineEdit ), lineEditValue( mMaxLineEdit ) );
265  emit widgetChanged();
266 }
267 
268 void QgsSingleBandPseudoColorRendererWidget::mMaxLineEdit_textChanged( const QString & )
269 {
270  whileBlocking( mColorRampShaderWidget )->setMinimumMaximum( lineEditValue( mMinLineEdit ), lineEditValue( mMaxLineEdit ) );
271  emit widgetChanged();
272 }
273 
274 
275 void QgsSingleBandPseudoColorRendererWidget::minMaxModified()
276 {
277  mMinMaxWidget->userHasSetManualMinMaxValues();
278 }
279 
280 QString QgsSingleBandPseudoColorRendererWidget::displayValueWithMaxPrecision( const double value )
281 {
282  if ( mRasterLayer->dataProvider() )
283  {
284  return QgsGuiUtils::displayValueWithMaximumDecimals( mRasterLayer->dataProvider()->dataType( mBandComboBox->currentBand() ), value );
285  }
286  else
287  {
288  // Use QLocale default
289  return QLocale().toString( value, 'g' );
290  }
291 }
292 
293 void QgsSingleBandPseudoColorRendererWidget::setMin( const QString &value, int )
294 {
295  mMinLineEdit->setText( value );
296  minMaxModified();
297  mColorRampShaderWidget->classify();
298 }
299 
300 void QgsSingleBandPseudoColorRendererWidget::setMax( const QString &value, int )
301 {
302  mMaxLineEdit->setText( value );
303  minMaxModified();
304  mColorRampShaderWidget->classify();
305 }
QgsRasterMinMaxWidget::userHasSetManualMinMaxValues
void userHasSetManualMinMaxValues()
Uncheck cumulative cut, min/max, std-dev radio buttons.
Definition: qgsrasterminmaxwidget.cpp:89
QgsRasterBandComboBox::bandChanged
void bandChanged(int band)
Emitted when the currently selected band changes.
QgsSingleBandPseudoColorRendererWidget::loadMinMaxFromTree
void loadMinMaxFromTree(double min, double max)
called when the color ramp tree has changed
Definition: qgssinglebandpseudocolorrendererwidget.cpp:220
QgsSingleBandPseudoColorRendererWidget::min
QString min(int index=0) override
Definition: qgssinglebandpseudocolorrendererwidget.h:61
qgsrasterlayer.h
QgsRasterDataProvider::dataType
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
QgsRasterMinMaxWidget::widgetChanged
void widgetChanged()
Emitted when something on the widget has changed.
QgsSingleBandPseudoColorRendererWidget::loadMinMax
void loadMinMax(int bandNo, double min, double max)
called when new min/max values are loaded
Definition: qgssinglebandpseudocolorrendererwidget.cpp:184
QgsSingleBandPseudoColorRendererWidget::minMaxWidget
QgsRasterMinMaxWidget * minMaxWidget() override
Returns min/max widget when it exists.
Definition: qgssinglebandpseudocolorrendererwidget.cpp:134
qgsmapcanvas.h
QgsRasterRenderer::minMaxOrigin
const QgsRasterMinMaxOrigin & minMaxOrigin() const
Returns const reference to origin of min/max values.
Definition: qgsrasterrenderer.h:154
QgsRasterRendererWidget::mRasterLayer
QgsRasterLayer * mRasterLayer
Definition: qgsrasterrendererwidget.h:123
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsRasterShader::rasterShaderFunction
QgsRasterShaderFunction * rasterShaderFunction()
Definition: qgsrastershader.h:66
QgsColorRampShaderWidget::minimumMaximumChangedFromTree
void minimumMaximumChangedFromTree(double minimum, double maximum)
Color ramp tree has changed.
QgsSingleBandPseudoColorRendererWidget::setFromRenderer
void setFromRenderer(const QgsRasterRenderer *r)
Sets the widget state from the specified renderer.
Definition: qgssinglebandpseudocolorrendererwidget.cpp:143
QgsMapCanvas
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:89
QgsSingleBandPseudoColorRenderer::setBand
void setBand(int bandNo)
Sets the band used by the renderer.
Definition: qgssinglebandpseudocolorrenderer.cpp:40
QgsSingleBandPseudoColorRenderer::classificationMin
double classificationMin() const
Definition: qgssinglebandpseudocolorrenderer.h:99
QgsSettings
This class is a composition of two QSettings instances:
Definition: qgssettings.h:61
QgsSingleBandPseudoColorRendererWidget::setMax
void setMax(const QString &value, int index=0) override
Definition: qgssinglebandpseudocolorrendererwidget.cpp:300
QgsSingleBandPseudoColorRenderer::band
int band() const
Returns the band used by the renderer.
Definition: qgssinglebandpseudocolorrenderer.h:90
QgsColorRampShader
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
Definition: qgscolorrampshader.h:42
qgssinglebandpseudocolorrenderer.h
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsRasterMinMaxWidget::setFromMinMaxOrigin
void setFromMinMaxOrigin(const QgsRasterMinMaxOrigin &)
Sets the "source" of min/max values.
Definition: qgsrasterminmaxwidget.cpp:102
QgsSingleBandPseudoColorRendererWidget::setMapCanvas
void setMapCanvas(QgsMapCanvas *canvas) override
Sets the map canvas associated with the widget.
Definition: qgssinglebandpseudocolorrendererwidget.cpp:136
QgsRasterMinMaxOrigin
This class describes the origin of min/max values. It does not store by itself the min/max values.
Definition: qgsrasterminmaxorigin.h:33
QgsRasterMinMaxWidget::minMaxOrigin
QgsRasterMinMaxOrigin minMaxOrigin()
Returns a QgsRasterMinMaxOrigin object with the widget values.
Definition: qgsrasterminmaxwidget.cpp:145
QgsRasterLayer::renderer
QgsRasterRenderer * renderer() const
Returns the raster's renderer.
Definition: qgsrasterlayer.cpp:1758
QgsRasterRendererWidget::setMapCanvas
virtual void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
Definition: qgsrasterrendererwidget.cpp:23
QgsSingleBandPseudoColorRendererWidget::doComputations
void doComputations() override
Load programmatically with current values.
Definition: qgssinglebandpseudocolorrendererwidget.cpp:129
QgsRasterMinMaxWidget
Definition: qgsrasterminmaxwidget.h:37
QgsSingleBandPseudoColorRenderer::classificationMax
double classificationMax() const
Definition: qgssinglebandpseudocolorrenderer.h:100
QgsGuiUtils::displayValueWithMaximumDecimals
QString displayValueWithMaximumDecimals(const Qgis::DataType dataType, const double value, bool displayTrailingZeroes)
Returns a localized string representation of the value with the appropriate number of decimals suppor...
Definition: qgsguiutils.cpp:292
QgsRasterMinMaxWidget::setExtent
void setExtent(const QgsRectangle &extent)
Sets the extent to use for minimum and maximum value calculation.
Definition: qgsrasterminmaxwidget.h:51
qgssinglebandpseudocolorrendererwidget.h
QgsRasterMinMaxOrigin::MinMax
@ MinMax
Real min-max values.
Definition: qgsrasterminmaxorigin.h:74
QgsRasterMinMaxWidget::load
void load(int bandNo, double min, double max)
signal emitted when new min/max values are computed from statistics.
whileBlocking
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:2191
QgsRasterRenderer
Raster renderer pipe that applies colors to a raster.
Definition: qgsrasterrenderer.h:40
qgscolorramp.h
QgsRasterMinMaxWidget::doComputations
void doComputations()
Load programmatically with current values.
Definition: qgsrasterminmaxwidget.cpp:186
QgsRasterMinMaxWidget::setMapCanvas
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
Definition: qgsrasterminmaxwidget.cpp:59
QgsDoubleValidator
QgsDoubleValidator is a QLineEdit Validator that combines QDoubleValidator and QRegularExpressionVali...
Definition: qgsdoublevalidator.h:40
QgsRasterLayer
Represents a raster layer.
Definition: qgsrasterlayer.h:76
qgsstyle.h
qgsrastershader.h
qgscolordialog.h
QgsSingleBandPseudoColorRendererWidget::setMin
void setMin(const QString &value, int index=0) override
Definition: qgssinglebandpseudocolorrendererwidget.cpp:293
QgsRasterRenderer::setMinMaxOrigin
void setMinMaxOrigin(const QgsRasterMinMaxOrigin &origin)
Sets origin of min/max values.
Definition: qgsrasterrenderer.h:157
QgsColorRampShaderWidget::widgetChanged
void widgetChanged()
Widget changed.
qgstreewidgetitem.h
qgsrasterminmaxwidget.h
QgsRasterMinMaxOrigin::setLimits
void setLimits(QgsRasterMinMaxOrigin::Limits limits)
Sets the limits.
Definition: qgsrasterminmaxorigin.h:129
QgsDoubleValidator::toDouble
static double toDouble(const QString &input, bool *ok)
Converts input string to double value.
Definition: qgsdoublevalidator.cpp:134
qgssettings.h
QgsRasterMinMaxWidget::extent
QgsRectangle extent()
Returns the extent selected by the user.
Definition: qgsrasterminmaxwidget.cpp:75
QgsRasterMinMaxWidget::setBands
void setBands(const QList< int > &bands)
Definition: qgsrasterminmaxwidget.cpp:69
QgsRasterRendererWidget
Abstract base class for widgets which configure a QgsRasterRenderer.
Definition: qgsrasterrendererwidget.h:39
QgsSingleBandPseudoColorRenderer
Raster renderer pipe for single band pseudocolor.
Definition: qgssinglebandpseudocolorrenderer.h:35
QgsRasterRendererWidget::mCanvas
QgsMapCanvas * mCanvas
Associated map canvas.
Definition: qgsrasterrendererwidget.h:129
QgsRasterRendererWidget::widgetChanged
void widgetChanged()
Emitted when something on the widget has changed.
QgsRasterShader::setRasterShaderFunction
void setRasterShaderFunction(QgsRasterShaderFunction *function)
A public method that allows the user to set their own shader function.
Definition: qgsrastershader.cpp:56
qgscolorrampbutton.h
qgsdoublevalidator.h
qgsguiutils.h
QgsRasterMinMaxOrigin::None
@ None
User defined.
Definition: qgsrasterminmaxorigin.h:73
QgsSingleBandPseudoColorRendererWidget::max
QString max(int index=0) override
Definition: qgssinglebandpseudocolorrendererwidget.h:62
QgsRasterShader
Interface for all raster shaders.
Definition: qgsrastershader.h:35
QgsSingleBandPseudoColorRenderer::shader
QgsRasterShader * shader()
Returns the raster shader.
Definition: qgssinglebandpseudocolorrenderer.h:58
QgsSingleBandPseudoColorRendererWidget::QgsSingleBandPseudoColorRendererWidget
QgsSingleBandPseudoColorRendererWidget(QgsRasterLayer *layer, const QgsRectangle &extent=QgsRectangle())
Creates new raster renderer widget.
Definition: qgssinglebandpseudocolorrendererwidget.cpp:45
QgsRasterDataProvider
Base class for raster data providers.
Definition: qgsrasterdataprovider.h:88
QgsRasterMinMaxOrigin::limits
QgsRasterMinMaxOrigin::Limits limits() const
Returns the raster limits.
Definition: qgsrasterminmaxorigin.h:109
QgsRasterLayer::dataProvider
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
Definition: qgsrasterlayer.cpp:257
QgsSingleBandPseudoColorRendererWidget::renderer
QgsRasterRenderer * renderer() override
Creates a new renderer, using the properties defined in the widget.
Definition: qgssinglebandpseudocolorrendererwidget.cpp:111
qgsrasterdataprovider.h