16 #include <QIntValidator>
18 #include <QTextStream>
19 #include <QMessageBox>
20 #include <QFileDialog>
22 #include "qgssettings.h"
40 , TRSTRING_NOT_SET( tr(
"Not Set" ) )
41 , mRasterLayer( layer )
42 , mMapCanvas( canvas )
45 connect( pbnAddValuesFromDisplay, &QToolButton::clicked,
this, &QgsRasterTransparencyWidget::pbnAddValuesFromDisplay_clicked );
46 connect( pbnAddValuesManually, &QToolButton::clicked,
this, &QgsRasterTransparencyWidget::pbnAddValuesManually_clicked );
47 connect( pbnDefaultValues, &QToolButton::clicked,
this, &QgsRasterTransparencyWidget::pbnDefaultValues_clicked );
48 connect( pbnExportTransparentPixelValues, &QToolButton::clicked,
this, &QgsRasterTransparencyWidget::pbnExportTransparentPixelValues_clicked );
49 connect( pbnImportTransparentPixelValues, &QToolButton::clicked,
this, &QgsRasterTransparencyWidget::pbnImportTransparentPixelValues_clicked );
50 connect( pbnRemoveSelectedRow, &QToolButton::clicked,
this, &QgsRasterTransparencyWidget::pbnRemoveSelectedRow_clicked );
52 mNodataColorButton->setShowNoColor(
true );
53 mNodataColorButton->setColorDialogTitle( tr(
"Select No Data Color" ) );
62 mPixelSelectorTool =
nullptr;
70 pbnAddValuesFromDisplay->setEnabled(
false );
83 gboxNoDataValue->setEnabled(
false );
84 gboxCustomTransparency->setEnabled(
false );
87 cboxTransparencyBand->setShowNotSetOption(
true, tr(
"None" ) );
88 cboxTransparencyBand->setLayer( mRasterLayer );
92 cboxTransparencyBand->setBand( renderer->
alphaBand() );
101 lblSrcNoDataValue->setText( tr(
"not defined" ) );
108 mSrcNoDataValueCheckBox->setEnabled( enableSrcNoData );
109 lblSrcNoDataValue->setEnabled( enableSrcNoData );
114 mNodataColorButton->setColor( renderer->
nodataColor() );
116 mNodataColorButton->setToNull();
120 QgsDebugMsg( QStringLiteral(
"noDataRangeList.size = %1" ).arg( noDataRangeList.size() ) );
121 if ( !noDataRangeList.isEmpty() )
124 leNoDataValue->setText( QLocale().toString( v ) );
128 leNoDataValue->setText( QString() );
131 populateTransparencyTable( mRasterLayer->
renderer() );
134 void QgsRasterTransparencyWidget::transparencyCellTextEdited(
const QString &text )
137 QgsDebugMsg( QStringLiteral(
"text = %1" ).arg( text ) );
143 int nBands = renderer->
usesBands().size();
146 QLineEdit *lineEdit = qobject_cast<QLineEdit *>( sender() );
147 if ( !lineEdit )
return;
150 for (
int r = 0; r < tableTransparency->rowCount(); r++ )
152 for (
int c = 0;
c < tableTransparency->columnCount();
c++ )
154 if ( tableTransparency->cellWidget( r,
c ) == sender() )
161 if ( row != -1 )
break;
163 QgsDebugMsg( QStringLiteral(
"row = %1 column =%2" ).arg( row ).arg( column ) );
167 QLineEdit *toLineEdit =
dynamic_cast<QLineEdit *
>( tableTransparency->cellWidget( row, 1 ) );
168 if ( !toLineEdit )
return;
169 bool toChanged = mTransparencyToEdited.value( row );
170 QgsDebugMsg( QStringLiteral(
"toChanged = %1" ).arg( toChanged ) );
173 toLineEdit->setText( lineEdit->text() );
176 else if ( column == 1 )
178 setTransparencyToEdited( row );
184 void QgsRasterTransparencyWidget::pbnAddValuesFromDisplay_clicked()
186 if ( mMapCanvas && mPixelSelectorTool )
192 void QgsRasterTransparencyWidget::pbnAddValuesManually_clicked()
200 tableTransparency->insertRow( tableTransparency->rowCount() );
205 for (
int i = 0; i < n; i++ )
207 setTransparencyCell( tableTransparency->rowCount() - 1, i, std::numeric_limits<double>::quiet_NaN() );
210 setTransparencyCell( tableTransparency->rowCount() - 1, n, 100 );
212 tableTransparency->resizeColumnsToContents();
213 tableTransparency->resizeRowsToContents();
216 void QgsRasterTransparencyWidget::pbnDefaultValues_clicked()
226 setupTransparencyTable( nBands );
228 tableTransparency->resizeColumnsToContents();
229 tableTransparency->resizeRowsToContents();
233 void QgsRasterTransparencyWidget::pbnExportTransparentPixelValues_clicked()
235 QgsSettings myQSettings;
236 QString myLastDir = myQSettings.value( QStringLiteral(
"lastRasterFileFilterDir" ), QDir::homePath() ).toString();
237 QString myFileName = QFileDialog::getSaveFileName(
this, tr(
"Save Pixel Values as File" ), myLastDir, tr(
"Textfile" ) +
" (*.txt)" );
238 if ( !myFileName.isEmpty() )
240 if ( !myFileName.endsWith( QLatin1String(
".txt" ), Qt::CaseInsensitive ) )
242 myFileName = myFileName +
".txt";
245 QFile myOutputFile( myFileName );
246 if ( myOutputFile.open( QFile::WriteOnly | QIODevice::Truncate ) )
248 QTextStream myOutputStream( &myOutputFile );
249 myOutputStream <<
"# " << tr(
"QGIS Generated Transparent Pixel Value Export File" ) <<
'\n';
250 if ( rasterIsMultiBandColor() )
252 myOutputStream <<
"#\n#\n# " << tr(
"Red" ) <<
"\t" << tr(
"Green" ) <<
"\t" << tr(
"Blue" ) <<
"\t" << tr(
"Percent Transparent" );
253 for (
int myTableRunner = 0; myTableRunner < tableTransparency->rowCount(); myTableRunner++ )
255 myOutputStream <<
'\n' << QString::number( transparencyCellValue( myTableRunner, 0 ) ) <<
"\t"
256 << QString::number( transparencyCellValue( myTableRunner, 1 ) ) <<
"\t"
257 << QString::number( transparencyCellValue( myTableRunner, 2 ) ) <<
"\t"
258 << QString::number( transparencyCellValue( myTableRunner, 3 ) );
263 myOutputStream <<
"#\n#\n# " << tr(
"Value" ) <<
"\t" << tr(
"Percent Transparent" );
265 for (
int myTableRunner = 0; myTableRunner < tableTransparency->rowCount(); myTableRunner++ )
267 myOutputStream <<
'\n' << QString::number( transparencyCellValue( myTableRunner, 0 ) ) <<
"\t"
268 << QString::number( transparencyCellValue( myTableRunner, 1 ) ) <<
"\t"
269 << QString::number( transparencyCellValue( myTableRunner, 2 ) );
275 QMessageBox::warning(
this, tr(
"Save Pixel Values as File" ), tr(
"Write access denied. Adjust the file permissions and try again.\n\n" ) );
280 void QgsRasterTransparencyWidget::pbnImportTransparentPixelValues_clicked()
282 int myLineCounter = 0;
283 bool myImportError =
false;
285 QgsSettings myQSettings;
286 QString myLastDir = myQSettings.value( QStringLiteral(
"lastRasterFileFilterDir" ), QDir::homePath() ).toString();
287 QString myFileName = QFileDialog::getOpenFileName(
this, tr(
"Load Pixel Values from File" ), myLastDir, tr(
"Textfile" ) +
" (*.txt)" );
288 QFile myInputFile( myFileName );
289 if ( myInputFile.open( QFile::ReadOnly ) )
291 QTextStream myInputStream( &myInputFile );
293 if ( rasterIsMultiBandColor() )
295 for (
int myTableRunner = tableTransparency->rowCount() - 1; myTableRunner >= 0; myTableRunner-- )
297 tableTransparency->removeRow( myTableRunner );
300 while ( !myInputStream.atEnd() )
303 myInputLine = myInputStream.readLine();
304 if ( !myInputLine.isEmpty() )
306 if ( !myInputLine.simplified().startsWith(
'#' ) )
308 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
309 QStringList myTokens = myInputLine.split( QRegExp(
"\\s+" ), QString::SkipEmptyParts );
311 QStringList myTokens = myInputLine.split( QRegExp(
"\\s+" ), Qt::SkipEmptyParts );
313 if ( myTokens.count() != 4 )
315 myImportError =
true;
316 myBadLines = myBadLines + QString::number( myLineCounter ) +
":\t[" + myInputLine +
"]\n";
320 tableTransparency->insertRow( tableTransparency->rowCount() );
321 for (
int col = 0; col < 4; col++ )
323 setTransparencyCell( tableTransparency->rowCount() - 1, col, myTokens[col].toDouble() );
332 for (
int myTableRunner = tableTransparency->rowCount() - 1; myTableRunner >= 0; myTableRunner-- )
334 tableTransparency->removeRow( myTableRunner );
337 while ( !myInputStream.atEnd() )
340 myInputLine = myInputStream.readLine();
341 if ( !myInputLine.isEmpty() )
343 if ( !myInputLine.simplified().startsWith(
'#' ) )
345 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
346 QStringList myTokens = myInputLine.split( QRegExp(
"\\s+" ), QString::SkipEmptyParts );
348 QStringList myTokens = myInputLine.split( QRegExp(
"\\s+" ), Qt::SkipEmptyParts );
350 if ( myTokens.count() != 3 && myTokens.count() != 2 )
352 myImportError =
true;
353 myBadLines = myBadLines + QString::number( myLineCounter ) +
":\t[" + myInputLine +
"]\n";
357 if ( myTokens.count() == 2 )
359 myTokens.insert( 1, myTokens[0] );
361 tableTransparency->insertRow( tableTransparency->rowCount() );
362 for (
int col = 0; col < 3; col++ )
364 setTransparencyCell( tableTransparency->rowCount() - 1, col, myTokens[col].toDouble() );
374 QMessageBox::warning(
this, tr(
"Load Pixel Values from File" ), tr(
"The following lines contained errors\n\n%1" ).arg( myBadLines ) );
377 else if ( !myFileName.isEmpty() )
379 QMessageBox::warning(
this, tr(
"Load Pixel Values from File" ), tr(
"Read access denied. Adjust the file permissions and try again.\n\n" ) );
381 tableTransparency->resizeColumnsToContents();
382 tableTransparency->resizeRowsToContents();
386 void QgsRasterTransparencyWidget::pbnRemoveSelectedRow_clicked()
388 if ( 0 < tableTransparency->rowCount() )
390 tableTransparency->removeRow( tableTransparency->currentRow() );
395 bool QgsRasterTransparencyWidget::rasterIsMultiBandColor()
404 if (
"" != leNoDataValue->text() )
406 bool myDoubleOk =
false;
411 myNoDataRangeList << myNoDataRange;
414 for (
int bandNo = 1; bandNo <= mRasterLayer->
dataProvider()->bandCount(); bandNo++ )
422 if ( rasterRenderer )
424 rasterRenderer->
setAlphaBand( cboxTransparencyBand->currentBand() );
429 if ( tableTransparency->columnCount() == 4 )
432 QList<QgsRasterTransparency::TransparentThreeValuePixel> myTransparentThreeValuePixelList;
433 myTransparentThreeValuePixelList.reserve( tableTransparency->rowCount() );
434 for (
int myListRunner = 0; myListRunner < tableTransparency->rowCount(); myListRunner++ )
436 myTransparentPixel.
red = transparencyCellValue( myListRunner, 0 );
437 myTransparentPixel.
green = transparencyCellValue( myListRunner, 1 );
438 myTransparentPixel.
blue = transparencyCellValue( myListRunner, 2 );
440 myTransparentThreeValuePixelList.append( myTransparentPixel );
444 else if ( tableTransparency->columnCount() == 3 )
447 QList<QgsRasterTransparency::TransparentSingleValuePixel> myTransparentSingleValuePixelList;
448 myTransparentSingleValuePixelList.reserve( tableTransparency->rowCount() );
449 for (
int myListRunner = 0; myListRunner < tableTransparency->rowCount(); myListRunner++ )
451 myTransparentPixel.
min = transparencyCellValue( myListRunner, 0 );
452 myTransparentPixel.
max = transparencyCellValue( myListRunner, 1 );
455 myTransparentSingleValuePixelList.append( myTransparentPixel );
463 rasterRenderer->
setOpacity( mOpacityWidget->opacity() );
467 void QgsRasterTransparencyWidget::pixelSelected(
const QgsPointXY &canvasPoint )
476 if ( mMapCanvas && mPixelSelectorTool )
485 int myWidth = mMapCanvas->
extent().
width() / mapUnitsPerPixel;
486 int myHeight = mMapCanvas->
extent().
height() / mapUnitsPerPixel;
490 QList<int> bands = renderer->
usesBands();
492 QList<double> values;
493 for (
int i = 0; i < bands.size(); ++i )
495 int bandNo = bands.value( i );
496 if ( myPixelMap.count( bandNo ) == 1 )
498 if ( myPixelMap.value( bandNo ).isNull() )
502 double value = myPixelMap.value( bandNo ).toDouble();
503 QgsDebugMsg( QStringLiteral(
"value = %1" ).arg( value, 0,
'g', 17 ) );
504 values.append( value );
507 if ( bands.size() == 1 )
510 values.insert( 1, values.value( 0 ) );
512 tableTransparency->insertRow( tableTransparency->rowCount() );
513 for (
int i = 0; i < values.size(); i++ )
515 setTransparencyCell( tableTransparency->rowCount() - 1, i, values.value( i ) );
517 setTransparencyCell( tableTransparency->rowCount() - 1, tableTransparency->columnCount() - 1, 100 );
520 tableTransparency->resizeColumnsToContents();
521 tableTransparency->resizeRowsToContents();
524 void QgsRasterTransparencyWidget::populateTransparencyTable(
QgsRasterRenderer *renderer )
536 int nBands = renderer->
usesBands().size();
537 setupTransparencyTable( nBands );
540 if ( !rasterTransparency )
548 for (
int i = 0; i < pixelList.size(); ++i )
550 tableTransparency->insertRow( i );
551 setTransparencyCell( i, 0, pixelList[i].min );
552 setTransparencyCell( i, 1, pixelList[i].max );
553 setTransparencyCell( i, 2, pixelList[i].percentTransparent );
555 if ( pixelList[i].min != pixelList[i].max )
557 setTransparencyToEdited( i );
561 else if ( nBands == 3 )
564 for (
int i = 0; i < pixelList.size(); ++i )
566 tableTransparency->insertRow( i );
567 setTransparencyCell( i, 0, pixelList[i].red );
568 setTransparencyCell( i, 1, pixelList[i].green );
569 setTransparencyCell( i, 2, pixelList[i].blue );
570 setTransparencyCell( i, 3, pixelList[i].percentTransparent );
574 tableTransparency->resizeColumnsToContents();
575 tableTransparency->resizeRowsToContents();
579 void QgsRasterTransparencyWidget::setupTransparencyTable(
int nBands )
581 tableTransparency->clear();
582 tableTransparency->setColumnCount( 0 );
583 tableTransparency->setRowCount( 0 );
584 mTransparencyToEdited.clear();
588 tableTransparency->setColumnCount( 4 );
589 tableTransparency->setHorizontalHeaderItem( 0,
new QTableWidgetItem( tr(
"Red" ) ) );
590 tableTransparency->setHorizontalHeaderItem( 1,
new QTableWidgetItem( tr(
"Green" ) ) );
591 tableTransparency->setHorizontalHeaderItem( 2,
new QTableWidgetItem( tr(
"Blue" ) ) );
592 tableTransparency->setHorizontalHeaderItem( 3,
new QTableWidgetItem( tr(
"Percent Transparent" ) ) );
596 tableTransparency->setColumnCount( 3 );
599 if ( QgsRasterLayer::PalettedColor != mRasterLayer->drawingStyle() &&
600 QgsRasterLayer::PalettedSingleBandGray != mRasterLayer->drawingStyle() &&
601 QgsRasterLayer::PalettedSingleBandPseudoColor != mRasterLayer->drawingStyle() &&
602 QgsRasterLayer::PalettedMultiBandColor != mRasterLayer->drawingStyle() )
604 tableTransparency->setHorizontalHeaderItem( 0,
new QTableWidgetItem( tr(
"Gray" ) ) );
608 tableTransparency->setHorizontalHeaderItem( 0,
new QTableWidgetItem( tr(
"Indexed Value" ) ) );
611 tableTransparency->setHorizontalHeaderItem( 0,
new QTableWidgetItem( tr(
"From" ) ) );
612 tableTransparency->setHorizontalHeaderItem( 1,
new QTableWidgetItem( tr(
"To" ) ) );
613 tableTransparency->setHorizontalHeaderItem( 2,
new QTableWidgetItem( tr(
"Percent Transparent" ) ) );
617 void QgsRasterTransparencyWidget::setTransparencyCell(
int row,
int column,
double value )
619 QgsDebugMsg( QStringLiteral(
"value = %1" ).arg( value, 0,
'g', 17 ) );
621 if ( !provider )
return;
624 if ( !renderer )
return;
625 int nBands = renderer->
usesBands().size();
627 QLineEdit *lineEdit =
new QLineEdit();
628 lineEdit->setFrame(
false );
630 lineEdit->setContentsMargins( 1, 1, 1, 1 );
632 if ( column == tableTransparency->columnCount() - 1 )
636 lineEdit->setValidator(
new QIntValidator(
nullptr ) );
637 lineEdit->setText( QString::number(
static_cast<int>( value ) ) );
648 if ( !std::isnan( value ) )
651 valueString = QLocale().toString( v );
655 lineEdit->setValidator(
new QIntValidator(
nullptr ) );
656 if ( !std::isnan( value ) )
658 valueString = QString::number(
static_cast<int>( value ) );
662 lineEdit->setText( valueString );
665 tableTransparency->setCellWidget( row, column, lineEdit );
666 adjustTransparencyCellWidth( row, column );
668 if ( nBands == 1 && ( column == 0 || column == 1 ) )
670 connect( lineEdit, &QLineEdit::textEdited,
this, &QgsRasterTransparencyWidget::transparencyCellTextEdited );
672 tableTransparency->resizeColumnsToContents();
676 void QgsRasterTransparencyWidget::adjustTransparencyCellWidth(
int row,
int column )
678 QLineEdit *lineEdit =
dynamic_cast<QLineEdit *
>( tableTransparency->cellWidget( row, column ) );
679 if ( !lineEdit )
return;
681 int width = std::max( lineEdit->fontMetrics().boundingRect( lineEdit->text() ).width() + 10, 100 );
682 width = std::max( width, tableTransparency->columnWidth( column ) );
684 lineEdit->setFixedWidth( width );
687 void QgsRasterTransparencyWidget::setTransparencyToEdited(
int row )
689 if ( row >= mTransparencyToEdited.size() )
691 mTransparencyToEdited.resize( row + 1 );
693 mTransparencyToEdited[row] =
true;
696 double QgsRasterTransparencyWidget::transparencyCellValue(
int row,
int column )
698 QLineEdit *lineEdit =
dynamic_cast<QLineEdit *
>( tableTransparency->cellWidget( row, column ) );
699 if ( !lineEdit || lineEdit->text().isEmpty() )
701 return std::numeric_limits<double>::quiet_NaN();
@ Float32
Thirty two bit floating point (float)
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
@ ARGB32
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
@ Float64
Sixty four bit floating point (double)
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.
void unsetMapTool(QgsMapTool *mapTool)
Unset the current map tool or last non zoom tool.
void setMapTool(QgsMapTool *mapTool, bool clean=false)
Sets the map tool currently being used on the canvas.
double mapUnitsPerPixel() const
Returns the mapUnitsPerPixel (map units per pixel) for the canvas.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
The QgsMapSettings class contains configuration for rendering of the map.
QgsPointXY mapToLayerCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from output CRS to layer's CRS
Renderer for multiband images with the color components.
A class to represent a 2D point.
void bandChanged(int band)
Emitted when the currently selected band changes.
static QString printValue(double value)
Print double value with all necessary significant digits.
Base class for raster data providers.
virtual bool sourceHasNoDataValue(int bandNo) const
Returns true if source band has no data value.
virtual bool useSourceNoDataValue(int bandNo) const
Returns the source nodata value usage.
Qgis::DataType sourceDataType(int bandNo) const override=0
Returns source data type for the band specified by number, source data type may be shorter than dataT...
virtual void setUseSourceNoDataValue(int bandNo, bool use)
Sets the source nodata value usage.
virtual double sourceNoDataValue(int bandNo) const
Value representing no data value.
virtual QgsRasterIdentifyResult identify(const QgsPointXY &point, QgsRaster::IdentifyFormat format, const QgsRectangle &boundingBox=QgsRectangle(), int width=0, int height=0, int dpi=96)
Identify raster value(s) found on the point position.
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
virtual QgsRasterRangeList userNoDataValues(int bandNo) const
Returns a list of user no data value ranges.
virtual void setUserNoDataValue(int bandNo, const QgsRasterRangeList &noData)
QMap< int, QVariant > results() const
Returns the identify results.
Represents a raster layer.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
QgsRasterRenderer * renderer() const
Returns the raster's renderer.
Raster values range container.
Raster renderer pipe that applies colors to a raster.
QColor nodataColor() const
Returns the color to use for shading nodata pixels.
const QgsRasterTransparency * rasterTransparency() const
double opacity() const
Returns the opacity for the renderer, where opacity is a value between 0 (totally transparent) and 1....
void setAlphaBand(int band)
void setOpacity(double opacity)
Sets the opacity for the renderer, where opacity is a value between 0 (totally transparent) and 1....
void setRasterTransparency(QgsRasterTransparency *t)
virtual QList< int > usesBands() const
Returns a list of band numbers used by the renderer.
void setNodataColor(const QColor &color)
Sets the color to use for shading nodata pixels.
Defines the list of pixel values to be considered as transparent or semi transparent when rendering r...
void setTransparentSingleValuePixelList(const QList< QgsRasterTransparency::TransparentSingleValuePixel > &newList)
Sets the transparent single value pixel list, replacing the whole existing list.
QList< QgsRasterTransparency::TransparentThreeValuePixel > transparentThreeValuePixelList() const
Returns the transparent three value pixel list.
void setTransparentThreeValuePixelList(const QList< QgsRasterTransparency::TransparentThreeValuePixel > &newList)
Sets the transparent three value pixel list, replacing the whole existing list.
QList< QgsRasterTransparency::TransparentSingleValuePixel > transparentSingleValuePixelList() const
Returns the transparent single value pixel list.
A rectangle specified with double values.
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QList< QgsRasterRange > QgsRasterRangeList
double percentTransparent
double percentTransparent