Skip to content

Commit

Permalink
[FEATURE] Add a color ramp combo to paletted raster renderer
Browse files Browse the repository at this point in the history
Allows rapid recoloring of palette to match a color ramp
  • Loading branch information
nyalldawson committed Apr 3, 2017
1 parent 40027ab commit bfe9621
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 33 deletions.
2 changes: 2 additions & 0 deletions python/core/raster/qgspalettedrasterrenderer.sip
Expand Up @@ -32,6 +32,8 @@ class QgsPalettedRasterRenderer : QgsRasterRenderer
void legendSymbologyItems( QList< QPair< QString, QColor > > &symbolItems /Out/ ) const;

QList<int> usesBands() const;
void setSourceColorRamp( QgsColorRamp *ramp /Transfer/ );
QgsColorRamp *sourceColorRamp() const;
static QgsPalettedRasterRenderer::ClassData colorTableToClassData( const QList<QgsColorRampShader::ColorRampItem> &table );

private:
Expand Down
30 changes: 30 additions & 0 deletions src/core/raster/qgspalettedrasterrenderer.cpp
Expand Up @@ -18,6 +18,7 @@
#include "qgspalettedrasterrenderer.h"
#include "qgsrastertransparency.h"
#include "qgsrasterviewport.h"
#include "qgssymbollayerutils.h"

#include <QColor>
#include <QDomDocument>
Expand All @@ -43,6 +44,9 @@ QgsPalettedRasterRenderer::~QgsPalettedRasterRenderer()
QgsPalettedRasterRenderer *QgsPalettedRasterRenderer::clone() const
{
QgsPalettedRasterRenderer *renderer = new QgsPalettedRasterRenderer( nullptr, mBand, mClassData );
if ( mSourceColorRamp )
renderer->setSourceColorRamp( mSourceColorRamp->clone() );

renderer->copyCommonProperties( this );
return renderer;
}
Expand Down Expand Up @@ -78,8 +82,17 @@ QgsRasterRenderer *QgsPalettedRasterRenderer::create( const QDomElement &elem, Q
classData.insert( value, Class( color, label ) );
}
}

QgsPalettedRasterRenderer *r = new QgsPalettedRasterRenderer( input, bandNumber, classData );
r->readXml( elem );

// try to load color ramp (optional)
QDomElement sourceColorRampElem = elem.firstChildElement( QStringLiteral( "colorramp" ) );
if ( !sourceColorRampElem.isNull() && sourceColorRampElem.attribute( QStringLiteral( "name" ) ) == QLatin1String( "[source]" ) )
{
r->setSourceColorRamp( QgsSymbolLayerUtils::loadColorRamp( sourceColorRampElem ) );
}

return r;
}

Expand Down Expand Up @@ -218,6 +231,13 @@ void QgsPalettedRasterRenderer::writeXml( QDomDocument &doc, QDomElement &parent
}
rasterRendererElem.appendChild( colorPaletteElem );

// save source color ramp
if ( mSourceColorRamp )
{
QDomElement colorRampElem = QgsSymbolLayerUtils::saveColorRamp( QStringLiteral( "[source]" ), mSourceColorRamp.get(), doc );
rasterRendererElem.appendChild( colorRampElem );
}

parentElem.appendChild( rasterRendererElem );
}

Expand Down Expand Up @@ -255,6 +275,16 @@ QList<int> QgsPalettedRasterRenderer::usesBands() const
return bandList;
}

void QgsPalettedRasterRenderer::setSourceColorRamp( QgsColorRamp *ramp )
{
mSourceColorRamp.reset( ramp );
}

QgsColorRamp *QgsPalettedRasterRenderer::sourceColorRamp() const
{
return mSourceColorRamp.get();
}

