QGIS API Documentation  3.15.0-Master (4fe3d2f4e6)
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 }
void unsetMapTool(QgsMapTool *mapTool)
Unset the current map tool or last non zoom tool.
A panel widget that can be shown in the map style dock.
virtual int bandCount() const =0
Gets number of bands.
QgsRasterTransparencyWidget(QgsRasterLayer *layer, QgsMapCanvas *canvas, QWidget *parent=nullptr)
Widget to control a layers transparency and related options.
A rectangle specified with double values.
Definition: qgsrectangle.h:41
static QString printValue(double value)
Print double value with all necessary significant digits.
virtual void setUseSourceNoDataValue(int bandNo, bool use)
Sets the source nodata value usage.
void setTransparentThreeValuePixelList(const QList< QgsRasterTransparency::TransparentThreeValuePixel > &newList)
Sets the transparent three value pixel list, replacing the whole existing list.
void canvasClicked(const QgsPointXY &point, Qt::MouseButton button)
signal emitted on canvas click
This class is a composition of two QSettings instances:
Definition: qgssettings.h:61
QColor nodataColor() const
Returns the color to use for shading nodata pixels.
virtual QList< int > usesBands() const
Returns a list of band numbers used by the renderer.
double opacity() const
Returns the opacity for the renderer, where opacity is a value between 0 (totally transparent) and 1...
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
Represents a raster layer.
A class to represent a 2D point.
Definition: qgspointxy.h:43
Qgis::DataType sourceDataType(int bandNo) const override=0
Returns source data type for the band specified by number, source data type may be shorter than dataT...
Raster values range container.
QgsRasterRenderer * renderer() const
Returns the raster&#39;s renderer.
Thirty two bit floating point (float)
Definition: qgis.h:109
virtual double sourceNoDataValue(int bandNo) const
Value representing no data value.
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:84
const QgsRasterTransparency * rasterTransparency() const
Sixty four bit floating point (double)
Definition: qgis.h:110
The QgsMapSettings class contains configuration for rendering of the map.
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
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
Definition: qgis.h:116
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
void setMapTool(QgsMapTool *mapTool, bool clean=false)
Sets the map tool currently being used on the canvas.
void syncToLayer()
Sync the widget state to the layer set for the widget.
double mapUnitsPerPixel() const
Returns the mapUnitsPerPixel (map units per pixel) for the canvas.
void opacityChanged(double opacity)
Emitted when the opacity is changed in the widget, where opacity ranges from 0.0 (transparent) to 1...
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:202
void bandChanged(int band)
Emitted when the currently selected band changes.
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
void setAlphaBand(int band)
QgsDoubleValidator is a QLineEdit Validator that combines QDoubleValidator and QRegularExpressionVali...
void apply() override
Apply any changes on the widget to the set layer.
void widgetChanged()
Emitted when the widget state changes.
virtual bool sourceHasNoDataValue(int bandNo) const
Returns true if source band has no data value.
QList< QgsRasterTransparency::TransparentSingleValuePixel > transparentSingleValuePixelList() const
Returns the transparent single value pixel list.
QMap< int, QVariant > results() const
Returns the identify results.
void setTransparentSingleValuePixelList(const QList< QgsRasterTransparency::TransparentSingleValuePixel > &newList)
Sets the transparent single value pixel list, replacing the whole existing list.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
void colorChanged(const QColor &color)
Emitted whenever a new color is set for the button.
void setNodataColor(const QColor &color)
Sets the color to use for shading nodata pixels.
QList< QgsRasterRange > QgsRasterRangeList
virtual QgsRasterIdentifyResult identify(const QgsPointXY &point, QgsRaster::IdentifyFormat format, const QgsRectangle &boundingBox=QgsRectangle(), int width=0, int height=0, int dpi=96)
Identify raster value(s) found on the point position.
Renderer for multiband images with the color components.
virtual QgsRasterRangeList userNoDataValues(int bandNo) const
Returns a list of user no data value ranges.
Defines the list of pixel values to be considered as transparent or semi transparent when rendering r...
void setOpacity(double opacity)
Sets the opacity for the renderer, where opacity is a value between 0 (totally transparent) and 1...
virtual bool useSourceNoDataValue(int bandNo) const
Returns the source nodata value usage.
QList< QgsRasterTransparency::TransparentThreeValuePixel > transparentThreeValuePixelList() const
Returns the transparent three value pixel list.
virtual void setUserNoDataValue(int bandNo, const QgsRasterRangeList &noData)
QgsPointXY mapToLayerCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from output CRS to layer&#39;s CRS
void setRasterTransparency(QgsRasterTransparency *t)
A map tool that simply emits a point when clicking on the map.
Raster renderer pipe that applies colors to a raster.
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
static double toDouble(const QString &input, bool *ok)
Converts input string to double value.
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
Definition: qgis.h:115
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:209
Base class for raster data providers.