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