QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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->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
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:90
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:62
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.
int band() const
Returns the band used by the renderer.
void setBand(int bandNo)
Sets the band used by the renderer.
QgsRasterShader * shader()
Returns the raster shader.
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:2453
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39