Skip to content

Commit ec50cac

Browse files
committedSep 14, 2016
[FEATURE] New "preset" colors color ramp option
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!)
1 parent 8ac1460 commit ec50cac

13 files changed

+793
-3
lines changed
 

‎python/core/qgscolorramp.sip

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ class QgsColorRamp
1616
sipType = sipType_QgsLimitedRandomColorRamp;
1717
else if (sipCpp->type() == "randomcolors")
1818
sipType = sipType_QgsRandomColorRamp;
19+
else if (sipCpp->type() == "preset")
20+
sipType = sipType_QgsPresetSchemeColorRamp;
1921
else if (sipCpp->type() == "colorbrewer")
2022
sipType = sipType_QgsColorBrewerColorRamp;
2123
else if (sipCpp->type() == "cpt-city")
@@ -285,6 +287,64 @@ class QgsRandomColorRamp : QgsColorRamp
285287
QgsStringMap properties() const;
286288
};
287289

290+
/** \ingroup core
291+
* \class QgsPresetSchemeColorRamp
292+
* \brief A scheme based color ramp consisting of a list of predefined colors.
293+
* \note added in QGIS 3.0
294+
*/
295+
class QgsPresetSchemeColorRamp : QgsColorRamp, QgsColorScheme
296+
{
297+
%TypeHeaderCode
298+
#include <qgscolorramp.h>
299+
%End
300+
301+
public:
302+
303+
/** Constructor for QgsPresetSchemeColorRamp.
304+
* @param colors list of colors in ramp
305+
*/
306+
QgsPresetSchemeColorRamp( const QList< QColor >& colors = QList< QColor >() );
307+
308+
/** Constructor for QgsPresetColorRamp.
309+
* @param colors list of named colors in ramp
310+
* @note not available in Python bindings - use setColors instead
311+
*/
312+
//QgsPresetSchemeColorRamp( const QgsNamedColorList& colors );
313+
314+
/** Returns a new QgsPresetSchemeColorRamp color ramp created using the properties encoded in a string
315+
* map.
316+
* @param properties color ramp properties
317+
* @see properties()
318+
*/
319+
static QgsColorRamp* create( const QgsStringMap& properties = QgsStringMap() );
320+
321+
/** Sets the list of colors used by the ramp.
322+
* @param colors list of colors
323+
* @see colors()
324+
*/
325+
bool setColors( const QgsNamedColorList& colors, const QString& = QString(), const QColor& = QColor() );
326+
327+
/** Returns the list of colors used by the ramp.
328+
* @see setColors()
329+
*/
330+
QList< QColor > colors() const;
331+
332+
// QgsColorRamp interface
333+
virtual double value( int index ) const;
334+
virtual QColor color( double value ) const;
335+
virtual QString type() const;
336+
virtual QgsPresetSchemeColorRamp* clone() const /Factory/;
337+
virtual QgsStringMap properties() const;
338+
int count() const;
339+
340+
// QgsColorScheme interface
341+
QString schemeName() const;
342+
QgsNamedColorList fetchColors( const QString &context = QString(),
343+
const QColor &baseColor = QColor() );
344+
bool isEditable() const;
345+
346+
};
347+
288348
/** \ingroup core
289349
* \class QgsColorBrewerColorRamp
290350
*/

‎python/gui/gui.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@
141141
%Include qgspanelwidgetstack.sip
142142
%Include qgspixmaplabel.sip
143143
%Include qgspluginmanagerinterface.sip
144+
%Include qgspresetcolorrampdialog.sip
144145
%Include qgsprevieweffect.sip
145146
%Include qgsprojectbadlayerguihandler.sip
146147
%Include qgsprojectionselectionwidget.sip
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/** \ingroup gui
2+
* \class QgsPresetColorRampWidget
3+
* A widget which allows users to modify the properties of a QgsPresetSchemeColorRamp.
4+
* \note added in QGIS 3.0
5+
*/
6+
7+
class QgsPresetColorRampWidget : QgsPanelWidget
8+
{
9+
%TypeHeaderCode
10+
#include <qgspresetcolorrampdialog.h>
11+
%End
12+
13+
public:
14+
15+
/** Constructor for QgsPresetColorRampWidget.
16+
* @param ramp initial ramp to show in dialog
17+
* @param parent parent widget
18+
*/
19+
QgsPresetColorRampWidget( const QgsPresetSchemeColorRamp& ramp, QWidget* parent /TransferThis/ = nullptr );
20+
21+
~QgsPresetColorRampWidget();
22+
23+
/** Returns a color ramp representing the current settings from the dialog.
24+
* @see setRamp()
25+
*/
26+
QgsPresetSchemeColorRamp ramp() const;
27+
28+
/** Sets the color ramp to show in the dialog.
29+
* @param ramp color ramp
30+
* @see ramp()
31+
*/
32+
void setRamp( const QgsPresetSchemeColorRamp& ramp );
33+
34+
signals:
35+
36+
//! Emitted when the dialog settings change
37+
void changed();
38+
};
39+
40+
/** \ingroup gui
41+
* \class QgsPresetColorRampDialog
42+
* A dialog which allows users to modify the properties of a QgsPresetSchemeColorRamp.
43+
* \note added in QGIS 3.0
44+
*/
45+
46+
class QgsPresetColorRampDialog : QDialog
47+
{
48+
%TypeHeaderCode
49+
#include <qgspresetcolorrampdialog.h>
50+
%End
51+
52+
public:
53+
54+
/** Constructor for QgsPresetColorRampDialog.
55+
* @param ramp initial ramp to show in dialog
56+
* @param parent parent widget
57+
*/
58+
QgsPresetColorRampDialog( const QgsPresetSchemeColorRamp& ramp, QWidget* parent /TransferThis/ = nullptr );
59+
60+
/** Returns a color ramp representing the current settings from the dialog.
61+
* @see setRamp()
62+
*/
63+
QgsPresetSchemeColorRamp ramp() const;
64+
65+
/** Sets the color ramp to show in the dialog.
66+
* @param ramp color ramp
67+
* @see ramp()
68+
*/
69+
void setRamp( const QgsPresetSchemeColorRamp& ramp );
70+
71+
signals:
72+
73+
//! Emitted when the dialog settings change
74+
void changed();
75+
};

