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 "kconfigbackend_p.h"
11 #include "kconfiggroup.h"
12 #include "kconfig_p.h"
13 #include <QCoreApplication>
14 #include <QThread>
15 #include <QThreadStorage>
16 
17 void _k_globalMainConfigSync();
18 
19 class GlobalSharedConfigList : public QList<KSharedConfig *>
20 {
21 public:
22  GlobalSharedConfigList()
23  : wasTestModeEnabled(false)
24  {
25  if (!qApp || QThread::currentThread() == qApp->thread()) {
26  // We want to force the sync() before the QCoreApplication
27  // instance is gone. Otherwise we trigger a QLockFile::lock()
28  // after QCoreApplication is gone, calling qAppName() for a non
29  // existent app...
30  qAddPostRoutine(&_k_globalMainConfigSync);
31  }
32  // In other threads, QThreadStorage takes care of deleting the GlobalSharedConfigList when
33  // the thread exits.
34  }
35 
36  // in addition to the list, we need to hold the main config,
37  // so that it's not created and destroyed all the time.
38  KSharedConfigPtr mainConfig;
39  bool wasTestModeEnabled;
40 };
41 
43 template <typename T>
44 T * perThreadGlobalStatic()
45 {
46  if (!s_storage.hasLocalData()) {
47  s_storage.setLocalData(new T);
48  }
49  return s_storage.localData();
50 }
51 
52 // Q_GLOBAL_STATIC(GlobalSharedConfigList, globalSharedConfigList), but per thread:
53 static GlobalSharedConfigList *globalSharedConfigList() { return perThreadGlobalStatic<GlobalSharedConfigList>(); }
54 
55 void _k_globalMainConfigSync()
56 {
57  KSharedConfigPtr mainConfig = globalSharedConfigList()->mainConfig;
58  if (mainConfig) {
59  mainConfig->sync();
60  }
61 }
62 
64  OpenFlags flags,
66 {
67  QString fileName(_fileName);
68  GlobalSharedConfigList *list = globalSharedConfigList();
69  if (fileName.isEmpty() && !flags.testFlag(KConfig::SimpleConfig)) {
70  // Determine the config file name that KConfig will make up (see KConfigPrivate::changeFileName)
71  fileName = KConfig::mainConfigName();
72  }
73 
74  if (!list->wasTestModeEnabled && QStandardPaths::isTestModeEnabled()) {
75  list->wasTestModeEnabled = true;
76  list->clear();
77  list->mainConfig = nullptr;
78  }
79 
80  for (auto cfg : qAsConst(*list)) {
81  if (cfg->name() == fileName &&
82  cfg->d_ptr->openFlags == flags &&
83  cfg->locationType() == resType
84 // cfg->backend()->type() == backend
85  ) {
86  return KSharedConfigPtr(cfg);
87  }
88  }
89 
90  KSharedConfigPtr ptr(new KSharedConfig(fileName, flags, resType));
91 
92  if (_fileName.isEmpty() && flags == FullConfig && resType == QStandardPaths::GenericConfigLocation) {
93  list->mainConfig = ptr;
94 
95  const bool isMainThread = !qApp || QThread::currentThread() == qApp->thread();
96  static bool userWarned = false;
97  if (isMainThread && !userWarned) {
98  userWarned = true;
99  const bool isReadOnly = qEnvironmentVariableIsEmpty("KDE_HOME_READONLY");
100  if (isReadOnly && QCoreApplication::applicationName() != QLatin1String("kdialog")) {
101  if (ptr->group("General").readEntry(QStringLiteral("warn_unwritable_config"), true)) {
102  ptr->isConfigWritable(true);
103  }
104  }
105  }
106  }
107 
108  return ptr;
109 }
110 
112 {
113  QString fileName(_fileName);
114 
115  if (fileName.isEmpty()) {
116  fileName = QCoreApplication::applicationName() + QLatin1String("staterc");
117  }
118 
119  return openConfig(fileName, SimpleConfig, QStandardPaths::AppDataLocation);
120 }
121 
122 KSharedConfig::KSharedConfig(const QString &fileName,
123  OpenFlags flags,
125  : KConfig(fileName, flags, resType)
126 {
127  globalSharedConfigList()->append(this);
128 }
129 
130 KSharedConfig::~KSharedConfig()
131 {
132  if (s_storage.hasLocalData()) {
133  globalSharedConfigList()->removeAll(this);
134  }
135 }
136 
137 KConfigGroup KSharedConfig::groupImpl(const QByteArray &groupName)
138 {
139  KSharedConfigPtr ptr(this);
140  return KConfigGroup(ptr, groupName.constData());
141 }
142 
143 const KConfigGroup KSharedConfig::groupImpl(const QByteArray &groupName) const
144 {
145  const KSharedConfigPtr ptr(const_cast<KSharedConfig *>(this));
146  return KConfigGroup(ptr, groupName.constData());
147 }
KConfig variant using shared memory.
Definition: ksharedconfig.h:31
Just a single config file.
Definition: kconfig.h:86
QThread * thread() const const
void setLocalData(T data)
static KSharedConfig::Ptr openStateConfig(const QString &fileName=QString())
Creates a KSharedConfig object to manipulate a configuration file suitable for storing state informat...
bool hasLocalData() const const
bool isEmpty() const const
const char * constData() 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.
A class for one specific group in a KConfig object.
Definition: kconfiggroup.h:38
The central class of the KDE configuration data system.
Definition: kconfig.h:56
QThread * currentThread()
bool testFlag(Enum flag) const const
QString applicationName()
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Thu Aug 6 2020 22:47:20 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.