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() );
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() )
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 );
181 emit widgetChanged();
184 void QgsRasterTransparencyWidget::pbnAddValuesFromDisplay_clicked()
186 if ( mMapCanvas && mPixelSelectorTool )
188 mMapCanvas->setMapTool( 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();
375 emit widgetChanged();
378 void QgsRasterTransparencyWidget::pbnRemoveSelectedRow_clicked()
380 if ( 0 < tableTransparency->rowCount() )
382 tableTransparency->removeRow( tableTransparency->currentRow() );
384 emit widgetChanged();
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++ )
408 mRasterLayer->dataProvider()->setUserNoDataValue( bandNo, myNoDataRangeList );
409 mRasterLayer->dataProvider()->setUseSourceNoDataValue( bandNo, mSrcNoDataValueCheckBox->isChecked() );
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 )
470 mMapCanvas->unsetMapTool( mPixelSelectorTool );
476 double mapUnitsPerPixel = mMapCanvas->mapUnitsPerPixel();
477 int myWidth = mMapCanvas->extent().width() / mapUnitsPerPixel;
478 int myHeight = mMapCanvas->extent().height() / mapUnitsPerPixel;
480 QMap<int, QVariant> myPixelMap = mRasterLayer->dataProvider()->identify( myPoint,
QgsRaster::IdentifyFormatValue, myExtent, myWidth, myHeight ).results();
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();
665 emit widgetChanged();
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();