KConfig

kconfigdata.cpp
1 /*
2  This file is part of the KDE libraries
3  SPDX-FileCopyrightText: 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
4  SPDX-FileCopyrightText: 1999-2000 Preston Brown <pbrown@kde.org>
5  SPDX-FileCopyrightText: 1996-2000 Matthias Kalle Dalheimer <kalle@kde.org>
6 
7  SPDX-License-Identifier: LGPL-2.0-or-later
8 */
9 
10 #include "kconfigdata_p.h"
11 
12 QDebug operator<<(QDebug dbg, const KEntryKey &key)
13 {
14  dbg.nospace() << "[" << key.mGroup << ", " << key.mKey << (key.bLocal ? " localized" : "") << (key.bDefault ? " default" : "") << (key.bRaw ? " raw" : "")
15  << "]";
16  return dbg.space();
17 }
18 
19 QDebug operator<<(QDebug dbg, const KEntry &entry)
20 {
21  dbg.nospace() << "[" << entry.mValue << (entry.bDirty ? " dirty" : "") << (entry.bGlobal ? " global" : "")
22  << (entry.bOverridesGlobal ? " overrides global" : "") << (entry.bImmutable ? " immutable" : "") << (entry.bDeleted ? " deleted" : "")
23  << (entry.bReverted ? " reverted" : "") << (entry.bExpand ? " expand" : "") << "]";
24 
25  return dbg.space();
26 }
27 
28 KEntryMapIterator KEntryMap::findExactEntry(const QString &group, QAnyStringView key, KEntryMap::SearchFlags flags)
29 {
30  const KEntryKeyView theKey(group, key, bool(flags & SearchLocalized), bool(flags & SearchDefaults));
31  return find(theKey);
32 }
33 
34 KEntryMapIterator KEntryMap::findEntry(const QString &group, QAnyStringView key, KEntryMap::SearchFlags flags)
35 {
36  KEntryKeyView theKey(group, key, false, bool(flags & SearchDefaults));
37 
38  // try the localized key first
39  if (flags & SearchLocalized) {
40  theKey.bLocal = true;
41 
42  iterator it = find(theKey);
43  if (it != end()) {
44  return it;
45  }
46 
47  theKey.bLocal = false;
48  }
49  return find(theKey);
50 }
51 
52 KEntryMapConstIterator KEntryMap::constFindEntry(const QString &group, QAnyStringView key, SearchFlags flags) const
53 {
54  KEntryKeyView theKey(group, key, false, bool(flags & SearchDefaults));
55 
56  // try the localized key first
57  if (flags & SearchLocalized) {
58  theKey.bLocal = true;
59 
60  auto it = find(theKey);
61  if (it != cend()) {
62  return it;
63  }
64 
65  theKey.bLocal = false;
66  }
67 
68  return find(theKey);
69 }
70 
71 bool KEntryMap::setEntry(const QString &group, const QByteArray &key, const QByteArray &value, KEntryMap::EntryOptions options)
72 {
73  KEntryKey k;
74  KEntry e;
75  bool newKey = false;
76 
77  const iterator it = findExactEntry(group, key, SearchFlags(options >> 16));
78 
79  if (key.isEmpty()) { // inserting a group marker
80  k.mGroup = group;
81  e.bImmutable = (options & EntryImmutable);
82  if (options & EntryDeleted) {
83  qWarning("Internal KConfig error: cannot mark groups as deleted");
84  }
85  if (it == end()) {
86  insert_or_assign(k, e);
87  return true;
88  } else if (it->second == e) {
89  return false;
90  }
91 
92  it->second = e;
93  return true;
94  }
95 
96  if (it != end()) {
97  if (it->second.bImmutable) {
98  return false; // we cannot change this entry. Inherits group immutability.
99  }
100  k = it->first;
101  e = it->second;
102  // qDebug() << "found existing entry for key" << k;
103  // If overridden entry is global and not default. And it's overridden by a non global
104  if (e.bGlobal && !(options & EntryGlobal) && !k.bDefault) {
105  e.bOverridesGlobal = true;
106  }
107  } else {
108  // make sure the group marker is in the map
109  KEntryMap const *that = this;
110  auto cit = that->constFindEntry(group);
111  if (cit == cend()) {
112  insert_or_assign(KEntryKey(group), KEntry());
113  } else if (cit->second.bImmutable) {
114  return false; // this group is immutable, so we cannot change this entry.
115  }
116 
117  k = KEntryKey(group, key);
118  newKey = true;
119  }
120 
121  // set these here, since we may be changing the type of key from the one we found
122  k.bLocal = (options & EntryLocalized);
123  k.bDefault = (options & EntryDefault);
124  k.bRaw = (options & EntryRawKey);
125 
126  e.mValue = value;
127  e.bDirty = e.bDirty || (options & EntryDirty);
128  e.bNotify = e.bNotify || (options & EntryNotify);
129 
130  e.bGlobal = (options & EntryGlobal); // we can't use || here, because changes to entries in
131  // kdeglobals would be written to kdeglobals instead
132  // of the local config file, regardless of the globals flag
133  e.bImmutable = e.bImmutable || (options & EntryImmutable);
134  if (value.isNull()) {
135  e.bDeleted = e.bDeleted || (options & EntryDeleted);
136  } else {
137  e.bDeleted = false; // setting a value to a previously deleted entry
138  }
139  e.bExpand = (options & EntryExpansion);
140  e.bReverted = false;
141  if (options & EntryLocalized) {
142  e.bLocalizedCountry = (options & EntryLocalizedCountry);
143  } else {
144  e.bLocalizedCountry = false;
145  }
146 
147  if (newKey) {
148  // qDebug() << "inserting" << k << "=" << value;
149  insert_or_assign(k, e);
150  if (k.bDefault) {
151  k.bDefault = false;
152  // qDebug() << "also inserting" << k << "=" << value;
153  insert_or_assign(k, e);
154  }
155  // TODO check for presence of unlocalized key
156  return true;
157  }
158 
159  // KEntry e2 = it->second;
160  if (options & EntryLocalized) {
161  // fast exit checks for cases where the existing entry is more specific
162  const KEntry &e2 = it->second;
163  if (e2.bLocalizedCountry && !e.bLocalizedCountry) {
164  // lang_COUNTRY > lang
165  return false;
166  }
167  }
168 
169  if (it->second != e) {
170  // qDebug() << "changing" << k << "from" << it->second.mValue << "to" << value << e;
171  it->second = e;
172  if (k.bDefault) {
173  KEntryKey nonDefaultKey(k);
174  nonDefaultKey.bDefault = false;
175  insert_or_assign(nonDefaultKey, e);
176  }
177  if (!(options & EntryLocalized)) {
178  KEntryKey theKey(group, key, true, false);
179  // qDebug() << "non-localized entry, remove localized one:" << theKey;
180  erase(theKey);
181  if (k.bDefault) {
182  theKey.bDefault = true;
183  erase(theKey);
184  }
185  }
186  return true;
187  }
188 
189  // qDebug() << k << "was already set to" << e.mValue;
190  if (!(options & EntryLocalized)) {
191  // qDebug() << "unchanged non-localized entry, remove localized one.";
192  KEntryKey theKey(group, key, true, false);
193  bool ret = false;
194  iterator cit = find(theKey);
195  if (cit != end()) {
196  erase(cit);
197  ret = true;
198  }
199  if (k.bDefault) {
200  theKey.bDefault = true;
201  iterator cit = find(theKey);
202  if (cit != end()) {
203  erase(cit);
204  return true;
205  }
206  }
207  return ret;
208  }
209 
210  // qDebug() << "localized entry, unchanged, return false";
211  // When we are writing a default, we know that the non-
212  // default is the same as the default, so we can simply
213  // use the same branch.
214  return false;
215 }
216 
217 QString KEntryMap::getEntry(const QString &group, QAnyStringView key, const QString &defaultValue, KEntryMap::SearchFlags flags, bool *expand) const
218 {
219  const auto it = constFindEntry(group, key, flags);
220  QString theValue = defaultValue;
221 
222  if (it != cend() && !it->second.bDeleted) {
223  if (!it->second.mValue.isNull()) {
224  const QByteArray data = it->second.mValue;
225  theValue = QString::fromUtf8(data.constData(), data.length());
226  if (expand) {
227  *expand = it->second.bExpand;
228  }
229  }
230  }
231 
232  return theValue;
233 }
234 
235 bool KEntryMap::hasEntry(const QString &group, QAnyStringView key, KEntryMap::SearchFlags flags) const
236 {
237  const auto it = constFindEntry(group, key, flags);
238  if (it == cend()) {
239  return false;
240  }
241  if (it->second.bDeleted) {
242  return false;
243  }
244  if (key.isNull()) { // looking for group marker
245  return it->second.mValue.isNull();
246  }
247  // if it->bReverted, we'll just return true; the real answer depends on lookup up with SearchDefaults, though.
248  return true;
249 }
250 
251 bool KEntryMap::getEntryOption(const KEntryMapConstIterator &it, KEntryMap::EntryOption option) const
252 {
253  if (it == cend()) {
254  return false;
255  }
256 
257  switch (option) {
258  case EntryDirty:
259  return it->second.bDirty;
260  case EntryLocalized:
261  return it->first.bLocal;
262  case EntryGlobal:
263  return it->second.bGlobal;
264  case EntryImmutable:
265  return it->second.bImmutable;
266  case EntryDeleted:
267  return it->second.bDeleted;
268  case EntryExpansion:
269  return it->second.bExpand;
270  case EntryNotify:
271  return it->second.bNotify;
272  default:
273  return false;
274  }
275 }
276 
277 void KEntryMap::setEntryOption(KEntryMapIterator it, KEntryMap::EntryOption option, bool bf)
278 {
279  if (it == end()) {
280  return;
281  }
282 
283  switch (option) {
284  case EntryDirty:
285  it->second.bDirty = bf;
286  return;
287  case EntryGlobal:
288  it->second.bGlobal = bf;
289  return;
290  case EntryImmutable:
291  it->second.bImmutable = bf;
292  return;
293  case EntryDeleted:
294  it->second.bDeleted = bf;
295  return;
296  case EntryExpansion:
297  it->second.bExpand = bf;
298  return;
299  case EntryNotify:
300  it->second.bNotify = bf;
301  return;
302  default:
303  return; // fall through
304  }
305 }
306 
307 bool KEntryMap::revertEntry(const QString &group, QAnyStringView key, KEntryMap::EntryOptions options, KEntryMap::SearchFlags flags)
308 {
309  Q_ASSERT((flags & KEntryMap::SearchDefaults) == 0);
310  iterator entry = findEntry(group, key, flags);
311  if (entry == end()) {
312  return false;
313  }
314 
315  // qDebug() << "reverting" << entry->first << " = " << entry->mValue;
316  if (entry->second.bReverted) { // already done before
317  return false;
318  }
319 
320  KEntryKey defaultKey(entry->first);
321  defaultKey.bDefault = true;
322  // qDebug() << "looking up default entry with key=" << defaultKey;
323  const auto defaultEntry = find(defaultKey);
324  if (defaultEntry != cend()) {
325  Q_ASSERT(defaultEntry->first.bDefault);
326  // qDebug() << "found, update entry";
327  entry->second = defaultEntry->second; // copy default value, for subsequent lookups
328  } else {
329  entry->second.mValue = QByteArray();
330  }
331  entry->second.bNotify = entry->second.bNotify || (options & EntryNotify);
332  entry->second.bDirty = true;
333  entry->second.bReverted = true; // skip it when writing out to disk
334 
335  // qDebug() << "Here's what we have now:" << *this;
336  return true;
337 }
bool isNull() const const
KCALENDARCORE_EXPORT QDataStream & operator<<(QDataStream &out, const KCalendarCore::Alarm::Ptr &)
QString fromUtf8(const char *str, int size)
QDebug & nospace()
QDebug & space()
QAction * find(const QObject *recvr, const char *slot, QObject *parent)
bool isEmpty() const const
QAction * end(const QObject *recvr, const char *slot, QObject *parent)
const char * constData() const const
int length() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Thu Feb 15 2024 04:07:59 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.