KConfig

ksharedconfig.cpp
1 /*
2  This file is part of the KDE libraries
3  SPDX-FileCopyrightText: 1999 Preston Brown <[email protected]>
4  SPDX-FileCopyrightText: 1997-1999 Matthias Kalle Dalheimer <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #include "ksharedconfig.h"
10 #include "kconfig_p.h"
11 #include "kconfigbackend_p.h"
12 #include "kconfiggroup.h"
13 #include <QCoreApplication>
14 #include <QThread>
15 #include <QThreadStorage>
16 
17 void _k_globalMainConfigSync();
18 
20 
21 class GlobalSharedConfig
22 {
23 public:
24  GlobalSharedConfig()
25  : wasTestModeEnabled(false)
26  {
27  if (!qApp || QThread::currentThread() == qApp->thread()) {
28  // We want to force the sync() before the QCoreApplication
29  // instance is gone. Otherwise we trigger a QLockFile::lock()
30  // after QCoreApplication is gone, calling qAppName() for a non
31  // existent app...
32  qAddPostRoutine(&_k_globalMainConfigSync);
33  }
34  // In other threads, QThreadStorage takes care of deleting the GlobalSharedConfigList when
35  // the thread exits.
36  }
37 
38  SharedConfigList configList;
39  // in addition to the list, we need to hold the main config,
40  // so that it's not created and destroyed all the time.
41  KSharedConfigPtr mainConfig;
42  bool wasTestModeEnabled;
43 };
44 
46 template<typename T>
47 T *perThreadGlobalStatic()
48 {
49  if (!s_storage.hasLocalData()) {
50  s_storage.setLocalData(new T);
51  }
52  return s_storage.localData();
53 }
54 
55 // Q_GLOBAL_STATIC(GlobalSharedConfigList, globalSharedConfigList), but per thread:
56 static GlobalSharedConfig *globalSharedConfig()
57 {
58  return perThreadGlobalStatic<GlobalSharedConfig>();
59 }
60 
61 void _k_globalMainConfigSync()
62 {
63  KSharedConfigPtr mainConfig = globalSharedConfig()->mainConfig;
64  if (mainConfig) {
65  mainConfig->sync();
66  }
67 }
68 
70 {
71  QString fileName(_fileName);
72  GlobalSharedConfig *global = globalSharedConfig();
73  if (fileName.isEmpty() && !flags.testFlag(KConfig::SimpleConfig)) {
74  // Determine the config file name that KConfig will make up (see KConfigPrivate::changeFileName)
75  fileName = KConfig::mainConfigName();
76  }
77 
78  if (!global->wasTestModeEnabled && QStandardPaths::isTestModeEnabled()) {
79  global->wasTestModeEnabled = true;
80  global->configList.clear();
81  global->mainConfig = nullptr;
82  }
83 
84  for (auto *cfg : std::as_const(global->configList)) {
85  if (cfg->name() == fileName && cfg->d_ptr->openFlags == flags && cfg->locationType() == resType
86  // cfg->backend()->type() == backend
87  ) {
88  return KSharedConfigPtr(cfg);
89  }
90  }
91 
92  KSharedConfigPtr ptr(new KSharedConfig(fileName, flags, resType));
93 
94  if (_fileName.isEmpty() && flags == FullConfig && resType == QStandardPaths::GenericConfigLocation) {
95  global->mainConfig = ptr;
96 
97  const bool isMainThread = !qApp || QThread::currentThread() == qApp->thread();
98  static bool userWarned = false;
99  if (isMainThread && !userWarned) {
100  userWarned = true;
101  const bool isReadOnly = qEnvironmentVariableIsEmpty("KDE_HOME_READONLY");
102  if (isReadOnly && QCoreApplication::applicationName() != QLatin1String("kdialog")) {
103  if (ptr->group("General").readEntry(QStringLiteral("warn_unwritable_config"), true)) {
104  ptr->isConfigWritable(true);
105  }
106  }
107  }
108  }
109 
110  return ptr;
111 }
112 
114 {
115  // KF6 TODO: port this to XDG_STATE_HOME (default ~/.local/state)
116  // See https://gitlab.freedesktop.org/xdg/xdg-specs/-/blob/master/basedir/basedir-spec.xml
117  QString fileName(_fileName);
118 
119  if (fileName.isEmpty()) {
120  fileName = QCoreApplication::applicationName() + QLatin1String("staterc");
121  }
122 
124 }
125 
126 KSharedConfig::KSharedConfig(const QString &fileName, OpenFlags flags, QStandardPaths::StandardLocation resType)
127  : KConfig(fileName, flags, resType)
128 {
129  globalSharedConfig()->configList.append(this);
130 }
131 
132 KSharedConfig::~KSharedConfig()
133 {
134  if (s_storage.hasLocalData()) {
135  globalSharedConfig()->configList.removeAll(this);
136  }
137 }
138 
139 KConfigGroup KSharedConfig::groupImpl(const QByteArray &groupName)
140 {
141  KSharedConfigPtr ptr(this);
142  return KConfigGroup(ptr, groupName.constData());
143 }
144 
145 const KConfigGroup KSharedConfig::groupImpl(const QByteArray &groupName) const
146 {
147  const KSharedConfigPtr ptr(const_cast<KSharedConfig *>(this));
148  return KConfigGroup(ptr, groupName.constData());
149 }
bool testFlag(Enum flag) const const
The central class of the KDE configuration data system.
Definition: kconfig.h:56
QThread * thread() const const
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
Creates a KSharedConfig object to manipulate a configuration file.
@ FullConfig
Fully-fledged config, including globals and cascading to system settings.
Definition: kconfig.h:89
bool isEmpty() const const
static KSharedConfig::Ptr openStateConfig(const QString &fileName=QString())
Creates a KSharedConfig object to manipulate a configuration file suitable for storing state informat...
QThread * currentThread()
const char * constData() const const
static QString mainConfigName()
Get the name of application config file.
Definition: kconfig.cpp:591
@ SimpleConfig
Just a single config file.
Definition: kconfig.h:86
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sat Dec 2 2023 04:11:08 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.