‎src/core/qgscolorramp.cpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -738,3 +738,102 @@ bool QgsCptCityColorRamp::loadFile()
738738
mFileLoaded = true;
739739
return true;
740740
}
741+
742+
743+
//
744+
// QgsPresetColorRamp
745+
//
746+
747+
QgsPresetSchemeColorRamp::QgsPresetSchemeColorRamp( const QList<QColor>& colors )
748+
{
749+
Q_FOREACH ( const QColor& color, colors )
750+
{
751+
mColors << qMakePair( color, color.name() );
752+
}
753+
// need at least one color
754+
if ( mColors.isEmpty() )
755+
mColors << qMakePair( QColor( 250, 75, 60 ), QString( "#fa4b3c" ) );
756+
}
757+
758+
QgsPresetSchemeColorRamp::QgsPresetSchemeColorRamp( const QgsNamedColorList& colors )
759+
: mColors( colors )
760+
{
761+
// need at least one color
762+
if ( mColors.isEmpty() )
763+
mColors << qMakePair( QColor( 250, 75, 60 ), QString( "#fa4b3c" ) );
764+
}
765+
766+
QgsColorRamp* QgsPresetSchemeColorRamp::create( const QgsStringMap& properties )
767+
{
768+
QgsNamedColorList colors;
769+
770+
int i = 0;
771+
QString colorString = properties.value( QString( "preset_color_%1" ).arg( i ), QString() );
772+
QString colorName = properties.value( QString( "preset_color_name_%1" ).arg( i ), QString() );
773+
while ( !colorString.isEmpty() )
774+
{
775+
colors << qMakePair( QgsSymbolLayerUtils::decodeColor( colorString ), colorName );
776+
i++;
777+
colorString = properties.value( QString( "preset_color_%1" ).arg( i ), QString() );
778+
colorName = properties.value( QString( "preset_color_name_%1" ).arg( i ), QString() );
779+
}
780+
781+
return new QgsPresetSchemeColorRamp( colors );
782+
}
783+
784+
QList<QColor> QgsPresetSchemeColorRamp::colors() const
785+
{
786+
QList< QColor > l;
787+
for ( int i = 0; i < mColors.count(); ++i )
788+
{
789+
l << mColors.at( i ).first;
790+
}
791+
return l;
792+
}
793+
794+
double QgsPresetSchemeColorRamp::value( int index ) const
795+
{
796+
if ( mColors.size() < 1 )
797+
return 0;
798+
return static_cast< double >( index ) / ( mColors.size() - 1 );
799+
}
800+
801+
QColor QgsPresetSchemeColorRamp::color( double value ) const
802+
{
803+
if ( value < 0 || value > 1 )
804+
return QColor();
805+
806+
int colorCnt = mColors.count();
807+
int colorIdx = qMin( static_cast< int >( value * colorCnt ), colorCnt - 1 );
808+
809+
if ( colorIdx >= 0 && colorIdx < colorCnt )
810+
return mColors.at( colorIdx ).first;
811+
812+
return QColor();
813+
}
814+
815+
QgsPresetSchemeColorRamp* QgsPresetSchemeColorRamp::clone() const
816+
{
817+
return new QgsPresetSchemeColorRamp( *this );
818+
}
819+
820+
QgsStringMap QgsPresetSchemeColorRamp::properties() const
821+
{
822+
QgsStringMap props;
823+
for ( int i = 0; i < mColors.count(); ++i )
824+
{
825+
props.insert( QString( "preset_color_%1" ).arg( i ), QgsSymbolLayerUtils::encodeColor( mColors.at( i ).first ) );
826+
props.insert( QString( "preset_color_name_%1" ).arg( i ), mColors.at( i ).second );
827+
}
828+
return props;
829+
}
830+
831+
int QgsPresetSchemeColorRamp::count() const
832+
{
833+
return mColors.count();
834+
}
835+
836+
QgsNamedColorList QgsPresetSchemeColorRamp::fetchColors( const QString& , const QColor& )
837+
{
838+
return mColors;
839+
}

