Skip to content

Commit

Permalink
[FEATURE] New "preset" colors color ramp option
Browse files Browse the repository at this point in the history
Allows use of a color ramp consisting of a list of selected colors.
Currently there's no way in QGIS to classify a renderer using
some list of colors you've previously selected. So you can modify
the colors manually after classifying, but that's a pain
if you're regularly using the same color scheme.

Basically, it's like the color brewer color ramp options but
allowing users to pick their own preset list of colors to use*

(Because Cynthia Brewer isn't the only cartographic color expert!)
  • Loading branch information
nyalldawson committed Sep 14, 2016
1 parent 8ac1460 commit ec50cac
Show file tree
Hide file tree
Showing 13 changed files with 793 additions and 3 deletions.
60 changes: 60 additions & 0 deletions python/core/qgscolorramp.sip
Expand Up @@ -16,6 +16,8 @@ class QgsColorRamp
sipType = sipType_QgsLimitedRandomColorRamp;
else if (sipCpp->type() == "randomcolors")
sipType = sipType_QgsRandomColorRamp;
else if (sipCpp->type() == "preset")
sipType = sipType_QgsPresetSchemeColorRamp;
else if (sipCpp->type() == "colorbrewer")
sipType = sipType_QgsColorBrewerColorRamp;
else if (sipCpp->type() == "cpt-city")
Expand Down Expand Up @@ -285,6 +287,64 @@ class QgsRandomColorRamp : QgsColorRamp
QgsStringMap properties() const;
};

/** \ingroup core
* \class QgsPresetSchemeColorRamp
* \brief A scheme based color ramp consisting of a list of predefined colors.
* \note added in QGIS 3.0
*/
class QgsPresetSchemeColorRamp : QgsColorRamp, QgsColorScheme
{
%TypeHeaderCode
#include <qgscolorramp.h>
%End

public:

/** Constructor for QgsPresetSchemeColorRamp.
* @param colors list of colors in ramp
*/
QgsPresetSchemeColorRamp( const QList< QColor >& colors = QList< QColor >() );

/** Constructor for QgsPresetColorRamp.
* @param colors list of named colors in ramp
* @note not available in Python bindings - use setColors instead
*/
//QgsPresetSchemeColorRamp( const QgsNamedColorList& colors );

/** Returns a new QgsPresetSchemeColorRamp color ramp created using the properties encoded in a string
* map.
* @param properties color ramp properties
* @see properties()
*/
static QgsColorRamp* create( const QgsStringMap& properties = QgsStringMap() );

/** Sets the list of colors used by the ramp.
* @param colors list of colors
* @see colors()
*/
bool setColors( const QgsNamedColorList& colors, const QString& = QString(), const QColor& = QColor() );

/** Returns the list of colors used by the ramp.
* @see setColors()
*/
QList< QColor > colors() const;

// QgsColorRamp interface
virtual double value( int index ) const;
virtual QColor color( double value ) const;
virtual QString type() const;
virtual QgsPresetSchemeColorRamp* clone() const /Factory/;
virtual QgsStringMap properties() const;
int count() const;

// QgsColorScheme interface
QString schemeName() const;
QgsNamedColorList fetchColors( const QString &context = QString(),
const QColor &baseColor = QColor() );
bool isEditable() const;

};

/** \ingroup core
* \class QgsColorBrewerColorRamp
*/
Expand Down
1 change: 1 addition & 0 deletions python/gui/gui.sip
Expand Up @@ -141,6 +141,7 @@
%Include qgspanelwidgetstack.sip
%Include qgspixmaplabel.sip
%Include qgspluginmanagerinterface.sip
%Include qgspresetcolorrampdialog.sip
%Include qgsprevieweffect.sip
%Include qgsprojectbadlayerguihandler.sip
%Include qgsprojectionselectionwidget.sip
Expand Down
75 changes: 75 additions & 0 deletions python/gui/qgspresetcolorrampdialog.sip
@@ -0,0 +1,75 @@
/** \ingroup gui
* \class QgsPresetColorRampWidget
* A widget which allows users to modify the properties of a QgsPresetSchemeColorRamp.
* \note added in QGIS 3.0
*/