QgsPalettedRasterRenderer::ClassData QgsPalettedRasterRenderer::colorTableToClassData( const QList<QgsColorRampShader::ColorRampItem> &table )
{
QList<QgsColorRampShader::ColorRampItem>::const_iterator colorIt = table.constBegin();
Expand Down
15 changes: 15 additions & 0 deletions src/core/raster/qgspalettedrasterrenderer.h
Expand Up @@ -90,6 +90,19 @@ class CORE_EXPORT QgsPalettedRasterRenderer: public QgsRasterRenderer

QList<int> usesBands() const override;

/**
* Set the source color \a ramp. Ownership is transferred to the renderer.
* @note added in QGIS 3.0
* @see sourceColorRamp()
*/
void setSourceColorRamp( QgsColorRamp *ramp );

/** Get the source color ramp
* @note added in QGIS 3.0
* @see setSourceColorRamp()
*/
QgsColorRamp *sourceColorRamp() const;

/**
* Converts a raster color \a table to paletted renderer class data.
* @note added in QGIS 3.0
Expand All @@ -102,6 +115,8 @@ class CORE_EXPORT QgsPalettedRasterRenderer: public QgsRasterRenderer
int mMaxColorIndex = -INT_MAX;
ClassData mClassData;

//! Source color ramp
std::unique_ptr<QgsColorRamp> mSourceColorRamp;

//! Premultiplied color array
QRgb *mColors = nullptr;
Expand Down
76 changes: 74 additions & 2 deletions src/gui/raster/qgspalettedrendererwidget.cpp
Expand Up @@ -20,6 +20,7 @@
#include "qgsrasterdataprovider.h"
#include "qgsrasterlayer.h"
#include "qgscolordialog.h"
#include "qgssettings.h"

#include <QColorDialog>
#include <QInputDialog>
Expand Down Expand Up @@ -47,6 +48,11 @@ QgsPalettedRendererWidget::QgsPalettedRendererWidget( QgsRasterLayer *layer, con
connect( mTreeView, &QTreeView::customContextMenuRequested, [ = ]( const QPoint & ) { contextMenu->exec( QCursor::pos() ); }
);

QgsSettings settings;
QString defaultPalette = settings.value( QStringLiteral( "Raster/defaultPalette" ), QString() ).toString();
btnColorRamp->setColorRampFromName( defaultPalette );
connect( btnColorRamp, &QgsColorRampButton::colorRampChanged, this, &QgsPalettedRendererWidget::applyColorRamp );

if ( mRasterLayer )
{
QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
Expand Down Expand Up @@ -75,7 +81,13 @@ QgsRasterRenderer *QgsPalettedRendererWidget::renderer()
{
QgsPalettedRasterRenderer::ClassData classes = mModel->classData();
int bandNumber = mBandComboBox->currentData().toInt();
return new QgsPalettedRasterRenderer( mRasterLayer->dataProvider(), bandNumber, classes );

QgsPalettedRasterRenderer *r = new QgsPalettedRasterRenderer( mRasterLayer->dataProvider(), bandNumber, classes );
if ( !btnColorRamp->isNull() )
{
r->setSourceColorRamp( btnColorRamp->colorRamp() );
}
return r;
}

void QgsPalettedRendererWidget::setFromRenderer( const QgsRasterRenderer *r )
Expand All @@ -85,6 +97,17 @@ void QgsPalettedRendererWidget::setFromRenderer( const QgsRasterRenderer *r )
{
//read values and colors and fill into tree widget
mModel->setClassData( pr->classes() );

if ( pr->sourceColorRamp() )
{
whileBlocking( btnColorRamp )->setColorRamp( pr->sourceColorRamp() );
}
else
{
QgsSettings settings;
QString defaultPalette = settings.value( "/Raster/defaultPalette", "Spectral" ).toString();
whileBlocking( btnColorRamp )->setColorRampFromName( defaultPalette );
}
}
else
{
Expand All @@ -95,6 +118,9 @@ void QgsPalettedRendererWidget::setFromRenderer( const QgsRasterRenderer *r )
QgsPalettedRasterRenderer::ClassData classes = QgsPalettedRasterRenderer::colorTableToClassData( provider->colorTable( mBandComboBox->currentData().toInt() ) );
mModel->setClassData( classes );
}
QgsSettings settings;
QString defaultPalette = settings.value( "/Raster/defaultPalette", "Spectral" ).toString();
whileBlocking( btnColorRamp )->setColorRampFromName( defaultPalette );
}
}

Expand Down Expand Up @@ -137,7 +163,14 @@ void QgsPalettedRendererWidget::deleteEntry()
void QgsPalettedRendererWidget::addEntry()
{
disconnect( mModel, &QgsPalettedRendererModel::classesChanged, this, &QgsPalettedRendererWidget::widgetChanged );
mModel->insertRow( mModel->rowCount() );

QColor color( 150, 150, 150 );
std::unique_ptr< QgsColorRamp > ramp( btnColorRamp->colorRamp() );
if ( ramp )
{
color = ramp->color( 1.0 );
}
mModel->addEntry( color );
connect( mModel, &QgsPalettedRendererModel::classesChanged, this, &QgsPalettedRendererWidget::widgetChanged );
emit widgetChanged();
}
Expand Down Expand Up @@ -231,6 +264,39 @@ void QgsPalettedRendererWidget::changeLabel()
}
}

void QgsPalettedRendererWidget::applyColorRamp()
{
std::unique_ptr< QgsColorRamp > ramp( btnColorRamp->colorRamp() );
if ( !ramp )
{
return;
}

if ( !btnColorRamp->colorRampName().isEmpty() )
{
// Remember last used color ramp
QgsSettings settings;
settings.setValue( QStringLiteral( "Raster/defaultPalette" ), btnColorRamp->colorRampName() );
}

disconnect( mModel, &QgsPalettedRendererModel::classesChanged, this, &QgsPalettedRendererWidget::widgetChanged );

QgsPalettedRasterRenderer::ClassData data = mModel->classData();
QgsPalettedRasterRenderer::ClassData::iterator cIt = data.begin();

double numberOfEntries = data.count();
int i = 0;
for ( ; cIt != data.end(); ++cIt )
{
cIt->color = ramp->color( i / numberOfEntries );
i++;
}
mModel->setClassData( data );

connect( mModel, &QgsPalettedRendererModel::classesChanged, this, &QgsPalettedRendererWidget::widgetChanged );
emit widgetChanged();
}

//
// QgsPalettedRendererModel
//
Expand Down Expand Up @@ -465,5 +531,11 @@ bool QgsPalettedRendererModel::insertRows( int row, int count, const QModelIndex
return true;
}

void QgsPalettedRendererModel::addEntry( const QColor &color )
{
insertRow( rowCount() );
setData( index( mData.count() - 1, 1 ), color );
}

///@endcond PRIVATE

3 changes: 3 additions & 0 deletions src/gui/raster/qgspalettedrendererwidget.h
Expand Up @@ -55,6 +55,8 @@ class QgsPalettedRendererModel : public QAbstractTableModel
bool removeRows( int row, int count, const QModelIndex &parent = QModelIndex() ) override;
virtual bool insertRows( int row, int count, const QModelIndex &parent = QModelIndex() ) override;

void addEntry( const QColor &color );

signals:

void classesChanged();
Expand Down Expand Up @@ -98,6 +100,7 @@ class GUI_EXPORT QgsPalettedRendererWidget: public QgsRasterRendererWidget, priv
void changeColor();
void changeTransparency();
void changeLabel();
void applyColorRamp();
};

#endif // QGSPALETTEDRENDERERWIDGET_H
90 changes: 60 additions & 30 deletions src/ui/qgspalettedrendererwidgetbase.ui
Expand Up @@ -26,7 +26,59 @@
<property name="bottomMargin">
<number>3</number>
</property>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="mBandLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Band</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="mBandComboBox"/>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QTreeView" name="mTreeView">
<property name="minimumSize">
<size>
<width>0</width>
<height>280</height>
</size>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QgsColorRampButton" name="btnColorRamp">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="3" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="mAddEntryButton">
Expand Down Expand Up @@ -65,38 +117,16 @@
</item>
</layout>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="mBandLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Band</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="mBandComboBox"/>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QTreeView" name="mTreeView">
<property name="minimumSize">
<size>
<width>0</width>
<height>280</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsColorRampButton</class>
<extends>QToolButton</extends>
<header>qgscolorrampbutton.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>mBandComboBox</tabstop>
<tabstop>mTreeView</tabstop>
Expand Down

0 comments on commit bfe9621

Please sign in to comment.