QGIS API Documentation 4.3.0-Master (ca159e4aeaf)
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 std::unique_ptr<QSettings> sSettings;
41 thread_local bool sCreatedBeforeInit = true;
42
43 if ( !sSettings || ( sCreatedBeforeInit && sSettingsInitialized ) )
44 {
45 sSettings = std::make_unique< QSettings >();
46 sCreatedBeforeInit = !sSettingsInitialized;
47 }
48 return *sSettings;
49}
50
51void QgsSettingsEntryBase::setupUserSettings( const QString &profilePath )
52{
54
55 if ( sSettingsInitialized )
56 return;
57
58 QSettings::setDefaultFormat( QSettings::IniFormat );
59 QSettings::setPath( QSettings::IniFormat, QSettings::UserScope, profilePath );
60 sSettingsInitialized = true;
61}
62
64{
65 return sUserSettings();
66}
67
69 : mParentTreeElement( parent )
70 , mName( key )
71 , mDefaultValue( defaultValue )
72 , mDescription( description )
73 , mOptions( options )
74{
75 mKey = QDir::cleanPath( u"%1/%2"_s.arg( parent ? parent->completeKey() : QString(), key ) );
76
77 if ( parent )
78 {
79 parent->registerChildSetting( this, key );
80 }
81}
82
84{
85 if ( mParentTreeElement )
86 mParentTreeElement->unregisterChildSetting( this );
87}
88
90{
91 return QString::fromUtf8( sSettingsTypeMetaEnum.valueToKey( static_cast<int>( settingsType() ) ) );
92}
93
94
95QString QgsSettingsEntryBase::key( const QString &dynamicKeyPart ) const
96{
97 return key( dynamicKeyPartToList( dynamicKeyPart ) );
98}
99
100QString QgsSettingsEntryBase::key( const QStringList &dynamicKeyPartList ) const
101{
102 return completeKeyPrivate( mKey, dynamicKeyPartList );
103}
104
105QString QgsSettingsEntryBase::completeKeyPrivate( const QString &key, const QStringList &dynamicKeyPartList ) const
106{
107 QString completeKey = key;
108
109 if ( dynamicKeyPartList.isEmpty() )
110 {
111 if ( hasDynamicKey() )
112 QgsDebugError( u"Settings '%1' have a dynamic key but the dynamic key part was not provided"_s.arg( completeKey ) );
113
114 return completeKey;
115 }
116 else
117 {
118 if ( !hasDynamicKey() )
119 {
120 QgsDebugError( u"Settings '%1' don't have a dynamic key, the provided dynamic key part will be ignored"_s.arg( completeKey ) );
121 return completeKey;
122 }
123
124 for ( int i = 0; i < dynamicKeyPartList.size(); i++ )
125 {
126 completeKey.replace( u"%"_s.append( QString::number( i + 1 ) ), dynamicKeyPartList.at( i ) );
127 }
128 }
129 return completeKey;
130}
131
132bool QgsSettingsEntryBase::keyIsValid( const QString &key ) const
133{
134 if ( !hasDynamicKey() )
135 {
136 if ( !key.contains( definitionKey() ) )
137 return false;
138 else
139 return key == definitionKey();
140 }
141
142 const thread_local QRegularExpression digitRx( u"%\\d+"_s );
143 const QRegularExpression regularExpression( definitionKey().replace( digitRx, u".*"_s ) );
144 const QRegularExpressionMatch regularExpressionMatch = regularExpression.match( key );
145 return regularExpressionMatch.hasMatch();
146}
147
149{
150 return mKey;
151}
152
154{
155 const thread_local QRegularExpression regularExpression( u"%\\d+"_s );
156 return mKey.contains( regularExpression );
157}
158
159bool QgsSettingsEntryBase::exists( const QString &dynamicKeyPart ) const
160{
161 return sUserSettings().contains( key( dynamicKeyPart ) );
162}
163
164bool QgsSettingsEntryBase::exists( const QStringList &dynamicKeyPartList ) const
165{
166 return sUserSettings().contains( key( dynamicKeyPartList ) );
167}
168
169Qgis::SettingsOrigin QgsSettingsEntryBase::origin( const QStringList &dynamicKeyPartList ) const
170{
171 if ( sUserSettings().contains( key( dynamicKeyPartList ) ) )
173
175}
176
177void QgsSettingsEntryBase::remove( const QString &dynamicKeyPart ) const
178{
179 sUserSettings().remove( key( dynamicKeyPart ) );
180}
181
182void QgsSettingsEntryBase::remove( const QStringList &dynamicKeyPartList ) const
183{
184 sUserSettings().remove( key( dynamicKeyPartList ) );
185}
186
191
192bool QgsSettingsEntryBase::setVariantValue( const QVariant &value, const QString &dynamicKeyPart ) const
193{
194 return setVariantValue( value, dynamicKeyPartToList( dynamicKeyPart ) );
195}
196
197bool QgsSettingsEntryBase::setVariantValue( const QVariant &value, const QStringList &dynamicKeyPartList ) const
198{
199 mHasChanged = true;
200 const QString resolvedKey = key( dynamicKeyPartList );
201
202 if ( mOptions.testFlag( Qgis::SettingsOption::SaveFormerValue ) )
203 {
204 if ( exists( dynamicKeyPartList ) )
205 {
206 QVariant currentValue = valueAsVariant( dynamicKeyPartList );
207 if ( value != currentValue )
208 {
209 sUserSettings().setValue( formerValuekey( dynamicKeyPartList ), currentValue );
210 }
211 }
212 }
213
214 sUserSettings().setValue( resolvedKey, value );
215 return true;
216}
217
218QStringList QgsSettingsEntryBase::dynamicKeyPartToList( const QString &dynamicKeyPart )
219{
220 QStringList dynamicKeyPartList;
221 if ( !dynamicKeyPart.isNull() )
222 dynamicKeyPartList.append( dynamicKeyPart );
223 return dynamicKeyPartList;
224}
225
226QVariant QgsSettingsEntryBase::valueAsVariant( const QString &dynamicKeyPart ) const
227{
228 return valueAsVariant( dynamicKeyPartToList( dynamicKeyPart ) );
229}
230
231QVariant QgsSettingsEntryBase::valueAsVariant( const QStringList &dynamicKeyPartList ) const
232{
233 return sUserSettings().value( key( dynamicKeyPartList ), mDefaultValue );
234}
235
236QVariant QgsSettingsEntryBase::valueAsVariant( const QString &dynamicKeyPart, bool useDefaultValueOverride, const QVariant &defaultValueOverride ) const
237{
239 return valueAsVariant( dynamicKeyPartToList( dynamicKeyPart ), useDefaultValueOverride, defaultValueOverride );
241}
242
243QVariant QgsSettingsEntryBase::valueAsVariant( const QStringList &dynamicKeyPartList, bool useDefaultValueOverride, const QVariant &defaultValueOverride ) const
244{
245 if ( useDefaultValueOverride )
246 return sUserSettings().value( key( dynamicKeyPartList ), defaultValueOverride );
247 else
248 return sUserSettings().value( key( dynamicKeyPartList ), mDefaultValue );
249}
250
251QVariant QgsSettingsEntryBase::valueAsVariantWithDefaultOverride( const QVariant &defaultValueOverride, const QString &dynamicKeyPart ) const
252{
253 return sUserSettings().value( key( dynamicKeyPart ), defaultValueOverride );
254}
255
256QVariant QgsSettingsEntryBase::valueAsVariantWithDefaultOverride( const QVariant &defaultValueOverride, const QStringList &dynamicKeyPartList ) const
257{
258 return sUserSettings().value( key( dynamicKeyPartList ), defaultValueOverride );
259}
260
262{
263 return mDefaultValue;
264}
265
267{
268 return mDescription;
269}
270
271QVariant QgsSettingsEntryBase::formerValueAsVariant( const QString &dynamicKeyPart ) const
272{
273 return formerValueAsVariant( dynamicKeyPartToList( dynamicKeyPart ) );
274}
275
276QVariant QgsSettingsEntryBase::formerValueAsVariant( const QStringList &dynamicKeyPartList ) const
277{
278 Q_ASSERT( mOptions.testFlag( Qgis::SettingsOption::SaveFormerValue ) );
279 QVariant defaultValueOverride = valueAsVariant( dynamicKeyPartList );
280 return sUserSettings().value( formerValuekey( dynamicKeyPartList ), defaultValueOverride );
281}
282
283bool QgsSettingsEntryBase::copyValueFromKey( const QString &key, const QStringList &dynamicKeyPartList, bool removeSettingAtKey ) const
284{
285 QSettings &settings = sUserSettings();
286
287 const QString oldCompleteKey = completeKeyPrivate( key, dynamicKeyPartList );
288
289 if ( settings.contains( oldCompleteKey ) )
290 {
291 if ( !exists( dynamicKeyPartList ) )
292 {
293 QVariant oldValue = settings.value( oldCompleteKey, mDefaultValue );
294 // do not copy if it is equal to the default value
295 if ( oldValue != defaultValueAsVariant() )
296 setVariantValue( oldValue, dynamicKeyPartList );
297 }
298 if ( removeSettingAtKey )
299 settings.remove( oldCompleteKey );
300 return true;
301 }
302
303 return false;
304}
305
306void QgsSettingsEntryBase::copyValueToKey( const QString &key, const QStringList &dynamicKeyPartList ) const
307{
308 const QString completeKey = completeKeyPrivate( key, dynamicKeyPartList );
309 sUserSettings().setValue( completeKey, valueAsVariant( dynamicKeyPartList ) );
310}
311
312void QgsSettingsEntryBase::copyValueToKeyIfChanged( const QString &key, const QStringList &dynamicKeyPartList ) const
313{
314 if ( hasChanged() )
315 {
316 copyValueToKey( key, dynamicKeyPartList );
317 }
318}
319
320QString QgsSettingsEntryBase::formerValuekey( const QStringList &dynamicKeyPartList ) const
321{
322 return key( dynamicKeyPartList ) + u"_formervalue"_s;
323}
@ SaveFormerValue
Save the former value of the settings.
Definition qgis.h:786
QFlags< SettingsOption > SettingsOptions
Definition qgis.h:790
SettingsOrigin
The setting origin describes where a setting is stored.
Definition qgis.h:4965
@ Local
Local settings are stored in the user profile.
Definition qgis.h:4968
@ Any
From any origin.
Definition qgis.h:4966
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:8361
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:8360
#define QgsDebugError(str)
Definition qgslogger.h:71
#define QGIS_CHECK_MAIN_THREAD_ACCESS