QGIS API Documentation 4.1.0-Master (376402f9aeb)
Loading...
Searching...
No Matches
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
18#include "qgslogger.h"
19#include "qgssettings.h"
20#include "qgssettingstreenode.h"
21#include "qgsthreadingutils.h"
22
23#include <QDir>
24#include <QRegularExpression>
25#include <QSettings>
26#include <QString>
27
28using namespace Qt::StringLiterals;
29
30/*
31 * Set to true by setupUserSettings() once QSettings::setDefaultFormat()
32 * and setPath() have been called. Each thread's QSettings instance is
33 * (re-)created on first access after this flag becomes true, so it
34 * picks up the correct IniFormat and profile path.
35 */
36static bool sSettingsInitialized = false;
37
38static QSettings &sUserSettings()
39{
40 thread_local QSettings *sSettings = nullptr;
41 thread_local bool sCreatedBeforeInit = true;
42
43 if ( !sSettings || ( sCreatedBeforeInit && sSettingsInitialized ) )
44 {
45 delete sSettings;
46 sSettings = new QSettings();
47 sCreatedBeforeInit = !sSettingsInitialized;
48 }
49 return *sSettings;
50}
51
52void QgsSettingsEntryBase::setupUserSettings( const QString &profilePath )
53{
55
56 if ( sSettingsInitialized )
57 return;
58
59 QSettings::setDefaultFormat( QSettings::IniFormat );
60 QSettings::setPath( QSettings::IniFormat, QSettings::UserScope, profilePath );
61 sSettingsInitialized = true;
62}
63
65{
66 return sUserSettings();
67}
68
70 : mParentTreeElement( parent )
71 , mName( key )
72 , mDefaultValue( defaultValue )
73 , mDescription( description )
74 , mOptions( options )
75{
76 mKey = QDir::cleanPath( u"%1/%2"_s.arg( parent ? parent->completeKey() : QString(), key ) );
77
78 if ( parent )
79 {
80 parent->registerChildSetting( this, key );
81 }
82}
83
85{
86 if ( mParentTreeElement )
87 mParentTreeElement->unregisterChildSetting( this );
88}
89
91{
92 return QString::fromUtf8( sSettingsTypeMetaEnum.valueToKey( static_cast<int>( settingsType() ) ) );
93}
94
95
96QString QgsSettingsEntryBase::key( const QString &dynamicKeyPart ) const
97{
98 return key( dynamicKeyPartToList( dynamicKeyPart ) );
99}
100
101QString QgsSettingsEntryBase::key( const QStringList &dynamicKeyPartList ) const
102{
103 return completeKeyPrivate( mKey, dynamicKeyPartList );
104}
105
106QString QgsSettingsEntryBase::completeKeyPrivate( const QString &key, const QStringList &dynamicKeyPartList ) const
107{
108 QString completeKey = key;
109
110 if ( dynamicKeyPartList.isEmpty() )
111 {
112 if ( hasDynamicKey() )
113 QgsDebugError( u"Settings '%1' have a dynamic key but the dynamic key part was not provided"_s.arg( completeKey ) );
114
115 return completeKey;
116 }
117 else
118 {
119 if ( !hasDynamicKey() )
120 {
121 QgsDebugError( u"Settings '%1' don't have a dynamic key, the provided dynamic key part will be ignored"_s.arg( completeKey ) );
122 return completeKey;
123 }
124
125 for ( int i = 0; i < dynamicKeyPartList.size(); i++ )
126 {
127 completeKey.replace( u"%"_s.append( QString::number( i + 1 ) ), dynamicKeyPartList.at( i ) );
128 }
129 }
130 return completeKey;
131}
132
133bool QgsSettingsEntryBase::keyIsValid( const QString &key ) const
134{
135 if ( !hasDynamicKey() )
136 {
137 if ( !key.contains( definitionKey() ) )
138 return false;
139 else
140 return key == definitionKey();
141 }
142
143 const thread_local QRegularExpression digitRx( u"%\\d+"_s );
144 const QRegularExpression regularExpression( definitionKey().replace( digitRx, u".*"_s ) );
145 const QRegularExpressionMatch regularExpressionMatch = regularExpression.match( key );
146 return regularExpressionMatch.hasMatch();
147}
148
150{
151 return mKey;
152}
153
155{
156 const thread_local QRegularExpression regularExpression( u"%\\d+"_s );
157 return mKey.contains( regularExpression );
158}
159
160bool QgsSettingsEntryBase::exists( const QString &dynamicKeyPart ) const
161{
162 return sUserSettings().contains( key( dynamicKeyPart ) );
163}
164
165bool QgsSettingsEntryBase::exists( const QStringList &dynamicKeyPartList ) const
166{
167 return sUserSettings().contains( key( dynamicKeyPartList ) );
168}
169
170Qgis::SettingsOrigin QgsSettingsEntryBase::origin( const QStringList &dynamicKeyPartList ) const
171{
172 if ( sUserSettings().contains( key( dynamicKeyPartList ) ) )
174
176}
177
178void QgsSettingsEntryBase::remove( const QString &dynamicKeyPart ) const
179{
180 sUserSettings().remove( key( dynamicKeyPart ) );
181}
182
183void QgsSettingsEntryBase::remove( const QStringList &dynamicKeyPartList ) const
184{
185 sUserSettings().remove( key( dynamicKeyPartList ) );
186}
187
192
193bool QgsSettingsEntryBase::setVariantValue( const QVariant &value, const QString &dynamicKeyPart ) const
194{
195 return setVariantValue( value, dynamicKeyPartToList( dynamicKeyPart ) );
196}
197
198bool QgsSettingsEntryBase::setVariantValue( const QVariant &value, const QStringList &dynamicKeyPartList ) const
199{
200 mHasChanged = true;
201 const QString resolvedKey = key( dynamicKeyPartList );
202
203 if ( mOptions.testFlag( Qgis::SettingsOption::SaveFormerValue ) )
204 {
205 if ( exists( dynamicKeyPartList ) )
206 {
207 QVariant currentValue = valueAsVariant( dynamicKeyPartList );
208 if ( value != currentValue )
209 {
210 sUserSettings().setValue( formerValuekey( dynamicKeyPartList ), currentValue );
211 }
212 }
213 }
214
215 sUserSettings().setValue( resolvedKey, value );
216 return true;
217}
218
219QStringList QgsSettingsEntryBase::dynamicKeyPartToList( const QString &dynamicKeyPart )
220{
221 QStringList dynamicKeyPartList;
222 if ( !dynamicKeyPart.isNull() )
223 dynamicKeyPartList.append( dynamicKeyPart );
224 return dynamicKeyPartList;
225}
226
227QVariant QgsSettingsEntryBase::valueAsVariant( const QString &dynamicKeyPart ) const
228{
229 return valueAsVariant( dynamicKeyPartToList( dynamicKeyPart ) );
230}
231
232QVariant QgsSettingsEntryBase::valueAsVariant( const QStringList &dynamicKeyPartList ) const
233{
234 return sUserSettings().value( key( dynamicKeyPartList ), mDefaultValue );
235}
236
237QVariant QgsSettingsEntryBase::valueAsVariant( const QString &dynamicKeyPart, bool useDefaultValueOverride, const QVariant &defaultValueOverride ) const
238{
240 return valueAsVariant( dynamicKeyPartToList( dynamicKeyPart ), useDefaultValueOverride, defaultValueOverride );
242}
243
244QVariant QgsSettingsEntryBase::valueAsVariant( const QStringList &dynamicKeyPartList, bool useDefaultValueOverride, const QVariant &defaultValueOverride ) const
245{
246 if ( useDefaultValueOverride )
247 return sUserSettings().value( key( dynamicKeyPartList ), defaultValueOverride );
248 else
249 return sUserSettings().value( key( dynamicKeyPartList ), mDefaultValue );
250}
251
252QVariant QgsSettingsEntryBase::valueAsVariantWithDefaultOverride( const QVariant &defaultValueOverride, const QString &dynamicKeyPart ) const
253{
254 return sUserSettings().value( key( dynamicKeyPart ), defaultValueOverride );
255}
256
257QVariant QgsSettingsEntryBase::valueAsVariantWithDefaultOverride( const QVariant &defaultValueOverride, const QStringList &dynamicKeyPartList ) const
258{
259 return sUserSettings().value( key( dynamicKeyPartList ), defaultValueOverride );
260}
261
263{
264 return mDefaultValue;
265}
266
268{
269 return mDescription;
270}
271
272QVariant QgsSettingsEntryBase::formerValueAsVariant( const QString &dynamicKeyPart ) const
273{
274 return formerValueAsVariant( dynamicKeyPartToList( dynamicKeyPart ) );
275}
276
277QVariant QgsSettingsEntryBase::formerValueAsVariant( const QStringList &dynamicKeyPartList ) const
278{
279 Q_ASSERT( mOptions.testFlag( Qgis::SettingsOption::SaveFormerValue ) );
280 QVariant defaultValueOverride = valueAsVariant( dynamicKeyPartList );
281 return sUserSettings().value( formerValuekey( dynamicKeyPartList ), defaultValueOverride );
282}
283
284bool QgsSettingsEntryBase::copyValueFromKey( const QString &key, const QStringList &dynamicKeyPartList, bool removeSettingAtKey ) const
285{
286 QSettings &settings = sUserSettings();
287
288 const QString oldCompleteKey = completeKeyPrivate( key, dynamicKeyPartList );
289
290 if ( settings.contains( oldCompleteKey ) )
291 {
292 if ( !exists( dynamicKeyPartList ) )
293 {
294 QVariant oldValue = settings.value( oldCompleteKey, mDefaultValue );
295 // do not copy if it is equal to the default value
296 if ( oldValue != defaultValueAsVariant() )
297 setVariantValue( oldValue, dynamicKeyPartList );
298 }
299 if ( removeSettingAtKey )
300 settings.remove( oldCompleteKey );
301 return true;
302 }
303
304 return false;
305}
306
307void QgsSettingsEntryBase::copyValueToKey( const QString &key, const QStringList &dynamicKeyPartList ) const
308{
309 const QString completeKey = completeKeyPrivate( key, dynamicKeyPartList );
310 sUserSettings().setValue( completeKey, valueAsVariant( dynamicKeyPartList ) );
311}
312
313void QgsSettingsEntryBase::copyValueToKeyIfChanged( const QString &key, const QStringList &dynamicKeyPartList ) const
314{
315 if ( hasChanged() )
316 {
317 copyValueToKey( key, dynamicKeyPartList );
318 }
319}
320
321QString QgsSettingsEntryBase::formerValuekey( const QStringList &dynamicKeyPartList ) const
322{
323 return key( dynamicKeyPartList ) + u"_formervalue"_s;
324}
@ SaveFormerValue
Save the former value of the settings.
Definition qgis.h:752
QFlags< SettingsOption > SettingsOptions
Definition qgis.h:756
SettingsOrigin
The setting origin describes where a setting is stored.
Definition qgis.h:4765
@ Local
Local settings are stored in the user profile.
Definition qgis.h:4768
@ Any
From any origin.
Definition qgis.h:4766
virtual QString typeId() const
Returns the id of the type of settings This can be re-implemented in a custom implementation of a set...
bool copyValueFromKey(const QString &key, bool removeSettingAtKey=false) const
Copies the value from a given key if it exists.
bool exists(const QString &dynamicKeyPart=QString()) const
Returns true if the settings is contained in the underlying QSettings.
Qgis::SettingsOptions options() const
Returns the settings options.
bool hasChanged() const
Returns true if the setting was changed during the current QGIS session.
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.
static QSettings & userSettings()
Returns a reference to the thread-local QSettings instance used internally by all QgsSettingsEntry op...
QgsSettingsTreeNode * parent() const
Returns the parent tree element.
void copyValueToKeyIfChanged(const QString &key, const QStringList &dynamicKeyPartList=QStringList()) const
Copies the settings to the given key, if it has changed during the current QGIS session (see hasChang...
Q_DECL_DEPRECATED int section() const
Returns settings section.
Qgis::SettingsOrigin origin(const QStringList &dynamicKeyPartList) const
Returns the origin of the setting if it exists.
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.
bool setVariantValue(const QVariant &value, const QString &dynamicKeyPart=QString()) const
Set settings value.
static void setupUserSettings(const QString &profilePath)
Configures QSettings to use IniFormat at the given profilePath so that each thread's QSettings instan...
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.
void copyValueToKey(const QString &key, const QStringList &dynamicKeyPartList=QStringList()) const
Copies the settings to the given key.
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.
virtual Qgis::SettingsType settingsType() const
Returns the settings entry type.
QgsSettingsEntryBase(const QString &key, const QString &section, const QVariant &defaultValue=QVariant(), const QString &description=QString(), Qgis::SettingsOptions options=Qgis::SettingsOptions())
Constructor for QgsSettingsEntryBase.
A tree node for the settings tree to help organizing and introspecting the tree.
#define Q_NOWARN_DEPRECATED_POP
Definition qgis.h:7678
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:7677
#define QgsDebugError(str)
Definition qgslogger.h:59
#define QGIS_CHECK_MAIN_THREAD_ACCESS