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