QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgscolorscheme.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgscolorscheme.cpp
3 -------------------
4 begin : July 2014
5 copyright : (C) 2014 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include "qgscolorscheme.h"
20
21#include "qgsproject.h"
22#include "qgssymbollayerutils.h"
23#include "qgsapplication.h"
24#include "qgssettings.h"
25
26#include <QDir>
27#include <QRegularExpression>
28#include <QTextStream>
29
30bool QgsColorScheme::setColors( const QgsNamedColorList &colors, const QString &context, const QColor &baseColor )
31{
32 //base implementation does nothing
33 Q_UNUSED( colors )
34 Q_UNUSED( context )
35 Q_UNUSED( baseColor )
36 return false;
37}
38
39
40//
41// QgsRecentColorScheme
42//
43
44QgsNamedColorList QgsRecentColorScheme::fetchColors( const QString &context, const QColor &baseColor )
45{
46 Q_UNUSED( context )
47 Q_UNUSED( baseColor )
48
49 //fetch recent colors
50 const QgsSettings settings;
51 const QList< QVariant > recentColorVariants = settings.value( QStringLiteral( "colors/recent" ) ).toList();
52
53 //generate list from recent colors
54 QgsNamedColorList colorList;
55 const auto constRecentColorVariants = recentColorVariants;
56 for ( const QVariant &color : constRecentColorVariants )
57 {
58 colorList.append( qMakePair( color.value<QColor>(), QgsSymbolLayerUtils::colorToName( color.value<QColor>() ) ) );
59 }
60 return colorList;
61}
62
64{
65 return new QgsRecentColorScheme();
66}
67
68void QgsRecentColorScheme::addRecentColor( const QColor &color )
69{
70 if ( !color.isValid() )
71 {
72 return;
73 }
74
75 //strip alpha from color
76 QColor opaqueColor = color;
77 opaqueColor.setAlpha( 255 );
78
79 QgsSettings settings;
80 QList< QVariant > recentColorVariants = settings.value( QStringLiteral( "colors/recent" ) ).toList();
81
82 //remove colors by name
83 for ( int colorIdx = recentColorVariants.length() - 1; colorIdx >= 0; --colorIdx )
84 {
85 if ( ( recentColorVariants.at( colorIdx ).value<QColor>() ).name() == opaqueColor.name() )
86 {
87 recentColorVariants.removeAt( colorIdx );
88 }
89 }
90
91 //add color
92 const QVariant colorVariant = QVariant( opaqueColor );
93 recentColorVariants.prepend( colorVariant );
94
95 //trim to 20 colors
96 while ( recentColorVariants.count() > 20 )
97 {
98 recentColorVariants.pop_back();
99 }
100
101 settings.setValue( QStringLiteral( "colors/recent" ), recentColorVariants );
102}
103
105{
106 //fetch recent colors
107 const QgsSettings settings;
108 const QList< QVariant > recentColorVariants = settings.value( QStringLiteral( "colors/recent" ) ).toList();
109
110 if ( recentColorVariants.isEmpty() )
111 return QColor();
112
113 return recentColorVariants.at( 0 ).value<QColor>();
114}
115
116QgsNamedColorList QgsCustomColorScheme::fetchColors( const QString &context, const QColor &baseColor )
117{
118 Q_UNUSED( context )
119 Q_UNUSED( baseColor )
120
121 //fetch predefined custom colors
122 QgsNamedColorList colorList;
123 const QgsSettings settings;
124
125 //check if settings contains custom palette
126 if ( !settings.contains( QStringLiteral( "/colors/palettecolors" ) ) )
127 {
128 //no custom palette, return default colors
129 colorList.append( qMakePair( QColor( 0, 0, 0 ), QString() ) );
130 colorList.append( qMakePair( QColor( 255, 255, 255 ), QString() ) );
131 colorList.append( qMakePair( QColor( 166, 206, 227 ), QString() ) );
132 colorList.append( qMakePair( QColor( 31, 120, 180 ), QString() ) );
133 colorList.append( qMakePair( QColor( 178, 223, 138 ), QString() ) );
134 colorList.append( qMakePair( QColor( 51, 160, 44 ), QString() ) );
135 colorList.append( qMakePair( QColor( 251, 154, 153 ), QString() ) );
136 colorList.append( qMakePair( QColor( 227, 26, 28 ), QString() ) );
137 colorList.append( qMakePair( QColor( 253, 191, 111 ), QString() ) );
138 colorList.append( qMakePair( QColor( 255, 127, 0 ), QString() ) );
139
140 return colorList;
141 }
142
143 QList< QVariant > customColorVariants = settings.value( QStringLiteral( "colors/palettecolors" ) ).toList();
144 const QList< QVariant > customColorLabels = settings.value( QStringLiteral( "colors/palettelabels" ) ).toList();
145
146 //generate list from custom colors
147 int colorIndex = 0;
148 for ( QList< QVariant >::iterator it = customColorVariants.begin();
149 it != customColorVariants.end(); ++it )
150 {
151 const QColor color = ( *it ).value<QColor>();
152 QString label;
153 if ( customColorLabels.length() > colorIndex )
154 {
155 label = customColorLabels.at( colorIndex ).toString();
156 }
157
158 colorList.append( qMakePair( color, label ) );
159 colorIndex++;
160 }
161
162 return colorList;
163}
164
165bool QgsCustomColorScheme::setColors( const QgsNamedColorList &colors, const QString &context, const QColor &baseColor )
166{
167 Q_UNUSED( context )
168 Q_UNUSED( baseColor )
169
170 // save colors to settings
171 QgsSettings settings;
172 QList< QVariant > customColors;
173 QList< QVariant > customColorLabels;
174
175 QgsNamedColorList::const_iterator colorIt = colors.constBegin();
176 for ( ; colorIt != colors.constEnd(); ++colorIt )
177 {
178 const QVariant color = ( *colorIt ).first;
179 const QVariant label = ( *colorIt ).second;
180 customColors.append( color );
181 customColorLabels.append( label );
182 }
183 settings.setValue( QStringLiteral( "colors/palettecolors" ), customColors );
184 settings.setValue( QStringLiteral( "colors/palettelabels" ), customColorLabels );
185 return true;
186}
187
189{
190 return new QgsCustomColorScheme();
191}
192
193
194QgsNamedColorList QgsProjectColorScheme::fetchColors( const QString &context, const QColor &baseColor )
195{
196 Q_UNUSED( context )
197 Q_UNUSED( baseColor )
198
199 QgsNamedColorList colorList;
200
201 QStringList colorStrings = QgsProject::instance()->readListEntry( QStringLiteral( "Palette" ), QStringLiteral( "/Colors" ) );
202 const QStringList colorLabels = QgsProject::instance()->readListEntry( QStringLiteral( "Palette" ), QStringLiteral( "/Labels" ) );
203
204 //generate list from custom colors
205 int colorIndex = 0;
206 for ( QStringList::iterator it = colorStrings.begin();
207 it != colorStrings.end(); ++it )
208 {
209 const QColor color = QgsSymbolLayerUtils::decodeColor( *it );
210 QString label;
211 if ( colorLabels.length() > colorIndex )
212 {
213 label = colorLabels.at( colorIndex );
214 }
215
216 colorList.append( qMakePair( color, label ) );
217 colorIndex++;
218 }
219
220 return colorList;
221}
222
223bool QgsProjectColorScheme::setColors( const QgsNamedColorList &colors, const QString &context, const QColor &baseColor )
224{
225 Q_UNUSED( context )
226 Q_UNUSED( baseColor )
228 return true;
229}
230
232{
233 return new QgsProjectColorScheme();
234}
235
236
237//
238// QgsGplColorScheme
239//
240
241QgsNamedColorList QgsGplColorScheme::fetchColors( const QString &context, const QColor &baseColor )
242{
243 Q_UNUSED( context )
244 Q_UNUSED( baseColor )
245
246 const QString sourceFilePath = gplFilePath();
247 if ( sourceFilePath.isEmpty() )
248 {
249 QgsNamedColorList noColors;
250 return noColors;
251 }
252
253 bool ok;
254 QString name;
255 QFile sourceFile( sourceFilePath );
256 return QgsSymbolLayerUtils::importColorsFromGpl( sourceFile, ok, name );
257}
258
259bool QgsGplColorScheme::setColors( const QgsNamedColorList &colors, const QString &context, const QColor &baseColor )
260{
261 Q_UNUSED( context )
262 Q_UNUSED( baseColor )
263
264 const QString destFilePath = gplFilePath();
265 if ( destFilePath.isEmpty() )
266 {
267 return false;
268 }
269
270 QFile destFile( destFilePath );
271 if ( QgsSymbolLayerUtils::saveColorsToGpl( destFile, schemeName(), colors ) )
272 {
273 if ( QgsApplication::colorSchemeRegistry()->randomStyleColorScheme() == this )
274 {
275 // force a re-generation of the random style color list, since the color list has changed
277 }
278 return true;
279 }
280 else
281 {
282 return false;
283 }
284}
285
286
287//
288// QgsUserColorScheme
289//
290
292 : mFilename( filename )
293{
294 QFile sourceFile( gplFilePath() );
295
296 //read in name
297 if ( sourceFile.open( QIODevice::ReadOnly ) )
298 {
299 QTextStream in( &sourceFile );
300
301 //find name line
302 QString line;
303 while ( !in.atEnd() && !line.startsWith( QLatin1String( "Name:" ) ) )
304 {
305 line = in.readLine();
306 }
307 if ( !in.atEnd() )
308 {
309 const QRegularExpression rx( "Name:\\s*(\\S.*)$" );
310 const QRegularExpressionMatch match = rx.match( line );
311 if ( match.hasMatch() )
312 {
313 mName = match.captured( 1 );
314 }
315 }
316 }
317 if ( mName.isEmpty() )
318 {
320 }
321
322 // we consider this scheme writable if the user has permission, OR
323 // if it DOESN'T already exist (since new schemes are only created when
324 // first written to)
325 const QFileInfo sourceFileInfo( gplFilePath() );
326 mEditable = !sourceFileInfo.exists() || sourceFileInfo.isWritable();
327}
328
330{
331 return mName;
332}
333
335{
336 return new QgsUserColorScheme( mFilename );
337}
338
339QgsColorScheme::SchemeFlags QgsUserColorScheme::flags() const
340{
341 QgsColorScheme::SchemeFlags f = QgsGplColorScheme::flags();
342
343 const QgsSettings s;
344 const QStringList showInMenuSchemes = s.value( QStringLiteral( "/colors/showInMenuList" ) ).toStringList();
345
346 if ( showInMenuSchemes.contains( mName ) )
347 {
349 }
350
351 return f;
352}
353
355{
356 const QString filePath = gplFilePath();
357 if ( filePath.isEmpty() )
358 {
359 return false;
360 }
361
362 // if file does not exist, nothing to do on the disk, so we can consider erasing done
363 if ( ! QFile::exists( filePath ) )
364 {
365 return true;
366 }
367
368 //try to erase gpl file
369 return QFile::remove( filePath );
370}
371
373{
374 QgsSettings s;
375 QStringList showInMenuSchemes = s.value( QStringLiteral( "/colors/showInMenuList" ) ).toStringList();
376
377 if ( show && !showInMenuSchemes.contains( mName ) )
378 {
379 showInMenuSchemes << mName;
380 }
381 else if ( !show && showInMenuSchemes.contains( mName ) )
382 {
383 showInMenuSchemes.removeAll( mName );
384 }
385
386 s.setValue( QStringLiteral( "/colors/showInMenuList" ), showInMenuSchemes );
387}
388
390{
391 const QString palettesDir = QgsApplication::qgisSettingsDirPath() + "palettes";
392
393 const QDir localDir;
394 if ( !localDir.mkpath( palettesDir ) )
395 {
396 return QString();
397 }
398
399 return QDir( palettesDir ).filePath( mFilename );
400}
static QgsColorSchemeRegistry * colorSchemeRegistry()
Returns the application's color scheme registry, used for managing color schemes.
static QString qgisSettingsDirPath()
Returns the path to the settings directory in user's home dir.
void setRandomStyleColorScheme(QgsColorScheme *scheme)
Sets the color scheme to use when fetching random colors to use for symbol styles.
@ ShowInColorButtonMenu
Show scheme in color button drop-down menu.
virtual QString schemeName() const =0
Gets the name for the color scheme.
virtual bool setColors(const QgsNamedColorList &colors, const QString &context=QString(), const QColor &baseColor=QColor())
Sets the colors for the scheme.
virtual SchemeFlags flags() const
Returns the current flags for the color scheme.
A color scheme which contains custom colors set through QGIS app options dialog.
QgsNamedColorList fetchColors(const QString &context=QString(), const QColor &baseColor=QColor()) override
Gets a list of colors from the scheme.
bool setColors(const QgsNamedColorList &colors, const QString &context=QString(), const QColor &baseColor=QColor()) override
Sets the colors for the scheme.
QgsCustomColorScheme * clone() const override
Clones a color scheme.
QgsCustomColorScheme()=default
Constructor for QgsCustomColorScheme.
virtual QString gplFilePath()=0
Returns the file path for the associated gpl palette file.
QgsNamedColorList fetchColors(const QString &context=QString(), const QColor &baseColor=QColor()) override
Gets a list of colors from the scheme.
bool setColors(const QgsNamedColorList &colors, const QString &context=QString(), const QColor &baseColor=QColor()) override
Sets the colors for the scheme.
A color scheme which contains project specific colors set through project properties dialog.
QgsProjectColorScheme * clone() const override
Clones a color scheme.
bool setColors(const QgsNamedColorList &colors, const QString &context=QString(), const QColor &baseColor=QColor()) override
Sets the colors for the scheme.
QgsProjectColorScheme()=default
Constructor for QgsProjectColorScheme.
QgsNamedColorList fetchColors(const QString &context=QString(), const QColor &baseColor=QColor()) override
Gets a list of colors from the scheme.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:477
void setProjectColors(const QgsNamedColorList &colors)
Sets the colors for the project's color scheme (see QgsProjectColorScheme).
QStringList readListEntry(const QString &scope, const QString &key, const QStringList &def=QStringList(), bool *ok=nullptr) const
Reads a string list from the specified scope and key.
A color scheme which contains the most recently used colors.
QgsRecentColorScheme()=default
Constructor for QgsRecentColorScheme.
QgsNamedColorList fetchColors(const QString &context=QString(), const QColor &baseColor=QColor()) override
Gets a list of colors from the scheme.
static QColor lastUsedColor()
Returns the most recently used color.
QgsRecentColorScheme * clone() const override
Clones a color scheme.
static void addRecentColor(const QColor &color)
Adds a color to the list of recent colors.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
bool contains(const QString &key, QgsSettings::Section section=QgsSettings::NoSection) const
Returns true if there exists a setting called key; returns false otherwise.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
static QColor decodeColor(const QString &str)
static bool saveColorsToGpl(QFile &file, const QString &paletteName, const QgsNamedColorList &colors)
Exports colors to a gpl GIMP palette file.
static QgsNamedColorList importColorsFromGpl(QFile &file, bool &ok, QString &name)
Imports colors from a gpl GIMP palette file.
static QString colorToName(const QColor &color)
Returns a friendly display name for a color.
A color scheme which stores its colors in a gpl palette file within the "palettes" subfolder off the ...
QString schemeName() const override
Gets the name for the color scheme.
QgsUserColorScheme(const QString &filename)
Constructs a new user color scheme, using a specified gpl palette file.
QgsColorScheme::SchemeFlags flags() const override
Returns the current flags for the color scheme.
QString gplFilePath() override
Returns the file path for the associated gpl palette file.
bool erase()
Erases the associated gpl palette file from the users "palettes" folder.
void setShowSchemeInMenu(bool show)
Sets whether a this scheme should be shown in color button menus.
QgsUserColorScheme * clone() const override
Clones a color scheme.
QList< QPair< QColor, QString > > QgsNamedColorList
List of colors paired with a friendly display name identifying the color.