‎src/core/qgscolorramp.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <QColor>
2020
#include <QGradient>
2121
#include "qgis.h"
22+
#include "qgscolorscheme.h"
2223

2324
/** \ingroup core
2425
* \class QgsColorRamp
@@ -381,6 +382,64 @@ class CORE_EXPORT QgsRandomColorRamp: public QgsColorRamp
381382
};
382383

383384

385+
/** \ingroup core
386+
* \class QgsPresetSchemeColorRamp
387+
* \brief A scheme based color ramp consisting of a list of predefined colors.
388+
* \note added in QGIS 3.0
389+
*/
390+
class CORE_EXPORT QgsPresetSchemeColorRamp : public QgsColorRamp, public QgsColorScheme
391+
{
392+
public:
393+
394+
/** Constructor for QgsPresetSchemeColorRamp.
395+
* @param colors list of colors in ramp
396+
*/
397+
QgsPresetSchemeColorRamp( const QList< QColor >& colors = QList< QColor >() );
398+
399+
/** Constructor for QgsPresetColorRamp.
400+
* @param colors list of named colors in ramp
401+
* @note not available in Python bindings - use setColors instead
402+
*/
403+
QgsPresetSchemeColorRamp( const QgsNamedColorList& colors );
404+
405+
/** Returns a new QgsPresetSchemeColorRamp color ramp created using the properties encoded in a string
406+
* map.
407+
* @param properties color ramp properties
408+
* @see properties()
409+
*/
410+
static QgsColorRamp* create( const QgsStringMap& properties = QgsStringMap() );
411+
412+
/** Sets the list of colors used by the ramp.
413+
* @param colors list of colors
414+
* @see colors()
415+
*/
416+
bool setColors( const QgsNamedColorList& colors, const QString& = QString(), const QColor& = QColor() ) override { mColors = colors; return true; }
417+
418+
/** Returns the list of colors used by the ramp.
419+
* @see setColors()
420+
*/
421+
QList< QColor > colors() const;
422+
423+
// QgsColorRamp interface
424+
virtual double value( int index ) const override;
425+
virtual QColor color( double value ) const override;
426+
virtual QString type() const override { return "preset"; }
427+
virtual QgsPresetSchemeColorRamp* clone() const override;
428+
virtual QgsStringMap properties() const override;
429+
int count() const override;
430+
431+
// QgsColorScheme interface
432+
QString schemeName() const override { return "preset"; }
433+
QgsNamedColorList fetchColors( const QString &context = QString(),
434+
const QColor &baseColor = QColor() ) override;
435+
bool isEditable() const override { return true; }
436+
437+
private:
438+
439+
QgsNamedColorList mColors;
440+
};
441+
442+
384443
#define DEFAULT_COLORBREWER_SCHEMENAME "Spectral"
385444
#define DEFAULT_COLORBREWER_COLORS 5
386445

