QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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"
22#include "qgsrastershader.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->inputBand() );
149 mMinMaxWidget->setBands( QList< int >() << pr->inputBand() );
150 mColorRampShaderWidget->setRasterBand( pr->inputBand() );
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
175void 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
184void 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
228void 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
238double 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
248void QgsSingleBandPseudoColorRendererWidget::mMinLineEdit_textEdited( const QString & )
249{
250 minMaxModified();
251 whileBlocking( mColorRampShaderWidget )->setMinimumMaximumAndClassify( lineEditValue( mMinLineEdit ), lineEditValue( mMaxLineEdit ) );
252 emit widgetChanged();
253}
254
255void QgsSingleBandPseudoColorRendererWidget::mMaxLineEdit_textEdited( const QString & )
256{
257 minMaxModified();
258 whileBlocking( mColorRampShaderWidget )->setMinimumMaximumAndClassify( lineEditValue( mMinLineEdit ), lineEditValue( mMaxLineEdit ) );
259 emit widgetChanged();
260}
261
262void QgsSingleBandPseudoColorRendererWidget::mMinLineEdit_textChanged( const QString & )
263{
264 whileBlocking( mColorRampShaderWidget )->setMinimumMaximum( lineEditValue( mMinLineEdit ), lineEditValue( mMaxLineEdit ) );
265 emit widgetChanged();
266}
267
268void QgsSingleBandPseudoColorRendererWidget::mMaxLineEdit_textChanged( const QString & )
269{
270 whileBlocking( mColorRampShaderWidget )->setMinimumMaximum( lineEditValue( mMinLineEdit ), lineEditValue( mMaxLineEdit ) );
271 emit widgetChanged();
272}
273
274
275void QgsSingleBandPseudoColorRendererWidget::minMaxModified()
276{
277 mMinMaxWidget->userHasSetManualMinMaxValues();
278}
279
280QString 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
293void QgsSingleBandPseudoColorRendererWidget::setMin( const QString &value, int )
294{
295 mMinLineEdit->setText( value );
296 minMaxModified();
297 mColorRampShaderWidget->classify();
298}
299
300void QgsSingleBandPseudoColorRendererWidget::setMax( const QString &value, int )
301{
302 mMaxLineEdit->setText( value );
303 minMaxModified();
304 mColorRampShaderWidget->classify();
305}
void minimumMaximumChangedFromTree(double minimum, double maximum)
Color ramp tree has changed.
void widgetChanged()
Widget changed.
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
QgsDoubleValidator is a QLineEdit Validator that combines QDoubleValidator and QRegularExpressionVali...
static double toDouble(const QString &input, bool *ok)
Converts input string to double value.
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:93
void bandChanged(int band)
Emitted when the currently selected band changes.
Base class for raster data providers.
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
Represents a raster layer.
QgsRasterRenderer * renderer() const
Returns the raster's renderer.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
This class describes the origin of min/max values.
QgsRasterMinMaxOrigin::Limits limits() const
Returns the raster limits.
void setLimits(QgsRasterMinMaxOrigin::Limits limits)
Sets the limits.
@ MinMax
Real min-max values.
void setExtent(const QgsRectangle &extent)
Sets the extent to use for minimum and maximum value calculation.
QgsRectangle extent()
Returns the extent selected by the user.
void doComputations()
Load programmatically with current values.
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
void load(int bandNo, double min, double max)
signal emitted when new min/max values are computed from statistics.
void setFromMinMaxOrigin(const QgsRasterMinMaxOrigin &)
Sets the "source" of min/max values.
void setBands(const QList< int > &bands)
QgsRasterMinMaxOrigin minMaxOrigin()
Returns a QgsRasterMinMaxOrigin object with the widget values.
void widgetChanged()
Emitted when something on the widget has changed.
void userHasSetManualMinMaxValues()
Uncheck cumulative cut, min/max, std-dev radio buttons.
Abstract base class for widgets which configure a QgsRasterRenderer.
virtual void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
QgsMapCanvas * mCanvas
Associated map canvas.
void widgetChanged()
Emitted when something on the widget has changed.
Raster renderer pipe that applies colors to a raster.
void setMinMaxOrigin(const QgsRasterMinMaxOrigin &origin)
Sets origin of min/max values.
const QgsRasterMinMaxOrigin & minMaxOrigin() const
Returns const reference to origin of min/max values.
Interface for all raster shaders.
void setRasterShaderFunction(QgsRasterShaderFunction *function)
A public method that allows the user to set their own shader function.
QgsRasterShaderFunction * rasterShaderFunction()
A rectangle specified with double values.
Definition: qgsrectangle.h:42
This class is a composition of two QSettings instances:
Definition: qgssettings.h:64
void setMax(const QString &value, int index=0) override
QgsSingleBandPseudoColorRendererWidget(QgsRasterLayer *layer, const QgsRectangle &extent=QgsRectangle())
Creates new raster renderer widget.
void doComputations() override
Load programmatically with current values.
QgsRasterMinMaxWidget * minMaxWidget() override
Returns min/max widget when it exists.
void setMin(const QString &value, int index=0) override
void setMapCanvas(QgsMapCanvas *canvas) override
Sets the map canvas associated with the widget.
QgsRasterRenderer * renderer() override
Creates a new renderer, using the properties defined in the widget.
void setFromRenderer(const QgsRasterRenderer *r)
Sets the widget state from the specified renderer.
void loadMinMax(int bandNo, double min, double max)
called when new min/max values are loaded
void loadMinMaxFromTree(double min, double max)
called when the color ramp tree has changed
Raster renderer pipe for single band pseudocolor.
Q_DECL_DEPRECATED void setBand(int bandNo)
Sets the band used by the renderer.
QgsRasterShader * shader()
Returns the raster shader.
int inputBand() const override
Returns the input band for the renderer, or -1 if no input band is available.
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...
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:5111
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39