27 #include <QFileDialog> 28 #include <QMessageBox> 30 #include <QTextStream> 36 if ( role == Qt::EditRole )
56 else if ( ok1 || ok2 )
63 return text( column ) < other.
text( column );
69 , mMinMaxWidget( nullptr )
76 mColormapTreeWidget->setColumnWidth( ColorColumn, 50 );
82 QgsDebugMsg(
"defaultPalette = " + defaultPalette );
83 mColorRampComboBox->setCurrentIndex( mColorRampComboBox->findText( defaultPalette ) );
84 connect( mButtonEditRamp, SIGNAL( clicked() ), mColorRampComboBox, SLOT( editSourceRamp() ) );
107 mMinMaxContainerWidget->setLayout( layout );
109 connect( mMinMaxWidget, SIGNAL( load(
int,
double,
double,
int ) ),
110 this, SLOT(
loadMinMax(
int,
double,
double,
int ) ) );
115 for (
int i = 1; i <= nBands; ++i )
124 mClassificationModeComboBox->addItem(
tr(
"Continuous" ),
Continuous );
125 mClassificationModeComboBox->addItem(
tr(
"Equal interval" ),
EqualInterval );
126 mClassificationModeComboBox->addItem(
tr(
"Quantile" ),
Quantile );
128 mNumberOfEntriesSpinBox->setValue( 5 );
133 if ( mMinLineEdit->text().isEmpty() || mMaxLineEdit->text().isEmpty() )
135 mMinMaxWidget->
load();
138 on_mClassificationModeComboBox_currentIndexChanged( 0 );
140 resetClassifyButton();
142 connect( mClassificationModeComboBox, SIGNAL( currentIndexChanged(
int ) ),
this, SLOT( on_mClassifyButton_clicked() ) );
143 connect( mMinLineEdit, SIGNAL( textChanged(
QString ) ),
this, SLOT( on_mClassifyButton_clicked() ) );
144 connect( mMaxLineEdit, SIGNAL( textChanged(
QString ) ),
this, SLOT( on_mClassifyButton_clicked() ) );
145 connect( mColorRampComboBox, SIGNAL( sourceRampEdited() ),
this, SLOT( on_mClassifyButton_clicked() ) );
146 connect( mColorRampComboBox, SIGNAL( currentIndexChanged(
int ) ),
this, SLOT( on_mClassifyButton_clicked() ) );
147 connect( mInvertCheckBox, SIGNAL( stateChanged(
int ) ),
this, SLOT( on_mClassifyButton_clicked() ) );
148 connect( mNumberOfEntriesSpinBox, SIGNAL( valueChanged(
int ) ),
this, SLOT( on_mClassifyButton_clicked() ) );
149 connect( mBandComboBox, SIGNAL( currentIndexChanged(
int ) ),
this, SLOT( on_mClassifyButton_clicked() ) );
161 colorRampShader->
setClip( mClipCheckBox->isChecked() );
165 int topLevelItemCount = mColormapTreeWidget->topLevelItemCount();
167 for (
int i = 0; i < topLevelItemCount; ++i )
169 currentItem = mColormapTreeWidget->topLevelItem( i );
177 newColorRampItem.
label = currentItem->
text( LabelColumn );
178 colorRampItems.
append( newColorRampItem );
181 qSort( colorRampItems );
188 int bandNumber = mBandComboBox->itemData( mBandComboBox->currentIndex() ).toInt();
207 void QgsSingleBandPseudoColorRendererWidget::autoLabel()
211 QString unit = mUnitLineEdit->text();
213 int topLevelItemCount = mColormapTreeWidget->topLevelItemCount();
215 for (
int i = 0; i < topLevelItemCount; ++i )
217 currentItem = mColormapTreeWidget->topLevelItem( i );
219 if ( !currentItem || currentItem->
text( ValueColumn ).
isEmpty() )
228 label =
"<= " + currentItem->
text( ValueColumn ) + unit;
230 else if ( currentItem->
text( ValueColumn ).
toDouble() == std::numeric_limits<double>::infinity() )
232 label =
"> " + mColormapTreeWidget->topLevelItem( i - 1 )->text( ValueColumn ) + unit;
236 label = mColormapTreeWidget->topLevelItem( i - 1 )->text( ValueColumn ) +
" - " + currentItem->
text( ValueColumn ) + unit;
241 label = currentItem->
text( ValueColumn ) + unit;
246 currentItem->
setText( LabelColumn, label );
253 void QgsSingleBandPseudoColorRendererWidget::setUnitFromLabels()
259 int topLevelItemCount = mColormapTreeWidget->topLevelItemCount();
261 for (
int i = 0; i < topLevelItemCount; ++i )
263 currentItem = mColormapTreeWidget->topLevelItem( i );
265 if ( !currentItem || currentItem->
text( ValueColumn ).
isEmpty() )
274 label =
"<= " + currentItem->
text( ValueColumn );
276 else if ( currentItem->
text( ValueColumn ).
toDouble() == std::numeric_limits<double>::infinity() )
278 label =
"> " + mColormapTreeWidget->topLevelItem( i - 1 )->text( ValueColumn );
282 label = mColormapTreeWidget->topLevelItem( i - 1 )->text( ValueColumn ) +
" - " + currentItem->
text( ValueColumn );
287 label = currentItem->
text( ValueColumn );
300 for (
int i = 0; i < suffixes.
count(); ++i )
302 int n = allSuffixes.
count( suffixes[i] );
312 mUnitLineEdit->setText( unit );
317 void QgsSingleBandPseudoColorRendererWidget::on_mAddEntryButton_clicked()
320 newItem->
setText( ValueColumn,
"0" );
323 newItem->
setFlags( Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable );
325 this, SLOT( mColormapTreeWidget_itemEdited(
QTreeWidgetItem*,
int ) ) );
326 mColormapTreeWidget->sortItems( ValueColumn, Qt::AscendingOrder );
331 void QgsSingleBandPseudoColorRendererWidget::on_mDeleteEntryButton_clicked()
341 void QgsSingleBandPseudoColorRendererWidget::on_mNumberOfEntriesSpinBox_valueChanged()
345 void QgsSingleBandPseudoColorRendererWidget::on_mClassifyButton_clicked()
347 int bandComboIndex = mBandComboBox->currentIndex();
363 double min = lineEditValue( mMinLineEdit );
364 double max = lineEditValue( mMaxLineEdit );
366 if ( qIsNaN( min ) || qIsNaN( max ) )
373 if ( mClassificationModeComboBox->itemData( mClassificationModeComboBox->currentIndex() ).toInt() ==
Continuous )
375 if ( colorRamp.data() )
377 numberOfEntries = colorRamp->count();
378 entryValues.
reserve( numberOfEntries );
381 double intervalDiff = max -
min;
385 if ( colorGradientRamp != NULL && colorGradientRamp->
isDiscrete() )
393 intervalDiff *= ( numberOfEntries - 1 ) / (
double )numberOfEntries;
397 for (
int i = 1; i < numberOfEntries; ++i )
399 double value = colorRamp->
value( i );
400 entryValues.
push_back( min + value * intervalDiff );
402 entryValues.
push_back( std::numeric_limits<double>::infinity() );
406 for (
int i = 0; i < numberOfEntries; ++i )
408 if ( mInvertCheckBox->isChecked() )
410 double value = 1.0 - colorRamp->value( numberOfEntries - i - 1 );
411 entryValues.
push_back( min + value * ( max - min ) );
415 double value = colorRamp->value( i );
416 entryValues.
push_back( min + value * ( max - min ) );
421 for (
int i = 0; i < numberOfEntries; ++i )
423 int idx = mInvertCheckBox->isChecked() ? numberOfEntries - i - 1 : i;
424 entryColors.
push_back( colorRamp->color( colorRamp->value( idx ) ) );
430 numberOfEntries = mNumberOfEntriesSpinBox->value();
431 if ( numberOfEntries < 2 )
434 if ( mClassificationModeComboBox->itemData( mClassificationModeComboBox->currentIndex() ).toInt() ==
Quantile )
436 int bandNr = mBandComboBox->itemData( bandComboIndex ).toInt();
439 double cut1 = std::numeric_limits<double>::quiet_NaN();
440 double cut2 = std::numeric_limits<double>::quiet_NaN();
448 entryValues.
reserve( numberOfEntries );
451 double intervalDiff = 1.0 / ( numberOfEntries );
452 for (
int i = 1; i < numberOfEntries; ++i )
457 entryValues.
push_back( std::numeric_limits<double>::infinity() );
461 double intervalDiff = 1.0 / ( numberOfEntries - 1 );
462 for (
int i = 0; i < numberOfEntries; ++i )
471 entryValues.
reserve( numberOfEntries );
477 double intervalDiff = ( max -
min ) / ( numberOfEntries );
479 for (
int i = 1; i < numberOfEntries; ++i )
481 entryValues.
push_back( min + i * intervalDiff );
483 entryValues.
push_back( std::numeric_limits<double>::infinity() );
488 double intervalDiff = ( max -
min ) / ( numberOfEntries - 1 );
490 for (
int i = 0; i < numberOfEntries; ++i )
492 entryValues.
push_back( min + i * intervalDiff );
497 if ( !colorRamp.data() )
501 if ( numberOfEntries != 0 )
503 colorDiff = ( int )( 255 / numberOfEntries );
506 entryColors.
reserve( numberOfEntries );
507 for (
int i = 0; i < numberOfEntries; ++i )
510 int idx = mInvertCheckBox->isChecked() ? numberOfEntries - i - 1 : i;
511 currentColor.
setRgb( colorDiff*idx, 0, 255 - colorDiff * idx );
517 entryColors.
reserve( numberOfEntries );
518 for (
int i = 0; i < numberOfEntries; ++i )
520 int idx = mInvertCheckBox->isChecked() ? numberOfEntries - i - 1 : i;
521 entryColors.
push_back( colorRamp->color(((
double ) idx ) / ( numberOfEntries - 1 ) ) );
526 mColormapTreeWidget->clear();
532 double maxabs = log10( qMax( qAbs( max ), qAbs( min ) ) );
533 int nDecimals = qRound( qMax( 3.0 + maxabs - log10( max - min ), maxabs <= 15.0 ? maxabs + 0.49 : 0.0 ) );
535 for ( ; value_it != entryValues.
end(); ++value_it, ++color_it )
541 newItem->
setFlags( Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable );
543 this, SLOT( mColormapTreeWidget_itemEdited(
QTreeWidgetItem*,
int ) ) );
549 void QgsSingleBandPseudoColorRendererWidget::on_mClassificationModeComboBox_currentIndexChanged(
int index )
551 Mode mode =
static_cast< Mode >( mClassificationModeComboBox->itemData( index ).toInt() );
552 mNumberOfEntriesSpinBox->setEnabled( mode !=
Continuous );
553 mMinLineEdit->setEnabled( mode !=
Quantile );
554 mMaxLineEdit->setEnabled( mode !=
Quantile );
557 void QgsSingleBandPseudoColorRendererWidget::on_mColorRampComboBox_currentIndexChanged(
int index )
561 settings.
setValue(
"/Raster/defaultPalette", mColorRampComboBox->currentText() );
567 bool enableContinuous = ( ramp->
count() > 0 );
568 mClassificationModeComboBox->setEnabled( enableContinuous );
569 if ( !enableContinuous )
571 mClassificationModeComboBox->setCurrentIndex( mClassificationModeComboBox->findData(
EqualInterval ) );
577 mColormapTreeWidget->clear();
579 for ( ; it != colorRampItems.
constEnd(); ++it )
584 newItem->
setText( LabelColumn, it->label );
585 newItem->
setFlags( Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable );
587 this, SLOT( mColormapTreeWidget_itemEdited(
QTreeWidgetItem*,
int ) ) );
592 void QgsSingleBandPseudoColorRendererWidget::on_mLoadFromBandButton_clicked()
599 int bandIndex = mBandComboBox->itemData( mBandComboBox->currentIndex() ).toInt();
603 if ( !colorRampList.
isEmpty() )
605 populateColormapTreeWidget( colorRampList );
610 QMessageBox::warning(
this,
tr(
"Load Color Map" ),
tr(
"The color map for band %1 has no entries" ).arg( bandIndex ) );
615 void QgsSingleBandPseudoColorRendererWidget::on_mLoadFromFileButton_clicked()
618 bool importError =
false;
623 QFile inputFile( fileName );
624 if ( inputFile.
open( QFile::ReadOnly ) )
627 mColormapTreeWidget->clear();
635 while ( !inputStream.
atEnd() )
643 if ( inputLine.
contains(
"INTERPOLATION", Qt::CaseInsensitive ) )
645 inputStringComponents = inputLine.
split(
':' );
646 if ( inputStringComponents.
size() == 2 )
648 if ( inputStringComponents[1].trimmed().toUpper().compare(
"INTERPOLATED", Qt::CaseInsensitive ) == 0 )
652 else if ( inputStringComponents[1].trimmed().toUpper().compare(
"DISCRETE", Qt::CaseInsensitive ) == 0 )
664 badLines = badLines +
QString::number( lineCounter ) +
":\t[" + inputLine +
"]\n";
669 inputStringComponents = inputLine.
split(
',' );
670 if ( inputStringComponents.
size() == 6 )
673 QColor::fromRgb( inputStringComponents[1].toInt(), inputStringComponents[2].toInt(),
674 inputStringComponents[3].toInt(), inputStringComponents[4].toInt() ),
675 inputStringComponents[5] );
681 badLines = badLines +
QString::number( lineCounter ) +
":\t[" + inputLine +
"]\n";
688 populateColormapTreeWidget( colorRampItems );
698 else if ( !fileName.
isEmpty() )
700 QMessageBox::warning(
this,
tr(
"Read access denied" ),
tr(
"Read access denied. Adjust the file permissions and try again.\n\n" ) );
705 void QgsSingleBandPseudoColorRendererWidget::on_mExportToFileButton_clicked()
712 if ( !fileName.
endsWith(
".txt", Qt::CaseInsensitive ) )
714 fileName = fileName +
".txt";
717 QFile outputFile( fileName );
718 if ( outputFile.
open( QFile::WriteOnly ) )
721 outputStream <<
"# " <<
tr(
"QGIS Generated Color Map Export File" ) <<
'\n';
722 outputStream <<
"INTERPOLATION:";
724 switch ( interpolation )
727 outputStream <<
"INTERPOLATED\n";
730 outputStream <<
"DISCRETE\n";
733 outputStream <<
"EXACT\n";
737 int topLevelItemCount = mColormapTreeWidget->topLevelItemCount();
740 for (
int i = 0; i < topLevelItemCount; ++i )
742 currentItem = mColormapTreeWidget->topLevelItem( i );
748 outputStream << currentItem->
text( ValueColumn ).
toDouble() <<
',';
749 outputStream << color.
red() <<
',' << color.
green() <<
',' << color.
blue() <<
',' << color.
alpha() <<
',';
752 outputStream <<
"Color entry " << i + 1 <<
'\n';
756 outputStream << currentItem->
text( LabelColumn ) <<
'\n';
759 outputStream.
flush();
767 QMessageBox::warning(
this,
tr(
"Write access denied" ),
tr(
"Write access denied. Adjust the file permissions and try again.\n\n" ) );
772 void QgsSingleBandPseudoColorRendererWidget::on_mColormapTreeWidget_itemDoubleClicked(
QTreeWidgetItem* item,
int column )
779 if ( column == ColorColumn )
781 item->
setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
791 if ( column == LabelColumn )
796 item->
setFlags( Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable );
801 void QgsSingleBandPseudoColorRendererWidget::mColormapTreeWidget_itemEdited(
QTreeWidgetItem* item,
int column )
805 if ( column == ValueColumn )
807 mColormapTreeWidget->sortItems( ValueColumn, Qt::AscendingOrder );
811 else if ( column == LabelColumn )
823 mBandComboBox->setCurrentIndex( mBandComboBox->findData( pr->
band() ) );
829 if ( colorRampShader )
831 mColorInterpolationComboBox->setCurrentIndex( mColorInterpolationComboBox->findData( colorRampShader->
colorRampType() ) );
835 for ( ; it != colorRampItemList.
end(); ++it )
840 newItem->
setText( LabelColumn, it->label );
841 newItem->
setFlags( Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable );
843 this, SLOT( mColormapTreeWidget_itemEdited(
QTreeWidgetItem*,
int ) ) );
846 mClipCheckBox->setChecked( colorRampShader->
clip() );
856 void QgsSingleBandPseudoColorRendererWidget::on_mBandComboBox_currentIndexChanged(
int index )
859 bands.
append( mBandComboBox->itemData( index ).toInt() );
863 void QgsSingleBandPseudoColorRendererWidget::on_mColorInterpolationComboBox_currentIndexChanged(
int index )
871 switch ( interpolation )
874 valueLabel =
tr(
"Value" );
875 valueToolTip =
tr(
"Value for color stop" );
878 valueLabel =
tr(
"Value <=" );
879 valueToolTip =
tr(
"Maximum value for class" );
882 valueLabel =
tr(
"Value =" );
883 valueToolTip =
tr(
"Value for color" );
888 header->
setText( ValueColumn, valueLabel );
889 header->
setToolTip( ValueColumn, valueToolTip );
897 Q_UNUSED( theBandNo );
898 QgsDebugMsg(
QString(
"theBandNo = %1 theMin = %2 theMax = %3" ).arg( theBandNo ).arg( theMin ).arg( theMax ) );
900 if ( qIsNaN( theMin ) )
902 mMinLineEdit->clear();
909 if ( qIsNaN( theMax ) )
911 mMaxLineEdit->clear();
918 mMinMaxOrigin = theOrigin;
922 void QgsSingleBandPseudoColorRendererWidget::showMinMaxOrigin()
927 void QgsSingleBandPseudoColorRendererWidget::setLineEditValue(
QLineEdit * theLineEdit,
double theValue )
930 if ( !qIsNaN( theValue ) )
937 double QgsSingleBandPseudoColorRendererWidget::lineEditValue(
const QLineEdit * theLineEdit )
const 939 if ( theLineEdit->
text().isEmpty() )
941 return std::numeric_limits<double>::quiet_NaN();
944 return theLineEdit->
text().toDouble();
947 void QgsSingleBandPseudoColorRendererWidget::resetClassifyButton()
949 mClassifyButton->setEnabled(
true );
950 double min = lineEditValue( mMinLineEdit );
951 double max = lineEditValue( mMaxLineEdit );
952 if ( qIsNaN( min ) || qIsNaN( max ) || min >= max )
954 mClassifyButton->setEnabled(
false );
Assigns the color of the exact matching value in the color ramp item list.
virtual int bandCount() const =0
Get number of bands.
A rectangle specified with double values.
double classificationMin() const
Interface for all raster shaders.
void setContentsMargins(int left, int top, int right, int bottom)
QgsColorRampShader::ColorRamp_TYPE colorRampType() const
Get the color ramp type.
QString readLine(qint64 maxlen)
void push_back(const T &value)
void setText(const QString &)
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
virtual QList< QgsColorRampShader::ColorRampItem > colorTable(int bandNo) const
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
void setClassificationMinMaxOrigin(int origin)
QString simplified() const
QList< QgsColorRampShader::ColorRampItem > colorRampItemList() const
Get the custom colormap.
bool isDiscrete() const
Returns true if the gradient is using discrete interpolation, rather than smoothly interpolating betw...
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &theList)
Set custom colormap.
QgsRasterRenderer * renderer() const
void setClip(bool clip)
Sets whether the shader should not render values out of range.
void setRgb(int r, int g, int b, int a)
double toDouble(bool *ok) const
QgsRasterShader * shader()
QString tr(const char *sourceText, const char *disambiguation, int n)
void setClassificationMax(double max)
Map canvas is a class for displaying all GIS data types on a canvas.
int classificationMinMaxOrigin() const
const QColor & color() const
void setValue(const QString &key, const QVariant &value)
QString number(int n, int base)
int count(const T &value) const
void append(const T &value)
QgsRasterShaderFunction * rasterShaderFunction()
double classificationMax() const
static QgsStyleV2 * defaultStyle()
return default application-wide style
static QString minMaxOriginLabel(int theOrigin)
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
Raster renderer pipe for single band pseudocolor.
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
void setRasterShaderFunction(QgsRasterShaderFunction *)
A public method that allows the user to set their own shader function.
void setColorRampType(QgsColorRampShader::ColorRamp_TYPE theColorRampType)
Set the color ramp type.
bool contains(QChar ch, Qt::CaseSensitivity cs) const
QVariant value(const QString &key, const QVariant &defaultValue) const
virtual int count() const =0
Returns number of defined colors, or -1 if undefined.
static QColor getColor(const QColor &initialColor, QWidget *parent, const QString &title=QString(), const bool allowAlpha=false)
Return a color selection from a color dialog.
void setClassificationMin(double min)
QString mid(int position, int n) const
QString absolutePath() const
Interpolates the color between two class breaks linearly.
Assigns the color of the higher class for every pixel between two class breaks.
void setText(int column, const QString &text)
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFlags< QFileDialog::Option > options)
bool clip() const
Returns whether the shader will clip values which are out of range.
void push_back(const T &value)
StandardButton warning(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
QgsRasterDataProvider * dataProvider()
Returns the data provider.
virtual double value(int index) const override
Returns relative value between [0,1] of color at specified index.
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFlags< QFileDialog::Option > options)
const_iterator constEnd() const
const_iterator constBegin() const
virtual void cumulativeCut(int theBandNo, double theLowerCount, double theUpperCount, double &theLowerValue, double &theUpperValue, const QgsRectangle &theExtent=QgsRectangle(), int theSampleSize=0)
Find values for cumulative pixel count cut.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Abstract base class for color ramps.
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
QString text(int column) const
ColorRamp_TYPE
Supported methods for color interpolation.
Raster renderer pipe that applies colors to a raster.
int band() const
Returns the band used by the renderer.
Base class for raster data providers.