23#include <QCoreApplication>
26#include <QRegularExpression>
30using namespace Qt::StringLiterals;
38static bool sSettingsInitialized =
false;
40static QSettings &sUserSettings()
42 thread_local std::unique_ptr<QSettings> sSettings;
43 thread_local bool sCreatedBeforeInit =
true;
45 if ( !sSettings || ( sCreatedBeforeInit && sSettingsInitialized ) )
47 sSettings = std::make_unique< QSettings >();
48 sCreatedBeforeInit = !sSettingsInitialized;
57 if ( sSettingsInitialized )
60 QSettings::setDefaultFormat( QSettings::IniFormat );
61 QSettings::setPath( QSettings::IniFormat, QSettings::UserScope, profilePath );
62 sSettingsInitialized =
true;
67 return sUserSettings();
70QHash<QString, QVariant> QgsSettingsEntryBase::sGlobalDefaults;
75 if ( QCoreApplication::instance() )
80 static bool sGlobalDefaultsLoaded =
false;
81 if ( sGlobalDefaultsLoaded )
82 QgsDebugMsgLevel( u
"Global settings are being reloaded from %1"_s.arg( path ), 2 );
83 sGlobalDefaultsLoaded =
true;
85 sGlobalDefaults.clear();
86 if ( path.isEmpty() || !QFile::exists( path ) )
89 const QSettings globalSettings( path, QSettings::IniFormat );
90 const QStringList keys = globalSettings.allKeys();
91 sGlobalDefaults.reserve( keys.size() );
92 for (
const QString &
key : keys )
94 sGlobalDefaults.insert(
key, globalSettings.value(
key ) );
102 return sGlobalDefaults.contains( sanitizeGlobalKey(
key ) );
107 return sGlobalDefaults.value( sanitizeGlobalKey(
key ) );
112 QString normalizedPrefix = sanitizeGlobalKey( prefix );
113 if ( !normalizedPrefix.endsWith(
'/' ) )
114 normalizedPrefix.append(
'/' );
116 const int prefixLen = normalizedPrefix.size();
119 for ( QHash<QString, QVariant>::const_iterator it = sGlobalDefaults.constBegin(); it != sGlobalDefaults.constEnd(); ++it )
121 if ( it.key().startsWith( normalizedPrefix ) )
123 const int slashPos = it.key().indexOf(
'/', prefixLen );
124 const QString group = ( slashPos < 0 ) ? it.key().mid( prefixLen ) : it.key().mid( prefixLen, slashPos - prefixLen );
125 if ( !group.isEmpty() && !result.contains( group ) )
126 result.append( group );
132QString QgsSettingsEntryBase::sanitizeGlobalKey(
const QString &key )
134 if (
key.startsWith(
'/' ) )
139QVariant QgsSettingsEntryBase::valueFromSettingsWithGlobalDefault(
const QString &resolvedKey,
const QVariant &defaultValue )
const
141 if ( sUserSettings().contains( resolvedKey ) )
142 return sUserSettings().value( resolvedKey );
146 const QHash<QString, QVariant>::const_iterator it = sGlobalDefaults.constFind( sanitizeGlobalKey( resolvedKey ) );
147 if ( it != sGlobalDefaults.constEnd() )
154 : mParentTreeElement(
parent )
156 , mDefaultValue( defaultValue )
160 mKey = QDir::cleanPath( u
"%1/%2"_s.arg(
parent ?
parent->completeKey() : QString(),
key ) );
164 parent->registerChildSetting(
this,
key );
170 if ( mParentTreeElement )
171 mParentTreeElement->unregisterChildSetting(
this );
176 return QString::fromUtf8( sSettingsTypeMetaEnum.valueToKey(
static_cast<int>(
settingsType() ) ) );
187 return completeKeyPrivate( mKey, dynamicKeyPartList );
190QString QgsSettingsEntryBase::completeKeyPrivate(
const QString &key,
const QStringList &dynamicKeyPartList )
const
192 QString completeKey =
key;
194 if ( dynamicKeyPartList.isEmpty() )
197 QgsDebugError( u
"Settings '%1' have a dynamic key but the dynamic key part was not provided"_s.arg( completeKey ) );
205 QgsDebugError( u
"Settings '%1' don't have a dynamic key, the provided dynamic key part will be ignored"_s.arg( completeKey ) );
209 for (
int i = 0; i < dynamicKeyPartList.size(); i++ )
211 completeKey.replace( u
"%"_s.append( QString::number( i + 1 ) ), dynamicKeyPartList.at( i ) );
227 const thread_local QRegularExpression digitRx( u
"%\\d+"_s );
228 const QRegularExpression regularExpression(
definitionKey().replace( digitRx, u
".*"_s ) );
229 const QRegularExpressionMatch regularExpressionMatch = regularExpression.match(
key );
230 return regularExpressionMatch.hasMatch();
240 const thread_local QRegularExpression regularExpression( u
"%\\d+"_s );
241 return mKey.contains( regularExpression );
246 const QString resolvedKey =
key( dynamicKeyPart );
247 return sUserSettings().contains( resolvedKey ) || sGlobalDefaults.contains( sanitizeGlobalKey( resolvedKey ) );
252 const QString resolvedKey =
key( dynamicKeyPartList );
253 return sUserSettings().contains( resolvedKey ) || sGlobalDefaults.contains( sanitizeGlobalKey( resolvedKey ) );
258 const QString resolvedKey =
key( dynamicKeyPartList );
260 if ( sGlobalDefaults.contains( sanitizeGlobalKey( resolvedKey ) ) )
263 if ( sUserSettings().contains( resolvedKey ) )
271 sUserSettings().remove(
key( dynamicKeyPart ) );
276 sUserSettings().remove(
key( dynamicKeyPartList ) );
292 const QString resolvedKey =
key( dynamicKeyPartList );
296 if (
exists( dynamicKeyPartList ) )
299 if ( value != currentValue )
301 sUserSettings().setValue( formerValuekey( dynamicKeyPartList ), currentValue );
307 const QString sanitizedKey = sanitizeGlobalKey( resolvedKey );
308 if ( sGlobalDefaults.contains( sanitizedKey ) && sGlobalDefaults.value( sanitizedKey ) == value )
310 sUserSettings().remove( resolvedKey );
314 sUserSettings().setValue( resolvedKey, value );
321 QStringList dynamicKeyPartList;
322 if ( !dynamicKeyPart.isNull() )
323 dynamicKeyPartList.append( dynamicKeyPart );
324 return dynamicKeyPartList;
334 return valueFromSettingsWithGlobalDefault(
key( dynamicKeyPartList ), mDefaultValue );
346 if ( useDefaultValueOverride )
347 return valueFromSettingsWithGlobalDefault(
key( dynamicKeyPartList ), defaultValueOverride );
349 return valueFromSettingsWithGlobalDefault(
key( dynamicKeyPartList ), mDefaultValue );
354 return valueFromSettingsWithGlobalDefault(
key( dynamicKeyPart ), defaultValueOverride );
359 return valueFromSettingsWithGlobalDefault(
key( dynamicKeyPartList ), defaultValueOverride );
364 return mDefaultValue;
380 QVariant defaultValueOverride =
valueAsVariant( dynamicKeyPartList );
381 return sUserSettings().value( formerValuekey( dynamicKeyPartList ), defaultValueOverride );
386 QSettings &settings = sUserSettings();
388 const QString oldCompleteKey = completeKeyPrivate(
key, dynamicKeyPartList );
390 if ( settings.contains( oldCompleteKey ) )
392 if ( !
exists( dynamicKeyPartList ) )
394 QVariant oldValue = settings.value( oldCompleteKey, mDefaultValue );
399 if ( removeSettingAtKey )
400 settings.remove( oldCompleteKey );
409 const QString completeKey = completeKeyPrivate(
key, dynamicKeyPartList );
410 sUserSettings().setValue( completeKey,
valueAsVariant( dynamicKeyPartList ) );
421QString QgsSettingsEntryBase::formerValuekey(
const QStringList &dynamicKeyPartList )
const
423 return key( dynamicKeyPartList ) + u
"_formervalue"_s;
@ SaveFormerValue
Save the former value of the settings.
QFlags< SettingsOption > SettingsOptions
SettingsOrigin
The setting origin describes where a setting is stored.
@ Global
Global settings are stored in qgis_global_settings.ini.
@ Local
Local settings are stored in the user profile.
static bool setGlobalSettingsPath(const QString &path)
Sets the path to the global settings INI file and loads all keys into an in-memory hash for use as de...
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.
static QStringList globalChildGroups(const QString &prefix)
Returns the list of child group names found under prefix in the global defaults hash.
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...
virtual ~QgsSettingsEntryBase()
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.
static bool hasGlobalDefault(const QString &key)
Returns true if the global settings INI file contains a value for the given key.
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 QVariant globalDefault(const QString &key)
Returns the global default value for the given key, or an invalid QVariant if not found.
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 §ion, 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
#define Q_NOWARN_DEPRECATED_PUSH
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
#define QGIS_CHECK_MAIN_THREAD_ACCESS