class QgsPresetColorRampWidget : QgsPanelWidget
{
%TypeHeaderCode
#include <qgspresetcolorrampdialog.h>
%End

public:

/** Constructor for QgsPresetColorRampWidget.
* @param ramp initial ramp to show in dialog
* @param parent parent widget
*/
QgsPresetColorRampWidget( const QgsPresetSchemeColorRamp& ramp, QWidget* parent /TransferThis/ = nullptr );

~QgsPresetColorRampWidget();

/** Returns a color ramp representing the current settings from the dialog.
* @see setRamp()
*/
QgsPresetSchemeColorRamp ramp() const;

/** Sets the color ramp to show in the dialog.
* @param ramp color ramp
* @see ramp()
*/
void setRamp( const QgsPresetSchemeColorRamp& ramp );

signals:

//! Emitted when the dialog settings change
void changed();
};

/** \ingroup gui
* \class QgsPresetColorRampDialog
* A dialog which allows users to modify the properties of a QgsPresetSchemeColorRamp.
* \note added in QGIS 3.0
*/

class QgsPresetColorRampDialog : QDialog
{
%TypeHeaderCode
#include <qgspresetcolorrampdialog.h>
%End

public:

/** Constructor for QgsPresetColorRampDialog.
* @param ramp initial ramp to show in dialog
* @param parent parent widget
*/
QgsPresetColorRampDialog( const QgsPresetSchemeColorRamp& ramp, QWidget* parent /TransferThis/ = nullptr );

/** Returns a color ramp representing the current settings from the dialog.
* @see setRamp()
*/
QgsPresetSchemeColorRamp ramp() const;

/** Sets the color ramp to show in the dialog.
* @param ramp color ramp
* @see ramp()
*/
void setRamp( const QgsPresetSchemeColorRamp& ramp );

signals:

//! Emitted when the dialog settings change
void changed();
};
99 changes: 99 additions & 0 deletions src/core/qgscolorramp.cpp
Expand Up @@ -738,3 +738,102 @@ bool QgsCptCityColorRamp::loadFile()
mFileLoaded = true;
return true;
}


//
// QgsPresetColorRamp
//

QgsPresetSchemeColorRamp::QgsPresetSchemeColorRamp( const QList<QColor>& colors )
{
Q_FOREACH ( const QColor& color, colors )
{
mColors << qMakePair( color, color.name() );
}
// need at least one color
if ( mColors.isEmpty() )
mColors << qMakePair( QColor( 250, 75, 60 ), QString( "#fa4b3c" ) );
}

QgsPresetSchemeColorRamp::QgsPresetSchemeColorRamp( const QgsNamedColorList& colors )
: mColors( colors )
{
// need at least one color
if ( mColors.isEmpty() )
mColors << qMakePair( QColor( 250, 75, 60 ), QString( "#fa4b3c" ) );
}

QgsColorRamp* QgsPresetSchemeColorRamp::create( const QgsStringMap& properties )
{
QgsNamedColorList colors;

int i = 0;
QString colorString = properties.value( QString( "preset_color_%1" ).arg( i ), QString() );
QString colorName = properties.value( QString( "preset_color_name_%1" ).arg( i ), QString() );
while ( !colorString.isEmpty() )
{
colors << qMakePair( QgsSymbolLayerUtils::decodeColor( colorString ), colorName );
i++;
colorString = properties.value( QString( "preset_color_%1" ).arg( i ), QString() );
colorName = properties.value( QString( "preset_color_name_%1" ).arg( i ), QString() );
}

return new QgsPresetSchemeColorRamp( colors );
}

QList<QColor> QgsPresetSchemeColorRamp::colors() const
{
QList< QColor > l;
for ( int i = 0; i < mColors.count(); ++i )
{
l << mColors.at( i ).first;
}
return l;
}

double QgsPresetSchemeColorRamp::value( int index ) const
{
if ( mColors.size() < 1 )
return 0;
return static_cast< double >( index ) / ( mColors.size() - 1 );
}

QColor QgsPresetSchemeColorRamp::color( double value ) const
{
if ( value < 0 || value > 1 )
return QColor();

int colorCnt = mColors.count();
int colorIdx = qMin( static_cast< int >( value * colorCnt ), colorCnt - 1 );

if ( colorIdx >= 0 && colorIdx < colorCnt )
return mColors.at( colorIdx ).first;

return QColor();
}

QgsPresetSchemeColorRamp* QgsPresetSchemeColorRamp::clone() const
{
return new QgsPresetSchemeColorRamp( *this );
}

