QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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 <QDoubleValidator>
17 #include <QIntValidator>
18 #include <QFile>
19 #include <QTextStream>
20 #include <QMessageBox>
21 #include <QFileDialog>
22 
23 #include "qgssettings.h"
25 #include "qgsrasterlayer.h"
26 #include "qgsraster.h"
27 #include "qgsrasterlayerrenderer.h"
28 #include "qgsrasterdataprovider.h"
29 #include "qgsrastertransparency.h"
30 #include "qgsmaptoolemitpoint.h"
31 #include "qgsmapsettings.h"
32 #include "qgsrectangle.h"
33 #include "qgsmapcanvas.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  leNoDataValue->setText( QgsRasterBlock::printValue( noDataRangeList.value( 0 ).min() ) );
124  }
125  else
126  {
127  leNoDataValue->setText( QString() );
128  }
129 
130  populateTransparencyTable( mRasterLayer->renderer() );
131 }
132 
133 void QgsRasterTransparencyWidget::transparencyCellTextEdited( const QString &text )
134 {
135  Q_UNUSED( text )
136  QgsDebugMsg( QStringLiteral( "text = %1" ).arg( text ) );
137  QgsRasterRenderer *renderer = mRasterLayer->renderer();
138  if ( !renderer )
139  {
140  return;
141  }
142  int nBands = renderer->usesBands().size();
143  if ( nBands == 1 )
144  {
145  QLineEdit *lineEdit = qobject_cast<QLineEdit *>( sender() );
146  if ( !lineEdit ) return;
147  int row = -1;
148  int column = -1;
149  for ( int r = 0; r < tableTransparency->rowCount(); r++ )
150  {
151  for ( int c = 0; c < tableTransparency->columnCount(); c++ )
152  {
153  if ( tableTransparency->cellWidget( r, c ) == sender() )
154  {
155  row = r;
156  column = c;
157  break;
158  }
159  }
160  if ( row != -1 ) break;
161  }
162  QgsDebugMsg( QStringLiteral( "row = %1 column =%2" ).arg( row ).arg( column ) );
163 
164  if ( column == 0 )
165  {
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 ) );
170  if ( !toChanged )
171  {
172  toLineEdit->setText( lineEdit->text() );
173  }
174  }
175  else if ( column == 1 )
176  {
177  setTransparencyToEdited( row );
178  }
179  }
180  emit widgetChanged();
181 }
182 
183 void QgsRasterTransparencyWidget::pbnAddValuesFromDisplay_clicked()
184 {
185  if ( mMapCanvas && mPixelSelectorTool )
186  {
187  mMapCanvas->setMapTool( mPixelSelectorTool );
188  }
189 }
190 
191 void QgsRasterTransparencyWidget::pbnAddValuesManually_clicked()
192 {
193  QgsRasterRenderer *renderer = mRasterLayer->renderer();
194  if ( !renderer )
195  {
196  return;
197  }
198 
199  tableTransparency->insertRow( tableTransparency->rowCount() );
200 
201  int n = renderer->usesBands().size();
202  if ( n == 1 ) n++;
203 
204  for ( int i = 0; i < n; i++ )
205  {
206  setTransparencyCell( tableTransparency->rowCount() - 1, i, std::numeric_limits<double>::quiet_NaN() );
207  }
208 
209  setTransparencyCell( tableTransparency->rowCount() - 1, n, 100 );
210 
211  tableTransparency->resizeColumnsToContents();
212  tableTransparency->resizeRowsToContents();
213 }
214 
215 void QgsRasterTransparencyWidget::pbnDefaultValues_clicked()
216 {
217  QgsRasterRenderer *r = mRasterLayer->renderer();
218  if ( !r )
219  {
220  return;
221  }
222 
223  int nBands = r->usesBands().size();
224 
225  setupTransparencyTable( nBands );
226 
227  tableTransparency->resizeColumnsToContents(); // works only with values
228  tableTransparency->resizeRowsToContents();
229 
230 }
231 
232 void QgsRasterTransparencyWidget::pbnExportTransparentPixelValues_clicked()
233 {
234  QgsSettings myQSettings;
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() )
238  {
239  if ( !myFileName.endsWith( QLatin1String( ".txt" ), Qt::CaseInsensitive ) )
240  {
241  myFileName = myFileName + ".txt";
242  }
243 
244  QFile myOutputFile( myFileName );
245  if ( myOutputFile.open( QFile::WriteOnly | QIODevice::Truncate ) )
246  {
247  QTextStream myOutputStream( &myOutputFile );
248  myOutputStream << "# " << tr( "QGIS Generated Transparent Pixel Value Export File" ) << '\n';
249  if ( rasterIsMultiBandColor() )
250  {
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++ )
253  {
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 ) );
258  }
259  }
260  else
261  {
262  myOutputStream << "#\n#\n# " << tr( "Value" ) << "\t" << tr( "Percent Transparent" );
263 
264  for ( int myTableRunner = 0; myTableRunner < tableTransparency->rowCount(); myTableRunner++ )
265  {
266  myOutputStream << '\n' << QString::number( transparencyCellValue( myTableRunner, 0 ) ) << "\t"
267  << QString::number( transparencyCellValue( myTableRunner, 1 ) ) << "\t"
268  << QString::number( transparencyCellValue( myTableRunner, 2 ) );
269  }
270  }
271  }
272  else
273  {
274  QMessageBox::warning( this, tr( "Save Pixel Values as File" ), tr( "Write access denied. Adjust the file permissions and try again.\n\n" ) );
275  }
276  }
277 }
278 
279 void QgsRasterTransparencyWidget::pbnImportTransparentPixelValues_clicked()
280 {
281  int myLineCounter = 0;
282  bool myImportError = false;
283  QString myBadLines;
284  QgsSettings myQSettings;
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 ) )
289  {
290  QTextStream myInputStream( &myInputFile );
291  QString myInputLine;
292  if ( rasterIsMultiBandColor() )
293  {
294  for ( int myTableRunner = tableTransparency->rowCount() - 1; myTableRunner >= 0; myTableRunner-- )
295  {
296  tableTransparency->removeRow( myTableRunner );
297  }
298 
299  while ( !myInputStream.atEnd() )
300  {
301  myLineCounter++;
302  myInputLine = myInputStream.readLine();
303  if ( !myInputLine.isEmpty() )
304  {
305  if ( !myInputLine.simplified().startsWith( '#' ) )
306  {
307  QStringList myTokens = myInputLine.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
308  if ( myTokens.count() != 4 )
309  {
310  myImportError = true;
311  myBadLines = myBadLines + QString::number( myLineCounter ) + ":\t[" + myInputLine + "]\n";
312  }
313  else
314  {
315  tableTransparency->insertRow( tableTransparency->rowCount() );
316  for ( int col = 0; col < 4; col++ )
317  {
318  setTransparencyCell( tableTransparency->rowCount() - 1, col, myTokens[col].toDouble() );
319  }
320  }
321  }
322  }
323  }
324  }
325  else
326  {
327  for ( int myTableRunner = tableTransparency->rowCount() - 1; myTableRunner >= 0; myTableRunner-- )
328  {
329  tableTransparency->removeRow( myTableRunner );
330  }
331 
332  while ( !myInputStream.atEnd() )
333  {
334  myLineCounter++;
335  myInputLine = myInputStream.readLine();
336  if ( !myInputLine.isEmpty() )
337  {
338  if ( !myInputLine.simplified().startsWith( '#' ) )
339  {
340  QStringList myTokens = myInputLine.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
341  if ( myTokens.count() != 3 && myTokens.count() != 2 ) // 2 for QGIS < 1.9 compatibility
342  {
343  myImportError = true;
344  myBadLines = myBadLines + QString::number( myLineCounter ) + ":\t[" + myInputLine + "]\n";
345  }
346  else
347  {
348  if ( myTokens.count() == 2 )
349  {
350  myTokens.insert( 1, myTokens[0] ); // add 'to' value, QGIS < 1.9 compatibility
351  }
352  tableTransparency->insertRow( tableTransparency->rowCount() );
353  for ( int col = 0; col < 3; col++ )
354  {
355  setTransparencyCell( tableTransparency->rowCount() - 1, col, myTokens[col].toDouble() );
356  }
357  }
358  }
359  }
360  }
361  }
362 
363  if ( myImportError )
364  {
365  QMessageBox::warning( this, tr( "Load Pixel Values from File" ), tr( "The following lines contained errors\n\n%1" ).arg( myBadLines ) );
366  }
367  }
368  else if ( !myFileName.isEmpty() )
369  {
370  QMessageBox::warning( this, tr( "Load Pixel Values from File" ), tr( "Read access denied. Adjust the file permissions and try again.\n\n" ) );
371  }
372  tableTransparency->resizeColumnsToContents();
373  tableTransparency->resizeRowsToContents();
374  emit widgetChanged();
375 }
376 
377 void QgsRasterTransparencyWidget::pbnRemoveSelectedRow_clicked()
378 {
379  if ( 0 < tableTransparency->rowCount() )
380  {
381  tableTransparency->removeRow( tableTransparency->currentRow() );
382  }
383  emit widgetChanged();
384 }
385 
386 bool QgsRasterTransparencyWidget::rasterIsMultiBandColor()
387 {
388  return mRasterLayer && nullptr != dynamic_cast<QgsMultiBandColorRenderer *>( mRasterLayer->renderer() );
389 }
390 
392 {
393  //set NoDataValue
394  QgsRasterRangeList myNoDataRangeList;
395  if ( "" != leNoDataValue->text() )
396  {
397  bool myDoubleOk = false;
398  double myNoDataValue = leNoDataValue->text().toDouble( &myDoubleOk );
399  if ( myDoubleOk )
400  {
401  QgsRasterRange myNoDataRange( myNoDataValue, myNoDataValue );
402  myNoDataRangeList << myNoDataRange;
403  }
404  }
405  for ( int bandNo = 1; bandNo <= mRasterLayer->dataProvider()->bandCount(); bandNo++ )
406  {
407  mRasterLayer->dataProvider()->setUserNoDataValue( bandNo, myNoDataRangeList );
408  mRasterLayer->dataProvider()->setUseSourceNoDataValue( bandNo, mSrcNoDataValueCheckBox->isChecked() );
409  }
410 
411  //transparency settings
412  QgsRasterRenderer *rasterRenderer = mRasterLayer->renderer();
413  if ( rasterRenderer )
414  {
415  rasterRenderer->setAlphaBand( cboxTransparencyBand->currentBand() );
416  rasterRenderer->setNodataColor( mNodataColorButton->color() );
417 
418  //Walk through each row in table and test value. If not valid set to 0.0 and continue building transparency list
419  QgsRasterTransparency *rasterTransparency = new QgsRasterTransparency();
420  if ( tableTransparency->columnCount() == 4 )
421  {
423  QList<QgsRasterTransparency::TransparentThreeValuePixel> myTransparentThreeValuePixelList;
424  myTransparentThreeValuePixelList.reserve( tableTransparency->rowCount() );
425  for ( int myListRunner = 0; myListRunner < tableTransparency->rowCount(); myListRunner++ )
426  {
427  myTransparentPixel.red = transparencyCellValue( myListRunner, 0 );
428  myTransparentPixel.green = transparencyCellValue( myListRunner, 1 );
429  myTransparentPixel.blue = transparencyCellValue( myListRunner, 2 );
430  myTransparentPixel.percentTransparent = transparencyCellValue( myListRunner, 3 );
431  myTransparentThreeValuePixelList.append( myTransparentPixel );
432  }
433  rasterTransparency->setTransparentThreeValuePixelList( myTransparentThreeValuePixelList );
434  }
435  else if ( tableTransparency->columnCount() == 3 )
436  {
438  QList<QgsRasterTransparency::TransparentSingleValuePixel> myTransparentSingleValuePixelList;
439  myTransparentSingleValuePixelList.reserve( tableTransparency->rowCount() );
440  for ( int myListRunner = 0; myListRunner < tableTransparency->rowCount(); myListRunner++ )
441  {
442  myTransparentPixel.min = transparencyCellValue( myListRunner, 0 );
443  myTransparentPixel.max = transparencyCellValue( myListRunner, 1 );
444  myTransparentPixel.percentTransparent = transparencyCellValue( myListRunner, 2 );
445 
446  myTransparentSingleValuePixelList.append( myTransparentPixel );
447  }
448  rasterTransparency->setTransparentSingleValuePixelList( myTransparentSingleValuePixelList );
449  }
450 
451  rasterRenderer->setRasterTransparency( rasterTransparency );
452 
453  //set global transparency
454  rasterRenderer->setOpacity( mOpacityWidget->opacity() );
455  }
456 }
457 
458 void QgsRasterTransparencyWidget::pixelSelected( const QgsPointXY &canvasPoint )
459 {
460  QgsRasterRenderer *renderer = mRasterLayer->renderer();
461  if ( !renderer )
462  {
463  return;
464  }
465 
466  //Get the pixel values and add a new entry to the transparency table
467  if ( mMapCanvas && mPixelSelectorTool )
468  {
469  mMapCanvas->unsetMapTool( mPixelSelectorTool );
470 
471  const QgsMapSettings &ms = mMapCanvas->mapSettings();
472  QgsPointXY myPoint = ms.mapToLayerCoordinates( mRasterLayer, canvasPoint );
473 
474  QgsRectangle myExtent = ms.mapToLayerCoordinates( mRasterLayer, mMapCanvas->extent() );
475  double mapUnitsPerPixel = mMapCanvas->mapUnitsPerPixel();
476  int myWidth = mMapCanvas->extent().width() / mapUnitsPerPixel;
477  int myHeight = mMapCanvas->extent().height() / mapUnitsPerPixel;
478 
479  QMap<int, QVariant> myPixelMap = mRasterLayer->dataProvider()->identify( myPoint, QgsRaster::IdentifyFormatValue, myExtent, myWidth, myHeight ).results();
480 
481  QList<int> bands = renderer->usesBands();
482 
483  QList<double> values;
484  for ( int i = 0; i < bands.size(); ++i )
485  {
486  int bandNo = bands.value( i );
487  if ( myPixelMap.count( bandNo ) == 1 )
488  {
489  if ( myPixelMap.value( bandNo ).isNull() )
490  {
491  return; // Don't add nodata, transparent anyway
492  }
493  double value = myPixelMap.value( bandNo ).toDouble();
494  QgsDebugMsg( QStringLiteral( "value = %1" ).arg( value, 0, 'g', 17 ) );
495  values.append( value );
496  }
497  }
498  if ( bands.size() == 1 )
499  {
500  // Set 'to'
501  values.insert( 1, values.value( 0 ) );
502  }
503  tableTransparency->insertRow( tableTransparency->rowCount() );
504  for ( int i = 0; i < values.size(); i++ )
505  {
506  setTransparencyCell( tableTransparency->rowCount() - 1, i, values.value( i ) );
507  }
508  setTransparencyCell( tableTransparency->rowCount() - 1, tableTransparency->columnCount() - 1, 100 );
509  }
510 
511  tableTransparency->resizeColumnsToContents();
512  tableTransparency->resizeRowsToContents();
513 }
514 
515 void QgsRasterTransparencyWidget::populateTransparencyTable( QgsRasterRenderer *renderer )
516 {
517  if ( !mRasterLayer )
518  {
519  return;
520  }
521 
522  if ( !renderer )
523  {
524  return;
525  }
526 
527  int nBands = renderer->usesBands().size();
528  setupTransparencyTable( nBands );
529 
530  const QgsRasterTransparency *rasterTransparency = renderer->rasterTransparency();
531  if ( !rasterTransparency )
532  {
533  return;
534  }
535 
536  if ( nBands == 1 )
537  {
538  QList<QgsRasterTransparency::TransparentSingleValuePixel> pixelList = rasterTransparency->transparentSingleValuePixelList();
539  for ( int i = 0; i < pixelList.size(); ++i )
540  {
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 );
545  // break synchronization only if values differ
546  if ( pixelList[i].min != pixelList[i].max )
547  {
548  setTransparencyToEdited( i );
549  }
550  }
551  }
552  else if ( nBands == 3 )
553  {
554  QList<QgsRasterTransparency::TransparentThreeValuePixel> pixelList = rasterTransparency->transparentThreeValuePixelList();
555  for ( int i = 0; i < pixelList.size(); ++i )
556  {
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 );
562  }
563  }
564 
565  tableTransparency->resizeColumnsToContents();
566  tableTransparency->resizeRowsToContents();
567 
568 }
569 
570 void QgsRasterTransparencyWidget::setupTransparencyTable( int nBands )
571 {
572  tableTransparency->clear();
573  tableTransparency->setColumnCount( 0 );
574  tableTransparency->setRowCount( 0 );
575  mTransparencyToEdited.clear();
576 
577  if ( nBands == 3 )
578  {
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" ) ) );
584  }
585  else //1 band
586  {
587  tableTransparency->setColumnCount( 3 );
588 // Is it important to distinguish the header? It becomes difficult with range.
589 #if 0
590  if ( QgsRasterLayer::PalettedColor != mRasterLayer->drawingStyle() &&
591  QgsRasterLayer::PalettedSingleBandGray != mRasterLayer->drawingStyle() &&
592  QgsRasterLayer::PalettedSingleBandPseudoColor != mRasterLayer->drawingStyle() &&
593  QgsRasterLayer::PalettedMultiBandColor != mRasterLayer->drawingStyle() )
594  {
595  tableTransparency->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Gray" ) ) );
596  }
597  else
598  {
599  tableTransparency->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Indexed Value" ) ) );
600  }
601 #endif
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" ) ) );
605  }
606 }
607 
608 void QgsRasterTransparencyWidget::setTransparencyCell( int row, int column, double value )
609 {
610  QgsDebugMsg( QStringLiteral( "value = %1" ).arg( value, 0, 'g', 17 ) );
611  QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
612  if ( !provider ) return;
613 
614  QgsRasterRenderer *renderer = mRasterLayer->renderer();
615  if ( !renderer ) return;
616  int nBands = renderer->usesBands().size();
617 
618  QLineEdit *lineEdit = new QLineEdit();
619  lineEdit->setFrame( false ); // frame looks bad in table
620  // Without margins row selection is not displayed (important for delete row)
621  lineEdit->setContentsMargins( 1, 1, 1, 1 );
622 
623  if ( column == tableTransparency->columnCount() - 1 )
624  {
625  // transparency
626  // Who needs transparency as floating point?
627  lineEdit->setValidator( new QIntValidator( nullptr ) );
628  lineEdit->setText( QString::number( static_cast<int>( value ) ) );
629  }
630  else
631  {
632  // value
633  QString valueString;
634  switch ( provider->sourceDataType( 1 ) )
635  {
636  case Qgis::Float32:
637  case Qgis::Float64:
638  lineEdit->setValidator( new QDoubleValidator( nullptr ) );
639  if ( !std::isnan( value ) )
640  {
641  valueString = QgsRasterBlock::printValue( value );
642  }
643  break;
644  default:
645  lineEdit->setValidator( new QIntValidator( nullptr ) );
646  if ( !std::isnan( value ) )
647  {
648  valueString = QString::number( static_cast<int>( value ) );
649  }
650  break;
651  }
652  lineEdit->setText( valueString );
653  connect( lineEdit, &QLineEdit::textEdited, this, &QgsPanelWidget::widgetChanged );
654  }
655  tableTransparency->setCellWidget( row, column, lineEdit );
656  adjustTransparencyCellWidth( row, column );
657 
658  if ( nBands == 1 && ( column == 0 || column == 1 ) )
659  {
660  connect( lineEdit, &QLineEdit::textEdited, this, &QgsRasterTransparencyWidget::transparencyCellTextEdited );
661  }
662  tableTransparency->resizeColumnsToContents();
663  emit widgetChanged();
664 }
665 
666 void QgsRasterTransparencyWidget::adjustTransparencyCellWidth( int row, int column )
667 {
668  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( tableTransparency->cellWidget( row, column ) );
669  if ( !lineEdit ) return;
670 
671  int width = std::max( lineEdit->fontMetrics().boundingRect( lineEdit->text() ).width() + 10, 100 );
672  width = std::max( width, tableTransparency->columnWidth( column ) );
673 
674  lineEdit->setFixedWidth( width );
675 }
676 
677 void QgsRasterTransparencyWidget::setTransparencyToEdited( int row )
678 {
679  if ( row >= mTransparencyToEdited.size() )
680  {
681  mTransparencyToEdited.resize( row + 1 );
682  }
683  mTransparencyToEdited[row] = true;
684 }
685 
686 double QgsRasterTransparencyWidget::transparencyCellValue( int row, int column )
687 {
688  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( tableTransparency->cellWidget( row, column ) );
689  if ( !lineEdit || lineEdit->text().isEmpty() )
690  {
691  return std::numeric_limits<double>::quiet_NaN();
692  }
693  return lineEdit->text().toDouble();
694 
695 }
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:122
QgsMapSettings::mapToLayerCoordinates
QgsPointXY mapToLayerCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from output CRS to layer's CRS
Definition: qgsmapsettings.cpp:516
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
Definition: qgsmapcanvas.h:83
QgsRasterTransparency::TransparentThreeValuePixel::percentTransparent
double percentTransparent
Definition: qgsrastertransparency.h:50
QgsSettings
Definition: qgssettings.h:61
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:132
QgsRectangle
Definition: qgsrectangle.h:41
QgsMapLayerConfigWidget
A panel widget that can be shown in the map style dock.
Definition: qgsmaplayerconfigwidget.h:33
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:73
QgsRasterRenderer
Definition: qgsrasterrenderer.h:38
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
QgsRasterTransparencyWidget::apply
void apply() override
Apply any changes on the widget to the set layer.
Definition: qgsrastertransparencywidget.cpp:391
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:53
QgsMultiBandColorRenderer
Definition: qgsmultibandcolorrenderer.h:32
QgsRasterLayer
Definition: qgsrasterlayer.h:72
QgsRasterTransparency
Definition: qgsrastertransparency.h:32
qgsrastertransparency.h
qgsrasterlayerrenderer.h
QgsPointXY
Definition: qgspointxy.h:43
QgsMapToolEmitPoint
Definition: qgsmaptoolemitpoint.h:30
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:129
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
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:45
QgsRasterRange
Definition: qgsrasterrange.h:35
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:128
QgsMapSettings
Definition: qgsmapsettings.h:86
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
Definition: qgsrasterdataprovider.h:88
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:123