mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-18 00:03:05 -04:00
[FEATURE] Add a color ramp combo to paletted raster renderer
Allows rapid recoloring of palette to match a color ramp
This commit is contained in:
parent
40027abcd2
commit
bfe96214b2
@ -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:
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "qgspalettedrasterrenderer.h"
|
||||
#include "qgsrastertransparency.h"
|
||||
#include "qgsrasterviewport.h"
|
||||
#include "qgssymbollayerutils.h"
|
||||
|
||||
#include <QColor>
|
||||
#include <QDomDocument>
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 );
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
@ -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
|
||||
@ -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;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "qgsrasterdataprovider.h"
|
||||
#include "qgsrasterlayer.h"
|
||||
#include "qgscolordialog.h"
|
||||
#include "qgssettings.h"
|
||||
|
||||
#include <QColorDialog>
|
||||
#include <QInputDialog>
|
||||
@ -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();
|
||||
@ -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 )
|
||||
@ -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
|
||||
{
|
||||
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
@ -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
|
||||
//
|
||||
@ -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
|
||||
|
||||
|
@ -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();
|
||||
@ -98,6 +100,7 @@ class GUI_EXPORT QgsPalettedRendererWidget: public QgsRasterRendererWidget, priv
|
||||
void changeColor();
|
||||
void changeTransparency();
|
||||
void changeLabel();
|
||||
void applyColorRamp();
|
||||
};
|
||||
|
||||
#endif // QGSPALETTEDRENDERERWIDGET_H
|
||||
|
@ -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">
|
||||
@ -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>
|
||||
|
@ -34,7 +34,8 @@ from qgis.core import (QgsRaster,
|
||||
QgsRenderChecker,
|
||||
QgsPalettedRasterRenderer,
|
||||
QgsSingleBandGrayRenderer,
|
||||
QgsSingleBandPseudoColorRenderer)
|
||||
QgsSingleBandPseudoColorRenderer,
|
||||
QgsLimitedRandomColorRamp)
|
||||
from utilities import unitTestDataPath
|
||||
from qgis.testing import start_app, unittest
|
||||
|
||||
@ -329,6 +330,12 @@ class TestQgsRasterLayer(unittest.TestCase):
|
||||
renderer.setLabel(3, 'new class')
|
||||
self.assertEqual(renderer.label(3), 'new class')
|
||||
|
||||
# color ramp
|
||||
r = QgsLimitedRandomColorRamp(5)
|
||||
renderer.setSourceColorRamp(r)
|
||||
self.assertEqual(renderer.sourceColorRamp().type(), 'random')
|
||||
self.assertEqual(renderer.sourceColorRamp().count(), 5)
|
||||
|
||||
# clone
|
||||
new_renderer = renderer.clone()
|
||||
classes = new_renderer.classes()
|
||||
@ -336,6 +343,8 @@ class TestQgsRasterLayer(unittest.TestCase):
|
||||
self.assertEqual(classes[3].label, 'new class')
|
||||
self.assertEqual(classes[1].color.name(), '#00ff00')
|
||||
self.assertEqual(classes[3].color.name(), '#ff0000')
|
||||
self.assertEqual(new_renderer.sourceColorRamp().type(), 'random')
|
||||
self.assertEqual(new_renderer.sourceColorRamp().count(), 5)
|
||||
|
||||
# write to xml and read
|
||||
doc = QDomDocument('testdoc')
|
||||
@ -350,6 +359,8 @@ class TestQgsRasterLayer(unittest.TestCase):
|
||||
self.assertEqual(classes[3].label, 'new class')
|
||||
self.assertEqual(classes[1].color.name(), '#00ff00')
|
||||
self.assertEqual(classes[3].color.name(), '#ff0000')
|
||||
self.assertEqual(restored.sourceColorRamp().type(), 'random')
|
||||
self.assertEqual(restored.sourceColorRamp().count(), 5)
|
||||
|
||||
# render test
|
||||
layer.setRenderer(renderer)
|
||||
@ -376,5 +387,6 @@ class TestQgsRasterLayer(unittest.TestCase):
|
||||
self.assertEqual(classes[3].color.name(), '#00ff00')
|
||||
self.assertEqual(classes[6].color.name(), '#0000ff')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user