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 );
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() );
95 if ( mRasterLayer->dataProvider()->sourceHasNoDataValue( 1 ) )
101 lblSrcNoDataValue->setText( tr(
"not defined" ) );
104 mSrcNoDataValueCheckBox->setChecked( mRasterLayer->dataProvider()->useSourceNoDataValue( 1 ) );
106 bool enableSrcNoData = mRasterLayer->dataProvider()->sourceHasNoDataValue( 1 ) && !std::isnan( mRasterLayer->dataProvider()->sourceNoDataValue( 1 ) );
108 mSrcNoDataValueCheckBox->setEnabled( enableSrcNoData );
109 lblSrcNoDataValue->setEnabled( enableSrcNoData );
114 mNodataColorButton->setColor( renderer->
nodataColor() );
116 mNodataColorButton->setToNull();
119 QgsRasterRangeList noDataRangeList = mRasterLayer->dataProvider()->userNoDataValues( 1 );
120 QgsDebugMsg( QStringLiteral(
"noDataRangeList.size = %1" ).arg( noDataRangeList.size() ) );
121 if ( !noDataRangeList.isEmpty() )
127 leNoDataValue->setText( QString() );
130 populateTransparencyTable( mRasterLayer->renderer() );
133 void QgsRasterTransparencyWidget::transparencyCellTextEdited(
const QString &text )
136 QgsDebugMsg( QStringLiteral(
"text = %1" ).arg( text ) );
142 int nBands = renderer->
usesBands().size();
145 QLineEdit *lineEdit = qobject_cast<QLineEdit *>( sender() );
146 if ( !lineEdit )
return;
149 for (
int r = 0; r < tableTransparency->rowCount(); r++ )
151 for (
int c = 0;
c < tableTransparency->columnCount();
c++ )
153 if ( tableTransparency->cellWidget( r,
c ) == sender() )
160 if ( row != -1 )
break;
162 QgsDebugMsg( QStringLiteral(
"row = %1 column =%2" ).arg( row ).arg( column ) );
166 QLineEdit *toLineEdit =
dynamic_cast<QLineEdit *
>( tableTransparency->cellWidget( row, 1 ) );
167 if ( !toLineEdit )
return;
168 bool toChanged = mTransparencyToEdited.value( row );
169 QgsDebugMsg( QStringLiteral(
"toChanged = %1" ).arg( toChanged ) );
172 toLineEdit->setText( lineEdit->text() );
175 else if ( column == 1 )
177 setTransparencyToEdited( row );
180 emit widgetChanged();
183 void QgsRasterTransparencyWidget::pbnAddValuesFromDisplay_clicked()
185 if ( mMapCanvas && mPixelSelectorTool )
187 mMapCanvas->setMapTool( mPixelSelectorTool );
191 void QgsRasterTransparencyWidget::pbnAddValuesManually_clicked()
199 tableTransparency->insertRow( tableTransparency->rowCount() );
204 for (
int i = 0; i < n; i++ )
206 setTransparencyCell( tableTransparency->rowCount() - 1, i, std::numeric_limits<double>::quiet_NaN() );
209 setTransparencyCell( tableTransparency->rowCount() - 1, n, 100 );
211 tableTransparency->resizeColumnsToContents();
212 tableTransparency->resizeRowsToContents();
215 void QgsRasterTransparencyWidget::pbnDefaultValues_clicked()
225 setupTransparencyTable( nBands );
227 tableTransparency->resizeColumnsToContents();
228 tableTransparency->resizeRowsToContents();
232 void QgsRasterTransparencyWidget::pbnExportTransparentPixelValues_clicked()
235 QString myLastDir = myQSettings.
value( QStringLiteral(
"lastRasterFileFilterDir" ), QDir::homePath() ).toString();
236 QString myFileName = QFileDialog::getSaveFileName(
this, tr(
"Save Pixel Values as File" ), myLastDir, tr(
"Textfile" ) +
" (*.txt)" );
237 if ( !myFileName.isEmpty() )
239 if ( !myFileName.endsWith( QLatin1String(
".txt" ), Qt::CaseInsensitive ) )
241 myFileName = myFileName +
".txt";
244 QFile myOutputFile( myFileName );
245 if ( myOutputFile.open( QFile::WriteOnly | QIODevice::Truncate ) )
247 QTextStream myOutputStream( &myOutputFile );
248 myOutputStream <<
"# " << tr(
"QGIS Generated Transparent Pixel Value Export File" ) <<
'\n';
249 if ( rasterIsMultiBandColor() )
251 myOutputStream <<
"#\n#\n# " << tr(
"Red" ) <<
"\t" << tr(
"Green" ) <<
"\t" << tr(
"Blue" ) <<
"\t" << tr(
"Percent Transparent" );
252 for (
int myTableRunner = 0; myTableRunner < tableTransparency->rowCount(); myTableRunner++ )
254 myOutputStream <<
'\n' << QString::number( transparencyCellValue( myTableRunner, 0 ) ) <<
"\t"
255 << QString::number( transparencyCellValue( myTableRunner, 1 ) ) <<
"\t"
256 << QString::number( transparencyCellValue( myTableRunner, 2 ) ) <<
"\t"
257 << QString::number( transparencyCellValue( myTableRunner, 3 ) );
262 myOutputStream <<
"#\n#\n# " << tr(
"Value" ) <<
"\t" << tr(
"Percent Transparent" );
264 for (
int myTableRunner = 0; myTableRunner < tableTransparency->rowCount(); myTableRunner++ )
266 myOutputStream <<
'\n' << QString::number( transparencyCellValue( myTableRunner, 0 ) ) <<
"\t"
267 << QString::number( transparencyCellValue( myTableRunner, 1 ) ) <<
"\t"
268 << QString::number( transparencyCellValue( myTableRunner, 2 ) );
274 QMessageBox::warning(
this, tr(
"Save Pixel Values as File" ), tr(
"Write access denied. Adjust the file permissions and try again.\n\n" ) );
279 void QgsRasterTransparencyWidget::pbnImportTransparentPixelValues_clicked()
281 int myLineCounter = 0;
282 bool myImportError =
false;
285 QString myLastDir = myQSettings.
value( QStringLiteral(
"lastRasterFileFilterDir" ), QDir::homePath() ).toString();
286 QString myFileName = QFileDialog::getOpenFileName(
this, tr(
"Load Pixel Values from File" ), myLastDir, tr(
"Textfile" ) +
" (*.txt)" );
287 QFile myInputFile( myFileName );
288 if ( myInputFile.open( QFile::ReadOnly ) )
290 QTextStream myInputStream( &myInputFile );
292 if ( rasterIsMultiBandColor() )
294 for (
int myTableRunner = tableTransparency->rowCount() - 1; myTableRunner >= 0; myTableRunner-- )
296 tableTransparency->removeRow( myTableRunner );
299 while ( !myInputStream.atEnd() )
302 myInputLine = myInputStream.readLine();
303 if ( !myInputLine.isEmpty() )
305 if ( !myInputLine.simplified().startsWith(
'#' ) )
307 QStringList myTokens = myInputLine.split( QRegExp(
"\\s+" ), QString::SkipEmptyParts );
308 if ( myTokens.count() != 4 )
310 myImportError =
true;
311 myBadLines = myBadLines + QString::number( myLineCounter ) +
":\t[" + myInputLine +
"]\n";
315 tableTransparency->insertRow( tableTransparency->rowCount() );
316 for (
int col = 0; col < 4; col++ )
318 setTransparencyCell( tableTransparency->rowCount() - 1, col, myTokens[col].toDouble() );
327 for (
int myTableRunner = tableTransparency->rowCount() - 1; myTableRunner >= 0; myTableRunner-- )
329 tableTransparency->removeRow( myTableRunner );
332 while ( !myInputStream.atEnd() )
335 myInputLine = myInputStream.readLine();
336 if ( !myInputLine.isEmpty() )
338 if ( !myInputLine.simplified().startsWith(
'#' ) )
340 QStringList myTokens = myInputLine.split( QRegExp(
"\\s+" ), QString::SkipEmptyParts );
341 if ( myTokens.count() != 3 && myTokens.count() != 2 )
343 myImportError =
true;
344 myBadLines = myBadLines + QString::number( myLineCounter ) +
":\t[" + myInputLine +
"]\n";
348 if ( myTokens.count() == 2 )
350 myTokens.insert( 1, myTokens[0] );
352 tableTransparency->insertRow( tableTransparency->rowCount() );
353 for (
int col = 0; col < 3; col++ )
355 setTransparencyCell( tableTransparency->rowCount() - 1, col, myTokens[col].toDouble() );
365 QMessageBox::warning(
this, tr(
"Load Pixel Values from File" ), tr(
"The following lines contained errors\n\n%1" ).arg( myBadLines ) );
368 else if ( !myFileName.isEmpty() )
370 QMessageBox::warning(
this, tr(
"Load Pixel Values from File" ), tr(
"Read access denied. Adjust the file permissions and try again.\n\n" ) );
372 tableTransparency->resizeColumnsToContents();
373 tableTransparency->resizeRowsToContents();
374 emit widgetChanged();
377 void QgsRasterTransparencyWidget::pbnRemoveSelectedRow_clicked()
379 if ( 0 < tableTransparency->rowCount() )
381 tableTransparency->removeRow( tableTransparency->currentRow() );
383 emit widgetChanged();
386 bool QgsRasterTransparencyWidget::rasterIsMultiBandColor()
395 if (
"" != leNoDataValue->text() )
397 bool myDoubleOk =
false;
398 double myNoDataValue = leNoDataValue->text().toDouble( &myDoubleOk );
402 myNoDataRangeList << myNoDataRange;
405 for (
int bandNo = 1; bandNo <= mRasterLayer->dataProvider()->bandCount(); bandNo++ )
407 mRasterLayer->dataProvider()->setUserNoDataValue( bandNo, myNoDataRangeList );
408 mRasterLayer->dataProvider()->setUseSourceNoDataValue( bandNo, mSrcNoDataValueCheckBox->isChecked() );
413 if ( rasterRenderer )
415 rasterRenderer->
setAlphaBand( cboxTransparencyBand->currentBand() );
420 if ( tableTransparency->columnCount() == 4 )
423 QList<QgsRasterTransparency::TransparentThreeValuePixel> myTransparentThreeValuePixelList;
424 myTransparentThreeValuePixelList.reserve( tableTransparency->rowCount() );
425 for (
int myListRunner = 0; myListRunner < tableTransparency->rowCount(); myListRunner++ )
427 myTransparentPixel.
red = transparencyCellValue( myListRunner, 0 );
428 myTransparentPixel.
green = transparencyCellValue( myListRunner, 1 );
429 myTransparentPixel.
blue = transparencyCellValue( myListRunner, 2 );
431 myTransparentThreeValuePixelList.append( myTransparentPixel );
435 else if ( tableTransparency->columnCount() == 3 )
438 QList<QgsRasterTransparency::TransparentSingleValuePixel> myTransparentSingleValuePixelList;
439 myTransparentSingleValuePixelList.reserve( tableTransparency->rowCount() );
440 for (
int myListRunner = 0; myListRunner < tableTransparency->rowCount(); myListRunner++ )
442 myTransparentPixel.
min = transparencyCellValue( myListRunner, 0 );
443 myTransparentPixel.
max = transparencyCellValue( myListRunner, 1 );
446 myTransparentSingleValuePixelList.append( myTransparentPixel );
454 rasterRenderer->
setOpacity( mOpacityWidget->opacity() );
458 void QgsRasterTransparencyWidget::pixelSelected(
const QgsPointXY &canvasPoint )
467 if ( mMapCanvas && mPixelSelectorTool )
469 mMapCanvas->unsetMapTool( mPixelSelectorTool );
475 double mapUnitsPerPixel = mMapCanvas->mapUnitsPerPixel();
476 int myWidth = mMapCanvas->extent().width() / mapUnitsPerPixel;
477 int myHeight = mMapCanvas->extent().height() / mapUnitsPerPixel;
479 QMap<int, QVariant> myPixelMap = mRasterLayer->dataProvider()->identify( myPoint,
QgsRaster::IdentifyFormatValue, myExtent, myWidth, myHeight ).results();
481 QList<int> bands = renderer->
usesBands();
483 QList<double> values;
484 for (
int i = 0; i < bands.size(); ++i )
486 int bandNo = bands.value( i );
487 if ( myPixelMap.count( bandNo ) == 1 )
489 if ( myPixelMap.value( bandNo ).isNull() )
493 double value = myPixelMap.value( bandNo ).toDouble();
494 QgsDebugMsg( QStringLiteral(
"value = %1" ).arg( value, 0,
'g', 17 ) );
495 values.append( value );
498 if ( bands.size() == 1 )
501 values.insert( 1, values.value( 0 ) );
503 tableTransparency->insertRow( tableTransparency->rowCount() );
504 for (
int i = 0; i < values.size(); i++ )
506 setTransparencyCell( tableTransparency->rowCount() - 1, i, values.value( i ) );
508 setTransparencyCell( tableTransparency->rowCount() - 1, tableTransparency->columnCount() - 1, 100 );
511 tableTransparency->resizeColumnsToContents();
512 tableTransparency->resizeRowsToContents();
515 void QgsRasterTransparencyWidget::populateTransparencyTable(
QgsRasterRenderer *renderer )
527 int nBands = renderer->
usesBands().size();
528 setupTransparencyTable( nBands );
531 if ( !rasterTransparency )
539 for (
int i = 0; i < pixelList.size(); ++i )
541 tableTransparency->insertRow( i );
542 setTransparencyCell( i, 0, pixelList[i].min );
543 setTransparencyCell( i, 1, pixelList[i].max );
544 setTransparencyCell( i, 2, pixelList[i].percentTransparent );
546 if ( pixelList[i].min != pixelList[i].max )
548 setTransparencyToEdited( i );
552 else if ( nBands == 3 )
555 for (
int i = 0; i < pixelList.size(); ++i )
557 tableTransparency->insertRow( i );
558 setTransparencyCell( i, 0, pixelList[i].red );
559 setTransparencyCell( i, 1, pixelList[i].green );
560 setTransparencyCell( i, 2, pixelList[i].blue );
561 setTransparencyCell( i, 3, pixelList[i].percentTransparent );
565 tableTransparency->resizeColumnsToContents();
566 tableTransparency->resizeRowsToContents();
570 void QgsRasterTransparencyWidget::setupTransparencyTable(
int nBands )
572 tableTransparency->clear();
573 tableTransparency->setColumnCount( 0 );
574 tableTransparency->setRowCount( 0 );
575 mTransparencyToEdited.clear();
579 tableTransparency->setColumnCount( 4 );
580 tableTransparency->setHorizontalHeaderItem( 0,
new QTableWidgetItem( tr(
"Red" ) ) );
581 tableTransparency->setHorizontalHeaderItem( 1,
new QTableWidgetItem( tr(
"Green" ) ) );
582 tableTransparency->setHorizontalHeaderItem( 2,
new QTableWidgetItem( tr(
"Blue" ) ) );
583 tableTransparency->setHorizontalHeaderItem( 3,
new QTableWidgetItem( tr(
"Percent Transparent" ) ) );
587 tableTransparency->setColumnCount( 3 );
590 if ( QgsRasterLayer::PalettedColor != mRasterLayer->drawingStyle() &&
591 QgsRasterLayer::PalettedSingleBandGray != mRasterLayer->drawingStyle() &&
592 QgsRasterLayer::PalettedSingleBandPseudoColor != mRasterLayer->drawingStyle() &&
593 QgsRasterLayer::PalettedMultiBandColor != mRasterLayer->drawingStyle() )
595 tableTransparency->setHorizontalHeaderItem( 0,
new QTableWidgetItem( tr(
"Gray" ) ) );
599 tableTransparency->setHorizontalHeaderItem( 0,
new QTableWidgetItem( tr(
"Indexed Value" ) ) );
602 tableTransparency->setHorizontalHeaderItem( 0,
new QTableWidgetItem( tr(
"From" ) ) );
603 tableTransparency->setHorizontalHeaderItem( 1,
new QTableWidgetItem( tr(
"To" ) ) );
604 tableTransparency->setHorizontalHeaderItem( 2,
new QTableWidgetItem( tr(
"Percent Transparent" ) ) );
608 void QgsRasterTransparencyWidget::setTransparencyCell(
int row,
int column,
double value )
610 QgsDebugMsg( QStringLiteral(
"value = %1" ).arg( value, 0,
'g', 17 ) );
612 if ( !provider )
return;
615 if ( !renderer )
return;
616 int nBands = renderer->
usesBands().size();
618 QLineEdit *lineEdit =
new QLineEdit();
619 lineEdit->setFrame(
false );
621 lineEdit->setContentsMargins( 1, 1, 1, 1 );
623 if ( column == tableTransparency->columnCount() - 1 )
627 lineEdit->setValidator(
new QIntValidator(
nullptr ) );
628 lineEdit->setText( QString::number(
static_cast<int>( value ) ) );
638 lineEdit->setValidator(
new QDoubleValidator(
nullptr ) );
639 if ( !std::isnan( value ) )
645 lineEdit->setValidator(
new QIntValidator(
nullptr ) );
646 if ( !std::isnan( value ) )
648 valueString = QString::number(
static_cast<int>( value ) );
652 lineEdit->setText( valueString );
655 tableTransparency->setCellWidget( row, column, lineEdit );
656 adjustTransparencyCellWidth( row, column );
658 if ( nBands == 1 && ( column == 0 || column == 1 ) )
660 connect( lineEdit, &QLineEdit::textEdited,
this, &QgsRasterTransparencyWidget::transparencyCellTextEdited );
662 tableTransparency->resizeColumnsToContents();
663 emit widgetChanged();
666 void QgsRasterTransparencyWidget::adjustTransparencyCellWidth(
int row,
int column )
668 QLineEdit *lineEdit =
dynamic_cast<QLineEdit *
>( tableTransparency->cellWidget( row, column ) );
669 if ( !lineEdit )
return;
671 int width = std::max( lineEdit->fontMetrics().boundingRect( lineEdit->text() ).width() + 10, 100 );
672 width = std::max( width, tableTransparency->columnWidth( column ) );
674 lineEdit->setFixedWidth( width );
677 void QgsRasterTransparencyWidget::setTransparencyToEdited(
int row )
679 if ( row >= mTransparencyToEdited.size() )
681 mTransparencyToEdited.resize( row + 1 );
683 mTransparencyToEdited[row] =
true;
686 double QgsRasterTransparencyWidget::transparencyCellValue(
int row,
int column )
688 QLineEdit *lineEdit =
dynamic_cast<QLineEdit *
>( tableTransparency->cellWidget( row, column ) );
689 if ( !lineEdit || lineEdit->text().isEmpty() )
691 return std::numeric_limits<double>::quiet_NaN();
693 return lineEdit->text().toDouble();