QgsStringMap QgsPresetSchemeColorRamp::properties() const
{
QgsStringMap props;
for ( int i = 0; i < mColors.count(); ++i )
{
props.insert( QString( "preset_color_%1" ).arg( i ), QgsSymbolLayerUtils::encodeColor( mColors.at( i ).first ) );
props.insert( QString( "preset_color_name_%1" ).arg( i ), mColors.at( i ).second );
}
return props;
}

int QgsPresetSchemeColorRamp::count() const
{
return mColors.count();
}

QgsNamedColorList QgsPresetSchemeColorRamp::fetchColors( const QString& , const QColor& )
{
return mColors;
}
59 changes: 59 additions & 0 deletions src/core/qgscolorramp.h
Expand Up @@ -19,6 +19,7 @@
#include <QColor>
#include <QGradient>
#include "qgis.h"
#include "qgscolorscheme.h"

/** \ingroup core
* \class QgsColorRamp
Expand Down Expand Up @@ -381,6 +382,64 @@ class CORE_EXPORT QgsRandomColorRamp: public QgsColorRamp
};


/** \ingroup core
* \class QgsPresetSchemeColorRamp
* \brief A scheme based color ramp consisting of a list of predefined colors.
* \note added in QGIS 3.0
*/
class CORE_EXPORT QgsPresetSchemeColorRamp : public QgsColorRamp, public QgsColorScheme
{
public:

/** Constructor for QgsPresetSchemeColorRamp.
* @param colors list of colors in ramp
*/
QgsPresetSchemeColorRamp( const QList< QColor >& colors = QList< QColor >() );

/** Constructor for QgsPresetColorRamp.
* @param colors list of named colors in ramp
* @note not available in Python bindings - use setColors instead
*/
QgsPresetSchemeColorRamp( const QgsNamedColorList& colors );

/** Returns a new QgsPresetSchemeColorRamp color ramp created using the properties encoded in a string
* map.
* @param properties color ramp properties
* @see properties()
*/
static QgsColorRamp* create( const QgsStringMap& properties = QgsStringMap() );

/** Sets the list of colors used by the ramp.
* @param colors list of colors
* @see colors()
*/
bool setColors( const QgsNamedColorList& colors, const QString& = QString(), const QColor& = QColor() ) override { mColors = colors; return true; }

/** Returns the list of colors used by the ramp.
* @see setColors()
*/
QList< QColor > colors() const;

// QgsColorRamp interface
virtual double value( int index ) const override;
virtual QColor color( double value ) const override;
virtual QString type() const override { return "preset"; }
virtual QgsPresetSchemeColorRamp* clone() const override;
virtual QgsStringMap properties() const override;
int count() const override;

// QgsColorScheme interface
QString schemeName() const override { return "preset"; }
QgsNamedColorList fetchColors( const QString &context = QString(),
const QColor &baseColor = QColor() ) override;
bool isEditable() const override { return true; }

private:

QgsNamedColorList mColors;
};


#define DEFAULT_COLORBREWER_SCHEMENAME "Spectral"
#define DEFAULT_COLORBREWER_COLORS 5

Expand Down
2 changes: 2 additions & 0 deletions src/core/symbology-ng/qgssymbollayerutils.cpp
Expand Up @@ -2665,6 +2665,8 @@ QgsColorRamp* QgsSymbolLayerUtils::loadColorRamp( QDomElement& element )
return QgsColorBrewerColorRamp::create( props );
else if ( rampType == "cpt-city" )
return QgsCptCityColorRamp::create( props );
else if ( rampType == "preset" )
return QgsPresetSchemeColorRamp::create( props );
else
{
QgsDebugMsg( "unknown colorramp type " + rampType );
Expand Down
2 changes: 2 additions & 0 deletions src/gui/CMakeLists.txt
Expand Up @@ -279,6 +279,7 @@ SET(QGIS_GUI_SRCS
qgspanelwidgetstack.cpp
qgspixmaplabel.cpp
qgspluginmanagerinterface.cpp
qgspresetcolorrampdialog.cpp
qgsprevieweffect.cpp
qgsprojectbadlayerguihandler.cpp
qgsprojectionselectionwidget.cpp
Expand Down Expand Up @@ -434,6 +435,7 @@ SET(QGIS_GUI_MOC_HDRS
qgspanelwidgetstack.h
qgspixmaplabel.h
qgspluginmanagerinterface.h
qgspresetcolorrampdialog.h
qgsprevieweffect.h
qgsprojectbadlayerguihandler.h
qgsprojectionselectionwidget.h
Expand Down

0 comments on commit ec50cac

Please sign in to comment.