16 #include <QDoubleValidator> 17 #include <QIntValidator> 19 #include <QTextStream> 20 #include <QMessageBox> 21 #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 );
59 mPixelSelectorTool =
nullptr;
67 pbnAddValuesFromDisplay->setEnabled(
false );
80 gboxNoDataValue->setEnabled(
false );
81 gboxCustomTransparency->setEnabled(
false );
84 cboxTransparencyBand->setShowNotSetOption(
true, tr(
"None" ) );
85 cboxTransparencyBand->setLayer( mRasterLayer );
89 cboxTransparencyBand->setBand( renderer->
alphaBand() );
98 lblSrcNoDataValue->setText( tr(
"not defined" ) );
105 mSrcNoDataValueCheckBox->setEnabled( enableSrcNoData );
106 lblSrcNoDataValue->setEnabled( enableSrcNoData );
109 QgsDebugMsg( QString(
"noDataRangeList.size = %1" ).arg( noDataRangeList.size() ) );
110 if ( !noDataRangeList.isEmpty() )
116 leNoDataValue->insert( QLatin1String(
"" ) );
119 populateTransparencyTable( mRasterLayer->
renderer() );
122 void QgsRasterTransparencyWidget::transparencyCellTextEdited(
const QString &text )
131 int nBands = renderer->
usesBands().size();
134 QLineEdit *lineEdit =
dynamic_cast<QLineEdit *
>( sender() );
135 if ( !lineEdit )
return;
138 for (
int r = 0; r < tableTransparency->rowCount(); r++ )
140 for (
int c = 0; c < tableTransparency->columnCount(); c++ )
142 if ( tableTransparency->cellWidget( r, c ) == sender() )
149 if ( row != -1 )
break;
151 QgsDebugMsg( QString(
"row = %1 column =%2" ).arg( row ).arg( column ) );
155 QLineEdit *toLineEdit =
dynamic_cast<QLineEdit *
>( tableTransparency->cellWidget( row, 1 ) );
156 if ( !toLineEdit )
return;
157 bool toChanged = mTransparencyToEdited.value( row );
158 QgsDebugMsg( QString(
"toChanged = %1" ).arg( toChanged ) );
161 toLineEdit->setText( lineEdit->text() );
164 else if ( column == 1 )
166 setTransparencyToEdited( row );
172 void QgsRasterTransparencyWidget::pbnAddValuesFromDisplay_clicked()
174 if ( mMapCanvas && mPixelSelectorTool )
180 void QgsRasterTransparencyWidget::pbnAddValuesManually_clicked()
188 tableTransparency->insertRow( tableTransparency->rowCount() );
193 for (
int i = 0; i < n; i++ )
195 setTransparencyCell( tableTransparency->rowCount() - 1, i, std::numeric_limits<double>::quiet_NaN() );
198 setTransparencyCell( tableTransparency->rowCount() - 1, n, 100 );
200 tableTransparency->resizeColumnsToContents();
201 tableTransparency->resizeRowsToContents();
204 void QgsRasterTransparencyWidget::pbnDefaultValues_clicked()
214 setupTransparencyTable( nBands );
216 tableTransparency->resizeColumnsToContents();
217 tableTransparency->resizeRowsToContents();
221 void QgsRasterTransparencyWidget::pbnExportTransparentPixelValues_clicked()
224 QString myLastDir = myQSettings.
value( QStringLiteral(
"lastRasterFileFilterDir" ), QDir::homePath() ).toString();
225 QString myFileName = QFileDialog::getSaveFileName(
this, tr(
"Save Pixel Values as File" ), myLastDir, tr(
"Textfile" ) +
" (*.txt)" );
226 if ( !myFileName.isEmpty() )
228 if ( !myFileName.endsWith( QLatin1String(
".txt" ), Qt::CaseInsensitive ) )
230 myFileName = myFileName +
".txt";
233 QFile myOutputFile( myFileName );
234 if ( myOutputFile.open( QFile::WriteOnly | QIODevice::Truncate ) )
236 QTextStream myOutputStream( &myOutputFile );
237 myOutputStream <<
"# " << tr(
"QGIS Generated Transparent Pixel Value Export File" ) <<
'\n';
238 if ( rasterIsMultiBandColor() )
240 myOutputStream <<
"#\n#\n# " << tr(
"Red" ) <<
"\t" << tr(
"Green" ) <<
"\t" << tr(
"Blue" ) <<
"\t" << tr(
"Percent Transparent" );
241 for (
int myTableRunner = 0; myTableRunner < tableTransparency->rowCount(); myTableRunner++ )
243 myOutputStream <<
'\n' << QString::number( transparencyCellValue( myTableRunner, 0 ) ) <<
"\t" 244 << QString::number( transparencyCellValue( myTableRunner, 1 ) ) <<
"\t" 245 << QString::number( transparencyCellValue( myTableRunner, 2 ) ) <<
"\t" 246 << QString::number( transparencyCellValue( myTableRunner, 3 ) );
251 myOutputStream <<
"#\n#\n# " << tr(
"Value" ) <<
"\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 ) );
263 QMessageBox::warning(
this, tr(
"Save Pixel Values as File" ), tr(
"Write access denied. Adjust the file permissions and try again.\n\n" ) );
268 void QgsRasterTransparencyWidget::pbnImportTransparentPixelValues_clicked()
270 int myLineCounter = 0;
271 bool myImportError =
false;
274 QString myLastDir = myQSettings.
value( QStringLiteral(
"lastRasterFileFilterDir" ), QDir::homePath() ).toString();
275 QString myFileName = QFileDialog::getOpenFileName(
this, tr(
"Load Pixel Values from File" ), myLastDir, tr(
"Textfile" ) +
" (*.txt)" );
276 QFile myInputFile( myFileName );
277 if ( myInputFile.open( QFile::ReadOnly ) )
279 QTextStream myInputStream( &myInputFile );
281 if ( rasterIsMultiBandColor() )
283 for (
int myTableRunner = tableTransparency->rowCount() - 1; myTableRunner >= 0; myTableRunner-- )
285 tableTransparency->removeRow( myTableRunner );
288 while ( !myInputStream.atEnd() )
291 myInputLine = myInputStream.readLine();
292 if ( !myInputLine.isEmpty() )
294 if ( !myInputLine.simplified().startsWith(
'#' ) )
296 QStringList myTokens = myInputLine.split( QRegExp(
"\\s+" ), QString::SkipEmptyParts );
297 if ( myTokens.count() != 4 )
299 myImportError =
true;
300 myBadLines = myBadLines + QString::number( myLineCounter ) +
":\t[" + myInputLine +
"]\n";
304 tableTransparency->insertRow( tableTransparency->rowCount() );
305 for (
int col = 0; col < 4; col++ )
307 setTransparencyCell( tableTransparency->rowCount() - 1, col, myTokens[col].toDouble() );
316 for (
int myTableRunner = tableTransparency->rowCount() - 1; myTableRunner >= 0; myTableRunner-- )
318 tableTransparency->removeRow( myTableRunner );
321 while ( !myInputStream.atEnd() )
324 myInputLine = myInputStream.readLine();
325 if ( !myInputLine.isEmpty() )
327 if ( !myInputLine.simplified().startsWith(
'#' ) )
329 QStringList myTokens = myInputLine.split( QRegExp(
"\\s+" ), QString::SkipEmptyParts );
330 if ( myTokens.count() != 3 && myTokens.count() != 2 )
332 myImportError =
true;
333 myBadLines = myBadLines + QString::number( myLineCounter ) +
":\t[" + myInputLine +
"]\n";
337 if ( myTokens.count() == 2 )
339 myTokens.insert( 1, myTokens[0] );
341 tableTransparency->insertRow( tableTransparency->rowCount() );
342 for (
int col = 0; col < 3; col++ )
344 setTransparencyCell( tableTransparency->rowCount() - 1, col, myTokens[col].toDouble() );
354 QMessageBox::warning(
this, tr(
"Load Pixel Values from File" ), tr(
"The following lines contained errors\n\n%1" ).arg( myBadLines ) );
357 else if ( !myFileName.isEmpty() )
359 QMessageBox::warning(
this, tr(
"Load Pixel Values from File" ), tr(
"Read access denied. Adjust the file permissions and try again.\n\n" ) );
361 tableTransparency->resizeColumnsToContents();
362 tableTransparency->resizeRowsToContents();
366 void QgsRasterTransparencyWidget::pbnRemoveSelectedRow_clicked()
368 if ( 0 < tableTransparency->rowCount() )
370 tableTransparency->removeRow( tableTransparency->currentRow() );
375 bool QgsRasterTransparencyWidget::rasterIsMultiBandColor()
384 if (
"" != leNoDataValue->text() )
386 bool myDoubleOk =
false;
387 double myNoDataValue = leNoDataValue->text().toDouble( &myDoubleOk );
391 myNoDataRangeList << myNoDataRange;
402 if ( rasterRenderer )
404 rasterRenderer->
setAlphaBand( cboxTransparencyBand->currentBand() );
408 if ( tableTransparency->columnCount() == 4 )
411 QList<QgsRasterTransparency::TransparentThreeValuePixel> myTransparentThreeValuePixelList;
412 myTransparentThreeValuePixelList.reserve( tableTransparency->rowCount() );
413 for (
int myListRunner = 0; myListRunner < tableTransparency->rowCount(); myListRunner++ )
415 myTransparentPixel.
red = transparencyCellValue( myListRunner, 0 );
416 myTransparentPixel.
green = transparencyCellValue( myListRunner, 1 );
417 myTransparentPixel.
blue = transparencyCellValue( myListRunner, 2 );
419 myTransparentThreeValuePixelList.append( myTransparentPixel );
423 else if ( tableTransparency->columnCount() == 3 )
426 QList<QgsRasterTransparency::TransparentSingleValuePixel> myTransparentSingleValuePixelList;
427 myTransparentSingleValuePixelList.reserve( tableTransparency->rowCount() );
428 for (
int myListRunner = 0; myListRunner < tableTransparency->rowCount(); myListRunner++ )
430 myTransparentPixel.
min = transparencyCellValue( myListRunner, 0 );
431 myTransparentPixel.
max = transparencyCellValue( myListRunner, 1 );
434 myTransparentSingleValuePixelList.append( myTransparentPixel );
442 rasterRenderer->
setOpacity( mOpacityWidget->opacity() );
446 void QgsRasterTransparencyWidget::pixelSelected(
const QgsPointXY &canvasPoint )
455 if ( mMapCanvas && mPixelSelectorTool )
464 int myWidth = mMapCanvas->
extent().
width() / mapUnitsPerPixel;
465 int myHeight = mMapCanvas->
extent().
height() / mapUnitsPerPixel;
469 QList<int> bands = renderer->
usesBands();
471 QList<double> values;
472 for (
int i = 0; i < bands.size(); ++i )
474 int bandNo = bands.value( i );
475 if ( myPixelMap.count( bandNo ) == 1 )
477 if ( myPixelMap.value( bandNo ).isNull() )
481 double value = myPixelMap.value( bandNo ).toDouble();
482 QgsDebugMsg( QString(
"value = %1" ).arg( value, 0,
'g', 17 ) );
483 values.append( value );
486 if ( bands.size() == 1 )
489 values.insert( 1, values.value( 0 ) );
491 tableTransparency->insertRow( tableTransparency->rowCount() );
492 for (
int i = 0; i < values.size(); i++ )
494 setTransparencyCell( tableTransparency->rowCount() - 1, i, values.value( i ) );
496 setTransparencyCell( tableTransparency->rowCount() - 1, tableTransparency->columnCount() - 1, 100 );
499 tableTransparency->resizeColumnsToContents();
500 tableTransparency->resizeRowsToContents();
503 void QgsRasterTransparencyWidget::populateTransparencyTable(
QgsRasterRenderer *renderer )
515 int nBands = renderer->
usesBands().size();
516 setupTransparencyTable( nBands );
519 if ( !rasterTransparency )
527 for (
int i = 0; i < pixelList.size(); ++i )
529 tableTransparency->insertRow( i );
530 setTransparencyCell( i, 0, pixelList[i].min );
531 setTransparencyCell( i, 1, pixelList[i].max );
532 setTransparencyCell( i, 2, pixelList[i].percentTransparent );
534 if ( pixelList[i].min != pixelList[i].max )
536 setTransparencyToEdited( i );
540 else if ( nBands == 3 )
543 for (
int i = 0; i < pixelList.size(); ++i )
545 tableTransparency->insertRow( i );
546 setTransparencyCell( i, 0, pixelList[i].red );
547 setTransparencyCell( i, 1, pixelList[i].green );
548 setTransparencyCell( i, 2, pixelList[i].blue );
549 setTransparencyCell( i, 3, pixelList[i].percentTransparent );
553 tableTransparency->resizeColumnsToContents();
554 tableTransparency->resizeRowsToContents();
558 void QgsRasterTransparencyWidget::setupTransparencyTable(
int nBands )
560 tableTransparency->clear();
561 tableTransparency->setColumnCount( 0 );
562 tableTransparency->setRowCount( 0 );
563 mTransparencyToEdited.clear();
567 tableTransparency->setColumnCount( 4 );
568 tableTransparency->setHorizontalHeaderItem( 0,
new QTableWidgetItem( tr(
"Red" ) ) );
569 tableTransparency->setHorizontalHeaderItem( 1,
new QTableWidgetItem( tr(
"Green" ) ) );
570 tableTransparency->setHorizontalHeaderItem( 2,
new QTableWidgetItem( tr(
"Blue" ) ) );
571 tableTransparency->setHorizontalHeaderItem( 3,
new QTableWidgetItem( tr(
"Percent Transparent" ) ) );
575 tableTransparency->setColumnCount( 3 );
578 if ( QgsRasterLayer::PalettedColor != mRasterLayer->drawingStyle() &&
579 QgsRasterLayer::PalettedSingleBandGray != mRasterLayer->drawingStyle() &&
580 QgsRasterLayer::PalettedSingleBandPseudoColor != mRasterLayer->drawingStyle() &&
581 QgsRasterLayer::PalettedMultiBandColor != mRasterLayer->drawingStyle() )
583 tableTransparency->setHorizontalHeaderItem( 0,
new QTableWidgetItem( tr(
"Gray" ) ) );
587 tableTransparency->setHorizontalHeaderItem( 0,
new QTableWidgetItem( tr(
"Indexed Value" ) ) );
590 tableTransparency->setHorizontalHeaderItem( 0,
new QTableWidgetItem( tr(
"From" ) ) );
591 tableTransparency->setHorizontalHeaderItem( 1,
new QTableWidgetItem( tr(
"To" ) ) );
592 tableTransparency->setHorizontalHeaderItem( 2,
new QTableWidgetItem( tr(
"Percent Transparent" ) ) );
596 void QgsRasterTransparencyWidget::setTransparencyCell(
int row,
int column,
double value )
598 QgsDebugMsg( QString(
"value = %1" ).arg( value, 0,
'g', 17 ) );
600 if ( !provider )
return;
603 if ( !renderer )
return;
604 int nBands = renderer->
usesBands().size();
606 QLineEdit *lineEdit =
new QLineEdit();
607 lineEdit->setFrame(
false );
609 lineEdit->setContentsMargins( 1, 1, 1, 1 );
611 if ( column == tableTransparency->columnCount() - 1 )
615 lineEdit->setValidator(
new QIntValidator(
nullptr ) );
616 lineEdit->setText( QString::number( static_cast<int>( value ) ) );
626 lineEdit->setValidator(
new QDoubleValidator(
nullptr ) );
627 if ( !std::isnan( value ) )
633 lineEdit->setValidator(
new QIntValidator(
nullptr ) );
634 if ( !std::isnan( value ) )
636 valueString = QString::number( static_cast<int>( value ) );
640 lineEdit->setText( valueString );
643 tableTransparency->setCellWidget( row, column, lineEdit );
644 adjustTransparencyCellWidth( row, column );
646 if ( nBands == 1 && ( column == 0 || column == 1 ) )
648 connect( lineEdit, &QLineEdit::textEdited,
this, &QgsRasterTransparencyWidget::transparencyCellTextEdited );
650 tableTransparency->resizeColumnsToContents();
654 void QgsRasterTransparencyWidget::adjustTransparencyCellWidth(
int row,
int column )
656 QLineEdit *lineEdit =
dynamic_cast<QLineEdit *
>( tableTransparency->cellWidget( row, column ) );
657 if ( !lineEdit )
return;
659 int width = std::max( lineEdit->fontMetrics().width( lineEdit->text() ) + 10, 100 );
660 width = std::max( width, tableTransparency->columnWidth( column ) );
662 lineEdit->setFixedWidth( width );
665 void QgsRasterTransparencyWidget::setTransparencyToEdited(
int row )
667 if ( row >= mTransparencyToEdited.size() )
669 mTransparencyToEdited.resize( row + 1 );
671 mTransparencyToEdited[row] =
true;
674 double QgsRasterTransparencyWidget::transparencyCellValue(
int row,
int column )
676 QLineEdit *lineEdit =
dynamic_cast<QLineEdit *
>( tableTransparency->cellWidget( row, column ) );
677 if ( !lineEdit || lineEdit->text().isEmpty() )
679 std::numeric_limits<double>::quiet_NaN();
681 return lineEdit->text().toDouble();
void unsetMapTool(QgsMapTool *mapTool)
Unset the current map tool or last non zoom tool.
virtual int bandCount() const =0
Get number of bands.
A rectangle specified with double values.
static QString printValue(double value)
Print double value with all necessary significant digits.
virtual void setUseSourceNoDataValue(int bandNo, bool use)
Set source nodata value usage.
void setTransparentThreeValuePixelList(const QList< QgsRasterTransparency::TransparentThreeValuePixel > &newList)
Mutator for transparentThreeValuePixelList.
This class is a composition of two QSettings instances:
virtual QList< int > usesBands() const
Returns a list of band numbers used by the renderer.
double opacity() const
Returns the opacity for the renderer, where opacity is a value between 0 (totally transparent) and 1...
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
A class to represent a 2D point.
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...
Raster values range container.
QgsRasterRenderer * renderer() const
Thirty two bit floating point (float)
virtual double sourceNoDataValue(int bandNo) const
Value representing no data value.
Map canvas is a class for displaying all GIS data types on a canvas.
const QgsRasterTransparency * rasterTransparency() const
Sixty four bit floating point (double)
The QgsMapSettings class contains configuration for rendering of the map.
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
QgsRasterDataProvider * dataProvider() override
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.
double percentTransparent
double width() const
Returns the width of the rectangle.
void bandChanged(int band)
This signal is emitted when the currently selected band changes.
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
void setAlphaBand(int band)
virtual bool sourceHasNoDataValue(int bandNo) const
Return true if source band has no data value.
QList< QgsRasterTransparency::TransparentSingleValuePixel > transparentSingleValuePixelList() const
Accessor for transparentSingleValuePixelList.
QMap< int, QVariant > results() const
Get results.
void setTransparentSingleValuePixelList(const QList< QgsRasterTransparency::TransparentSingleValuePixel > &newList)
Mutator for transparentSingleValuePixelList.
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
QList< QgsRasterRange > QgsRasterRangeList
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=NoSection) const
Returns the value for setting key.
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.
Renderer for multiband images with the color components.
virtual QgsRasterRangeList userNoDataValues(int bandNo) const
Get list of user no data value ranges.
Defines the list of pixel values to be considered as transparent or semi transparent when rendering r...
void setOpacity(double opacity)
Sets the opacity for the renderer, where opacity is a value between 0 (totally transparent) and 1...
virtual bool useSourceNoDataValue(int bandNo) const
Get source nodata value usage.
QList< QgsRasterTransparency::TransparentThreeValuePixel > transparentThreeValuePixelList() const
Accessor for transparentThreeValuePixelList.
virtual void setUserNoDataValue(int bandNo, const QgsRasterRangeList &noData)
QgsPointXY mapToLayerCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from output CRS to layer's CRS
void setRasterTransparency(QgsRasterTransparency *t)
double percentTransparent
Raster renderer pipe that applies colors to a raster.
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
double height() const
Returns the height of the rectangle.
Base class for raster data providers.