‎src/core/symbology-ng/qgssymbollayerutils.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2665,6 +2665,8 @@ QgsColorRamp* QgsSymbolLayerUtils::loadColorRamp( QDomElement& element )
26652665
return QgsColorBrewerColorRamp::create( props );
26662666
else if ( rampType == "cpt-city" )
26672667
return QgsCptCityColorRamp::create( props );
2668+
else if ( rampType == "preset" )
2669+
return QgsPresetSchemeColorRamp::create( props );
26682670
else
26692671
{
26702672
QgsDebugMsg( "unknown colorramp type " + rampType );

‎src/gui/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ SET(QGIS_GUI_SRCS
279279
qgspanelwidgetstack.cpp
280280
qgspixmaplabel.cpp
281281
qgspluginmanagerinterface.cpp
282+
qgspresetcolorrampdialog.cpp
282283
qgsprevieweffect.cpp
283284
qgsprojectbadlayerguihandler.cpp
284285
qgsprojectionselectionwidget.cpp
@@ -434,6 +435,7 @@ SET(QGIS_GUI_MOC_HDRS
434435
qgspanelwidgetstack.h
435436
qgspixmaplabel.h
436437
qgspluginmanagerinterface.h
438+
qgspresetcolorrampdialog.h
437439
qgsprevieweffect.h
438440
qgsprojectbadlayerguihandler.h
439441
qgsprojectionselectionwidget.h

‎src/gui/qgspresetcolorrampdialog.cpp

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/***************************************************************************
2+
qgspresetcolorrampdialog.cpp
3+
----------------------------
4+
begin : September 2016
5+
copyright : (C) 2016 by Nyall Dawson
6+
email : nyall dot dawson at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include "qgspresetcolorrampdialog.h"
17+
18+
#include "qgssymbollayerutils.h"
19+
#include "qgscolordialog.h"
20+
#include <QFileDialog>
21+
#include <QAbstractButton>
22+
#include <QDialogButtonBox>
23+
#include <QMessageBox>
24+
25+
QgsPresetColorRampWidget::QgsPresetColorRampWidget( const QgsPresetSchemeColorRamp& ramp, QWidget* parent )
26+
: QgsPanelWidget( parent )
27+
, mRamp( ramp )
28+
{
29+
setupUi( this );
30+
mTreeColors->setScheme( &mRamp );
31+
32+
connect( mButtonCopyColors, SIGNAL( clicked() ), mTreeColors, SLOT( copyColors() ) );
33+
connect( mButtonRemoveColor, SIGNAL( clicked() ), mTreeColors, SLOT( removeSelection() ) );
34+
connect( mButtonPasteColors, SIGNAL( clicked() ), mTreeColors, SLOT( pasteColors() ) );
35+
connect( mButtonImportColors, SIGNAL( clicked( bool ) ), mTreeColors, SLOT( showImportColorsDialog() ) );
36+
connect( mButtonExportColors, SIGNAL( clicked( bool ) ), mTreeColors, SLOT( showExportColorsDialog() ) );
37+
38+
connect( mTreeColors->model(), SIGNAL( dataChanged( QModelIndex, QModelIndex, QVector<int> ) ), this, SLOT( schemeChanged() ) );
39+
connect( mTreeColors->model(), SIGNAL( rowsRemoved( QModelIndex, int, int ) ), this, SLOT( schemeChanged() ) );
40+
41+
updatePreview();
42+
}
43+
44+
QgsPresetColorRampWidget::~QgsPresetColorRampWidget()
45+
{
46+
}
47+
48+
QgsPresetSchemeColorRamp QgsPresetColorRampWidget::ramp() const
49+
{
50+
return mRamp;
51+
}
52+
53+
void QgsPresetColorRampWidget::setRamp( const QgsPresetSchemeColorRamp& ramp )
54+
{
55+
mRamp = ramp;
56+
mTreeColors->setScheme( &mRamp );
57+
updatePreview();
58+
emit changed();
59+
}
60+
61+
void QgsPresetColorRampWidget::updatePreview()
62+
{
63+
QSize size( 300, 40 );
64+
lblPreview->setPixmap( QgsSymbolLayerUtils::colorRampPreviewPixmap( &mRamp, size ) );
65+
}
66+
67+
void QgsPresetColorRampWidget::setColors()
68+
{
69+
updatePreview();
70+
emit changed();
71+
}
72+
73+
void QgsPresetColorRampWidget::on_mButtonAddColor_clicked()
74+
{
75+
if ( dockMode() )
76+
{
77+
mTreeColors->addColor( QgsRecentColorScheme::lastUsedColor(), QgsSymbolLayerUtils::colorToName( QgsRecentColorScheme::lastUsedColor() ) );
78+
79+
QgsCompoundColorWidget* colorWidget = new QgsCompoundColorWidget( this, QgsRecentColorScheme::lastUsedColor(), QgsCompoundColorWidget::LayoutVertical );
80+
colorWidget->setPanelTitle( tr( "Select Color" ) );
81+
colorWidget->setAllowAlpha( true );
82+
connect( colorWidget, SIGNAL( currentColorChanged( QColor ) ), this, SLOT( newColorChanged( QColor ) ) );
83+
openPanel( colorWidget );
84+
}
85+
else
86+
{
87+
QColor newColor = QgsColorDialog::getColor( QColor(), this->parentWidget(), tr( "Select Color" ), true );
88+
if ( !newColor.isValid() )
89+
{
90+
return;
91+
}
92+
activateWindow();
93+
94+
mTreeColors->addColor( newColor, QgsSymbolLayerUtils::colorToName( newColor ) );
95+
}
96+
}
97+
98+
void QgsPresetColorRampWidget::schemeChanged()
99+
{
100+
mTreeColors->saveColorsToScheme();
101+
updatePreview();
102+
emit changed();
103+
}
104+
105+
void QgsPresetColorRampWidget::newColorChanged( const QColor& color )
106+
{
107+
int row = mTreeColors->model()->rowCount() - 1;
108+
QModelIndex colorIndex = mTreeColors->model()->index( row, 0 );
109+
mTreeColors->model()->setData( colorIndex, color );
110+
}
111+
112+
QgsPresetColorRampDialog::QgsPresetColorRampDialog( const QgsPresetSchemeColorRamp& ramp, QWidget* parent )
113+
: QDialog( parent )
114+
{
115+
QVBoxLayout* vLayout = new QVBoxLayout();
116+
mWidget = new QgsPresetColorRampWidget( ramp );
117+
vLayout->addWidget( mWidget );
118+
QDialogButtonBox* bbox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal );
119+
connect( bbox, SIGNAL( accepted() ), this, SLOT( accept() ) );
120+
connect( bbox, SIGNAL( rejected() ), this, SLOT( reject() ) );
121+
vLayout->addWidget( bbox );
122+
setLayout( vLayout );
123+
connect( mWidget, SIGNAL( changed() ), this, SIGNAL( changed() ) );
124+
}

‎src/gui/qgspresetcolorrampdialog.h

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/***************************************************************************
2+
qgspresetcolorrampdialog.h
3+
---------------------
4+
begin : September 2016
5+
copyright : (C) 2016 by Nyall Dawson
6+
email : nyall dot dawson at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#ifndef QGSPRESETCOLORRAMPDIALOG_H
17+
#define QGSPRESETCOLORRAMPDIALOG_H
18+
19+
#include <QDialog>
20+
#include "qgspanelwidget.h"
21+
#include "qgscolorramp.h"
22+
#include "ui_qgspresetcolorrampwidgetbase.h"
23+
24+
/** \ingroup gui
25+
* \class QgsPresetColorRampWidget
26+
* A widget which allows users to modify the properties of a QgsPresetSchemeColorRamp.
27+
* \note added in QGIS 3.0
28+
*/
29+
class GUI_EXPORT QgsPresetColorRampWidget : public QgsPanelWidget, private Ui::QgsPresetColorRampWidgetBase
30+
{
31+
Q_OBJECT
32+
Q_PROPERTY( QgsPresetSchemeColorRamp ramp READ ramp WRITE setRamp )
33+
34+
public:
35+
36+
/** Constructor for QgsPresetColorRampWidget.
37+
* @param ramp initial ramp to show in dialog
38+
* @param parent parent widget
39+
*/
40+
QgsPresetColorRampWidget( const QgsPresetSchemeColorRamp& ramp, QWidget* parent = nullptr );
41+
42+
~QgsPresetColorRampWidget();
43+
44+
/** Returns a color ramp representing the current settings from the dialog.
45+
* @see setRamp()
46+
*/
47+
QgsPresetSchemeColorRamp ramp() const;
48+
49+
/** Sets the color ramp to show in the dialog.
50+
* @param ramp color ramp
51+
* @see ramp()
52+
*/
53+
void setRamp( const QgsPresetSchemeColorRamp& ramp );
54+
55+
signals:
56+
57+
//! Emitted when the dialog settings change
58+
void changed();
59+
60+
private slots:
61+
void setColors();
62+
63+
void on_mButtonAddColor_clicked();
64+
65+
void newColorChanged( const QColor& color );
66+
void schemeChanged();
67+
68+
private:
69+
70+
void updatePreview();
71+
QgsPresetSchemeColorRamp mRamp;
72+
};
73+
74+
/** \ingroup gui
75+
* \class QgsPresetColorRampDialog
76+
* A dialog which allows users to modify the properties of a QgsPresetSchemeColorRamp.
77+
* \note added in QGIS 3.0
78+
*/
79+
class GUI_EXPORT QgsPresetColorRampDialog : public QDialog
80+
{
81+
Q_OBJECT
82+
Q_PROPERTY( QgsPresetSchemeColorRamp ramp READ ramp WRITE setRamp )
83+
84+
public:
85+
86+
/** Constructor for QgsPresetColorRampDialog.
87+
* @param ramp initial ramp to show in dialog
88+
* @param parent parent widget
89+
*/
90+
QgsPresetColorRampDialog( const QgsPresetSchemeColorRamp& ramp, QWidget* parent = nullptr );
91+
92+
/** Returns a color ramp representing the current settings from the dialog.
93+
* @see setRamp()
94+
*/
95+
QgsPresetSchemeColorRamp ramp() const { return mWidget->ramp(); }
96+
97+
/** Sets the color ramp to show in the dialog.
98+
* @param ramp color ramp
99+
* @see ramp()
100+
*/
101+
void setRamp( const QgsPresetSchemeColorRamp& ramp ) { mWidget->setRamp( ramp ); }
102+
103+
signals:
104+
105+
//! Emitted when the dialog settings change
106+
void changed();
107+
108+
private:
109+
110+
QgsPresetColorRampWidget* mWidget;
111+
112+
};
113+
114+
#endif //QGSPRESETCOLORRAMPDIALOG_H

‎src/gui/symbology-ng/qgscolorrampcombobox.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "qgslimitedrandomcolorrampdialog.h"
2424
#include "qgscolorbrewercolorrampdialog.h"
2525
#include "qgscptcitycolorrampdialog.h"
26+
#include "qgspresetcolorrampdialog.h"
2627

2728
QSize QgsColorRampComboBox::rampIconSize( 50, 16 );
2829

@@ -172,6 +173,26 @@ void QgsColorRampComboBox::editSourceRamp()
172173
}
173174
}
174175
}
176+
else if ( currentRamp->type() == "preset" )
177+
{
178+
QgsPresetSchemeColorRamp* presetRamp = static_cast<QgsPresetSchemeColorRamp*>( currentRamp.data() );
179+
if ( panelMode )
180+
{
181+
QgsPresetColorRampWidget* widget = new QgsPresetColorRampWidget( *presetRamp, this );
182+
widget->setPanelTitle( tr( "Edit ramp" ) );
183+
connect( widget, SIGNAL( changed() ), this, SLOT( rampWidgetUpdated() ) );
184+
panel->openPanel( widget );
185+
}
186+
else
187+
{
188+
QgsPresetColorRampDialog dlg( *presetRamp, this );
189+
if ( dlg.exec() )
190+
{
191+
setSourceColorRamp( dlg.ramp().clone() );
192+
emit sourceRampEdited();
193+
}
194+
}
195+
}
175196
else if ( currentRamp->type() == "colorbrewer" )
176197
{
177198
QgsColorBrewerColorRamp* brewerRamp = static_cast<QgsColorBrewerColorRamp*>( currentRamp.data() );
@@ -227,4 +248,11 @@ void QgsColorRampComboBox::rampWidgetUpdated()
227248
emit sourceRampEdited();
228249
return;
229250
}
251+
QgsPresetColorRampWidget* presetRampWidget = qobject_cast< QgsPresetColorRampWidget* >( sender() );
252+
if ( presetRampWidget )
253+
{
254+
setSourceColorRamp( presetRampWidget->ramp().clone() );
255+
emit sourceRampEdited();
256+
return;
257+
}
230258
}

