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