QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsrastertransparencywidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrastertransparencywidget.cpp
3  ---------------------
4  begin : May 2016
5  copyright : (C) 2016 by Nathan Woodrow
6  email : woodrow dot nathan at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 #include <QWidget>
16 #include <QIntValidator>
17 #include <QFile>
18 #include <QTextStream>
19 #include <QMessageBox>
20 #include <QFileDialog>
21 
22 #include "qgssettings.h"
24 #include "qgsrasterlayer.h"
25 #include "qgsraster.h"
26 #include "qgsrasterlayerrenderer.h"
27 #include "qgsrasterdataprovider.h"
28 #include "qgsrastertransparency.h"
29 #include "qgsmaptoolemitpoint.h"
30 #include "qgsmapsettings.h"
31 #include "qgsrectangle.h"
32 #include "qgsmapcanvas.h"
35 #include "qgsdoublevalidator.h"
36 
37 
39  : QgsMapLayerConfigWidget( layer, canvas, parent )
40  , TRSTRING_NOT_SET( tr( "Not Set" ) )
41  , mRasterLayer( layer )
42  , mMapCanvas( canvas )
43 {
44  setupUi( this );
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 );
51 
52  mNodataColorButton->setShowNoColor( true );
53  mNodataColorButton->setColorDialogTitle( tr( "Select No Data Color" ) );
54  syncToLayer();
55 
56  connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsPanelWidget::widgetChanged );
57  connect( cboxTransparencyBand, &QgsRasterBandComboBox::bandChanged, this, &QgsPanelWidget::widgetChanged );
58  connect( mSrcNoDataValueCheckBox, &QCheckBox::stateChanged, this, &QgsPanelWidget::widgetChanged );
59  connect( leNoDataValue, &QLineEdit::textEdited, this, &QgsPanelWidget::widgetChanged );
60  connect( mNodataColorButton, &QgsColorButton::colorChanged, this, &QgsPanelWidget::widgetChanged );
61 
62  mPixelSelectorTool = nullptr;
63  if ( mMapCanvas )
64  {
65  mPixelSelectorTool = new QgsMapToolEmitPoint( mMapCanvas );
66  connect( mPixelSelectorTool, &QgsMapToolEmitPoint::canvasClicked, this, &QgsRasterTransparencyWidget::pixelSelected );
67  }
68  else
69  {
70  pbnAddValuesFromDisplay->setEnabled( false );
71  }
72 }
73 
75 {
76  QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
77  QgsRasterRenderer *renderer = mRasterLayer->renderer();
78  if ( provider )
79  {
80  if ( provider->dataType( 1 ) == Qgis::ARGB32
81  || provider->dataType( 1 ) == Qgis::ARGB32_Premultiplied )
82  {
83  gboxNoDataValue->setEnabled( false );
84  gboxCustomTransparency->setEnabled( false );
85  }
86 
87  cboxTransparencyBand->setShowNotSetOption( true, tr( "None" ) );
88  cboxTransparencyBand->setLayer( mRasterLayer );
89 
90  mOpacityWidget->setOpacity( renderer->opacity() );
91 
92  cboxTransparencyBand->setBand( renderer->alphaBand() );
93  }
94 
95  if ( mRasterLayer->dataProvider()->sourceHasNoDataValue( 1 ) )
96  {
97  lblSrcNoDataValue->setText( QgsRasterBlock::printValue( mRasterLayer->dataProvider()->sourceNoDataValue( 1 ) ) );
98  }
99  else
100  {
101  lblSrcNoDataValue->setText( tr( "not defined" ) );
102  }
103 
104  mSrcNoDataValueCheckBox->setChecked( mRasterLayer->dataProvider()->useSourceNoDataValue( 1 ) );
105 
106  bool enableSrcNoData = mRasterLayer->dataProvider()->sourceHasNoDataValue( 1 ) && !std::isnan( mRasterLayer->dataProvider()->sourceNoDataValue( 1 ) );
107 
108  mSrcNoDataValueCheckBox->setEnabled( enableSrcNoData );
109  lblSrcNoDataValue->setEnabled( enableSrcNoData );
110 
111  if ( renderer )
112  {
113  if ( renderer->nodataColor().isValid() )
114  mNodataColorButton->setColor( renderer->nodataColor() );
115  else
116  mNodataColorButton->setToNull();
117  }
118 
119  QgsRasterRangeList noDataRangeList = mRasterLayer->dataProvider()->userNoDataValues( 1 );
120  QgsDebugMsg( QStringLiteral( "noDataRangeList.size = %1" ).arg( noDataRangeList.size() ) );
121  if ( !noDataRangeList.isEmpty() )
122  {
123  double v = QgsRasterBlock::printValue( noDataRangeList.value( 0 ).min() ).toDouble();
124  leNoDataValue->setText( QLocale().toString( v ) );
125  }
126  else
127  {
128  leNoDataValue->setText( QString() );
129  }
130 
131  populateTransparencyTable( mRasterLayer->renderer() );
132 }
133 
134 void QgsRasterTransparencyWidget::transparencyCellTextEdited( const QString &text )
135 {
136  Q_UNUSED( text )
137  QgsDebugMsg( QStringLiteral( "text = %1" ).arg( text ) );
138  QgsRasterRenderer *renderer = mRasterLayer->renderer();
139  if ( !renderer )
140  {
141  return;
142  }
143  int nBands = renderer->usesBands().size();
144  if ( nBands == 1 )
145  {
146  QLineEdit *lineEdit = qobject_cast<QLineEdit *>( sender() );
147  if ( !lineEdit ) return;
148  int row = -1;
149  int column = -1;
150  for ( int r = 0; r < tableTransparency->rowCount(); r++ )
151  {
152  for ( int c = 0; c < tableTransparency->columnCount(); c++ )
153  {
154  if ( tableTransparency->cellWidget( r, c ) == sender() )
155  {
156  row = r;
157  column = c;
158  break;
159  }
160  }
161  if ( row != -1 ) break;
162  }
163  QgsDebugMsg( QStringLiteral( "row = %1 column =%2" ).arg( row ).arg( column ) );
164 
165  if ( column == 0 )
166  {
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 ) );
171  if ( !toChanged )
172  {
173  toLineEdit->setText( lineEdit->text() );
174  }
175  }
176  else if ( column == 1 )
177  {
178  setTransparencyToEdited( row );
179  }
180  }
181  emit widgetChanged();
182 }
183 
184 void QgsRasterTransparencyWidget::pbnAddValuesFromDisplay_clicked()
185 {
186  if ( mMapCanvas && mPixelSelectorTool )
187  {
188  mMapCanvas->setMapTool( mPixelSelectorTool );
189  }
190 }
191 
192 void QgsRasterTransparencyWidget::pbnAddValuesManually_clicked()
193 {
194  QgsRasterRenderer *renderer = mRasterLayer->renderer();
195  if ( !renderer )
196  {
197  return;
198  }
199 
200  tableTransparency->insertRow( tableTransparency->rowCount() );
201 
202  int n = renderer->usesBands().size();
203  if ( n == 1 ) n++;
204 
205  for ( int i = 0; i < n; i++ )
206  {
207  setTransparencyCell( tableTransparency->rowCount() - 1, i, std::numeric_limits<double>::quiet_NaN() );
208  }
209 
210  setTransparencyCell( tableTransparency->rowCount() - 1, n, 100 );
211 
212  tableTransparency->resizeColumnsToContents();
213  tableTransparency->resizeRowsToContents();
214 }
215 
216 void QgsRasterTransparencyWidget::pbnDefaultValues_clicked()
217 {
218  QgsRasterRenderer *r = mRasterLayer->renderer();
219  if ( !r )
220  {
221  return;
222  }
223 
224  int nBands = r->usesBands().size();
225 
226  setupTransparencyTable( nBands );
227 
228  tableTransparency->resizeColumnsToContents(); // works only with values
229  tableTransparency->resizeRowsToContents();
230 
231 }
232 
233 void QgsRasterTransparencyWidget::pbnExportTransparentPixelValues_clicked()
234 {
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() )
239  {
240  if ( !myFileName.endsWith( QLatin1String( ".txt" ), Qt::CaseInsensitive ) )
241  {
242  myFileName = myFileName + ".txt";
243  }
244 
245  QFile myOutputFile( myFileName );
246  if ( myOutputFile.open( QFile::WriteOnly | QIODevice::Truncate ) )
247  {
248  QTextStream myOutputStream( &myOutputFile );
249  myOutputStream << "# " << tr( "QGIS Generated Transparent Pixel Value Export File" ) << '\n';
250  if ( rasterIsMultiBandColor() )
251  {
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++ )
254  {
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 ) );
259  }
260  }
261  else
262  {
263  myOutputStream << "#\n#\n# " << tr( "Value" ) << "\t" << tr( "Percent Transparent" );
264 
265  for ( int myTableRunner = 0; myTableRunner < tableTransparency->rowCount(); myTableRunner++ )
266  {
267  myOutputStream << '\n' << QString::number( transparencyCellValue( myTableRunner, 0 ) ) << "\t"
268  << QString::number( transparencyCellValue( myTableRunner, 1 ) ) << "\t"
269  << QString::number( transparencyCellValue( myTableRunner, 2 ) );
270  }
271  }
272  }
273  else
274  {
275  QMessageBox::warning( this, tr( "Save Pixel Values as File" ), tr( "Write access denied. Adjust the file permissions and try again.\n\n" ) );
276  }
277  }
278 }
279 
280 void QgsRasterTransparencyWidget::pbnImportTransparentPixelValues_clicked()
281 {
282  int myLineCounter = 0;
283  bool myImportError = false;
284  QString myBadLines;
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 ) )
290  {
291  QTextStream myInputStream( &myInputFile );
292  QString myInputLine;
293  if ( rasterIsMultiBandColor() )
294  {
295  for ( int myTableRunner = tableTransparency->rowCount() - 1; myTableRunner >= 0; myTableRunner-- )
296  {
297  tableTransparency->removeRow( myTableRunner );
298  }
299 
300  while ( !myInputStream.atEnd() )
301  {
302  myLineCounter++;
303  myInputLine = myInputStream.readLine();
304  if ( !myInputLine.isEmpty() )
305  {
306  if ( !myInputLine.simplified().startsWith( '#' ) )
307  {
308  QStringList myTokens = myInputLine.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
309  if ( myTokens.count() != 4 )
310  {
311  myImportError = true;
312  myBadLines = myBadLines + QString::number( myLineCounter ) + ":\t[" + myInputLine + "]\n";
313  }
314  else
315  {
316  tableTransparency->insertRow( tableTransparency->rowCount() );
317  for ( int col = 0; col < 4; col++ )
318  {
319  setTransparencyCell( tableTransparency->rowCount() - 1, col, myTokens[col].toDouble() );
320  }
321  }
322  }
323  }
324  }
325  }
326  else
327  {
328  for ( int myTableRunner = tableTransparency->rowCount() - 1; myTableRunner >= 0; myTableRunner-- )
329  {
330  tableTransparency->removeRow( myTableRunner );
331  }
332 
333  while ( !myInputStream.atEnd() )
334  {
335  myLineCounter++;
336  myInputLine = myInputStream.readLine();
337  if ( !myInputLine.isEmpty() )
338  {
339  if ( !myInputLine.simplified().startsWith( '#' ) )
340  {
341  QStringList myTokens = myInputLine.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
342  if ( myTokens.count() != 3 && myTokens.count() != 2 ) // 2 for QGIS < 1.9 compatibility
343  {
344  myImportError = true;
345  myBadLines = myBadLines + QString::number( myLineCounter ) + ":\t[" + myInputLine + "]\n";
346  }
347  else
348  {
349  if ( myTokens.count() == 2 )
350  {
351  myTokens.insert( 1, myTokens[0] ); // add 'to' value, QGIS < 1.9 compatibility
352  }
353  tableTransparency->insertRow( tableTransparency->rowCount() );
354  for ( int col = 0; col < 3; col++ )
355  {
356  setTransparencyCell( tableTransparency->rowCount() - 1, col, myTokens[col].toDouble() );
357  }
358  }
359  }
360  }
361  }
362  }
363 
364  if ( myImportError )
365  {
366  QMessageBox::warning( this, tr( "Load Pixel Values from File" ), tr( "The following lines contained errors\n\n%1" ).arg( myBadLines ) );
367  }
368  }
369  else if ( !myFileName.isEmpty() )
370  {
371  QMessageBox::warning( this, tr( "Load Pixel Values from File" ), tr( "Read access denied. Adjust the file permissions and try again.\n\n" ) );
372  }
373  tableTransparency->resizeColumnsToContents();
374  tableTransparency->resizeRowsToContents();
375  emit widgetChanged();
376 }
377 
378 void QgsRasterTransparencyWidget::pbnRemoveSelectedRow_clicked()
379 {
380  if ( 0 < tableTransparency->rowCount() )
381  {
382  tableTransparency->removeRow( tableTransparency->currentRow() );
383  }
384  emit widgetChanged();
385 }
386 
387 bool QgsRasterTransparencyWidget::rasterIsMultiBandColor()
388 {
389  return mRasterLayer && nullptr != dynamic_cast<QgsMultiBandColorRenderer *>( mRasterLayer->renderer() );
390 }
391 
393 {
394  //set NoDataValue
395  QgsRasterRangeList myNoDataRangeList;
396  if ( "" != leNoDataValue->text() )
397  {
398  bool myDoubleOk = false;
399  double myNoDataValue = QgsDoubleValidator::toDouble( leNoDataValue->text(), &myDoubleOk );
400  if ( myDoubleOk )
401  {
402  QgsRasterRange myNoDataRange( myNoDataValue, myNoDataValue );
403  myNoDataRangeList << myNoDataRange;
404  }
405  }
406  for ( int bandNo = 1; bandNo <= mRasterLayer->dataProvider()->bandCount(); bandNo++ )
407  {
408  mRasterLayer->dataProvider()->setUserNoDataValue( bandNo, myNoDataRangeList );
409  mRasterLayer->dataProvider()->setUseSourceNoDataValue( bandNo, mSrcNoDataValueCheckBox->isChecked() );
410  }
411 
412  //transparency settings
413  QgsRasterRenderer *rasterRenderer = mRasterLayer->renderer();
414  if ( rasterRenderer )
415  {
416  rasterRenderer->setAlphaBand( cboxTransparencyBand->currentBand() );
417  rasterRenderer->setNodataColor( mNodataColorButton->color() );
418 
419  //Walk through each row in table and test value. If not valid set to 0.0 and continue building transparency list
420  QgsRasterTransparency *rasterTransparency = new QgsRasterTransparency();
421  if ( tableTransparency->columnCount() == 4 )
422  {
424  QList<QgsRasterTransparency::TransparentThreeValuePixel> myTransparentThreeValuePixelList;
425  myTransparentThreeValuePixelList.reserve( tableTransparency->rowCount() );
426  for ( int myListRunner = 0; myListRunner < tableTransparency->rowCount(); myListRunner++ )
427  {
428  myTransparentPixel.red = transparencyCellValue( myListRunner, 0 );
429  myTransparentPixel.green = transparencyCellValue( myListRunner, 1 );
430  myTransparentPixel.blue = transparencyCellValue( myListRunner, 2 );
431  myTransparentPixel.percentTransparent = transparencyCellValue( myListRunner, 3 );
432  myTransparentThreeValuePixelList.append( myTransparentPixel );
433  }
434  rasterTransparency->setTransparentThreeValuePixelList( myTransparentThreeValuePixelList );
435  }
436  else if ( tableTransparency->columnCount() == 3 )
437  {
439  QList<QgsRasterTransparency::TransparentSingleValuePixel> myTransparentSingleValuePixelList;
440  myTransparentSingleValuePixelList.reserve( tableTransparency->rowCount() );
441  for ( int myListRunner = 0; myListRunner < tableTransparency->rowCount(); myListRunner++ )
442  {
443  myTransparentPixel.min = transparencyCellValue( myListRunner, 0 );
444  myTransparentPixel.max = transparencyCellValue( myListRunner, 1 );
445  myTransparentPixel.percentTransparent = transparencyCellValue( myListRunner, 2 );
446 
447  myTransparentSingleValuePixelList.append( myTransparentPixel );
448  }
449  rasterTransparency->setTransparentSingleValuePixelList( myTransparentSingleValuePixelList );
450  }
451 
452  rasterRenderer->setRasterTransparency( rasterTransparency );
453 
454  //set global transparency
455  rasterRenderer->setOpacity( mOpacityWidget->opacity() );
456  }
457 }
458 
459 void QgsRasterTransparencyWidget::pixelSelected( const QgsPointXY &canvasPoint )
460 {
461  QgsRasterRenderer *renderer = mRasterLayer->renderer();
462  if ( !renderer )
463  {
464  return;
465  }
466 
467  //Get the pixel values and add a new entry to the transparency table
468  if ( mMapCanvas && mPixelSelectorTool )
469  {
470  mMapCanvas->unsetMapTool( mPixelSelectorTool );
471 
472  const QgsMapSettings &ms = mMapCanvas->mapSettings();
473  QgsPointXY myPoint = ms.mapToLayerCoordinates( mRasterLayer, canvasPoint );
474 
475  QgsRectangle myExtent = ms.mapToLayerCoordinates( mRasterLayer, mMapCanvas->extent() );
476  double mapUnitsPerPixel = mMapCanvas->mapUnitsPerPixel();
477  int myWidth = mMapCanvas->extent().width() / mapUnitsPerPixel;
478  int myHeight = mMapCanvas->extent().height() / mapUnitsPerPixel;
479 
480  QMap<int, QVariant> myPixelMap = mRasterLayer->dataProvider()->identify( myPoint, QgsRaster::IdentifyFormatValue, myExtent, myWidth, myHeight ).results();
481 
482  QList<int> bands = renderer->usesBands();
483 
484  QList<double> values;
485  for ( int i = 0; i < bands.size(); ++i )
486  {
487  int bandNo = bands.value( i );
488  if ( myPixelMap.count( bandNo ) == 1 )
489  {
490  if ( myPixelMap.value( bandNo ).isNull() )
491  {
492  return; // Don't add nodata, transparent anyway
493  }
494  double value = myPixelMap.value( bandNo ).toDouble();
495  QgsDebugMsg( QStringLiteral( "value = %1" ).arg( value, 0, 'g', 17 ) );
496  values.append( value );
497  }
498  }
499  if ( bands.size() == 1 )
500  {
501  // Set 'to'
502  values.insert( 1, values.value( 0 ) );
503  }
504  tableTransparency->insertRow( tableTransparency->rowCount() );
505  for ( int i = 0; i < values.size(); i++ )
506  {
507  setTransparencyCell( tableTransparency->rowCount() - 1, i, values.value( i ) );
508  }
509  setTransparencyCell( tableTransparency->rowCount() - 1, tableTransparency->columnCount() - 1, 100 );
510  }
511 
512  tableTransparency->resizeColumnsToContents();
513  tableTransparency->resizeRowsToContents();
514 }
515 
516 void QgsRasterTransparencyWidget::populateTransparencyTable( QgsRasterRenderer *renderer )
517 {
518  if ( !mRasterLayer )
519  {
520  return;
521  }
522 
523  if ( !renderer )
524  {
525  return;
526  }
527 
528  int nBands = renderer->usesBands().size();
529  setupTransparencyTable( nBands );
530 
531  const QgsRasterTransparency *rasterTransparency = renderer->rasterTransparency();
532  if ( !rasterTransparency )
533  {
534  return;
535  }
536 
537  if ( nBands == 1 )
538  {
539  QList<QgsRasterTransparency::TransparentSingleValuePixel> pixelList = rasterTransparency->transparentSingleValuePixelList();
540  for ( int i = 0; i < pixelList.size(); ++i )
541  {
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 );
546  // break synchronization only if values differ
547  if ( pixelList[i].min != pixelList[i].max )
548  {
549  setTransparencyToEdited( i );
550  }
551  }
552  }
553  else if ( nBands == 3 )
554  {
555  QList<QgsRasterTransparency::TransparentThreeValuePixel> pixelList = rasterTransparency->transparentThreeValuePixelList();
556  for ( int i = 0; i < pixelList.size(); ++i )
557  {
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 );
563  }
564  }
565 
566  tableTransparency->resizeColumnsToContents();
567  tableTransparency->resizeRowsToContents();
568 
569 }
570 
571 void QgsRasterTransparencyWidget::setupTransparencyTable( int nBands )
572 {
573  tableTransparency->clear();
574  tableTransparency->setColumnCount( 0 );
575  tableTransparency->setRowCount( 0 );
576  mTransparencyToEdited.clear();
577 
578  if ( nBands == 3 )
579  {
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" ) ) );
585  }
586  else //1 band
587  {
588  tableTransparency->setColumnCount( 3 );
589 // Is it important to distinguish the header? It becomes difficult with range.
590 #if 0
591  if ( QgsRasterLayer::PalettedColor != mRasterLayer->drawingStyle() &&
592  QgsRasterLayer::PalettedSingleBandGray != mRasterLayer->drawingStyle() &&
593  QgsRasterLayer::PalettedSingleBandPseudoColor != mRasterLayer->drawingStyle() &&
594  QgsRasterLayer::PalettedMultiBandColor != mRasterLayer->drawingStyle() )
595  {
596  tableTransparency->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Gray" ) ) );
597  }
598  else
599  {
600  tableTransparency->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Indexed Value" ) ) );
601  }
602 #endif
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" ) ) );
606  }
607 }
608 
609 void QgsRasterTransparencyWidget::setTransparencyCell( int row, int column, double value )
610 {
611  QgsDebugMsg( QStringLiteral( "value = %1" ).arg( value, 0, 'g', 17 ) );
612  QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
613  if ( !provider ) return;
614 
615  QgsRasterRenderer *renderer = mRasterLayer->renderer();
616  if ( !renderer ) return;
617  int nBands = renderer->usesBands().size();
618 
619  QLineEdit *lineEdit = new QLineEdit();
620  lineEdit->setFrame( false ); // frame looks bad in table
621  // Without margins row selection is not displayed (important for delete row)
622  lineEdit->setContentsMargins( 1, 1, 1, 1 );
623 
624  if ( column == tableTransparency->columnCount() - 1 )
625  {
626  // transparency
627  // Who needs transparency as floating point?
628  lineEdit->setValidator( new QIntValidator( nullptr ) );
629  lineEdit->setText( QString::number( static_cast<int>( value ) ) );
630  }
631  else
632  {
633  // value
634  QString valueString;
635  switch ( provider->sourceDataType( 1 ) )
636  {
637  case Qgis::Float32:
638  case Qgis::Float64:
639  lineEdit->setValidator( new QgsDoubleValidator( nullptr ) );
640  if ( !std::isnan( value ) )
641  {
642  double v = QgsRasterBlock::printValue( value ).toDouble();
643  valueString = QLocale().toString( v );
644  }
645  break;
646  default:
647  lineEdit->setValidator( new QIntValidator( nullptr ) );
648  if ( !std::isnan( value ) )
649  {
650  valueString = QString::number( static_cast<int>( value ) );
651  }
652  break;
653  }
654  lineEdit->setText( valueString );
655  connect( lineEdit, &QLineEdit::textEdited, this, &QgsPanelWidget::widgetChanged );
656  }
657  tableTransparency->setCellWidget( row, column, lineEdit );
658  adjustTransparencyCellWidth( row, column );
659 
660  if ( nBands == 1 && ( column == 0 || column == 1 ) )
661  {
662  connect( lineEdit, &QLineEdit::textEdited, this, &QgsRasterTransparencyWidget::transparencyCellTextEdited );
663  }
664  tableTransparency->resizeColumnsToContents();
665  emit widgetChanged();
666 }
667 
668 void QgsRasterTransparencyWidget::adjustTransparencyCellWidth( int row, int column )
669 {
670  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( tableTransparency->cellWidget( row, column ) );
671  if ( !lineEdit ) return;
672 
673  int width = std::max( lineEdit->fontMetrics().boundingRect( lineEdit->text() ).width() + 10, 100 );
674  width = std::max( width, tableTransparency->columnWidth( column ) );
675 
676  lineEdit->setFixedWidth( width );
677 }
678 
679 void QgsRasterTransparencyWidget::setTransparencyToEdited( int row )
680 {
681  if ( row >= mTransparencyToEdited.size() )
682  {
683  mTransparencyToEdited.resize( row + 1 );
684  }
685  mTransparencyToEdited[row] = true;
686 }
687 
688 double QgsRasterTransparencyWidget::transparencyCellValue( int row, int column )
689 {
690  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( tableTransparency->cellWidget( row, column ) );
691  if ( !lineEdit || lineEdit->text().isEmpty() )
692  {
693  return std::numeric_limits<double>::quiet_NaN();
694  }
695  return QgsDoubleValidator::toDouble( lineEdit->text() );
696 
697 }
QgsOpacityWidget::opacityChanged
void opacityChanged(double opacity)
Emitted when the opacity is changed in the widget, where opacity ranges from 0.0 (transparent) to 1....
QgsRasterTransparency::setTransparentThreeValuePixelList
void setTransparentThreeValuePixelList(const QList< QgsRasterTransparency::TransparentThreeValuePixel > &newList)
Sets the transparent three value pixel list, replacing the whole existing list.
Definition: qgsrastertransparency.cpp:69
QgsRasterBandComboBox::bandChanged
void bandChanged(int band)
Emitted when the currently selected band changes.
QgsRasterBlock::printValue
static QString printValue(double value)
Print double value with all necessary significant digits.
Definition: qgsrasterblock.cpp:626
Qgis::Float32
@ Float32
Thirty two bit floating point (float)
Definition: qgis.h:109
QgsMapSettings::mapToLayerCoordinates
QgsPointXY mapToLayerCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from output CRS to layer's CRS
Definition: qgsmapsettings.cpp:537
qgsrasterlayer.h
QgsRasterRenderer::setRasterTransparency
void setRasterTransparency(QgsRasterTransparency *t)
Definition: qgsrasterrenderer.cpp:98
QgsRasterDataProvider::dataType
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
QgsSettings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Definition: qgssettings.cpp:174
qgsrectangle.h
qgsmapcanvas.h
QgsRasterTransparency::transparentSingleValuePixelList
QList< QgsRasterTransparency::TransparentSingleValuePixel > transparentSingleValuePixelList() const
Returns the transparent single value pixel list.
Definition: qgsrastertransparency.cpp:27
qgsrasteridentifyresult.h
QgsRasterTransparency::transparentThreeValuePixelList
QList< QgsRasterTransparency::TransparentThreeValuePixel > transparentThreeValuePixelList() const
Returns the transparent three value pixel list.
Definition: qgsrastertransparency.cpp:32
QgsRasterTransparency::TransparentSingleValuePixel::min
double min
Definition: qgsrastertransparency.h:55
QgsRasterRenderer::nodataColor
QColor nodataColor() const
Returns the color to use for shading nodata pixels.
Definition: qgsrasterrenderer.h:100
QgsMapCanvas
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:85
QgsRasterTransparency::TransparentThreeValuePixel::percentTransparent
double percentTransparent
Definition: qgsrastertransparency.h:50
QgsSettings
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
QgsMapToolEmitPoint::canvasClicked
void canvasClicked(const QgsPointXY &point, Qt::MouseButton button)
signal emitted on canvas click
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
qgsmapsettings.h
QgsRasterRenderer::usesBands
virtual QList< int > usesBands() const
Returns a list of band numbers used by the renderer.
Definition: qgsrasterrenderer.h:133
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QgsMapLayerConfigWidget
A panel widget that can be shown in the map style dock.
Definition: qgsmaplayerconfigwidget.h:34
QgsColorButton::colorChanged
void colorChanged(const QColor &color)
Emitted whenever a new color is set for the button.
QgsRasterTransparency::TransparentSingleValuePixel::percentTransparent
double percentTransparent
Definition: qgsrastertransparency.h:57
QgsRasterTransparency::TransparentThreeValuePixel::blue
double blue
Definition: qgsrastertransparency.h:49
qgsraster.h
QgsRaster::IdentifyFormatValue
@ IdentifyFormatValue
Definition: qgsraster.h:60
QgsRasterRenderer
Raster renderer pipe that applies colors to a raster.
Definition: qgsrasterrenderer.h:39
QgsRasterRenderer::rasterTransparency
const QgsRasterTransparency * rasterTransparency() const
Definition: qgsrasterrenderer.h:114
QgsRasterTransparencyWidget::syncToLayer
void syncToLayer()
Sync the widget state to the layer set for the widget.
Definition: qgsrastertransparencywidget.cpp:74
qgsrastertransparencywidget.h
QgsRasterRenderer::setAlphaBand
void setAlphaBand(int band)
Definition: qgsrasterrenderer.h:116
QgsDoubleValidator
QgsDoubleValidator is a QLineEdit Validator that combines QDoubleValidator and QRegularExpressionVali...
Definition: qgsdoublevalidator.h:39
QgsRasterTransparencyWidget::apply
void apply() override
Apply any changes on the widget to the set layer.
Definition: qgsrastertransparencywidget.cpp:392
QgsPanelWidget::widgetChanged
void widgetChanged()
Emitted when the widget state changes.
QgsRasterTransparency::TransparentSingleValuePixel::max
double max
Definition: qgsrastertransparency.h:56
QgsRasterRangeList
QList< QgsRasterRange > QgsRasterRangeList
Definition: qgsrasterrange.h:26
QgsRasterTransparency::setTransparentSingleValuePixelList
void setTransparentSingleValuePixelList(const QList< QgsRasterTransparency::TransparentSingleValuePixel > &newList)
Sets the transparent single value pixel list, replacing the whole existing list.
Definition: qgsrastertransparency.cpp:64
QgsRasterTransparency::TransparentSingleValuePixel
Definition: qgsrastertransparency.h:54
QgsMultiBandColorRenderer
Renderer for multiband images with the color components.
Definition: qgsmultibandcolorrenderer.h:33
QgsRasterLayer
Represents a raster layer.
Definition: qgsrasterlayer.h:71
QgsRasterTransparency
Defines the list of pixel values to be considered as transparent or semi transparent when rendering r...
Definition: qgsrastertransparency.h:33
qgsrastertransparency.h
qgsrasterlayerrenderer.h
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:44
QgsMapToolEmitPoint
A map tool that simply emits a point when clicking on the map.
Definition: qgsmaptoolemitpoint.h:31
QgsRasterDataProvider::sourceDataType
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...
Qgis::ARGB32_Premultiplied
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
Definition: qgis.h:116
c
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
Definition: porting_processing.dox:1
QgsRasterRenderer::alphaBand
int alphaBand() const
Definition: qgsrasterrenderer.h:117
qgsmultibandcolorrenderer.h
QgsDoubleValidator::toDouble
static double toDouble(const QString &input, bool *ok)
Converts input string to double value.
Definition: qgsdoublevalidator.cpp:122
qgssettings.h
QgsRasterTransparencyWidget::QgsRasterTransparencyWidget
QgsRasterTransparencyWidget(QgsRasterLayer *layer, QgsMapCanvas *canvas, QWidget *parent=nullptr)
Widget to control a layers transparency and related options.
Definition: qgsrastertransparencywidget.cpp:38
QgsRasterTransparency::TransparentThreeValuePixel
Definition: qgsrastertransparency.h:46
QgsRasterRange
Raster values range container.
Definition: qgsrasterrange.h:36
QgsRasterRenderer::setNodataColor
void setNodataColor(const QColor &color)
Sets the color to use for shading nodata pixels.
Definition: qgsrasterrenderer.h:111
QgsRasterTransparency::TransparentThreeValuePixel::red
double red
Definition: qgsrastertransparency.h:47
Qgis::ARGB32
@ ARGB32
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
Definition: qgis.h:115
qgsdoublevalidator.h
QgsMapSettings
The QgsMapSettings class contains configuration for rendering of the map.
Definition: qgsmapsettings.h:88
QgsRasterTransparency::TransparentThreeValuePixel::green
double green
Definition: qgsrastertransparency.h:48
QgsRasterRenderer::setOpacity
void setOpacity(double opacity)
Sets the opacity for the renderer, where opacity is a value between 0 (totally transparent) and 1....
Definition: qgsrasterrenderer.h:81
QgsRasterDataProvider
Base class for raster data providers.
Definition: qgsrasterdataprovider.h:89
qgsmaptoolemitpoint.h
qgsrasterdataprovider.h
QgsRasterRenderer::opacity
double opacity() const
Returns the opacity for the renderer, where opacity is a value between 0 (totally transparent) and 1....
Definition: qgsrasterrenderer.h:88
Qgis::Float64
@ Float64
Sixty four bit floating point (double)
Definition: qgis.h:110