QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgscolorrampshaderwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscolorrampshaderwidget.cpp
3  ----------------------------
4  begin : Jun 2018
5  copyright : (C) 2018 by Peter Petrik
6  email : zilolv at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgsrasterdataprovider.h"
19 
22 #include "qgsrasterlayer.h"
23 #include "qgsrasterdataprovider.h"
24 #include "qgsrastershader.h"
25 #include "qgsrasterminmaxwidget.h"
26 #include "qgstreewidgetitem.h"
27 #include "qgssettings.h"
28 #include "qgsstyle.h"
29 #include "qgscolorramp.h"
30 #include "qgscolorrampbutton.h"
31 #include "qgscolordialog.h"
32 #include "qgsrasterrendererutils.h"
33 #include "qgsfileutils.h"
34 #include "qgsguiutils.h"
35 #include "qgsdoublevalidator.h"
38 
39 #include <QCursor>
40 #include <QPushButton>
41 #include <QInputDialog>
42 #include <QFileDialog>
43 #include <QMenu>
44 #include <QMessageBox>
45 #include <QTextStream>
46 #include <QTreeView>
47 
48 
50  : QWidget( parent )
51 {
52  QgsSettings settings;
53 
54  setupUi( this );
55  mLoadFromBandButton->setVisible( false ); // only for raster version
56 
57  connect( mAddEntryButton, &QPushButton::clicked, this, &QgsColorRampShaderWidget::mAddEntryButton_clicked );
58  connect( mDeleteEntryButton, &QPushButton::clicked, this, &QgsColorRampShaderWidget::mDeleteEntryButton_clicked );
59  connect( mLoadFromBandButton, &QPushButton::clicked, this, &QgsColorRampShaderWidget::mLoadFromBandButton_clicked );
60  connect( mLoadFromFileButton, &QPushButton::clicked, this, &QgsColorRampShaderWidget::mLoadFromFileButton_clicked );
61  connect( mExportToFileButton, &QPushButton::clicked, this, &QgsColorRampShaderWidget::mExportToFileButton_clicked );
62  connect( mUnitLineEdit, &QLineEdit::textEdited, this, &QgsColorRampShaderWidget::mUnitLineEdit_textEdited );
63  connect( mColormapTreeWidget, &QTreeWidget::itemDoubleClicked, this, &QgsColorRampShaderWidget::mColormapTreeWidget_itemDoubleClicked );
64  connect( mColorInterpolationComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsColorRampShaderWidget::mColorInterpolationComboBox_currentIndexChanged );
65  connect( mClassificationModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsColorRampShaderWidget::mClassificationModeComboBox_currentIndexChanged );
66 
67  connect( mLegendSettingsButton, &QPushButton::clicked, this, &QgsColorRampShaderWidget::showLegendSettings );
68 
69  contextMenu = new QMenu( tr( "Options" ), this );
70  contextMenu->addAction( tr( "Change Color…" ), this, SLOT( changeColor() ) );
71  contextMenu->addAction( tr( "Change Opacity…" ), this, SLOT( changeOpacity() ) );
72 
73  mColormapTreeWidget->setItemDelegateForColumn( ColorColumn, new QgsColorSwatchDelegate( this ) );
74  mValueDelegate = new QgsLocaleAwareNumericLineEditDelegate( Qgis::DataType::UnknownDataType, this );
75  mColormapTreeWidget->setItemDelegateForColumn( ValueColumn, mValueDelegate );
76 
77  mColormapTreeWidget->setColumnWidth( ColorColumn, Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 6.6 );
78 
79  mColormapTreeWidget->setContextMenuPolicy( Qt::CustomContextMenu );
80  mColormapTreeWidget->setSelectionMode( QAbstractItemView::ExtendedSelection );
81  connect( mColormapTreeWidget, &QTreeView::customContextMenuRequested, this, [ = ]( QPoint ) { contextMenu->exec( QCursor::pos() ); } );
82 
83  QString defaultPalette = settings.value( QStringLiteral( "Raster/defaultPalette" ), "" ).toString();
84  btnColorRamp->setColorRampFromName( defaultPalette );
85 
86  mColorInterpolationComboBox->addItem( tr( "Discrete" ), QgsColorRampShader::Discrete );
87  mColorInterpolationComboBox->addItem( tr( "Linear" ), QgsColorRampShader::Interpolated );
88  mColorInterpolationComboBox->addItem( tr( "Exact" ), QgsColorRampShader::Exact );
89  mColorInterpolationComboBox->setCurrentIndex( mColorInterpolationComboBox->findData( QgsColorRampShader::Interpolated ) );
90 
91  mClassificationModeComboBox->addItem( tr( "Continuous" ), QgsColorRampShader::Continuous );
92  mClassificationModeComboBox->addItem( tr( "Equal Interval" ), QgsColorRampShader::EqualInterval );
93  // Quantile added only on demand
94  mClassificationModeComboBox->setCurrentIndex( mClassificationModeComboBox->findData( QgsColorRampShader::Continuous ) );
95 
96  mNumberOfEntriesSpinBox->setValue( 5 ); // some default
97 
98  mClassificationModeComboBox_currentIndexChanged( 0 );
99 
100  resetClassifyButton();
101 
102  connect( mClassificationModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsColorRampShaderWidget::classify );
103  connect( mColorInterpolationComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsColorRampShaderWidget::classify );
104  connect( mClassifyButton, &QPushButton::clicked, this, &QgsColorRampShaderWidget::classify );
105  connect( btnColorRamp, &QgsColorRampButton::colorRampChanged, this, &QgsColorRampShaderWidget::applyColorRamp );
106  connect( mNumberOfEntriesSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsColorRampShaderWidget::classify );
107  connect( mClipCheckBox, &QAbstractButton::toggled, this, &QgsColorRampShaderWidget::widgetChanged );
108  connect( mLabelPrecisionSpinBox, qOverload<int>( &QSpinBox::valueChanged ), this, [ = ]( int )
109  {
110  autoLabel();
111  } );
112 }
113 
115 {
116  Q_ASSERT( mClassificationModeComboBox->findData( QgsColorRampShader::Quantile < 0 ) );
117  mClassificationModeComboBox->addItem( tr( "Quantile" ), QgsColorRampShader::Quantile );
118 }
119 
121 {
122  mRasterDataProvider = dp;
123  mLoadFromBandButton->setVisible( bool( mRasterDataProvider ) ); // only for raster version
124 }
125 
127 {
128  mBand = band;
129  // Assume double by default
130  Qgis::DataType dataType { ( mRasterDataProvider &&mBand > 0 ) ? mRasterDataProvider->dataType( mBand ) : Qgis::DataType::Float64 };
131 
132  // Set the maximum number of digits in the precision spin box
133  const int maxDigits { QgsGuiUtils::significantDigits( dataType ) };
134  mLabelPrecisionSpinBox->setMaximum( maxDigits );
135  mValueDelegate->setDataType( dataType );
136 }
137 
139 {
140  mExtent = extent;
141 }
142 
144 {
145  QgsColorRampShader colorRampShader( mMin, mMax );
146  colorRampShader.setLabelPrecision( mLabelPrecisionSpinBox->value() );
147  colorRampShader.setColorRampType( static_cast< QgsColorRampShader::Type >( mColorInterpolationComboBox->currentData().toInt() ) );
148  colorRampShader.setClassificationMode( static_cast< QgsColorRampShader::ClassificationMode >( mClassificationModeComboBox->currentData().toInt() ) );
149  colorRampShader.setClip( mClipCheckBox->isChecked() );
150 
151  //iterate through mColormapTreeWidget and set colormap info of layer
152  QList<QgsColorRampShader::ColorRampItem> colorRampItems;
153  int topLevelItemCount = mColormapTreeWidget->topLevelItemCount();
154  QTreeWidgetItem *currentItem = nullptr;
155  for ( int i = 0; i < topLevelItemCount; ++i )
156  {
157  currentItem = mColormapTreeWidget->topLevelItem( i );
158  if ( !currentItem )
159  {
160  continue;
161  }
162  QgsColorRampShader::ColorRampItem newColorRampItem;
163  newColorRampItem.value = currentItem->data( ValueColumn, Qt::ItemDataRole::DisplayRole ).toDouble();
164  newColorRampItem.color = currentItem->data( ColorColumn, Qt::ItemDataRole::EditRole ).value<QColor>();
165  newColorRampItem.label = currentItem->text( LabelColumn );
166  colorRampItems.append( newColorRampItem );
167  }
168  // sort the shader items
169  std::sort( colorRampItems.begin(), colorRampItems.end() );
170  colorRampShader.setColorRampItemList( colorRampItems );
171 
172  if ( !btnColorRamp->isNull() )
173  {
174  colorRampShader.setSourceColorRamp( btnColorRamp->colorRamp() );
175  }
176 
177  colorRampShader.setLegendSettings( new QgsColorRampLegendNodeSettings( mLegendSettings ) );
178  return colorRampShader;
179 }
180 
181 void QgsColorRampShaderWidget::autoLabel()
182 {
183 
184  mColormapTreeWidget->sortItems( ValueColumn, Qt::AscendingOrder );
185 
186 #ifdef QGISDEBUG
187  dumpClasses();
188 #endif
189 
190  const QString unit = mUnitLineEdit->text();
191  int topLevelItemCount = mColormapTreeWidget->topLevelItemCount();
192 
193  QTreeWidgetItem *currentItem = nullptr;
194  for ( int i = 0; i < topLevelItemCount; ++i )
195  {
196  currentItem = mColormapTreeWidget->topLevelItem( i );
197  //If the item is null or does not have a pixel values set, skip
198  if ( !currentItem || currentItem->data( ValueColumn, Qt::ItemDataRole::DisplayRole ).toString().isEmpty() )
199  {
200  continue;
201  }
202 
203  const QString lbl = createLabel( currentItem, i, unit );
204 
205  if ( currentItem->text( LabelColumn ).isEmpty() || currentItem->text( LabelColumn ) == lbl || currentItem->foreground( LabelColumn ).color() == QColor( Qt::gray ) )
206  {
207  currentItem->setText( LabelColumn, lbl );
208  currentItem->setForeground( LabelColumn, QBrush( QColor( Qt::gray ) ) );
209  }
210  }
211 
212 }
213 
214 void QgsColorRampShaderWidget::setUnitFromLabels()
215 {
216  QStringList allSuffixes;
217  QString label;
218  int topLevelItemCount = mColormapTreeWidget->topLevelItemCount();
219  QTreeWidgetItem *currentItem = nullptr;
220  for ( int i = 0; i < topLevelItemCount; ++i )
221  {
222  currentItem = mColormapTreeWidget->topLevelItem( i );
223  //If the item is null or does not have a pixel values set, skip
224  if ( !currentItem || currentItem->text( ValueColumn ).isEmpty() )
225  {
226  continue;
227  }
228 
229  label = createLabel( currentItem, i, QString() );
230 
231  if ( currentItem->text( LabelColumn ).startsWith( label ) )
232  {
233  allSuffixes.append( currentItem->text( LabelColumn ).mid( label.length() ) );
234  }
235  }
236  // find most common suffix
237  QStringList suffixes = QStringList( allSuffixes );
238  suffixes.removeDuplicates();
239  int max = 0;
240  QString unit;
241  for ( int i = 0; i < suffixes.count(); ++i )
242  {
243  int n = allSuffixes.count( suffixes[i] );
244  if ( n > max )
245  {
246  max = n;
247  unit = suffixes[i];
248  }
249  }
250  // Set this suffix as unit if at least used twice
251  if ( max >= 2 )
252  {
253  mUnitLineEdit->setText( unit );
254  }
255 }
256 
257 #ifdef QGISDEBUG
258 void QgsColorRampShaderWidget::dumpClasses()
259 {
260  for ( int row = 0; row < mColormapTreeWidget->model()->rowCount(); ++row )
261  {
262  const auto labelData { mColormapTreeWidget->model()->itemData( mColormapTreeWidget->model()->index( row, LabelColumn ) ) };
263  const auto valueData { mColormapTreeWidget->model()->itemData( mColormapTreeWidget->model()->index( row, ValueColumn ) ) };
264  QgsDebugMsgLevel( QStringLiteral( "Class %1 : %2 %3" ).arg( row )
265  .arg( labelData[ Qt::ItemDataRole::DisplayRole ].toString(),
266  valueData[ Qt::ItemDataRole::DisplayRole ].toString() ), 2 );
267  }
268 }
269 #endif
270 
271 void QgsColorRampShaderWidget::mAddEntryButton_clicked()
272 {
273  QgsTreeWidgetItemObject *newItem = new QgsTreeWidgetItemObject( mColormapTreeWidget );
274  newItem->setData( ValueColumn, Qt::ItemDataRole::DisplayRole, 0 );
275  newItem->setData( ColorColumn, Qt::ItemDataRole::EditRole, QColor( Qt::magenta ) );
276  newItem->setText( LabelColumn, QString() );
277  newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable );
278  connect( newItem, &QgsTreeWidgetItemObject::itemEdited,
279  this, &QgsColorRampShaderWidget::mColormapTreeWidget_itemEdited );
280  autoLabel();
281 
283  updateColorRamp();
284  emit widgetChanged();
285 }
286 
287 void QgsColorRampShaderWidget::mDeleteEntryButton_clicked()
288 {
289  QList<QTreeWidgetItem *> itemList;
290  itemList = mColormapTreeWidget->selectedItems();
291  if ( itemList.isEmpty() )
292  {
293  return;
294  }
295 
296  const auto constItemList = itemList;
297  for ( QTreeWidgetItem *item : constItemList )
298  {
299  delete item;
300  }
301 
303  updateColorRamp();
304  emit widgetChanged();
305 }
306 
308 {
309  std::unique_ptr< QgsColorRamp > ramp( btnColorRamp->colorRamp() );
310  if ( !ramp || std::isnan( mMin ) || std::isnan( mMax ) )
311  {
312  return;
313  }
314 
315  std::unique_ptr< QgsColorRampShader > colorRampShader( new QgsColorRampShader(
316  mMin, mMax,
317  ramp.release(),
318  static_cast< QgsColorRampShader::Type >( mColorInterpolationComboBox->currentData().toInt() ),
319  static_cast< QgsColorRampShader::ClassificationMode >( mClassificationModeComboBox->currentData().toInt() ) )
320  );
321 
322  // only for Quantile we need band and provider and extent
323  colorRampShader->classifyColorRamp( mNumberOfEntriesSpinBox->value(),
324  mBand,
325  mExtent,
326  mRasterDataProvider );
327  colorRampShader->setClip( mClipCheckBox->isChecked() );
328 
329  mColormapTreeWidget->clear();
330 
331  const QList<QgsColorRampShader::ColorRampItem> colorRampItemList = colorRampShader->colorRampItemList();
332  QList<QgsColorRampShader::ColorRampItem>::const_iterator it = colorRampItemList.constBegin();
333  for ( ; it != colorRampItemList.end(); ++it )
334  {
335  QgsTreeWidgetItemObject *newItem = new QgsTreeWidgetItemObject( mColormapTreeWidget );
336  newItem->setData( ValueColumn, Qt::ItemDataRole::DisplayRole, it->value );
337  newItem->setData( ColorColumn, Qt::ItemDataRole::EditRole, it->color );
338  newItem->setText( LabelColumn, QString() ); // Labels will be populated in autoLabel()
339  newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable );
340  connect( newItem, &QgsTreeWidgetItemObject::itemEdited,
341  this, &QgsColorRampShaderWidget::mColormapTreeWidget_itemEdited );
342  }
343 
344  mClipCheckBox->setChecked( colorRampShader->clip() );
345 
346  autoLabel();
347  emit widgetChanged();
348 }
349 
350 void QgsColorRampShaderWidget::mClassificationModeComboBox_currentIndexChanged( int index )
351 {
352  QgsColorRampShader::ClassificationMode mode = static_cast< QgsColorRampShader::ClassificationMode >( mClassificationModeComboBox->itemData( index ).toInt() );
353  mNumberOfEntriesSpinBox->setEnabled( mode != QgsColorRampShader::Continuous );
354  emit classificationModeChanged( mode );
355 }
356 
357 void QgsColorRampShaderWidget::updateColorRamp()
358 {
359  std::unique_ptr< QgsColorRamp > ramp( shader().createColorRamp() );
360  whileBlocking( btnColorRamp )->setColorRamp( ramp.get() );
361 }
362 
363 void QgsColorRampShaderWidget::applyColorRamp()
364 {
365  std::unique_ptr< QgsColorRamp > ramp( btnColorRamp->colorRamp() );
366  if ( !ramp )
367  {
368  return;
369  }
370 
371  if ( !btnColorRamp->colorRampName().isEmpty() )
372  {
373  // Remember last used color ramp
374  QgsSettings settings;
375  settings.setValue( QStringLiteral( "Raster/defaultPalette" ), btnColorRamp->colorRampName() );
376  }
377 
378  bool enableContinuous = ( ramp->count() > 0 );
379  mClassificationModeComboBox->setEnabled( enableContinuous );
380  if ( !enableContinuous )
381  {
382  mClassificationModeComboBox->setCurrentIndex( mClassificationModeComboBox->findData( QgsColorRampShader::EqualInterval ) );
383  }
384 
385  int topLevelItemCount = mColormapTreeWidget->topLevelItemCount();
386  if ( topLevelItemCount > 0 )
387  {
388  // We need to have valid min/max values here. If we haven't, load from colormap
389  double min, max;
390  if ( std::isnan( mMin ) || std::isnan( mMax ) )
391  {
392  colormapMinMax( min, max );
393  }
394  else
395  {
396  min = mMin;
397  max = mMax;
398  }
399 
400  // if the list values has been customized, maintain pre-existing values
401  QTreeWidgetItem *currentItem = nullptr;
402  for ( int i = 0; i < topLevelItemCount; ++i )
403  {
404  currentItem = mColormapTreeWidget->topLevelItem( i );
405  if ( !currentItem )
406  {
407  continue;
408  }
409 
410  double value = currentItem->data( ValueColumn, Qt::ItemDataRole::EditRole ).toDouble( );
411  double position = ( value - min ) / ( max - min );
412  whileBlocking( static_cast<QgsTreeWidgetItemObject *>( currentItem ) )->setData( ColorColumn, Qt::ItemDataRole::EditRole, ramp->color( position ) );
413  }
414 
415  emit widgetChanged();
416  }
417  else
418  {
419  classify();
420  }
421 }
422 
423 void QgsColorRampShaderWidget::populateColormapTreeWidget( const QList<QgsColorRampShader::ColorRampItem> &colorRampItems )
424 {
425  mColormapTreeWidget->clear();
426  QList<QgsColorRampShader::ColorRampItem>::const_iterator it = colorRampItems.constBegin();
427  int i = 0;
428  for ( ; it != colorRampItems.constEnd(); ++it )
429  {
430  QgsTreeWidgetItemObject *newItem = new QgsTreeWidgetItemObject( mColormapTreeWidget );
431  newItem->setData( ValueColumn, Qt::ItemDataRole::DisplayRole, it->value );
432  newItem->setData( ColorColumn, Qt::ItemDataRole::EditRole, it->color );
433  newItem->setText( LabelColumn, it->label );
434  newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable );
435  connect( newItem, &QgsTreeWidgetItemObject::itemEdited,
436  this, &QgsColorRampShaderWidget::mColormapTreeWidget_itemEdited );
437  ++i;
438  }
439 
440 #ifdef QGISDEBUG
441  dumpClasses();
442 #endif
443 
444  setUnitFromLabels();
445 
446  // Now we have the suffix
447  const QString unit = mUnitLineEdit->text();
448  for ( i = 0; i < mColormapTreeWidget->topLevelItemCount(); i++ )
449  {
450  QgsTreeWidgetItemObject *currentItem { static_cast<QgsTreeWidgetItemObject *>( mColormapTreeWidget->topLevelItem( i ) ) };
451  QString lbl { createLabel( currentItem, i, unit )};
452  if ( currentItem->text( LabelColumn ).isEmpty() || currentItem->text( LabelColumn ) == lbl || currentItem->foreground( LabelColumn ).color() == QColor( Qt::gray ) )
453  {
454  currentItem->setText( LabelColumn, lbl );
455  currentItem->setForeground( LabelColumn, QBrush( QColor( Qt::gray ) ) );
456  }
457  }
458 
459 }
460 
461 void QgsColorRampShaderWidget::mLoadFromBandButton_clicked()
462 {
463  if ( !mRasterDataProvider )
464  return;
465 
466  QList<QgsColorRampShader::ColorRampItem> colorRampList = mRasterDataProvider->colorTable( mBand );
467  if ( !colorRampList.isEmpty() )
468  {
469  populateColormapTreeWidget( colorRampList );
470  mColorInterpolationComboBox->setCurrentIndex( mColorInterpolationComboBox->findData( QgsColorRampShader::Interpolated ) );
471  }
472  else
473  {
474  QMessageBox::warning( this, tr( "Load Color Map" ), tr( "The color map for band %1 has no entries." ).arg( mBand ) );
475  }
477  emit widgetChanged();
478 }
479 
480 void QgsColorRampShaderWidget::mLoadFromFileButton_clicked()
481 {
482  QgsSettings settings;
483  QString lastDir = settings.value( QStringLiteral( "lastColorMapDir" ), QDir::homePath() ).toString();
484  const QString fileName = QFileDialog::getOpenFileName( this, tr( "Load Color Map from File" ), lastDir, tr( "Textfile (*.txt)" ) );
485  if ( fileName.isEmpty() )
486  return;
487 
488  QList<QgsColorRampShader::ColorRampItem> colorRampItems;
490  QStringList errors;
491  if ( QgsRasterRendererUtils::parseColorMapFile( fileName, colorRampItems, type, errors ) )
492  {
493  //clear the current tree
494  mColormapTreeWidget->clear();
495 
496  mColorInterpolationComboBox->setCurrentIndex( mColorInterpolationComboBox->findData( type ) );
497 
498  populateColormapTreeWidget( colorRampItems );
499 
500  if ( !errors.empty() )
501  {
502  QMessageBox::warning( this, tr( "Load Color Map from File" ), tr( "The following lines contained errors\n\n" ) + errors.join( '\n' ) );
503  }
504  }
505  else
506  {
507  const QString error = tr( "An error occurred while reading the color map\n\n" ) + errors.join( '\n' );
508  QMessageBox::warning( this, tr( "Load Color Map from File" ), error );
509  }
510 
511  QFileInfo fileInfo( fileName );
512  settings.setValue( QStringLiteral( "lastColorMapDir" ), fileInfo.absoluteDir().absolutePath() );
513 
515  updateColorRamp();
516  emit widgetChanged();
517 }
518 
519 void QgsColorRampShaderWidget::mExportToFileButton_clicked()
520 {
521  QgsSettings settings;
522  QString lastDir = settings.value( QStringLiteral( "lastColorMapDir" ), QDir::homePath() ).toString();
523  QString fileName = QFileDialog::getSaveFileName( this, tr( "Save Color Map as File" ), lastDir, tr( "Textfile (*.txt)" ) );
524  if ( fileName.isEmpty() )
525  return;
526 
527  fileName = QgsFileUtils::ensureFileNameHasExtension( fileName, QStringList() << QStringLiteral( "txt" ) );
528 
529  QList<QgsColorRampShader::ColorRampItem> colorRampItems;
530  int topLevelItemCount = mColormapTreeWidget->topLevelItemCount();
531  for ( int i = 0; i < topLevelItemCount; ++i )
532  {
533  QTreeWidgetItem *currentItem = mColormapTreeWidget->topLevelItem( i );
534  if ( !currentItem )
535  {
536  continue;
537  }
538 
540  item.value = currentItem->data( ValueColumn, Qt::ItemDataRole::DisplayRole ).toDouble( );
541  item.color = currentItem->data( ColorColumn, Qt::ItemDataRole::EditRole ).value<QColor>();
542  item.label = currentItem->text( LabelColumn );
543  colorRampItems << item;
544  }
545 
546  if ( !QgsRasterRendererUtils::saveColorMapFile( fileName, colorRampItems, static_cast< QgsColorRampShader::Type >( mColorInterpolationComboBox->currentData().toInt() ) ) )
547  {
548  QMessageBox::warning( this, tr( "Save Color Map as File" ), tr( "Write access denied. Adjust the file permissions and try again.\n\n" ) );
549  }
550 
551  QFileInfo fileInfo( fileName );
552  settings.setValue( QStringLiteral( "lastColorMapDir" ), fileInfo.absoluteDir().absolutePath() );
553 }
554 
555 void QgsColorRampShaderWidget::mColormapTreeWidget_itemDoubleClicked( QTreeWidgetItem *item, int column )
556 {
557  if ( !item )
558  {
559  return;
560  }
561 
562  if ( column == LabelColumn )
563  {
564  // Set text color to default black, which signifies a manually edited label
565  item->setForeground( LabelColumn, QBrush() );
566  }
567 }
568 
569 void QgsColorRampShaderWidget::mColormapTreeWidget_itemEdited( QTreeWidgetItem *item, int column )
570 {
571  Q_UNUSED( item )
572 
573  switch ( column )
574  {
575  case ValueColumn:
576  {
577  autoLabel();
579  updateColorRamp();
580  emit widgetChanged();
581  break;
582  }
583 
584  case LabelColumn:
585  {
586  // call autoLabel to fill when empty or gray out when same as autoLabel
587  autoLabel();
588  emit widgetChanged();
589  break;
590  }
591 
592  case ColorColumn:
593  {
595  updateColorRamp();
596  emit widgetChanged();
597  break;
598  }
599  }
600 }
601 
603 {
604  // Those objects are connected to classify() the color ramp shader if they change, or call widget change
605  // need to block them to avoid to classify and to alter the color ramp, or to call duplicate widget change
606  whileBlocking( mClipCheckBox )->setChecked( colorRampShader.clip() );
607  whileBlocking( mColorInterpolationComboBox )->setCurrentIndex( mColorInterpolationComboBox->findData( colorRampShader.colorRampType() ) );
608  mColorInterpolationComboBox_currentIndexChanged( mColorInterpolationComboBox->currentIndex() );
609  whileBlocking( mClassificationModeComboBox )->setCurrentIndex( mClassificationModeComboBox->findData( colorRampShader.classificationMode() ) );
610  mClassificationModeComboBox_currentIndexChanged( mClassificationModeComboBox->currentIndex() );
611  whileBlocking( mNumberOfEntriesSpinBox )->setValue( colorRampShader.colorRampItemList().count() ); // some default
612 
613  if ( colorRampShader.sourceColorRamp() )
614  {
615  whileBlocking( btnColorRamp )->setColorRamp( colorRampShader.sourceColorRamp() );
616  }
617  else
618  {
619  QgsSettings settings;
620  QString defaultPalette = settings.value( QStringLiteral( "/Raster/defaultPalette" ), "Spectral" ).toString();
621  btnColorRamp->setColorRampFromName( defaultPalette );
622  }
623 
624  mLabelPrecisionSpinBox->setValue( colorRampShader.labelPrecision() );
625 
626  populateColormapTreeWidget( colorRampShader.colorRampItemList() );
627 
628  if ( colorRampShader.legendSettings() )
629  mLegendSettings = *colorRampShader.legendSettings();
630 
631  emit widgetChanged();
632 }
633 
634 void QgsColorRampShaderWidget::mColorInterpolationComboBox_currentIndexChanged( int index )
635 {
636  QgsColorRampShader::Type interpolation = static_cast< QgsColorRampShader::Type >( mColorInterpolationComboBox->itemData( index ).toInt() );
637 
638  mClipCheckBox->setEnabled( interpolation == QgsColorRampShader::Interpolated );
639 
640  QString valueLabel;
641  QString valueToolTip;
642  switch ( interpolation )
643  {
645  valueLabel = tr( "Value" );
646  valueToolTip = tr( "Value for color stop" );
647  mLegendSettingsButton->setEnabled( true );
648  break;
650  valueLabel = tr( "Value <=" );
651  valueToolTip = tr( "Maximum value for class" );
652  mLegendSettingsButton->setEnabled( false );
653  break;
655  valueLabel = tr( "Value =" );
656  valueToolTip = tr( "Value for color" );
657  mLegendSettingsButton->setEnabled( false );
658  break;
659  }
660 
661  QTreeWidgetItem *header = mColormapTreeWidget->headerItem();
662  header->setText( ValueColumn, valueLabel );
663  header->setToolTip( ValueColumn, valueToolTip );
664 
665  autoLabel();
666  emit widgetChanged();
667 }
668 
670 {
671  if ( !qgsDoubleNear( mMin, min ) || !qgsDoubleNear( mMax, max ) )
672  {
673  setMinimumMaximum( min, max );
674  classify();
675  }
676 }
677 
678 void QgsColorRampShaderWidget::setMinimumMaximum( double min, double max )
679 {
680  mMin = min;
681  mMax = max;
682  resetClassifyButton();
683 }
684 
686 {
687  return mMin;
688 }
689 
691 {
692  return mMax;
693 }
694 
695 bool QgsColorRampShaderWidget::colormapMinMax( double &min, double &max ) const
696 {
697  QTreeWidgetItem *item = mColormapTreeWidget->topLevelItem( 0 );
698  if ( !item )
699  {
700  return false;
701  }
702 
703  // If using discrete, the first and last items contain the upper and lower
704  // values of the first and last classes, we don't want these values but real min/max
705  if ( ! std::isnan( mMin ) && ! std::isnan( mMax ) && static_cast< QgsColorRampShader::Type >( mColorInterpolationComboBox->currentData().toInt() ) == QgsColorRampShader::Type::Discrete )
706  {
707  min = mMin;
708  max = mMax;
709  }
710  else
711  {
712  min = item->data( ValueColumn, Qt::ItemDataRole::DisplayRole ).toDouble();
713  item = mColormapTreeWidget->topLevelItem( mColormapTreeWidget->topLevelItemCount() - 1 );
714  max = item->data( ValueColumn, Qt::ItemDataRole::DisplayRole ).toDouble();
715  }
716  return true;
717 }
718 
720 {
721  double min = 0, max = 0;
722  if ( ! colormapMinMax( min, max ) )
723  {
724  return;
725  }
726 
727  if ( !qgsDoubleNear( mMin, min ) || !qgsDoubleNear( mMax, max ) )
728  {
729  mMin = min;
730  mMax = max;
731  emit minimumMaximumChangedFromTree( min, max );
732  }
733 }
734 
735 void QgsColorRampShaderWidget::resetClassifyButton()
736 {
737  mClassifyButton->setEnabled( true );
738  if ( std::isnan( mMin ) || std::isnan( mMax ) || mMin >= mMax )
739  {
740  mClassifyButton->setEnabled( false );
741  }
742 }
743 
744 QString QgsColorRampShaderWidget::createLabel( QTreeWidgetItem *currentItem, int row, const QString unit )
745 {
746  auto applyPrecision = [ = ]( const QString & value )
747  {
748  double val { value.toDouble( ) };
749  Qgis::DataType dataType { mRasterDataProvider ? mRasterDataProvider->dataType( mBand ) : Qgis::DataType::Float64 };
750  switch ( dataType )
751  {
761  {
762  return QLocale().toString( std::round( val ), 'f', 0 );
763  }
766  {
767  if ( mLabelPrecisionSpinBox->value() < 0 )
768  {
769  const double factor = std::pow( 10, - mLabelPrecisionSpinBox->value() );
770  val = static_cast<qlonglong>( val / factor ) * factor;
771  return QLocale().toString( val, 'f', 0 );
772  }
773  return QLocale().toString( val, 'f', mLabelPrecisionSpinBox->value() );
774  }
778  {
779  if ( mLabelPrecisionSpinBox->value() < 0 )
780  {
781  const double factor = std::pow( 10, - mLabelPrecisionSpinBox->value() );
782  val = static_cast<qlonglong>( val / factor ) * factor;
783  return QLocale().toString( val, 'f', 0 );
784  }
785  return QLocale().toString( val, 'f', mLabelPrecisionSpinBox->value() );
786  }
787  }
788  return QString();
789  };
790 
791  QgsColorRampShader::Type interpolation = static_cast< QgsColorRampShader::Type >( mColorInterpolationComboBox->currentData().toInt() );
792  bool discrete = interpolation == QgsColorRampShader::Discrete;
793  QString lbl;
794 
795  if ( discrete )
796  {
797  if ( row == 0 )
798  {
799  lbl = "<= " + applyPrecision( currentItem->data( ValueColumn, Qt::ItemDataRole::DisplayRole ).toString() ) + unit;
800  }
801  else if ( currentItem->data( ValueColumn, Qt::ItemDataRole::DisplayRole ).toDouble( ) == std::numeric_limits<double>::infinity() )
802  {
803  lbl = "> " + applyPrecision( mColormapTreeWidget->topLevelItem( row - 1 )->data( ValueColumn, Qt::ItemDataRole::DisplayRole ).toString() ) + unit;
804  }
805  else
806  {
807  lbl = applyPrecision( mColormapTreeWidget->topLevelItem( row - 1 )->data( ValueColumn, Qt::ItemDataRole::DisplayRole ).toString() ) + " - " + applyPrecision( currentItem->data( ValueColumn, Qt::ItemDataRole::DisplayRole ).toString() ) + unit;
808  }
809  }
810  else
811  {
812  lbl = applyPrecision( currentItem->data( ValueColumn, Qt::ItemDataRole::DisplayRole ).toString() ) + unit;
813  }
814 
815  return lbl;
816 
817 }
818 
819 void QgsColorRampShaderWidget::changeColor()
820 {
821  QList<QTreeWidgetItem *> itemList;
822  itemList = mColormapTreeWidget->selectedItems();
823  if ( itemList.isEmpty() )
824  {
825  return;
826  }
827  QTreeWidgetItem *firstItem = itemList.first();
828 
829  QColor currentColor = firstItem->data( ColorColumn, Qt::ItemDataRole::EditRole ).value<QColor>();
830  QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( qobject_cast< QWidget * >( parent() ) );
831  if ( panel && panel->dockMode() )
832  {
834  colorWidget->setPanelTitle( tr( "Select Color" ) );
835  colorWidget->setAllowOpacity( true );
836  connect( colorWidget, &QgsCompoundColorWidget::currentColorChanged, this, [ = ]( const QColor & newColor )
837  {
838  for ( QTreeWidgetItem *item : std::as_const( itemList ) )
839  {
840  item->setData( ColorColumn, Qt::ItemDataRole::EditRole, newColor );
841  }
842 
844  emit widgetChanged();
845  } );
846  panel->openPanel( colorWidget );
847  }
848  else
849  {
850  // modal dialog version... yuck
851  QColor newColor = QgsColorDialog::getColor( currentColor, this, QStringLiteral( "Change Color" ), true );
852  if ( newColor.isValid() )
853  {
854  for ( QTreeWidgetItem *item : std::as_const( itemList ) )
855  {
856  item->setData( ColorColumn, Qt::ItemDataRole::EditRole, newColor );
857  }
858 
860  emit widgetChanged();
861  }
862  }
863 }
864 
865 void QgsColorRampShaderWidget::changeOpacity()
866 {
867  QList<QTreeWidgetItem *> itemList;
868  itemList = mColormapTreeWidget->selectedItems();
869  if ( itemList.isEmpty() )
870  {
871  return;
872  }
873  QTreeWidgetItem *firstItem = itemList.first();
874 
875  bool ok;
876  double oldOpacity = firstItem->data( ColorColumn, Qt::ItemDataRole::EditRole ).value<QColor>().alpha() / 255 * 100;
877  double opacity = QInputDialog::getDouble( this, tr( "Opacity" ), tr( "Change color opacity [%]" ), oldOpacity, 0.0, 100.0, 0, &ok );
878  if ( ok )
879  {
880  int newOpacity = static_cast<int>( opacity / 100 * 255 );
881  const auto constItemList = itemList;
882  for ( QTreeWidgetItem *item : constItemList )
883  {
884  QColor newColor = item->data( ColorColumn, Qt::ItemDataRole::EditRole ).value<QColor>();
885  newColor.setAlpha( newOpacity );
886  item->setData( ColorColumn, Qt::ItemDataRole::EditRole, newColor );
887  }
888 
890  emit widgetChanged();
891  }
892 }
893 
894 void QgsColorRampShaderWidget::showLegendSettings()
895 {
896  QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( qobject_cast< QWidget * >( parent() ) );
897  if ( panel && panel->dockMode() )
898  {
900  legendPanel->setPanelTitle( tr( "Legend Settings" ) );
901  legendPanel->setSettings( mLegendSettings );
902  connect( legendPanel, &QgsColorRampLegendNodeWidget::widgetChanged, this, [ = ]
903  {
904  mLegendSettings = legendPanel->settings();
905  emit widgetChanged();
906  } );
907  panel->openPanel( legendPanel );
908  }
909  else
910  {
911  QgsColorRampLegendNodeDialog dialog( mLegendSettings, this );
912  dialog.setWindowTitle( tr( "Legend Settings" ) );
913  if ( dialog.exec() )
914  {
915  mLegendSettings = dialog.settings();
916  emit widgetChanged();
917  }
918  }
919 }
QgsCompoundColorWidget::setAllowOpacity
void setAllowOpacity(bool allowOpacity)
Sets whether opacity modification (transparency) is permitted for the color dialog.
Definition: qgscompoundcolorwidget.cpp:303
QgsColorRampShaderWidget::classify
void classify()
Executes the single band pseudo raster classification.
Definition: qgscolorrampshaderwidget.cpp:307
QgsColorRampShader::EqualInterval
@ EqualInterval
Uses equal interval.
Definition: qgscolorrampshader.h:59
QgsColorRampShaderWidget::QgsColorRampShaderWidget
QgsColorRampShaderWidget(QWidget *parent=nullptr)
Creates new color ramp shader widget.
Definition: qgscolorrampshaderwidget.cpp:49
QgsColorRampShader::setSourceColorRamp
void setSourceColorRamp(QgsColorRamp *colorramp)
Set the source color ramp.
Definition: qgscolorrampshader.cpp:182
Qgis::DataType::CInt16
@ CInt16
Complex Int16.
qgsrasterlayer.h
QgsColorRampShaderWidget::setRasterBand
void setRasterBand(int band)
Sets raster band, only when used for raster layer.
Definition: qgscolorrampshaderwidget.cpp:126
QgsRasterDataProvider::dataType
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
QgsSettings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Definition: qgssettings.cpp:161
QgsColorRampShader::setClassificationMode
void setClassificationMode(ClassificationMode classificationMode)
Sets classification mode.
Definition: qgscolorrampshader.h:216
QgsColorRampLegendNodeWidget::settings
QgsColorRampLegendNodeSettings settings() const
Returns the legend node settings as defined by the widget.
Definition: qgscolorramplegendnodewidget.cpp:59
Qgis::DataType::UInt32
@ UInt32
Thirty two bit unsigned integer (quint32)
QgsColorSwatchDelegate
A delegate for showing a color swatch in a list.
Definition: qgscolorschemelist.h:36
qgsrasterrendererutils.h
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsPanelWidget::findParentPanel
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
Definition: qgspanelwidget.cpp:54
QgsColorRampShaderWidget::setRasterDataProvider
void setRasterDataProvider(QgsRasterDataProvider *dp)
Associates raster with the widget, only when used for raster layer.
Definition: qgscolorrampshaderwidget.cpp:120
QgsColorRampLegendNodeWidget
A widget for properties relating to a QgsColorRampLegendNode (QgsColorRampLegendNodeSettings).
Definition: qgscolorramplegendnodewidget.h:41
QgsColorRampShaderWidget::populateColormapTreeWidget
void populateColormapTreeWidget(const QList< QgsColorRampShader::ColorRampItem > &colorRampItems)
Populates color ramp tree from ramp items.
Definition: qgscolorrampshaderwidget.cpp:423
QgsColorRampShaderWidget::minimumMaximumChangedFromTree
void minimumMaximumChangedFromTree(double minimum, double maximum)
Color ramp tree has changed.
Qgis::DataType
DataType
Raster data types.
Definition: qgis.h:128
QgsPanelWidget::openPanel
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
Definition: qgspanelwidget.cpp:84
qgslocaleawarenumericlineeditdelegate.h
Qgis::DataType::Byte
@ Byte
Eight bit unsigned integer (quint8)
QgsSettings
This class is a composition of two QSettings instances:
Definition: qgssettings.h:61
Qgis::DataType::Int32
@ Int32
Thirty two bit signed integer (qint32)
QgsColorRampShader
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
Definition: qgscolorrampshader.h:42
qgssinglebandpseudocolorrenderer.h
QgsColorRampShader::Type
Type
Supported methods for color interpolation.
Definition: qgscolorrampshader.h:48
QgsPanelWidget::dockMode
bool dockMode()
Returns the dock mode state.
Definition: qgspanelwidget.h:93
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsColorRampShaderWidget::setMinimumMaximumAndClassify
void setMinimumMaximumAndClassify(double minimum, double maximum)
Sets min max and classify color tree.
Definition: qgscolorrampshaderwidget.cpp:669
QgsCompoundColorWidget
A custom QGIS widget for selecting a color, including options for selecting colors via hue wheel,...
Definition: qgscompoundcolorwidget.h:33
QgsColorRampShader::Quantile
@ Quantile
Uses quantile (i.e. equal pixel) count.
Definition: qgscolorrampshader.h:60
QgsColorRampShaderWidget::shader
QgsColorRampShader shader() const
Returns shared function used in the renderer.
Definition: qgscolorrampshaderwidget.cpp:143
QgsCompoundColorWidget::LayoutVertical
@ LayoutVertical
Use a narrower, vertically stacked layout.
Definition: qgscompoundcolorwidget.h:44
QgsColorRampShader::Discrete
@ Discrete
Assigns the color of the higher class for every pixel between two class breaks.
Definition: qgscolorrampshader.h:51
QgsTreeWidgetItemObject::setData
void setData(int column, int role, const QVariant &value) override
Sets the value for the item's column and role to the given value.
Definition: qgstreewidgetitem.cpp:139
QgsCompoundColorWidget::currentColorChanged
void currentColorChanged(const QColor &color)
Emitted when the dialog's color changes.
QgsColorRampLegendNodeDialog
A dialog for configuring a QgsColorRampLegendNode (QgsColorRampLegendNodeSettings).
Definition: qgscolorramplegendnodewidget.h:93
QgsColorRampShader::ColorRampItem::color
QColor color
Definition: qgscolorrampshader.h:118
QgsColorRampShader::setColorRampType
void setColorRampType(QgsColorRampShader::Type colorRampType)
Sets the color ramp type.
Definition: qgscolorrampshader.cpp:107
QgsRasterShaderFunction::setLabelPrecision
void setLabelPrecision(int labelPrecision)
Sets label precision to labelPrecision.
Definition: qgsrastershaderfunction.cpp:79
QgsPanelWidget
Base class for any widget that can be shown as a inline panel.
Definition: qgspanelwidget.h:29
QgsColorRampShader::Continuous
@ Continuous
Uses breaks from color palette.
Definition: qgscolorrampshader.h:58
QgsColorRampShader::sourceColorRamp
QgsColorRamp * sourceColorRamp() const
Returns the source color ramp.
Definition: qgscolorrampshader.cpp:133
QgsColorRampShader::setClip
void setClip(bool clip)
Sets whether the shader should not render values out of range.
Definition: qgscolorrampshader.h:226
QgsColorRampShader::ColorRampItem
Definition: qgscolorrampshader.h:105
whileBlocking
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:2191
QgsColorRampLegendNodeWidget::setSettings
void setSettings(const QgsColorRampLegendNodeSettings &settings)
Sets the settings to show in the widget.
Definition: qgscolorramplegendnodewidget.cpp:74
QgsColorRampShader::Exact
@ Exact
Assigns the color of the exact matching value in the color ramp item list.
Definition: qgscolorrampshader.h:52
QgsColorRampShaderWidget::setExtent
void setExtent(const QgsRectangle &extent)
Sets extent, only when used for raster layer.
Definition: qgscolorrampshaderwidget.cpp:138
qgscolorramp.h
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2265
Qgis::DataType::UnknownDataType
@ UnknownDataType
Unknown or unspecified type.
QgsColorRampShaderWidget::maximum
double maximum() const
Gets max value.
Definition: qgscolorrampshaderwidget.cpp:690
Qgis::DataType::Float64
@ Float64
Sixty four bit floating point (double)
QgsPanelWidget::widgetChanged
void widgetChanged()
Emitted when the widget state changes.
Qgis::DataType::CInt32
@ CInt32
Complex Int32.
Qgis::DataType::Int16
@ Int16
Sixteen bit signed integer (qint16)
Qgis::UI_SCALE_FACTOR
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition: qgis.h:2043
QgsColorRampShaderWidget::classificationModeChanged
void classificationModeChanged(QgsColorRampShader::ClassificationMode mode)
Classification mode changed.
QgsColorRampShader::setColorRampItemList
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &list)
Sets a custom colormap.
Definition: qgscolorrampshader.cpp:99
QgsSettings::setValue
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Definition: qgssettings.cpp:279
Qgis::DataType::ARGB32_Premultiplied
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
QgsRasterDataProvider::colorTable
virtual QList< QgsColorRampShader::ColorRampItem > colorTable(int bandNo) const
Definition: qgsrasterdataprovider.h:257
QgsColorRampShaderWidget::setMinimumMaximum
void setMinimumMaximum(double minimum, double maximum)
Sets min max.
Definition: qgscolorrampshaderwidget.cpp:678
Qgis::DataType::UInt16
@ UInt16
Sixteen bit unsigned integer (quint16)
QgsPanelWidget::setPanelTitle
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
Definition: qgspanelwidget.h:44
qgsfileutils.h
Qgis::DataType::ARGB32
@ ARGB32
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
QgsColorRampShaderWidget::setFromShader
void setFromShader(const QgsColorRampShader &colorRampShader)
Sets widget state from the color ramp shader.
Definition: qgscolorrampshaderwidget.cpp:602
qgsstyle.h
qgsrastershader.h
QgsColorRampShader::colorRampItemList
QList< QgsColorRampShader::ColorRampItem > colorRampItemList() const
Returns the custom colormap.
Definition: qgscolorrampshader.h:132
QgsColorRampShader::colorRampType
Type colorRampType() const
Returns the color ramp type.
Definition: qgscolorrampshader.h:135
qgscolordialog.h
QgsTreeWidgetItemObject::itemEdited
void itemEdited(QTreeWidgetItem *item, int column)
Emitted when the contents of the column in the specified item has been edited by the user.
QgsColorRampShader::ClassificationMode
ClassificationMode
Classification modes used to create the color ramp shader.
Definition: qgscolorrampshader.h:56
QgsFileUtils::ensureFileNameHasExtension
static QString ensureFileNameHasExtension(const QString &fileName, const QStringList &extensions)
Ensures that a fileName ends with an extension from the provided list of extensions.
Definition: qgsfileutils.cpp:111
QgsRasterRendererUtils::saveColorMapFile
static bool saveColorMapFile(const QString &path, const QList< QgsColorRampShader::ColorRampItem > &items, QgsColorRampShader::Type type)
Exports a list of color ramp items and ramp shader type to a color map file at the specified path.
Definition: qgsrasterrendererutils.cpp:96
QgsTreeWidgetItemObject
Custom QgsTreeWidgetItem with extra signals when item is edited.
Definition: qgstreewidgetitem.h:162
Qgis::DataType::Float32
@ Float32
Thirty two bit floating point (float)
QgsColorRampShaderWidget::widgetChanged
void widgetChanged()
Widget changed.
qgstreewidgetitem.h
qgscolorramplegendnodewidget.h
qgsrasterminmaxwidget.h
QgsColorRampShader::clip
bool clip() const
Returns whether the shader will clip values which are out of range.
Definition: qgscolorrampshader.h:232
qgssettings.h
Qgis::DataType::CFloat64
@ CFloat64
Complex Float64.
QgsColorRampShader::classificationMode
ClassificationMode classificationMode() const
Returns the classification mode.
Definition: qgscolorrampshader.h:219
QgsColorRampShaderWidget::loadMinimumMaximumFromTree
void loadMinimumMaximumFromTree()
Loads min and max values from color ramp tree.
Definition: qgscolorrampshaderwidget.cpp:719
QgsColorRampShaderWidget::minimum
double minimum() const
Gets min value.
Definition: qgscolorrampshaderwidget.cpp:685
QgsColorRampShader::ColorRampItem::label
QString label
Definition: qgscolorrampshader.h:116
qgscolorrampbutton.h
qgsdoublevalidator.h
qgsguiutils.h
qgscolorrampshaderwidget.h
QgsColorRampShaderWidget::initializeForUseWithRasterLayer
void initializeForUseWithRasterLayer()
Allows quantile classification mode for raster layers.
Definition: qgscolorrampshaderwidget.cpp:114
Qgis::DataType::CFloat32
@ CFloat32
Complex Float32.
QgsColorRampShader::Interpolated
@ Interpolated
Interpolates the color between two class breaks linearly.
Definition: qgscolorrampshader.h:50
QgsRasterShaderFunction::labelPrecision
int labelPrecision() const
Returns label precision.
Definition: qgsrastershaderfunction.cpp:74
QgsRasterDataProvider
Base class for raster data providers.
Definition: qgsrasterdataprovider.h:88
QgsGuiUtils::significantDigits
int significantDigits(const Qgis::DataType rasterDataType)
Returns the maximum number of significant digits a for the given rasterDataType.
Definition: qgsguiutils.cpp:311
QgsColorRampShader::ColorRampItem::value
double value
Definition: qgscolorrampshader.h:117
QgsColorDialog::getColor
static QColor getColor(const QColor &initialColor, QWidget *parent, const QString &title=QString(), bool allowOpacity=false)
Returns a color selection from a color dialog.
Definition: qgscolordialog.cpp:81
QgsColorRampLegendNodeSettings
Settings for a color ramp legend node.
Definition: qgscolorramplegendnodesettings.h:37
qgsrasterdataprovider.h
QgsColorRampButton::colorRampChanged
void colorRampChanged()
Emitted whenever a new color ramp is set for the button.
QgsColorRampShader::setLegendSettings
void setLegendSettings(QgsColorRampLegendNodeSettings *settings)
Sets the color ramp shader legend settings.
Definition: qgscolorrampshader.cpp:646
QgsColorRampShader::legendSettings
const QgsColorRampLegendNodeSettings * legendSettings() const
Returns the color ramp shader legend settings.
Definition: qgscolorrampshader.cpp:641
QgsRasterRendererUtils::parseColorMapFile
static bool parseColorMapFile(const QString &path, QList< QgsColorRampShader::ColorRampItem > &items, QgsColorRampShader::Type &type, QStringList &errors)
Parses an exported color map file at the specified path and extracts the stored color ramp items and ...
Definition: qgsrasterrendererutils.cpp:24