QGIS API Documentation  3.25.0-Master (6b426f5f8a)
qgssettingsentry.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssettingsentry.cpp
3  --------------------------------------
4  Date : February 2021
5  Copyright : (C) 2021 by Damiano Lombardi
6  Email : damiano at opengis dot ch
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 #include "qgssettingsentry.h"
17 #include "qgslogger.h"
18 
19 #include <QRegularExpression>
20 
21 
22 
23 
24 QgsSettingsEntryGroup::QgsSettingsEntryGroup( const QList<const QgsSettingsEntryBase *> settings, bool fatalErrorIfInvalid )
25  : mSettings( settings )
26 {
27  for ( const auto *setting : std::as_const( mSettings ) )
28  {
29  QString otherBaseKey = setting->definitionKey();
30  otherBaseKey = otherBaseKey.left( otherBaseKey.lastIndexOf( QStringLiteral( "/" ) ) );
31  if ( mDefinitionBaseKey.isEmpty() )
32  {
33  mDefinitionBaseKey = otherBaseKey;
34  }
35  else
36  {
37  if ( mDefinitionBaseKey != otherBaseKey )
38  {
39  QgsDebugMsg( "Settings do not share the same base definition key for this group. This will lead to unpredictable results." );
40  if ( fatalErrorIfInvalid )
41  Q_ASSERT( false );
42  mIsValid = false;
43  }
44  }
45  }
46 }
47 
48 QString QgsSettingsEntryGroup::baseKey( const QStringList &dynamicKeyPartList ) const
49 {
50  QString key = mDefinitionBaseKey;
51 
52  if ( dynamicKeyPartList.isEmpty() )
53  {
54  if ( hasDynamicKey() )
55  QgsDebugMsg( QStringLiteral( "Settings group '%1' have a dynamic key but the dynamic key part was not provided" ).arg( key ) );
56 
57  return key;
58  }
59  else
60  {
61  if ( !hasDynamicKey() )
62  {
63  QgsDebugMsg( QStringLiteral( "Settings group '%1' don't have a dynamic key, the provided dynamic key part will be ignored" ).arg( key ) );
64  return key;
65  }
66 
67  for ( int i = 0; i < dynamicKeyPartList.size(); i++ )
68  {
69  key.replace( QStringLiteral( "%" ).append( QString::number( i + 1 ) ), dynamicKeyPartList.at( i ) );
70  }
71  }
72 
73  return key;
74 }
75 
76 void QgsSettingsEntryGroup::removeAllSettingsAtBaseKey( const QStringList &dynamicKeyPartList ) const
77 {
78  QString key = baseKey( dynamicKeyPartList );
79  // https://regex101.com/r/kICr42/1
80  const thread_local QRegularExpression regularExpression( QStringLiteral( "^(\\/?(qgis\\/?)?)?$" ) );
81  if ( key.contains( regularExpression ) )
82  {
83  QgsDebugMsg( QStringLiteral( "Preventing mass removal of settings at key %1" ).arg( key ) );
84  return;
85  }
86 
88  settings.remove( key );
89 }
90 
91 void QgsSettingsEntryGroup::removeAllChildrenSettings( const QString &dynamicKeyPart ) const
92 {
94 }
95 
96 void QgsSettingsEntryGroup::removeAllChildrenSettings( const QStringList &dynamicKeyPartList ) const
97 {
98  for ( const auto *setting : mSettings )
99  setting->remove( dynamicKeyPartList );
100 }
101 
102 bool QgsSettingsEntryGroup::hasDynamicKey() const
103 {
104  const thread_local QRegularExpression regularExpression( QStringLiteral( "%\\d+" ) );
105  return mDefinitionBaseKey.contains( regularExpression );
106 }
107 
108 
109 QString QgsSettingsEntryBase::key( const QString &dynamicKeyPart ) const
110 {
111  return key( dynamicKeyPartToList( dynamicKeyPart ) );
112 }
113 
114 QString QgsSettingsEntryBase::key( const QStringList &dynamicKeyPartList ) const
115 {
116  QString completeKey = mKey;
117  if ( !mPluginName.isEmpty() )
118  {
119  if ( !completeKey.startsWith( '/' ) )
120  completeKey.prepend( '/' );
121  completeKey.prepend( mPluginName );
122  }
123 
124  if ( dynamicKeyPartList.isEmpty() )
125  {
126  if ( hasDynamicKey() )
127  QgsDebugMsg( QStringLiteral( "Settings '%1' have a dynamic key but the dynamic key part was not provided" ).arg( completeKey ) );
128 
129  return completeKey;
130  }
131  else
132  {
133  if ( !hasDynamicKey() )
134  {
135  QgsDebugMsg( QStringLiteral( "Settings '%1' don't have a dynamic key, the provided dynamic key part will be ignored" ).arg( completeKey ) );
136  return completeKey;
137  }
138 
139  for ( int i = 0; i < dynamicKeyPartList.size(); i++ )
140  {
141  completeKey.replace( QStringLiteral( "%" ).append( QString::number( i + 1 ) ), dynamicKeyPartList.at( i ) );
142  }
143  }
144  return completeKey;
145 }
146 
147 bool QgsSettingsEntryBase::keyIsValid( const QString &key ) const
148 {
149  if ( !hasDynamicKey() )
150  {
151  if ( !key.contains( definitionKey() ) )
152  return false;
153  else
154  return key == definitionKey();
155  }
156 
157  const QRegularExpression regularExpression( definitionKey().replace( QRegularExpression( QStringLiteral( "%\\d+" ) ), QStringLiteral( ".*" ) ) );
158  const QRegularExpressionMatch regularExpressionMatch = regularExpression.match( key );
159  return regularExpressionMatch.hasMatch();
160 }
161 
163 {
164  return mKey;
165 }
166 
168 {
169  const thread_local QRegularExpression regularExpression( QStringLiteral( "%\\d+" ) );
170  return mKey.contains( regularExpression );
171 }
172 
173 bool QgsSettingsEntryBase::exists( const QString &dynamicKeyPart ) const
174 {
175  return QgsSettings().contains( key( dynamicKeyPart ) );
176 }
177 
178 bool QgsSettingsEntryBase::exists( const QStringList &dynamicKeyPartList ) const
179 {
180  return QgsSettings().contains( key( dynamicKeyPartList ) );
181 }
182 
183 void QgsSettingsEntryBase::remove( const QString &dynamicKeyPart ) const
184 {
185  QgsSettings().remove( key( dynamicKeyPart ) );
186 }
187 
188 void QgsSettingsEntryBase::remove( const QStringList &dynamicKeyPartList ) const
189 {
190  QgsSettings().remove( key( dynamicKeyPartList ) );
191 }
192 
193 bool QgsSettingsEntryBase::setVariantValue( const QVariant &value, const QString &dynamicKeyPart ) const
194 {
195  return setVariantValuePrivate( value, dynamicKeyPartToList( dynamicKeyPart ) );
196 }
197 
198 bool QgsSettingsEntryBase::setVariantValue( const QVariant &value, const QStringList &dynamicKeyPartList ) const
199 {
200  return setVariantValuePrivate( value, dynamicKeyPartList );
201 }
202 
203 bool QgsSettingsEntryBase::setVariantValuePrivate( const QVariant &value, const QStringList &dynamicKeyPartList ) const
204 {
205  if ( mOptions.testFlag( Qgis::SettingsOption::SaveFormerValue ) )
206  {
207  if ( exists( dynamicKeyPartList ) )
208  {
209  QVariant currentValue = valueAsVariant( key( dynamicKeyPartList ) );
210  if ( value != currentValue )
211  {
212  QgsSettings().setValue( formerValuekey( dynamicKeyPartList ), currentValue );
213  }
214  }
215  }
216  QgsSettings().setValue( key( dynamicKeyPartList ), value );
217  return true;
218 }
219 
220 QStringList QgsSettingsEntryBase::dynamicKeyPartToList( const QString &dynamicKeyPart )
221 {
222  QStringList dynamicKeyPartList;
223  if ( !dynamicKeyPart.isNull() )
224  dynamicKeyPartList.append( dynamicKeyPart );
225  return dynamicKeyPartList;
226 }
227 
228 QVariant QgsSettingsEntryBase::valueAsVariant( const QString &dynamicKeyPart ) const
229 {
230  return valueAsVariant( dynamicKeyPartToList( dynamicKeyPart ) );
231 }
232 
233 QVariant QgsSettingsEntryBase::valueAsVariant( const QStringList &dynamicKeyPartList ) const
234 {
235  return QgsSettings().value( key( dynamicKeyPartList ), mDefaultValue );
236 }
237 
238 QVariant QgsSettingsEntryBase::valueAsVariant( const QString &dynamicKeyPart, bool useDefaultValueOverride, const QVariant &defaultValueOverride ) const
239 {
241  return valueAsVariant( dynamicKeyPartToList( dynamicKeyPart ), useDefaultValueOverride, defaultValueOverride );
243 }
244 
245 QVariant QgsSettingsEntryBase::valueAsVariant( const QStringList &dynamicKeyPartList, bool useDefaultValueOverride, const QVariant &defaultValueOverride ) const
246 {
247  if ( useDefaultValueOverride )
248  return QgsSettings().value( key( dynamicKeyPartList ), defaultValueOverride );
249  else
250  return QgsSettings().value( key( dynamicKeyPartList ), mDefaultValue );
251 }
252 
253 QVariant QgsSettingsEntryBase::valueAsVariantWithDefaultOverride( const QVariant &defaultValueOverride, const QString &dynamicKeyPart ) const
254 {
255  return QgsSettings().value( key( dynamicKeyPart ), defaultValueOverride );
256 }
257 
258 QVariant QgsSettingsEntryBase::valueAsVariantWithDefaultOverride( const QVariant &defaultValueOverride, const QStringList &dynamicKeyPartList ) const
259 {
260  return QgsSettings().value( key( dynamicKeyPartList ), defaultValueOverride );
261 }
262 
263 
265 {
266  return mDefaultValue;
267 }
268 
270 {
271  return mDescription;
272 }
273 
274 QVariant QgsSettingsEntryBase::formerValueAsVariant( const QString &dynamicKeyPart ) const
275 {
276  return formerValueAsVariant( dynamicKeyPartToList( dynamicKeyPart ) );
277 }
278 
279 QVariant QgsSettingsEntryBase::formerValueAsVariant( const QStringList &dynamicKeyPartList ) const
280 {
281  Q_ASSERT( mOptions.testFlag( Qgis::SettingsOption::SaveFormerValue ) );
282  QVariant defaultValueOverride = valueAsVariant( key( dynamicKeyPartList ) );
283  return QgsSettings().value( formerValuekey( dynamicKeyPartList ), defaultValueOverride );
284 }
285 
286 QString QgsSettingsEntryBase::formerValuekey( const QStringList &dynamicKeyPartList ) const
287 {
288  return key( dynamicKeyPartList ) + QStringLiteral( "_formervalue" );
289 }
290 
bool exists(const QString &dynamicKeyPart=QString()) const
Returns true if the settings is contained in the underlying QSettings.
QVariant defaultValueAsVariant() const
Returns settings default value.
bool keyIsValid(const QString &key) const
Returns true if the provided key match the settings entry.
QString description() const
Returns the settings entry description.
bool hasDynamicKey() const
Returns true if a part of the settings key is built dynamically.
void remove(const QString &dynamicKeyPart=QString()) const
Removes the settings from the underlying QSettings.
virtual Q_DECL_DEPRECATED bool setVariantValue(const QVariant &value, const QString &dynamicKeyPart=QString()) const
Set settings value.
QString definitionKey() const
Returns settings entry defining key.
QVariant formerValueAsVariant(const QString &dynamicKeyPart) const
Returns the former value of the settings if it has been enabled in the options.
QVariant valueAsVariant(const QString &dynamicKeyPart=QString()) const
Returns settings value with the dynamicKeyPart argument specifying the dynamic part of the settings k...
bool setVariantValuePrivate(const QVariant &value, const QStringList &dynamicKeyPartList=QStringList()) const
Sets the settings value with a variant value.
QString key(const QString &dynamicKeyPart=QString()) const
Returns settings entry key.
static QStringList dynamicKeyPartToList(const QString &dynamicKeyPart)
Transforms a dynamic key part string to list.
QVariant valueAsVariantWithDefaultOverride(const QVariant &defaultValueOverride, const QString &dynamicKeyPart=QString()) const
Returns settings value with a defaultValueOverride.
const QList< const QgsSettingsEntryBase * > settings() const
Returns all the settings.
void removeAllChildrenSettings(const QString &dynamicKeyPart=QString()) const
Removes all the settings from this group The dynamicKeyPart argument specifies the dynamic part of th...
void removeAllSettingsAtBaseKey(const QStringList &dynamicKeyPartList=QStringList()) const
Removes all the settings at the base key for the given dynamicKeyPartList This means it might remove ...
QgsSettingsEntryGroup(const QList< const QgsSettingsEntryBase * > settings)
Constructor.
QString baseKey(const QStringList &dynamicKeyPartList=QStringList()) const
Returns the base key for the given dynamicKeyPartList.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
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.
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.
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:2533
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:2532
#define QgsDebugMsg(str)
Definition: qgslogger.h:38