16 #include <QIntValidator>
18 #include <QTextStream>
19 #include <QMessageBox>
20 #include <QFileDialog>
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()
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;
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 QStringList myTokens = myInputLine.split( QRegExp(
"\\s+" ), QString::SkipEmptyParts );
309 if ( myTokens.count() != 4 )
311 myImportError =
true;
312 myBadLines = myBadLines + QString::number( myLineCounter ) +
":\t[" + myInputLine +
"]\n";
316 tableTransparency->insertRow( tableTransparency->rowCount() );
317 for (
int col = 0; col < 4; col++ )
319 setTransparencyCell( tableTransparency->rowCount() - 1, col, myTokens[col].toDouble() );
328 for (
int myTableRunner = tableTransparency->rowCount() - 1; myTableRunner >= 0; myTableRunner-- )
330 tableTransparency->removeRow( myTableRunner );
333 while ( !myInputStream.atEnd() )
336 myInputLine = myInputStream.readLine();
337 if ( !myInputLine.isEmpty() )
339 if ( !myInputLine.simplified().startsWith(
'#' ) )
341 QStringList myTokens = myInputLine.split( QRegExp(
"\\s+" ), QString::SkipEmptyParts );
342 if ( myTokens.count() != 3 && myTokens.count() != 2 )
344 myImportError =
true;
345 myBadLines = myBadLines + QString::number( myLineCounter ) +
":\t[" + myInputLine +
"]\n";
349 if ( myTokens.count() == 2 )
351 myTokens.insert( 1, myTokens[0] );
353 tableTransparency->insertRow( tableTransparency->rowCount() );
354 for (
int col = 0; col < 3; col++ )
356 setTransparencyCell( tableTransparency->rowCount() - 1, col, myTokens[col].toDouble() );
366 QMessageBox::warning(
this, tr(
"Load Pixel Values from File" ), tr(
"The following lines contained errors\n\n%1" ).arg( myBadLines ) );
369 else if ( !myFileName.isEmpty() )
371 QMessageBox::warning(
this, tr(
"Load Pixel Values from File" ), tr(
"Read access denied. Adjust the file permissions and try again.\n\n" ) );
373 tableTransparency->resizeColumnsToContents();
374 tableTransparency->resizeRowsToContents();
378 void QgsRasterTransparencyWidget::pbnRemoveSelectedRow_clicked()
380 if ( 0 < tableTransparency->rowCount() )
382 tableTransparency->removeRow( tableTransparency->currentRow() );
387 bool QgsRasterTransparencyWidget::rasterIsMultiBandColor()
396 if (
"" != leNoDataValue->text() )
398 bool myDoubleOk =
false;
403 myNoDataRangeList << myNoDataRange;
406 for (
int bandNo = 1; bandNo <= mRasterLayer->
dataProvider()->bandCount(); bandNo++ )
414 if ( rasterRenderer )
416 rasterRenderer->
setAlphaBand( cboxTransparencyBand->currentBand() );
421 if ( tableTransparency->columnCount() == 4 )
424 QList<QgsRasterTransparency::TransparentThreeValuePixel> myTransparentThreeValuePixelList;
425 myTransparentThreeValuePixelList.reserve( tableTransparency->rowCount() );
426 for (
int myListRunner = 0; myListRunner < tableTransparency->rowCount(); myListRunner++ )
428 myTransparentPixel.
red = transparencyCellValue( myListRunner, 0 );
429 myTransparentPixel.
green = transparencyCellValue( myListRunner, 1 );
430 myTransparentPixel.
blue = transparencyCellValue( myListRunner, 2 );
432 myTransparentThreeValuePixelList.append( myTransparentPixel );
436 else if ( tableTransparency->columnCount() == 3 )
439 QList<QgsRasterTransparency::TransparentSingleValuePixel> myTransparentSingleValuePixelList;
440 myTransparentSingleValuePixelList.reserve( tableTransparency->rowCount() );
441 for (
int myListRunner = 0; myListRunner < tableTransparency->rowCount(); myListRunner++ )
443 myTransparentPixel.
min = transparencyCellValue( myListRunner, 0 );
444 myTransparentPixel.
max = transparencyCellValue( myListRunner, 1 );
447 myTransparentSingleValuePixelList.append( myTransparentPixel );
455 rasterRenderer->
setOpacity( mOpacityWidget->opacity() );
459 void QgsRasterTransparencyWidget::pixelSelected(
const QgsPointXY &canvasPoint )
468 if ( mMapCanvas && mPixelSelectorTool )
477 int myWidth = mMapCanvas->
extent().
width() / mapUnitsPerPixel;
478 int myHeight = mMapCanvas->
extent().
height() / mapUnitsPerPixel;
482 QList<int> bands = renderer->
usesBands();
484 QList<double> values;
485 for (
int i = 0; i < bands.size(); ++i )
487 int bandNo = bands.value( i );
488 if ( myPixelMap.count( bandNo ) == 1 )
490 if ( myPixelMap.value( bandNo ).isNull() )
494 double value = myPixelMap.value( bandNo ).toDouble();
495 QgsDebugMsg( QStringLiteral(
"value = %1" ).arg( value, 0,
'g', 17 ) );
496 values.append( value );
499 if ( bands.size() == 1 )
502 values.insert( 1, values.value( 0 ) );
504 tableTransparency->insertRow( tableTransparency->rowCount() );
505 for (
int i = 0; i < values.size(); i++ )
507 setTransparencyCell( tableTransparency->rowCount() - 1, i, values.value( i ) );
509 setTransparencyCell( tableTransparency->rowCount() - 1, tableTransparency->columnCount() - 1, 100 );
512 tableTransparency->resizeColumnsToContents();
513 tableTransparency->resizeRowsToContents();
516 void QgsRasterTransparencyWidget::populateTransparencyTable(
QgsRasterRenderer *renderer )
528 int nBands = renderer->
usesBands().size();
529 setupTransparencyTable( nBands );
532 if ( !rasterTransparency )
540 for (
int i = 0; i < pixelList.size(); ++i )
542 tableTransparency->insertRow( i );
543 setTransparencyCell( i, 0, pixelList[i].min );
544 setTransparencyCell( i, 1, pixelList[i].max );
545 setTransparencyCell( i, 2, pixelList[i].percentTransparent );
547 if ( pixelList[i].min != pixelList[i].max )
549 setTransparencyToEdited( i );
553 else if ( nBands == 3 )
556 for (
int i = 0; i < pixelList.size(); ++i )
558 tableTransparency->insertRow( i );
559 setTransparencyCell( i, 0, pixelList[i].red );
560 setTransparencyCell( i, 1, pixelList[i].green );
561 setTransparencyCell( i, 2, pixelList[i].blue );
562 setTransparencyCell( i, 3, pixelList[i].percentTransparent );
566 tableTransparency->resizeColumnsToContents();
567 tableTransparency->resizeRowsToContents();
571 void QgsRasterTransparencyWidget::setupTransparencyTable(
int nBands )
573 tableTransparency->clear();
574 tableTransparency->setColumnCount( 0 );
575 tableTransparency->setRowCount( 0 );
576 mTransparencyToEdited.clear();
580 tableTransparency->setColumnCount( 4 );
581 tableTransparency->setHorizontalHeaderItem( 0,
new QTableWidgetItem( tr(
"Red" ) ) );
582 tableTransparency->setHorizontalHeaderItem( 1,
new QTableWidgetItem( tr(
"Green" ) ) );
583 tableTransparency->setHorizontalHeaderItem( 2,
new QTableWidgetItem( tr(
"Blue" ) ) );
584 tableTransparency->setHorizontalHeaderItem( 3,
new QTableWidgetItem( tr(
"Percent Transparent" ) ) );
588 tableTransparency->setColumnCount( 3 );
591 if ( QgsRasterLayer::PalettedColor != mRasterLayer->drawingStyle() &&
592 QgsRasterLayer::PalettedSingleBandGray != mRasterLayer->drawingStyle() &&
593 QgsRasterLayer::PalettedSingleBandPseudoColor != mRasterLayer->drawingStyle() &&
594 QgsRasterLayer::PalettedMultiBandColor != mRasterLayer->drawingStyle() )
596 tableTransparency->setHorizontalHeaderItem( 0,
new QTableWidgetItem( tr(
"Gray" ) ) );
600 tableTransparency->setHorizontalHeaderItem( 0,
new QTableWidgetItem( tr(
"Indexed Value" ) ) );
603 tableTransparency->setHorizontalHeaderItem( 0,
new QTableWidgetItem( tr(
"From" ) ) );
604 tableTransparency->setHorizontalHeaderItem( 1,
new QTableWidgetItem( tr(
"To" ) ) );
605 tableTransparency->setHorizontalHeaderItem( 2,
new QTableWidgetItem( tr(
"Percent Transparent" ) ) );
609 void QgsRasterTransparencyWidget::setTransparencyCell(
int row,
int column,
double value )
611 QgsDebugMsg( QStringLiteral(
"value = %1" ).arg( value, 0,
'g', 17 ) );
613 if ( !provider )
return;
616 if ( !renderer )
return;
617 int nBands = renderer->
usesBands().size();
619 QLineEdit *lineEdit =
new QLineEdit();
620 lineEdit->setFrame(
false );
622 lineEdit->setContentsMargins( 1, 1, 1, 1 );
624 if ( column == tableTransparency->columnCount() - 1 )
628 lineEdit->setValidator(
new QIntValidator(
nullptr ) );
629 lineEdit->setText( QString::number(
static_cast<int>( value ) ) );
640 if ( !std::isnan( value ) )
643 valueString = QLocale().toString( v );
647 lineEdit->setValidator(
new QIntValidator(
nullptr ) );
648 if ( !std::isnan( value ) )
650 valueString = QString::number(
static_cast<int>( value ) );
654 lineEdit->setText( valueString );
657 tableTransparency->setCellWidget( row, column, lineEdit );
658 adjustTransparencyCellWidth( row, column );
660 if ( nBands == 1 && ( column == 0 || column == 1 ) )
662 connect( lineEdit, &QLineEdit::textEdited,
this, &QgsRasterTransparencyWidget::transparencyCellTextEdited );
664 tableTransparency->resizeColumnsToContents();
668 void QgsRasterTransparencyWidget::adjustTransparencyCellWidth(
int row,
int column )
670 QLineEdit *lineEdit =
dynamic_cast<QLineEdit *
>( tableTransparency->cellWidget( row, column ) );
671 if ( !lineEdit )
return;
673 int width = std::max( lineEdit->fontMetrics().boundingRect( lineEdit->text() ).width() + 10, 100 );
674 width = std::max( width, tableTransparency->columnWidth( column ) );
676 lineEdit->setFixedWidth( width );
679 void QgsRasterTransparencyWidget::setTransparencyToEdited(
int row )
681 if ( row >= mTransparencyToEdited.size() )
683 mTransparencyToEdited.resize( row + 1 );
685 mTransparencyToEdited[row] =
true;
688 double QgsRasterTransparencyWidget::transparencyCellValue(
int row,
int column )
690 QLineEdit *lineEdit =
dynamic_cast<QLineEdit *
>( tableTransparency->cellWidget( row, column ) );
691 if ( !lineEdit || lineEdit->text().isEmpty() )
693 return std::numeric_limits<double>::quiet_NaN();
@ Float32
Thirty two bit floating point (float)
@ Float64
Sixty four bit floating point (double)
@ 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.
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.
This class is a composition of two QSettings instances:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
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