QGIS API Documentation 3.41.0-Master (3440c17df1d)
Loading...
Searching...
No Matches
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#include "qgscolorutils.h"
26
27#include <QDir>
28#include <QRegularExpression>
29#include <QTextStream>
30
31bool QgsColorScheme::setColors( const QgsNamedColorList &colors, const QString &context, const QColor &baseColor )
32{
33 //base implementation does nothing
34 Q_UNUSED( colors )
35 Q_UNUSED( context )
36 Q_UNUSED( baseColor )
37 return false;
38}
39
40
41//
42// QgsRecentColorScheme
43//
44
45QgsNamedColorList QgsRecentColorScheme::fetchColors( const QString &context, const QColor &baseColor )
46{
47 Q_UNUSED( context )
48 Q_UNUSED( baseColor )
49
50 //fetch recent colors
51 const QgsSettings settings;
52 const QList< QVariant > recentColorVariants = settings.value( QStringLiteral( "colors/recent" ) ).toList();
53
54 //generate list from recent colors
55 QgsNamedColorList colorList;
56 const auto constRecentColorVariants = recentColorVariants;
57 for ( const QVariant &color : constRecentColorVariants )
58 {
59 colorList.append( qMakePair( color.value<QColor>(), QgsSymbolLayerUtils::colorToName( color.value<QColor>() ) ) );
60 }
61 return colorList;
62}
63
68
69void QgsRecentColorScheme::addRecentColor( const QColor &color )
70{
71 if ( !color.isValid() )
72 {
73 return;
74 }
75
76 //strip alpha from color
77 QColor opaqueColor = color;
78 opaqueColor.setAlpha( 255 );
79
80 QgsSettings settings;
81 QList< QVariant > recentColorVariants = settings.value( QStringLiteral( "colors/recent" ) ).toList();
82
83 //remove colors by name
84 for ( int colorIdx = recentColorVariants.length() - 1; colorIdx >= 0; --colorIdx )
85 {
86 if ( ( recentColorVariants.at( colorIdx ).value<QColor>() ).name() == opaqueColor.name() )
87 {
88 recentColorVariants.removeAt( colorIdx );
89 }
90 }
91
92 //add color
93 const QVariant colorVariant = QVariant( opaqueColor );
94 recentColorVariants.prepend( colorVariant );
95
96 //trim to 20 colors
97 while ( recentColorVariants.count() > 20 )
98 {
99 recentColorVariants.pop_back();
100 }
101
102 settings.setValue( QStringLiteral( "colors/recent" ), recentColorVariants );
103}
104
106{
107 //fetch recent colors
108 const QgsSettings settings;
109 const QList< QVariant > recentColorVariants = settings.value( QStringLiteral( "colors/recent" ) ).toList();
110
111 if ( recentColorVariants.isEmpty() )
112 return QColor();
113
114 return recentColorVariants.at( 0 ).value<QColor>();
115}
116
117QgsNamedColorList QgsCustomColorScheme::fetchColors( const QString &context, const QColor &baseColor )
118{
119 Q_UNUSED( context )
120 Q_UNUSED( baseColor )
121
122 //fetch predefined custom colors
123 QgsNamedColorList colorList;
124 const QgsSettings settings;
125
126 //check if settings contains custom palette
127 if ( !settings.contains( QStringLiteral( "/colors/palettecolors" ) ) )
128 {
129 //no custom palette, return default colors
130 colorList.append( qMakePair( QColor( 0, 0, 0 ), QString() ) );
131 colorList.append( qMakePair( QColor( 255, 255, 255 ), QString() ) );
132 colorList.append( qMakePair( QColor( 166, 206, 227 ), QString() ) );
133 colorList.append( qMakePair( QColor( 31, 120, 180 ), QString() ) );
134 colorList.append( qMakePair( QColor( 178, 223, 138 ), QString() ) );
135 colorList.append( qMakePair( QColor( 51, 160, 44 ), QString() ) );
136 colorList.append( qMakePair( QColor( 251, 154, 153 ), QString() ) );
137 colorList.append( qMakePair( QColor( 227, 26, 28 ), QString() ) );
138 colorList.append( qMakePair( QColor( 253, 191, 111 ), QString() ) );
139 colorList.append( qMakePair( QColor( 255, 127, 0 ), QString() ) );
140
141 return colorList;
142 }
143
144 QList< QVariant > customColorVariants = settings.value( QStringLiteral( "colors/palettecolors" ) ).toList();
145 const QList< QVariant > customColorLabels = settings.value( QStringLiteral( "colors/palettelabels" ) ).toList();
146
147 //generate list from custom colors
148 int colorIndex = 0;
149 for ( QList< QVariant >::iterator it = customColorVariants.begin();
150 it != customColorVariants.end(); ++it )
151 {
152 const QColor color = ( *it ).value<QColor>();
153 QString label;
154 if ( customColorLabels.length() > colorIndex )
155 {
156 label = customColorLabels.at( colorIndex ).toString();
157 }
158
159 colorList.append( qMakePair( color, label ) );
160 colorIndex++;
161 }
162
163 return colorList;
164}
165
166bool QgsCustomColorScheme::setColors( const QgsNamedColorList &colors, const QString &context, const QColor &baseColor )
167{
168 Q_UNUSED( context )
169 Q_UNUSED( baseColor )
170
171 // save colors to settings
172 QgsSettings settings;
173 QList< QVariant > customColors;
174 QList< QVariant > customColorLabels;
175
176 QgsNamedColorList::const_iterator colorIt = colors.constBegin();
177 for ( ; colorIt != colors.constEnd(); ++colorIt )
178 {
179 const QVariant color = ( *colorIt ).first;
180 const QVariant label = ( *colorIt ).second;
181 customColors.append( color );
182 customColorLabels.append( label );
183 }
184 settings.setValue( QStringLiteral( "colors/palettecolors" ), customColors );
185 settings.setValue( QStringLiteral( "colors/palettelabels" ), customColorLabels );
186 return true;
187}
188
193
194
195QgsNamedColorList QgsProjectColorScheme::fetchColors( const QString &context, const QColor &baseColor )
196{
197 Q_UNUSED( context )
198 Q_UNUSED( baseColor )
199
200 QgsNamedColorList colorList;
201
202 QStringList colorStrings = QgsProject::instance()->readListEntry( QStringLiteral( "Palette" ), QStringLiteral( "/Colors" ) ); // skip-keyword-check
203 const QStringList colorLabels = QgsProject::instance()->readListEntry( QStringLiteral( "Palette" ), QStringLiteral( "/Labels" ) ); // skip-keyword-check
204
205 //generate list from custom colors
206 int colorIndex = 0;
207 for ( QStringList::iterator it = colorStrings.begin();
208 it != colorStrings.end(); ++it )
209 {
210 const QColor color = QgsColorUtils::colorFromString( *it );
211 QString label;
212 if ( colorLabels.length() > colorIndex )
213 {
214 label = colorLabels.at( colorIndex );
215 }
216
217 colorList.append( qMakePair( color, label ) );
218 colorIndex++;
219 }
220
221 return colorList;
222}
223
224bool QgsProjectColorScheme::setColors( const QgsNamedColorList &colors, const QString &context, const QColor &baseColor )
225{
226 Q_UNUSED( context )
227 Q_UNUSED( baseColor )
228 QgsProject::instance()->setProjectColors( colors ); // skip-keyword-check
229 return true;
230}
231
236
237
238//
239// QgsGplColorScheme
240//
241
242QgsNamedColorList QgsGplColorScheme::fetchColors( const QString &context, const QColor &baseColor )
243{
244 Q_UNUSED( context )
245 Q_UNUSED( baseColor )
246
247 const QString sourceFilePath = gplFilePath();
248 if ( sourceFilePath.isEmpty() )
249 {
250 QgsNamedColorList noColors;
251 return noColors;
252 }
253
254 bool ok;
255 QString name;
256 QFile sourceFile( sourceFilePath );
257 return QgsSymbolLayerUtils::importColorsFromGpl( sourceFile, ok, name );
258}
259
260bool QgsGplColorScheme::setColors( const QgsNamedColorList &colors, const QString &context, const QColor &baseColor )
261{
262 Q_UNUSED( context )
263 Q_UNUSED( baseColor )
264
265 const QString destFilePath = gplFilePath();
266 if ( destFilePath.isEmpty() )
267 {
268 return false;
269 }
270
271 QFile destFile( destFilePath );
272 if ( QgsSymbolLayerUtils::saveColorsToGpl( destFile, schemeName(), colors ) )
273 {
274 if ( QgsApplication::colorSchemeRegistry()->randomStyleColorScheme() == this )
275 {
276 // force a re-generation of the random style color list, since the color list has changed
278 }
279 return true;
280 }
281 else
282 {
283 return false;
284 }
285}
286
287
288//
289// QgsUserColorScheme
290//
291
293 : mFilename( filename )
294{
295 QFile sourceFile( gplFilePath() );
296
297 //read in name
298 if ( sourceFile.open( QIODevice::ReadOnly ) )
299 {
300 QTextStream in( &sourceFile );
301
302 //find name line
303 QString line;
304 while ( !in.atEnd() && !line.startsWith( QLatin1String( "Name:" ) ) )
305 {
306 line = in.readLine();
307 }
308 if ( !in.atEnd() )
309 {
310 const thread_local QRegularExpression rx( "Name:\\s*(\\S.*)$" );
311 const QRegularExpressionMatch match = rx.match( line );
312 if ( match.hasMatch() )
313 {
314 mName = match.captured( 1 );
315 }
316 }
317 }
318 if ( mName.isEmpty() )
319 {
321 }
322
323 // we consider this scheme writable if the user has permission, OR
324 // if it DOESN'T already exist (since new schemes are only created when
325 // first written to)
326 const QFileInfo sourceFileInfo( gplFilePath() );
327 mEditable = !sourceFileInfo.exists() || sourceFileInfo.isWritable();
328}
329
331{
332 return mName;
333}
334
339
341{
343
344 const QgsSettings s;
345 const QStringList showInMenuSchemes = s.value( QStringLiteral( "/colors/showInMenuList" ) ).toStringList();
346
347 if ( showInMenuSchemes.contains( mName ) )
348 {
350 }
351
352 return f;
353}
354
356{
357 const QString filePath = gplFilePath();
358 if ( filePath.isEmpty() )
359 {
360 return false;
361 }
362
363 // if file does not exist, nothing to do on the disk, so we can consider erasing done
364 if ( ! QFile::exists( filePath ) )
365 {
366 return true;
367 }
368
369 //try to erase gpl file
370 return QFile::remove( filePath );
371}
372
374{
375 QgsSettings s;
376 QStringList showInMenuSchemes = s.value( QStringLiteral( "/colors/showInMenuList" ) ).toStringList();
377
378 if ( show && !showInMenuSchemes.contains( mName ) )
379 {
380 showInMenuSchemes << mName;
381 }
382 else if ( !show && showInMenuSchemes.contains( mName ) )
383 {
384 showInMenuSchemes.removeAll( mName );
385 }
386
387 s.setValue( QStringLiteral( "/colors/showInMenuList" ), showInMenuSchemes );
388}
389
391{
392 const QString palettesDir = QgsApplication::qgisSettingsDirPath() + "palettes";
393
394 const QDir localDir;
395 if ( !localDir.mkpath( palettesDir ) )
396 {
397 return QString();
398 }
399
400 return QDir( palettesDir ).filePath( mFilename );
401}
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.
QFlags< SchemeFlag > SchemeFlags
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
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
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
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.
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
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:64
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 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.