QGIS API Documentation  3.27.0-Master (bef583a8ef)
qgssettings.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssettings.cpp
3  --------------------------------------
4  Date : January 2017
5  Copyright : (C) 2017 by Alessandro Pasotti
6  Email : apasotti at boundlessgeo dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 
17 #include <cstdlib>
18 
19 #include <QFileInfo>
20 #include <QSettings>
21 #include <QDir>
22 
23 #include "qgssettings.h"
24 #include "qgslogger.h"
25 
26 Q_GLOBAL_STATIC( QString, sGlobalSettingsPath )
27 
28 bool QgsSettings::setGlobalSettingsPath( const QString &path )
29 {
30  if ( QFileInfo::exists( path ) )
31  {
32  *sGlobalSettingsPath() = path;
33  return true;
34  }
35  return false;
36 }
37 
38 void QgsSettings::init()
39 {
40  if ( ! sGlobalSettingsPath()->isEmpty() )
41  {
42  mGlobalSettings = new QSettings( *sGlobalSettingsPath(), QSettings::IniFormat );
43 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
44  mGlobalSettings->setIniCodec( "UTF-8" );
45 #endif
46  }
47 }
48 
49 
50 QgsSettings::QgsSettings( const QString &organization, const QString &application, QObject *parent )
51 {
52  mUserSettings = new QSettings( organization, application, parent );
53  init();
54 }
55 
56 QgsSettings::QgsSettings( QSettings::Scope scope, const QString &organization,
57  const QString &application, QObject *parent )
58 {
59  mUserSettings = new QSettings( scope, organization, application, parent );
60  init();
61 }
62 
63 QgsSettings::QgsSettings( QSettings::Format format, QSettings::Scope scope,
64  const QString &organization, const QString &application, QObject *parent )
65 {
66  mUserSettings = new QSettings( format, scope, organization, application, parent );
67  init();
68 }
69 
70 QgsSettings::QgsSettings( const QString &fileName, QSettings::Format format, QObject *parent )
71 {
72  mUserSettings = new QSettings( fileName, format, parent );
73  init();
74 }
75 
76 QgsSettings::QgsSettings( QObject *parent )
77 {
78  mUserSettings = new QSettings( parent );
79  init();
80 }
81 
83 {
84  delete mUserSettings;
85  delete mGlobalSettings;
86 }
87 
88 
89 void QgsSettings::beginGroup( const QString &prefix, const QgsSettings::Section section )
90 {
91  const QString pKey = prefixedKey( prefix, section );
92  mUserSettings->beginGroup( pKey );
93  if ( mGlobalSettings )
94  {
95  mGlobalSettings->beginGroup( pKey );
96  }
97 }
98 
100 {
101  mUserSettings->endGroup();
102  if ( mGlobalSettings )
103  {
104  mGlobalSettings->endGroup();
105  }
106 }
107 
108 QString QgsSettings::group() const
109 {
110  return mUserSettings->group();
111 }
112 
113 QStringList QgsSettings::allKeys() const
114 {
115  QStringList keys = mUserSettings->allKeys();
116  if ( mGlobalSettings )
117  {
118  const QStringList constAllKeys = mGlobalSettings->allKeys();
119  std::copy_if( constAllKeys.constBegin(), constAllKeys.constEnd(), std::back_inserter( keys ), [&keys]( const QString & key ) {return !keys.contains( key );} );
120  }
121  return keys;
122 }
123 
124 
125 QStringList QgsSettings::childKeys() const
126 {
127  QStringList keys = mUserSettings->childKeys();
128  if ( mGlobalSettings )
129  {
130  const QStringList constChildKeys = mGlobalSettings->childKeys();
131  std::copy_if( constChildKeys.constBegin(), constChildKeys.constEnd(), std::back_inserter( keys ), [&keys]( const QString & key ) {return !keys.contains( key );} );
132  }
133  return keys;
134 }
135 
136 QStringList QgsSettings::childGroups() const
137 {
138  QStringList keys = mUserSettings->childGroups();
139  if ( mGlobalSettings )
140  {
141  const QStringList constChildGroups = mGlobalSettings->childGroups();
142  std::copy_if( constChildGroups.constBegin(), constChildGroups.constEnd(), std::back_inserter( keys ), [&keys]( const QString & key ) {return !keys.contains( key );} );
143  }
144  return keys;
145 }
147 {
148  QStringList keys;
149  if ( mGlobalSettings )
150  {
151  keys = mGlobalSettings->childGroups();
152  }
153  return keys;
154 }
155 
157 {
158  return *sGlobalSettingsPath();
159 }
160 
161 QVariant QgsSettings::value( const QString &key, const QVariant &defaultValue, const QgsSettings::Section section ) const
162 {
163  const QString pKey = prefixedKey( key, section );
164  if ( !mUserSettings->value( pKey ).isNull() )
165  {
166  return mUserSettings->value( pKey );
167  }
168  if ( mGlobalSettings )
169  {
170  return mGlobalSettings->value( pKey, defaultValue );
171  }
172  return defaultValue;
173 }
174 
175 bool QgsSettings::contains( const QString &key, const QgsSettings::Section section ) const
176 {
177  const QString pKey = prefixedKey( key, section );
178  return mUserSettings->contains( pKey ) ||
179  ( mGlobalSettings && mGlobalSettings->contains( pKey ) );
180 }
181 
182 QString QgsSettings::fileName() const
183 {
184  return mUserSettings->fileName();
185 }
186 
188 {
189  mUserSettings->sync();
190 }
191 
192 void QgsSettings::remove( const QString &key, const QgsSettings::Section section )
193 {
194  const QString pKey = prefixedKey( key, section );
195  mUserSettings->remove( pKey );
196 }
197 
198 QString QgsSettings::prefixedKey( const QString &key, const Section section ) const
199 {
200  QString prefix;
201  switch ( section )
202  {
203  case Section::Core:
204  prefix = QStringLiteral( "core" );
205  break;
206  case Section::Server:
207  prefix = QStringLiteral( "server" );
208  break;
209  case Section::Gui:
210  prefix = QStringLiteral( "gui" );
211  break;
212  case Section::Plugins:
213  prefix = QStringLiteral( "plugins" );
214  break;
215  case Section::Misc:
216  prefix = QStringLiteral( "misc" );
217  break;
218  case Section::Auth:
219  prefix = QStringLiteral( "auth" );
220  break;
221  case Section::App:
222  prefix = QStringLiteral( "app" );
223  break;
224  case Section::Providers:
225  prefix = QStringLiteral( "providers" );
226  break;
227  case Section::Expressions:
228  prefix = QStringLiteral( "expressions" );
229  break;
230  case Section::Gps:
231  prefix = QStringLiteral( "gps" );
232  break;
233  case Section::NoSection:
234  return sanitizeKey( key );
235  }
236  return prefix + "/" + sanitizeKey( key );
237 }
238 
239 
240 int QgsSettings::beginReadArray( const QString &prefix )
241 {
242  int size = mUserSettings->beginReadArray( sanitizeKey( prefix ) );
243  if ( 0 == size && mGlobalSettings )
244  {
245  size = mGlobalSettings->beginReadArray( sanitizeKey( prefix ) );
246  mUsingGlobalArray = ( size > 0 );
247  }
248  return size;
249 }
250 
251 void QgsSettings::beginWriteArray( const QString &prefix, int size )
252 {
253  mUsingGlobalArray = false;
254  mUserSettings->beginWriteArray( prefix, size );
255 }
256 
258 {
259  mUserSettings->endArray();
260  if ( mGlobalSettings )
261  {
262  mGlobalSettings->endArray();
263  }
264  mUsingGlobalArray = false;
265 }
266 
268 {
269  if ( mGlobalSettings && mUsingGlobalArray )
270  {
271  mGlobalSettings->setArrayIndex( i );
272  }
273  else
274  {
275  mUserSettings->setArrayIndex( i );
276  }
277 }
278 
279 void QgsSettings::setValue( const QString &key, const QVariant &value, const QgsSettings::Section section )
280 {
281  // TODO: add valueChanged signal
282  // Do not store if it hasn't changed from default value
283  // First check if the values are different and if at least one of them is valid.
284  // The valid check is required because different invalid QVariant types
285  // like QVariant(QVariant::String) and QVariant(QVariant::Int))
286  // may be considered different and we don't want to store the value in that case.
287  const QVariant currentValue = QgsSettings::value( prefixedKey( key, section ) );
288  if ( ( currentValue.isValid() || value.isValid() ) && ( currentValue != value ) )
289  {
290  mUserSettings->setValue( prefixedKey( key, section ), value );
291  }
292  // Deliberately an "else if" because we want to remove a value from the user settings
293  // only if the value is different than the one stored in the global settings (because
294  // it would be the default anyway). The first check is necessary because the global settings
295  // might be a nullptr (for example in case of standalone scripts or apps).
296  else if ( mGlobalSettings && mGlobalSettings->value( prefixedKey( key, section ) ) == currentValue )
297  {
298  mUserSettings->remove( prefixedKey( key, section ) );
299  }
300 }
301 
302 // To lower case and clean the path
303 QString QgsSettings::sanitizeKey( const QString &key ) const
304 {
305  return QDir::cleanPath( key );
306 }
307 
309 {
310  mUserSettings->clear();
311 }
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
QStringList childGroups() const
Returns a list of all key top-level groups that contain keys that can be read using the QSettings obj...
void endGroup()
Resets the group to what it was before the corresponding beginGroup() call.
Definition: qgssettings.cpp:99
void clear()
Removes all entries in the user settings.
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.
QString prefixedKey(const QString &key, QgsSettings::Section section) const
Returns the sanitized and prefixed key.
void endArray()
Closes the array that was started using beginReadArray() or beginWriteArray().
QString group() const
Returns the current group.
void beginGroup(const QString &prefix, QgsSettings::Section section=QgsSettings::NoSection)
Appends prefix to the current group.
Definition: qgssettings.cpp:89
~QgsSettings() override
Definition: qgssettings.cpp:82
QStringList childKeys() const
Returns a list of all top-level keys that can be read using the QSettings object.
static QString globalSettingsPath()
Returns the path to the Global Settings QSettings storage file.
QgsSettings(const QString &organization, const QString &application=QString(), QObject *parent=nullptr)
Constructs a QgsSettings object for accessing settings of the application called application from the...
Definition: qgssettings.cpp:50
void sync()
Writes any unsaved changes to permanent storage, and reloads any settings that have been changed in t...
QStringList globalChildGroups() const
Returns a list of all key top-level groups (same as childGroups) but only for groups defined in globa...
void beginWriteArray(const QString &prefix, int size=-1)
Adds prefix to the current group and starts writing an array of size size.
Section
Sections for namespaced settings.
Definition: qgssettings.h:68
void remove(const QString &key, QgsSettings::Section section=QgsSettings::NoSection)
Removes the setting key and any sub-settings of key in a section.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
QString fileName() const
Returns the path where settings written using this QSettings object are stored.
QStringList allKeys() const
Returns a list of all keys, including subkeys, that can be read using the QSettings object.
int beginReadArray(const QString &prefix)
Adds prefix to the current group and starts reading from an array. Returns the size of the array.
void setArrayIndex(int i)
Sets the current array index to i.
Q_GLOBAL_STATIC(QReadWriteLock, sDefinitionCacheLock)