QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 #include "qgscolorschemeregistry.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 
30 bool 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 
44 QgsNamedColorList 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 
68 void 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 
116 QgsNamedColorList 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 
165 bool 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 
194 QgsNamedColorList 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 
223 bool 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 
241 QgsNamedColorList 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 
259 bool 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 
291 QgsUserColorScheme::QgsUserColorScheme( const QString &filename )
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  {
319  mName = mFilename;
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 
339 QgsColorScheme::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 }
QgsUserColorScheme::mEditable
bool mEditable
Definition: qgscolorscheme.h:218
QgsColorScheme::flags
virtual SchemeFlags flags() const
Returns the current flags for the color scheme.
Definition: qgscolorscheme.h:96
qgscolorscheme.h
QgsSymbolLayerUtils::importColorsFromGpl
static QgsNamedColorList importColorsFromGpl(QFile &file, bool &ok, QString &name)
Imports colors from a gpl GIMP palette file.
Definition: qgssymbollayerutils.cpp:3745
QgsSettings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Definition: qgssettings.cpp:161
QgsUserColorScheme
A color scheme which stores its colors in a gpl palette file within the "palettes" subfolder off the ...
Definition: qgscolorscheme.h:175
qgssymbollayerutils.h
QgsRecentColorScheme::QgsRecentColorScheme
QgsRecentColorScheme()=default
Constructor for QgsRecentColorScheme.
QgsNamedColorList
QList< QPair< QColor, QString > > QgsNamedColorList
List of colors paired with a friendly display name identifying the color.
Definition: qgscolorscheme.h:34
QgsColorSchemeRegistry::setRandomStyleColorScheme
void setRandomStyleColorScheme(QgsColorScheme *scheme)
Sets the color scheme to use when fetching random colors to use for symbol styles.
Definition: qgscolorschemeregistry.cpp:113
QgsGplColorScheme::fetchColors
QgsNamedColorList fetchColors(const QString &context=QString(), const QColor &baseColor=QColor()) override
Gets a list of colors from the scheme.
Definition: qgscolorscheme.cpp:241
QgsSymbolLayerUtils::saveColorsToGpl
static bool saveColorsToGpl(QFile &file, const QString &paletteName, const QgsNamedColorList &colors)
Exports colors to a gpl GIMP palette file.
Definition: qgssymbollayerutils.cpp:3689
QgsProjectColorScheme::clone
QgsProjectColorScheme * clone() const override
Clones a color scheme.
Definition: qgscolorscheme.cpp:231
QgsGplColorScheme::setColors
bool setColors(const QgsNamedColorList &colors, const QString &context=QString(), const QColor &baseColor=QColor()) override
Sets the colors for the scheme.
Definition: qgscolorscheme.cpp:259
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:480
QgsApplication::colorSchemeRegistry
static QgsColorSchemeRegistry * colorSchemeRegistry()
Returns the application's color scheme registry, used for managing color schemes.
Definition: qgsapplication.cpp:2310
QgsUserColorScheme::mName
QString mName
Definition: qgscolorscheme.h:214
QgsProjectColorScheme
A color scheme which contains project specific colors set through project properties dialog.
Definition: qgscolorscheme.h:299
QgsSettings
This class is a composition of two QSettings instances:
Definition: qgssettings.h:61
QgsRecentColorScheme::fetchColors
QgsNamedColorList fetchColors(const QString &context=QString(), const QColor &baseColor=QColor()) override
Gets a list of colors from the scheme.
Definition: qgscolorscheme.cpp:44
QgsSymbolLayerUtils::decodeColor
static QColor decodeColor(const QString &str)
Definition: qgssymbollayerutils.cpp:69
QgsUserColorScheme::clone
QgsUserColorScheme * clone() const override
Clones a color scheme.
Definition: qgscolorscheme.cpp:334
QgsColorScheme::ShowInColorButtonMenu
@ ShowInColorButtonMenu
Show scheme in color button drop-down menu.
Definition: qgscolorscheme.h:74
qgsapplication.h
QgsUserColorScheme::QgsUserColorScheme
QgsUserColorScheme(const QString &filename)
Constructs a new user color scheme, using a specified gpl palette file.
Definition: qgscolorscheme.cpp:291
QgsUserColorScheme::mFilename
QString mFilename
Definition: qgscolorscheme.h:216
QgsProject::setProjectColors
void setProjectColors(const QgsNamedColorList &colors)
Sets the colors for the project's color scheme (see QgsProjectColorScheme).
Definition: qgsproject.cpp:4148
QgsApplication::qgisSettingsDirPath
static QString qgisSettingsDirPath()
Returns the path to the settings directory in user's home dir.
Definition: qgsapplication.cpp:1099
QgsCustomColorScheme::clone
QgsCustomColorScheme * clone() const override
Clones a color scheme.
Definition: qgscolorscheme.cpp:188
QgsUserColorScheme::flags
QgsColorScheme::SchemeFlags flags() const override
Returns the current flags for the color scheme.
Definition: qgscolorscheme.cpp:339
QgsGplColorScheme::gplFilePath
virtual QString gplFilePath()=0
Returns the file path for the associated gpl palette file.
QgsUserColorScheme::setShowSchemeInMenu
void setShowSchemeInMenu(bool show)
Sets whether a this scheme should be shown in color button menus.
Definition: qgscolorscheme.cpp:372
QgsSettings::setValue
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Definition: qgssettings.cpp:279
QgsProjectColorScheme::setColors
bool setColors(const QgsNamedColorList &colors, const QString &context=QString(), const QColor &baseColor=QColor()) override
Sets the colors for the scheme.
Definition: qgscolorscheme.cpp:223
QgsColorScheme::schemeName
virtual QString schemeName() const =0
Gets the name for the color scheme.
QgsRecentColorScheme::clone
QgsRecentColorScheme * clone() const override
Clones a color scheme.
Definition: qgscolorscheme.cpp:63
QgsCustomColorScheme::setColors
bool setColors(const QgsNamedColorList &colors, const QString &context=QString(), const QColor &baseColor=QColor()) override
Sets the colors for the scheme.
Definition: qgscolorscheme.cpp:165
QgsCustomColorScheme::QgsCustomColorScheme
QgsCustomColorScheme()=default
Constructor for QgsCustomColorScheme.
QgsCustomColorScheme::fetchColors
QgsNamedColorList fetchColors(const QString &context=QString(), const QColor &baseColor=QColor()) override
Gets a list of colors from the scheme.
Definition: qgscolorscheme.cpp:116
QgsRecentColorScheme::lastUsedColor
static QColor lastUsedColor()
Returns the most recently used color.
Definition: qgscolorscheme.cpp:104
QgsRecentColorScheme::addRecentColor
static void addRecentColor(const QColor &color)
Adds a color to the list of recent colors.
Definition: qgscolorscheme.cpp:68
QgsCustomColorScheme
A color scheme which contains custom colors set through QGIS app options dialog.
Definition: qgscolorscheme.h:270
qgssettings.h
qgscolorschemeregistry.h
QgsRecentColorScheme
A color scheme which contains the most recently used colors.
Definition: qgscolorscheme.h:230
QgsProjectColorScheme::fetchColors
QgsNamedColorList fetchColors(const QString &context=QString(), const QColor &baseColor=QColor()) override
Gets a list of colors from the scheme.
Definition: qgscolorscheme.cpp:194
QgsSettings::contains
bool contains(const QString &key, QgsSettings::Section section=QgsSettings::NoSection) const
Returns true if there exists a setting called key; returns false otherwise.
Definition: qgssettings.cpp:175
QgsProject::readListEntry
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.
Definition: qgsproject.cpp:2916
QgsUserColorScheme::erase
bool erase()
Erases the associated gpl palette file from the users "palettes" folder.
Definition: qgscolorscheme.cpp:354
QgsProjectColorScheme::QgsProjectColorScheme
QgsProjectColorScheme()=default
Constructor for QgsProjectColorScheme.
qgsproject.h
QgsUserColorScheme::schemeName
QString schemeName() const override
Gets the name for the color scheme.
Definition: qgscolorscheme.cpp:329
QgsSymbolLayerUtils::colorToName
static QString colorToName(const QColor &color)
Returns a friendly display name for a color.
Definition: qgssymbollayerutils.cpp:3416
QgsUserColorScheme::gplFilePath
QString gplFilePath() override
Returns the file path for the associated gpl palette file.
Definition: qgscolorscheme.cpp:389
QgsColorScheme::setColors
virtual bool setColors(const QgsNamedColorList &colors, const QString &context=QString(), const QColor &baseColor=QColor())
Sets the colors for the scheme.
Definition: qgscolorscheme.cpp:30