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