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