QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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  syncToLayer();
53 
54  connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsPanelWidget::widgetChanged );
55  connect( cboxTransparencyBand, &QgsRasterBandComboBox::bandChanged, this, &QgsPanelWidget::widgetChanged );
56  connect( mSrcNoDataValueCheckBox, &QCheckBox::stateChanged, this, &QgsPanelWidget::widgetChanged );
57  connect( leNoDataValue, &QLineEdit::textEdited, this, &QgsPanelWidget::widgetChanged );
58 
59  mPixelSelectorTool = nullptr;
60  if ( mMapCanvas )
61  {
62  mPixelSelectorTool = new QgsMapToolEmitPoint( mMapCanvas );
63  connect( mPixelSelectorTool, &QgsMapToolEmitPoint::canvasClicked, this, &QgsRasterTransparencyWidget::pixelSelected );
64  }
65  else
66  {
67  pbnAddValuesFromDisplay->setEnabled( false );
68  }
69 }
70 
72 {
73  if ( ! mRasterLayer->isValid() )
74  return;
75  QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
76  QgsRasterRenderer *renderer = mRasterLayer->renderer();
77  if ( provider )
78  {
79  if ( provider->dataType( 1 ) == Qgis::ARGB32
80  || provider->dataType( 1 ) == Qgis::ARGB32_Premultiplied )
81  {
82  gboxNoDataValue->setEnabled( false );
83  gboxCustomTransparency->setEnabled( false );
84  }
85 
86  cboxTransparencyBand->setShowNotSetOption( true, tr( "None" ) );
87  cboxTransparencyBand->setLayer( mRasterLayer );
88 
89  mOpacityWidget->setOpacity( renderer->opacity() );
90 
91  cboxTransparencyBand->setBand( renderer->alphaBand() );
92  }
93 
94  if ( mRasterLayer->dataProvider()->sourceHasNoDataValue( 1 ) )
95  {
96  lblSrcNoDataValue->setText( QgsRasterBlock::printValue( mRasterLayer->dataProvider()->sourceNoDataValue( 1 ) ) );
97  }
98  else
99  {
100  lblSrcNoDataValue->setText( tr( "not defined" ) );
101  }
102 
103  mSrcNoDataValueCheckBox->setChecked( mRasterLayer->dataProvider()->useSourceNoDataValue( 1 ) );
104 
105  bool enableSrcNoData = mRasterLayer->dataProvider()->sourceHasNoDataValue( 1 ) && !std::isnan( mRasterLayer->dataProvider()->sourceNoDataValue( 1 ) );
106 
107  mSrcNoDataValueCheckBox->setEnabled( enableSrcNoData );
108  lblSrcNoDataValue->setEnabled( enableSrcNoData );
109 
110  QgsRasterRangeList noDataRangeList = mRasterLayer->dataProvider()->userNoDataValues( 1 );
111  QgsDebugMsg( QStringLiteral( "noDataRangeList.size = %1" ).arg( noDataRangeList.size() ) );
112  if ( !noDataRangeList.isEmpty() )
113  {
114  leNoDataValue->insert( QgsRasterBlock::printValue( noDataRangeList.value( 0 ).min() ) );
115  }
116  else
117  {
118  leNoDataValue->insert( QString() );
119  }
120 
121  populateTransparencyTable( mRasterLayer->renderer() );
122 }
123 
124 void QgsRasterTransparencyWidget::transparencyCellTextEdited( const QString &text )
125 {
126  Q_UNUSED( text )
127  QgsDebugMsg( QStringLiteral( "text = %1" ).arg( text ) );
128  QgsRasterRenderer *renderer = mRasterLayer->renderer();
129  if ( !renderer )
130  {
131  return;
132  }
133  int nBands = renderer->usesBands().size();
134  if ( nBands == 1 )
135  {
136  QLineEdit *lineEdit = qobject_cast<QLineEdit *>( sender() );
137  if ( !lineEdit ) return;
138  int row = -1;
139  int column = -1;
140  for ( int r = 0; r < tableTransparency->rowCount(); r++ )
141  {
142  for ( int c = 0; c < tableTransparency->columnCount(); c++ )
143  {
144  if ( tableTransparency->cellWidget( r, c ) == sender() )
145  {
146  row = r;
147  column = c;
148  break;
149  }
150  }
151  if ( row != -1 ) break;
152  }
153  QgsDebugMsg( QStringLiteral( "row = %1 column =%2" ).arg( row ).arg( column ) );
154 
155  if ( column == 0 )
156  {
157  QLineEdit *toLineEdit = dynamic_cast<QLineEdit *>( tableTransparency->cellWidget( row, 1 ) );
158  if ( !toLineEdit ) return;
159  bool toChanged = mTransparencyToEdited.value( row );
160  QgsDebugMsg( QStringLiteral( "toChanged = %1" ).arg( toChanged ) );
161  if ( !toChanged )
162  {
163  toLineEdit->setText( lineEdit->text() );
164  }
165  }
166  else if ( column == 1 )
167  {
168  setTransparencyToEdited( row );
169  }
170  }
171  emit widgetChanged();
172 }
173 
174 void QgsRasterTransparencyWidget::pbnAddValuesFromDisplay_clicked()
175 {
176  if ( mMapCanvas && mPixelSelectorTool )
177  {
178  mMapCanvas->setMapTool( mPixelSelectorTool );
179  }
180 }
181 
182 void QgsRasterTransparencyWidget::pbnAddValuesManually_clicked()
183 {
184  QgsRasterRenderer *renderer = mRasterLayer->renderer();
185  if ( !renderer )
186  {
187  return;
188  }
189 
190  tableTransparency->insertRow( tableTransparency->rowCount() );
191 
192  int n = renderer->usesBands().size();
193  if ( n == 1 ) n++;
194 
195  for ( int i = 0; i < n; i++ )
196  {
197  setTransparencyCell( tableTransparency->rowCount() - 1, i, std::numeric_limits<double>::quiet_NaN() );
198  }
199 
200  setTransparencyCell( tableTransparency->rowCount() - 1, n, 100 );
201 
202  tableTransparency->resizeColumnsToContents();
203  tableTransparency->resizeRowsToContents();
204 }
205 
206 void QgsRasterTransparencyWidget::pbnDefaultValues_clicked()
207 {
208  QgsRasterRenderer *r = mRasterLayer->renderer();
209  if ( !r )
210  {
211  return;
212  }
213 
214  int nBands = r->usesBands().size();
215 
216  setupTransparencyTable( nBands );
217 
218  tableTransparency->resizeColumnsToContents(); // works only with values
219  tableTransparency->resizeRowsToContents();
220 
221 }
222 
223 void QgsRasterTransparencyWidget::pbnExportTransparentPixelValues_clicked()
224 {
225  QgsSettings myQSettings;
226  QString myLastDir = myQSettings.value( QStringLiteral( "lastRasterFileFilterDir" ), QDir::homePath() ).toString();
227  QString myFileName = QFileDialog::getSaveFileName( this, tr( "Save Pixel Values as File" ), myLastDir, tr( "Textfile" ) + " (*.txt)" );
228  if ( !myFileName.isEmpty() )
229  {
230  if ( !myFileName.endsWith( QLatin1String( ".txt" ), Qt::CaseInsensitive ) )
231  {
232  myFileName = myFileName + ".txt";
233  }
234 
235  QFile myOutputFile( myFileName );
236  if ( myOutputFile.open( QFile::WriteOnly | QIODevice::Truncate ) )
237  {
238  QTextStream myOutputStream( &myOutputFile );
239  myOutputStream << "# " << tr( "QGIS Generated Transparent Pixel Value Export File" ) << '\n';
240  if ( rasterIsMultiBandColor() )
241  {
242  myOutputStream << "#\n#\n# " << tr( "Red" ) << "\t" << tr( "Green" ) << "\t" << tr( "Blue" ) << "\t" << tr( "Percent Transparent" );
243  for ( int myTableRunner = 0; myTableRunner < tableTransparency->rowCount(); myTableRunner++ )
244  {
245  myOutputStream << '\n' << QString::number( transparencyCellValue( myTableRunner, 0 ) ) << "\t"
246  << QString::number( transparencyCellValue( myTableRunner, 1 ) ) << "\t"
247  << QString::number( transparencyCellValue( myTableRunner, 2 ) ) << "\t"
248  << QString::number( transparencyCellValue( myTableRunner, 3 ) );
249  }
250  }
251  else
252  {
253  myOutputStream << "#\n#\n# " << tr( "Value" ) << "\t" << tr( "Percent Transparent" );
254 
255  for ( int myTableRunner = 0; myTableRunner < tableTransparency->rowCount(); myTableRunner++ )
256  {
257  myOutputStream << '\n' << QString::number( transparencyCellValue( myTableRunner, 0 ) ) << "\t"
258  << QString::number( transparencyCellValue( myTableRunner, 1 ) ) << "\t"
259  << QString::number( transparencyCellValue( myTableRunner, 2 ) );
260  }
261  }
262  }
263  else
264  {
265  QMessageBox::warning( this, tr( "Save Pixel Values as File" ), tr( "Write access denied. Adjust the file permissions and try again.\n\n" ) );
266  }
267  }
268 }
269 
270 void QgsRasterTransparencyWidget::pbnImportTransparentPixelValues_clicked()
271 {
272  int myLineCounter = 0;
273  bool myImportError = false;
274  QString myBadLines;
275  QgsSettings myQSettings;
276  QString myLastDir = myQSettings.value( QStringLiteral( "lastRasterFileFilterDir" ), QDir::homePath() ).toString();
277  QString myFileName = QFileDialog::getOpenFileName( this, tr( "Load Pixel Values from File" ), myLastDir, tr( "Textfile" ) + " (*.txt)" );
278  QFile myInputFile( myFileName );
279  if ( myInputFile.open( QFile::ReadOnly ) )
280  {
281  QTextStream myInputStream( &myInputFile );
282  QString myInputLine;
283  if ( rasterIsMultiBandColor() )
284  {
285  for ( int myTableRunner = tableTransparency->rowCount() - 1; myTableRunner >= 0; myTableRunner-- )
286  {
287  tableTransparency->removeRow( myTableRunner );
288  }
289 
290  while ( !myInputStream.atEnd() )
291  {
292  myLineCounter++;
293  myInputLine = myInputStream.readLine();
294  if ( !myInputLine.isEmpty() )
295  {
296  if ( !myInputLine.simplified().startsWith( '#' ) )
297  {
298  QStringList myTokens = myInputLine.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
299  if ( myTokens.count() != 4 )
300  {
301  myImportError = true;
302  myBadLines = myBadLines + QString::number( myLineCounter ) + ":\t[" + myInputLine + "]\n";
303  }
304  else
305  {
306  tableTransparency->insertRow( tableTransparency->rowCount() );
307  for ( int col = 0; col < 4; col++ )
308  {
309  setTransparencyCell( tableTransparency->rowCount() - 1, col, myTokens[col].toDouble() );
310  }
311  }
312  }
313  }
314  }
315  }
316  else
317  {
318  for ( int myTableRunner = tableTransparency->rowCount() - 1; myTableRunner >= 0; myTableRunner-- )
319  {
320  tableTransparency->removeRow( myTableRunner );
321  }
322 
323  while ( !myInputStream.atEnd() )
324  {
325  myLineCounter++;
326  myInputLine = myInputStream.readLine();
327  if ( !myInputLine.isEmpty() )
328  {
329  if ( !myInputLine.simplified().startsWith( '#' ) )
330  {
331  QStringList myTokens = myInputLine.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
332  if ( myTokens.count() != 3 && myTokens.count() != 2 ) // 2 for QGIS < 1.9 compatibility
333  {
334  myImportError = true;
335  myBadLines = myBadLines + QString::number( myLineCounter ) + ":\t[" + myInputLine + "]\n";
336  }
337  else
338  {
339  if ( myTokens.count() == 2 )
340  {
341  myTokens.insert( 1, myTokens[0] ); // add 'to' value, QGIS < 1.9 compatibility
342  }
343  tableTransparency->insertRow( tableTransparency->rowCount() );
344  for ( int col = 0; col < 3; col++ )
345  {
346  setTransparencyCell( tableTransparency->rowCount() - 1, col, myTokens[col].toDouble() );
347  }
348  }
349  }
350  }
351  }
352  }
353 
354  if ( myImportError )
355  {
356  QMessageBox::warning( this, tr( "Load Pixel Values from File" ), tr( "The following lines contained errors\n\n%1" ).arg( myBadLines ) );
357  }
358  }
359  else if ( !myFileName.isEmpty() )
360  {
361  QMessageBox::warning( this, tr( "Load Pixel Values from File" ), tr( "Read access denied. Adjust the file permissions and try again.\n\n" ) );
362  }
363  tableTransparency->resizeColumnsToContents();
364  tableTransparency->resizeRowsToContents();
365  emit widgetChanged();
366 }
367 
368 void QgsRasterTransparencyWidget::pbnRemoveSelectedRow_clicked()
369 {
370  if ( 0 < tableTransparency->rowCount() )
371  {
372  tableTransparency->removeRow( tableTransparency->currentRow() );
373  }
374  emit widgetChanged();
375 }
376 
377 bool QgsRasterTransparencyWidget::rasterIsMultiBandColor()
378 {
379  return mRasterLayer && nullptr != dynamic_cast<QgsMultiBandColorRenderer *>( mRasterLayer->renderer() );
380 }
381 
383 {
384  //set NoDataValue
385  QgsRasterRangeList myNoDataRangeList;
386  if ( "" != leNoDataValue->text() )
387  {
388  bool myDoubleOk = false;
389  double myNoDataValue = leNoDataValue->text().toDouble( &myDoubleOk );
390  if ( myDoubleOk )
391  {
392  QgsRasterRange myNoDataRange( myNoDataValue, myNoDataValue );
393  myNoDataRangeList << myNoDataRange;
394  }
395  }
396  for ( int bandNo = 1; bandNo <= mRasterLayer->dataProvider()->bandCount(); bandNo++ )
397  {
398  mRasterLayer->dataProvider()->setUserNoDataValue( bandNo, myNoDataRangeList );
399  mRasterLayer->dataProvider()->setUseSourceNoDataValue( bandNo, mSrcNoDataValueCheckBox->isChecked() );
400  }
401 
402  //transparency settings
403  QgsRasterRenderer *rasterRenderer = mRasterLayer->renderer();
404  if ( rasterRenderer )
405  {
406  rasterRenderer->setAlphaBand( cboxTransparencyBand->currentBand() );
407 
408  //Walk through each row in table and test value. If not valid set to 0.0 and continue building transparency list
409  QgsRasterTransparency *rasterTransparency = new QgsRasterTransparency();
410  if ( tableTransparency->columnCount() == 4 )
411  {
413  QList<QgsRasterTransparency::TransparentThreeValuePixel> myTransparentThreeValuePixelList;
414  myTransparentThreeValuePixelList.reserve( tableTransparency->rowCount() );
415  for ( int myListRunner = 0; myListRunner < tableTransparency->rowCount(); myListRunner++ )
416  {
417  myTransparentPixel.red = transparencyCellValue( myListRunner, 0 );
418  myTransparentPixel.green = transparencyCellValue( myListRunner, 1 );
419  myTransparentPixel.blue = transparencyCellValue( myListRunner, 2 );
420  myTransparentPixel.percentTransparent = transparencyCellValue( myListRunner, 3 );
421  myTransparentThreeValuePixelList.append( myTransparentPixel );
422  }
423  rasterTransparency->setTransparentThreeValuePixelList( myTransparentThreeValuePixelList );
424  }
425  else if ( tableTransparency->columnCount() == 3 )
426  {
428  QList<QgsRasterTransparency::TransparentSingleValuePixel> myTransparentSingleValuePixelList;
429  myTransparentSingleValuePixelList.reserve( tableTransparency->rowCount() );
430  for ( int myListRunner = 0; myListRunner < tableTransparency->rowCount(); myListRunner++ )
431  {
432  myTransparentPixel.min = transparencyCellValue( myListRunner, 0 );
433  myTransparentPixel.max = transparencyCellValue( myListRunner, 1 );
434  myTransparentPixel.percentTransparent = transparencyCellValue( myListRunner, 2 );
435 
436  myTransparentSingleValuePixelList.append( myTransparentPixel );
437  }
438  rasterTransparency->setTransparentSingleValuePixelList( myTransparentSingleValuePixelList );
439  }
440 
441  rasterRenderer->setRasterTransparency( rasterTransparency );
442 
443  //set global transparency
444  rasterRenderer->setOpacity( mOpacityWidget->opacity() );
445  }
446 }
447 
448 void QgsRasterTransparencyWidget::pixelSelected( const QgsPointXY &canvasPoint )
449 {
450  QgsRasterRenderer *renderer = mRasterLayer->renderer();
451  if ( !renderer )
452  {
453  return;
454  }
455 
456  //Get the pixel values and add a new entry to the transparency table
457  if ( mMapCanvas && mPixelSelectorTool )
458  {
459  mMapCanvas->unsetMapTool( mPixelSelectorTool );
460 
461  const QgsMapSettings &ms = mMapCanvas->mapSettings();
462  QgsPointXY myPoint = ms.mapToLayerCoordinates( mRasterLayer, canvasPoint );
463 
464  QgsRectangle myExtent = ms.mapToLayerCoordinates( mRasterLayer, mMapCanvas->extent() );
465  double mapUnitsPerPixel = mMapCanvas->mapUnitsPerPixel();
466  int myWidth = mMapCanvas->extent().width() / mapUnitsPerPixel;
467  int myHeight = mMapCanvas->extent().height() / mapUnitsPerPixel;
468 
469  QMap<int, QVariant> myPixelMap = mRasterLayer->dataProvider()->identify( myPoint, QgsRaster::IdentifyFormatValue, myExtent, myWidth, myHeight ).results();
470 
471  QList<int> bands = renderer->usesBands();
472 
473  QList<double> values;
474  for ( int i = 0; i < bands.size(); ++i )
475  {
476  int bandNo = bands.value( i );
477  if ( myPixelMap.count( bandNo ) == 1 )
478  {
479  if ( myPixelMap.value( bandNo ).isNull() )
480  {
481  return; // Don't add nodata, transparent anyway
482  }
483  double value = myPixelMap.value( bandNo ).toDouble();
484  QgsDebugMsg( QStringLiteral( "value = %1" ).arg( value, 0, 'g', 17 ) );
485  values.append( value );
486  }
487  }
488  if ( bands.size() == 1 )
489  {
490  // Set 'to'
491  values.insert( 1, values.value( 0 ) );
492  }
493  tableTransparency->insertRow( tableTransparency->rowCount() );
494  for ( int i = 0; i < values.size(); i++ )
495  {
496  setTransparencyCell( tableTransparency->rowCount() - 1, i, values.value( i ) );
497  }
498  setTransparencyCell( tableTransparency->rowCount() - 1, tableTransparency->columnCount() - 1, 100 );
499  }
500 
501  tableTransparency->resizeColumnsToContents();
502  tableTransparency->resizeRowsToContents();
503 }
504 
505 void QgsRasterTransparencyWidget::populateTransparencyTable( QgsRasterRenderer *renderer )
506 {
507  if ( !mRasterLayer )
508  {
509  return;
510  }
511 
512  if ( !renderer )
513  {
514  return;
515  }
516 
517  int nBands = renderer->usesBands().size();
518  setupTransparencyTable( nBands );
519 
520  const QgsRasterTransparency *rasterTransparency = renderer->rasterTransparency();
521  if ( !rasterTransparency )
522  {
523  return;
524  }
525 
526  if ( nBands == 1 )
527  {
528  QList<QgsRasterTransparency::TransparentSingleValuePixel> pixelList = rasterTransparency->transparentSingleValuePixelList();
529  for ( int i = 0; i < pixelList.size(); ++i )
530  {
531  tableTransparency->insertRow( i );
532  setTransparencyCell( i, 0, pixelList[i].min );
533  setTransparencyCell( i, 1, pixelList[i].max );
534  setTransparencyCell( i, 2, pixelList[i].percentTransparent );
535  // break synchronization only if values differ
536  if ( pixelList[i].min != pixelList[i].max )
537  {
538  setTransparencyToEdited( i );
539  }
540  }
541  }
542  else if ( nBands == 3 )
543  {
544  QList<QgsRasterTransparency::TransparentThreeValuePixel> pixelList = rasterTransparency->transparentThreeValuePixelList();
545  for ( int i = 0; i < pixelList.size(); ++i )
546  {
547  tableTransparency->insertRow( i );
548  setTransparencyCell( i, 0, pixelList[i].red );
549  setTransparencyCell( i, 1, pixelList[i].green );
550  setTransparencyCell( i, 2, pixelList[i].blue );
551  setTransparencyCell( i, 3, pixelList[i].percentTransparent );
552  }
553  }
554 
555  tableTransparency->resizeColumnsToContents();
556  tableTransparency->resizeRowsToContents();
557 
558 }
559 
560 void QgsRasterTransparencyWidget::setupTransparencyTable( int nBands )
561 {
562  tableTransparency->clear();
563  tableTransparency->setColumnCount( 0 );
564  tableTransparency->setRowCount( 0 );
565  mTransparencyToEdited.clear();
566 
567  if ( nBands == 3 )
568  {
569  tableTransparency->setColumnCount( 4 );
570  tableTransparency->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Red" ) ) );
571  tableTransparency->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr( "Green" ) ) );
572  tableTransparency->setHorizontalHeaderItem( 2, new QTableWidgetItem( tr( "Blue" ) ) );
573  tableTransparency->setHorizontalHeaderItem( 3, new QTableWidgetItem( tr( "Percent Transparent" ) ) );
574  }
575  else //1 band
576  {
577  tableTransparency->setColumnCount( 3 );
578 // Is it important to distinguish the header? It becomes difficult with range.
579 #if 0
580  if ( QgsRasterLayer::PalettedColor != mRasterLayer->drawingStyle() &&
581  QgsRasterLayer::PalettedSingleBandGray != mRasterLayer->drawingStyle() &&
582  QgsRasterLayer::PalettedSingleBandPseudoColor != mRasterLayer->drawingStyle() &&
583  QgsRasterLayer::PalettedMultiBandColor != mRasterLayer->drawingStyle() )
584  {
585  tableTransparency->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Gray" ) ) );
586  }
587  else
588  {
589  tableTransparency->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Indexed Value" ) ) );
590  }
591 #endif
592  tableTransparency->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "From" ) ) );
593  tableTransparency->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr( "To" ) ) );
594  tableTransparency->setHorizontalHeaderItem( 2, new QTableWidgetItem( tr( "Percent Transparent" ) ) );
595  }
596 }
597 
598 void QgsRasterTransparencyWidget::setTransparencyCell( int row, int column, double value )
599 {
600  QgsDebugMsg( QStringLiteral( "value = %1" ).arg( value, 0, 'g', 17 ) );
601  QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
602  if ( !provider ) return;
603 
604  QgsRasterRenderer *renderer = mRasterLayer->renderer();
605  if ( !renderer ) return;
606  int nBands = renderer->usesBands().size();
607 
608  QLineEdit *lineEdit = new QLineEdit();
609  lineEdit->setFrame( false ); // frame looks bad in table
610  // Without margins row selection is not displayed (important for delete row)
611  lineEdit->setContentsMargins( 1, 1, 1, 1 );
612 
613  if ( column == tableTransparency->columnCount() - 1 )
614  {
615  // transparency
616  // Who needs transparency as floating point?
617  lineEdit->setValidator( new QIntValidator( nullptr ) );
618  lineEdit->setText( QString::number( static_cast<int>( value ) ) );
619  }
620  else
621  {
622  // value
623  QString valueString;
624  switch ( provider->sourceDataType( 1 ) )
625  {
626  case Qgis::Float32:
627  case Qgis::Float64:
628  lineEdit->setValidator( new QDoubleValidator( nullptr ) );
629  if ( !std::isnan( value ) )
630  {
631  valueString = QgsRasterBlock::printValue( value );
632  }
633  break;
634  default:
635  lineEdit->setValidator( new QIntValidator( nullptr ) );
636  if ( !std::isnan( value ) )
637  {
638  valueString = QString::number( static_cast<int>( value ) );
639  }
640  break;
641  }
642  lineEdit->setText( valueString );
643  connect( lineEdit, &QLineEdit::textEdited, this, &QgsPanelWidget::widgetChanged );
644  }
645  tableTransparency->setCellWidget( row, column, lineEdit );
646  adjustTransparencyCellWidth( row, column );
647 
648  if ( nBands == 1 && ( column == 0 || column == 1 ) )
649  {
650  connect( lineEdit, &QLineEdit::textEdited, this, &QgsRasterTransparencyWidget::transparencyCellTextEdited );
651  }
652  tableTransparency->resizeColumnsToContents();
653  emit widgetChanged();
654 }
655 
656 void QgsRasterTransparencyWidget::adjustTransparencyCellWidth( int row, int column )
657 {
658  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( tableTransparency->cellWidget( row, column ) );
659  if ( !lineEdit ) return;
660 
661  int width = std::max( lineEdit->fontMetrics().width( lineEdit->text() ) + 10, 100 );
662  width = std::max( width, tableTransparency->columnWidth( column ) );
663 
664  lineEdit->setFixedWidth( width );
665 }
666 
667 void QgsRasterTransparencyWidget::setTransparencyToEdited( int row )
668 {
669  if ( row >= mTransparencyToEdited.size() )
670  {
671  mTransparencyToEdited.resize( row + 1 );
672  }
673  mTransparencyToEdited[row] = true;
674 }
675 
676 double QgsRasterTransparencyWidget::transparencyCellValue( int row, int column )
677 {
678  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( tableTransparency->cellWidget( row, column ) );
679  if ( !lineEdit || lineEdit->text().isEmpty() )
680  {
681  std::numeric_limits<double>::quiet_NaN();
682  }
683  return lineEdit->text().toDouble();
684 
685 }
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:58
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
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
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
Thirty two bit floating point (float)
Definition: qgis.h:87
bool isValid() const
Returns the status of the layer.
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:73
const QgsRasterTransparency * rasterTransparency() const
Sixty four bit floating point (double)
Definition: qgis.h:88
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:94
QgsRasterDataProvider * dataProvider() override
Returns the layer&#39;s data provider, it may be nullptr.
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)
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.
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.
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
Definition: qgis.h:93
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:209
Base class for raster data providers.