‎src/gui/symbology-ng/qgsstylemanagerdialog.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "qgsgradientcolorrampdialog.h"
2525
#include "qgslimitedrandomcolorrampdialog.h"
2626
#include "qgscolorbrewercolorrampdialog.h"
27+
#include "qgspresetcolorrampdialog.h"
2728
#include "qgscptcitycolorrampdialog.h"
2829
#include "qgsstyleexportimportdialog.h"
2930
#include "qgssmartgroupeditordialog.h"
@@ -133,7 +134,7 @@ QgsStyleManagerDialog::QgsStyleManagerDialog( QgsStyle* style, QWidget* parent )
133134

134135
// Menu for the "Add item" toolbutton when in colorramp mode
135136
QStringList rampTypes;
136-
rampTypes << tr( "Gradient" ) << tr( "Random" ) << tr( "ColorBrewer" );
137+
rampTypes << tr( "Gradient" ) << tr( "Random" ) << tr( "ColorBrewer" ) << tr( "Preset colors" );
137138
rampTypes << tr( "cpt-city" ); // todo, only for rasters?
138139
mMenuBtnAddItemColorRamp = new QMenu( this );
139140
Q_FOREACH ( const QString& rampType, rampTypes )
@@ -443,7 +444,7 @@ QString QgsStyleManagerDialog::addColorRampStatic( QWidget* parent, QgsStyle* st
443444
if ( rampType.isEmpty() )
444445
{
445446
QStringList rampTypes;
446-
rampTypes << tr( "Gradient" ) << tr( "Random" ) << tr( "ColorBrewer" );
447+
rampTypes << tr( "Gradient" ) << tr( "Random" ) << tr( "ColorBrewer" ) << tr( "Preset colors" );
447448
rampTypes << tr( "cpt-city" ); // todo, only for rasters?
448449
rampType = QInputDialog::getItem( parent, tr( "Color ramp type" ),
449450
tr( "Please select color ramp type:" ), rampTypes, 0, false, &ok );
@@ -484,6 +485,16 @@ QString QgsStyleManagerDialog::addColorRampStatic( QWidget* parent, QgsStyle* st
484485
ramp.reset( dlg.ramp().clone() );
485486
name = dlg.ramp().schemeName() + QString::number( dlg.ramp().colors() );
486487
}
488+
else if ( rampType == tr( "Preset colors" ) )
489+
{
490+
QgsPresetColorRampDialog dlg( QgsPresetSchemeColorRamp(), parent );
491+
if ( !dlg.exec() )
492+
{
493+
return QString();
494+
}
495+
ramp.reset( dlg.ramp().clone() );
496+
name = tr( "new preset ramp" );
497+
}
487498
else if ( rampType == tr( "cpt-city" ) )
488499
{
489500
QgsCptCityColorRampDialog dlg( QgsCptCityColorRamp( "", "" ), parent );
@@ -654,6 +665,16 @@ bool QgsStyleManagerDialog::editColorRamp()
654665
}
655666
ramp.reset( dlg.ramp().clone() );
656667
}
668+
else if ( ramp->type() == "preset" )
669+
{
670+
QgsPresetSchemeColorRamp* presetRamp = static_cast<QgsPresetSchemeColorRamp*>( ramp.data() );
671+
QgsPresetColorRampDialog dlg( *presetRamp, this );
672+
if ( !dlg.exec() )
673+
{
674+
return false;
675+
}
676+
ramp.reset( dlg.ramp().clone() );
677+
}
657678
else if ( ramp->type() == "cpt-city" )
658679
{
659680
QgsCptCityColorRamp* cptCityRamp = static_cast<QgsCptCityColorRamp*>( ramp.data() );
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>QgsPresetColorRampWidgetBase</class>
4+
<widget class="QgsPanelWidget" name="QgsPresetColorRampWidgetBase">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>232</width>
10+
<height>282</height>
11+
</rect>
12+
</property>
13+
<property name="windowTitle">
14+
<string>ColorBrewer ramp</string>
15+
</property>
16+
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0,0">
17+
<item>
18+
<widget class="QgsColorSchemeList" name="mTreeColors" native="true"/>
19+
</item>
20+
<item>
21+
<layout class="QHBoxLayout" name="horizontalLayout">
22+
<item>
23+
<widget class="QToolButton" name="mButtonAddColor">
24+
<property name="toolTip">
25+
<string>Add color</string>
26+
</property>
27+
<property name="text">
28+
<string/>
29+
</property>
30+
<property name="icon">
31+
<iconset resource="../../images/images.qrc">
32+
<normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
33+
</property>
34+
</widget>
35+
</item>
36+
<item>
37+
<widget class="QToolButton" name="mButtonRemoveColor">
38+
<property name="toolTip">
39+
<string>Remove color</string>
40+
</property>
41+
<property name="text">
42+
<string/>
43+
</property>
44+
<property name="icon">
45+
<iconset resource="../../images/images.qrc">
46+
<normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
47+
</property>
48+
</widget>
49+
</item>
50+
<item>
51+
<widget class="QToolButton" name="mButtonCopyColors">
52+
<property name="toolTip">
53+
<string>Copy colors</string>
54+
</property>
55+
<property name="text">
56+
<string/>
57+
</property>
58+
<property name="icon">
59+
<iconset resource="../../images/images.qrc">
60+
<normaloff>:/images/themes/default/mActionCopySelected.png</normaloff>:/images/themes/default/mActionCopySelected.png</iconset>
61+
</property>
62+
</widget>
63+
</item>
64+
<item>
65+
<widget class="QToolButton" name="mButtonPasteColors">
66+
<property name="toolTip">
67+
<string>Paste colors</string>
68+
</property>
69+
<property name="text">
70+
<string/>
71+
</property>
72+
<property name="icon">
73+
<iconset resource="../../images/images.qrc">
74+
<normaloff>:/images/themes/default/mActionEditPaste.svg</normaloff>:/images/themes/default/mActionEditPaste.svg</iconset>
75+
</property>
76+
</widget>
77+
</item>
78+
<item>
79+
<widget class="QToolButton" name="mButtonImportColors">
80+
<property name="statusTip">
81+
<string>Import colors</string>
82+
</property>
83+
<property name="text">
84+
<string/>
85+
</property>
86+
<property name="icon">
87+
<iconset resource="../../images/images.qrc">
88+
<normaloff>:/images/themes/default/mActionFileOpen.svg</normaloff>:/images/themes/default/mActionFileOpen.svg</iconset>
89+
</property>
90+
</widget>
91+
</item>
92+
<item>
93+
<widget class="QToolButton" name="mButtonExportColors">
94+
<property name="toolTip">
95+
<string>Export colors</string>
96+
</property>
97+
<property name="text">
98+
<string/>
99+
</property>
100+
<property name="icon">
101+
<iconset resource="../../images/images.qrc">
102+
<normaloff>:/images/themes/default/mActionFileSave.svg</normaloff>:/images/themes/default/mActionFileSave.svg</iconset>
103+
</property>
104+
</widget>
105+
</item>
106+
<item>
107+
<spacer name="horizontalSpacer">
108+
<property name="orientation">
109+
<enum>Qt::Horizontal</enum>
110+
</property>
111+
<property name="sizeHint" stdset="0">
112+
<size>
113+
<width>40</width>
114+
<height>20</height>
115+
</size>
116+
</property>
117+
</spacer>
118+
</item>
119+
</layout>
120+
</item>
121+
<item>
122+
<widget class="QGroupBox" name="groupBox">
123+
<property name="title">
124+
<string>Preview</string>
125+
</property>
126+
<layout class="QVBoxLayout" name="verticalLayout_2">
127+
<item>
128+
<widget class="QLabel" name="lblPreview">
129+
<property name="frameShape">
130+
<enum>QFrame::NoFrame</enum>
131+
</property>
132+
<property name="text">
133+
<string/>
134+
</property>
135+
<property name="alignment">
136+
<set>Qt::AlignCenter</set>
137+
</property>
138+
</widget>
139+
</item>
140+
</layout>
141+
</widget>
142+
</item>
143+
</layout>
144+
</widget>
145+
<customwidgets>
146+
<customwidget>
147+
<class>QgsPanelWidget</class>
148+
<extends>QWidget</extends>
149+
<header>qgspanelwidget.h</header>
150+
<container>1</container>
151+
</customwidget>
152+
<customwidget>
153+
<class>QgsColorSchemeList</class>
154+
<extends>QWidget</extends>
155+
<header location="global">qgscolorschemelist.h</header>
156+
<container>1</container>
157+
</customwidget>
158+
</customwidgets>
159+
<resources>
160+
<include location="../../images/images.qrc"/>
161+
</resources>
162+
<connections/>
163+
</ui>

‎tests/src/python/test_qgsvectorcolorramp.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
QgsGradientStop,
1919
QgsLimitedRandomColorRamp,
2020
QgsRandomColorRamp,
21-
QgsColorBrewerColorRamp)
21+
QgsColorBrewerColorRamp,
22+
QgsPresetSchemeColorRamp)
2223
from qgis.PyQt.QtGui import QColor, QGradient
2324
from qgis.testing import unittest
2425

@@ -268,6 +269,47 @@ def testQgsRandomColorRampV2(self):
268269
c = r.color(j * 0.1)
269270
self.assertTrue(c.isValid())
270271

272+
def testQgsPresetSchemeColorRamp(self):
273+
# test preset color ramp
274+
r = QgsPresetSchemeColorRamp()
275+
self.assertEqual(r.type(), 'preset')
276+
# should be forced to have at least one color
277+
self.assertEqual(r.count(), 1)
278+
279+
# test getter/setter
280+
r = QgsPresetSchemeColorRamp([QColor(255, 0, 0), QColor(0, 255, 0), QColor(0, 0, 255), QColor(0, 0, 0)])
281+
self.assertEqual(r.colors(), [QColor(255, 0, 0), QColor(0, 255, 0), QColor(0, 0, 255), QColor(0, 0, 0)])
282+
r.setColors([(QColor(255, 0, 0), '1'), (QColor(0, 255, 0), '2')])
283+
self.assertEqual(r.colors(), [QColor(255, 0, 0), QColor(0, 255, 0)])
284+
self.assertEqual(r.fetchColors(), [(QColor(255, 0, 0), '1'), (QColor(0, 255, 0), '2')])
285+
286+
# test value
287+
r = QgsPresetSchemeColorRamp([QColor(255, 0, 0), QColor(0, 255, 0), QColor(0, 0, 255), QColor(0, 0, 0), QColor(255, 255, 255)])
288+
self.assertEqual(r.value(0), 0)
289+
self.assertEqual(r.value(1), 0.25)
290+
self.assertEqual(r.value(2), 0.5)
291+
self.assertEqual(r.value(3), 0.75)
292+
self.assertEqual(r.value(4), 1)
293+
294+
self.assertTrue(not r.color(-1).isValid())
295+
self.assertTrue(not r.color(5).isValid())
296+
297+
# test generated colors
298+
for i in range(5):
299+
self.assertEqual(r.color(r.value(i)), r.colors()[i])
300+
301+
# test creating from properties
302+
r.setColors([(QColor(255, 0, 0), '1'), (QColor(0, 255, 0), '2')])
303+
props = r.properties()
304+
fromProps = QgsPresetSchemeColorRamp.create(props)
305+
self.assertEqual(fromProps.count(), 2)
306+
self.assertEqual(fromProps.fetchColors(), r.fetchColors())
307+
308+
# test cloning ramp
309+
cloned = r.clone()
310+
self.assertEqual(cloned.count(), 2)
311+
self.assertEqual(cloned.fetchColors(), r.fetchColors())
312+
271313
def testQgsColorBrewerColorRampV2(self):
272314
# test color brewer color ramps
273315
r = QgsColorBrewerColorRamp('OrRd', 6)

0 commit comments

Comments
 (0)
Please sign in to comment.