• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.10.4 API Reference
  • KDE Home
  • Contact Us
 

KDECore

  • kdecore
  • config
kconfig.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the KDE libraries
3  Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
4  Copyright (c) 1999 Preston Brown <pbrown@kde.org>
5  Copyright (c) 1997-1999 Matthias Kalle Dalheimer <kalle@kde.org>
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Library General Public
9  License as published by the Free Software Foundation; either
10  version 2 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Library General Public License for more details.
16 
17  You should have received a copy of the GNU Library General Public License
18  along with this library; see the file COPYING.LIB. If not, write to
19  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  Boston, MA 02110-1301, USA.
21 */
22 
23 #include "kconfig.h"
24 #include "kconfig_p.h"
25 
26 #include <cstdlib>
27 #include <fcntl.h>
28 #include <unistd.h>
29 
30 #include "kconfigbackend.h"
31 #include "kconfiggroup.h"
32 #include <kde_file.h>
33 #include <kstringhandler.h>
34 #include <klocale.h>
35 #include <kstandarddirs.h>
36 #include <kurl.h>
37 #include <kcomponentdata.h>
38 #include <ktoolinvocation.h>
39 #include <kaboutdata.h>
40 #include <kdebug.h>
41 
42 #include <qbytearray.h>
43 #include <qfile.h>
44 #include <qdir.h>
45 #include <qdatetime.h>
46 #include <qrect.h>
47 #include <qsize.h>
48 #include <qcolor.h>
49 #include <QtCore/QProcess>
50 #include <QtCore/QPointer>
51 #include <QtCore/QSet>
52 #include <QtCore/QStack>
53 
54 bool KConfigPrivate::mappingsRegistered=false;
55 
56 KConfigPrivate::KConfigPrivate(const KComponentData &componentData_, KConfig::OpenFlags flags,
57  const char* resource)
58  : openFlags(flags), resourceType(resource), mBackend(0),
59  bDynamicBackend(true), bDirty(false), bReadDefaults(false),
60  bFileImmutable(false), bForceGlobal(false), bSuppressGlobal(false),
61  componentData(componentData_), configState(KConfigBase::NoAccess)
62 {
63  sGlobalFileName = componentData.dirs()->saveLocation("config", QString(), false) + QLatin1String("kdeglobals");
64 
65  static int use_etc_kderc = -1;
66  if (use_etc_kderc < 0)
67  use_etc_kderc = getenv("KDE_SKIP_KDERC") != 0 ? 0 : 1; // for unit tests
68  if (use_etc_kderc) {
69 
70  etc_kderc =
71 #ifdef Q_WS_WIN
72  QFile::decodeName( qgetenv("WINDIR") + "/kde4rc" );
73 #else
74  QLatin1String("/etc/kde4rc");
75 #endif
76  if (!KStandardDirs::checkAccess(etc_kderc, R_OK)) {
77  etc_kderc.clear();
78  }
79  }
80 
81 // if (!mappingsRegistered) {
82 // KEntryMap tmp;
83 // if (!etc_kderc.isEmpty()) {
84 // KSharedPtr<KConfigBackend> backend = KConfigBackend::create(componentData, etc_kderc, QLatin1String("INI"));
85 // backend->parseConfig( "en_US", tmp, KConfigBackend::ParseDefaults);
86 // }
87 // const QString kde4rc(QDir::home().filePath(".kde4rc"));
88 // if (KStandardDirs::checkAccess(kde4rc, R_OK)) {
89 // KSharedPtr<KConfigBackend> backend = KConfigBackend::create(componentData, kde4rc, QLatin1String("INI"));
90 // backend->parseConfig( "en_US", tmp, KConfigBackend::ParseOptions());
91 // }
92 // KConfigBackend::registerMappings(tmp);
93 // mappingsRegistered = true;
94 // }
95 
96  setLocale(KGlobal::hasLocale() ? KGlobal::locale()->language() : KLocale::defaultLanguage());
97 }
98 
99 
100 bool KConfigPrivate::lockLocal()
101 {
102  if (mBackend) {
103  return mBackend->lock(componentData);
104  }
105  // anonymous object - pretend we locked it
106  return true;
107 }
108 
109 void KConfigPrivate::copyGroup(const QByteArray& source, const QByteArray& destination,
110  KConfigGroup *otherGroup, KConfigBase::WriteConfigFlags flags) const
111 {
112  KEntryMap& otherMap = otherGroup->config()->d_ptr->entryMap;
113  const int len = source.length();
114  const bool sameName = (destination == source);
115 
116  // we keep this bool outside the foreach loop so that if
117  // the group is empty, we don't end up marking the other config
118  // as dirty erroneously
119  bool dirtied = false;
120 
121  for (KEntryMap::ConstIterator entryMapIt( entryMap.constBegin() ); entryMapIt != entryMap.constEnd(); ++entryMapIt) {
122  const QByteArray& group = entryMapIt.key().mGroup;
123 
124  if (!group.startsWith(source)) // nothing to do
125  continue;
126 
127  // don't copy groups that start with the same prefix, but are not sub-groups
128  if (group.length() > len && group[len] != '\x1d')
129  continue;
130 
131  KEntryKey newKey = entryMapIt.key();
132 
133  if (flags & KConfigBase::Localized) {
134  newKey.bLocal = true;
135  }
136 
137  if (!sameName)
138  newKey.mGroup.replace(0, len, destination);
139 
140  KEntry entry = entryMap[ entryMapIt.key() ];
141  dirtied = entry.bDirty = flags & KConfigBase::Persistent;
142 
143  if (flags & KConfigBase::Global) {
144  entry.bGlobal = true;
145  }
146 
147  otherMap[newKey] = entry;
148  }
149 
150  if (dirtied) {
151  otherGroup->config()->d_ptr->bDirty = true;
152  }
153 }
154 
155 QString KConfigPrivate::expandString(const QString& value)
156 {
157  QString aValue = value;
158 
159  // check for environment variables and make necessary translations
160  int nDollarPos = aValue.indexOf( QLatin1Char('$') );
161  while( nDollarPos != -1 && nDollarPos+1 < aValue.length()) {
162  // there is at least one $
163  if( aValue[nDollarPos+1] == QLatin1Char('(') ) {
164  int nEndPos = nDollarPos+1;
165  // the next character is not $
166  while ( (nEndPos <= aValue.length()) && (aValue[nEndPos]!=QLatin1Char(')')) )
167  nEndPos++;
168  nEndPos++;
169  QString cmd = aValue.mid( nDollarPos+2, nEndPos-nDollarPos-3 );
170 
171  QString result;
172  QByteArray oldpath = qgetenv( "PATH" );
173  QByteArray newpath;
174  if (KGlobal::hasMainComponent()) {
175  newpath = QFile::encodeName(KGlobal::dirs()->resourceDirs("exe").join(QChar::fromLatin1(KPATH_SEPARATOR)));
176  if (!newpath.isEmpty() && !oldpath.isEmpty())
177  newpath += KPATH_SEPARATOR;
178  }
179  newpath += oldpath;
180  setenv( "PATH", newpath, 1/*overwrite*/ );
181 // FIXME: wince does not have pipes
182 #ifndef _WIN32_WCE
183  FILE *fs = popen(QFile::encodeName(cmd).data(), "r");
184  if (fs) {
185  QTextStream ts(fs, QIODevice::ReadOnly);
186  result = ts.readAll().trimmed();
187  pclose(fs);
188  }
189 #endif
190  setenv( "PATH", oldpath, 1/*overwrite*/ );
191  aValue.replace( nDollarPos, nEndPos-nDollarPos, result );
192  nDollarPos += result.length();
193  } else if( aValue[nDollarPos+1] != QLatin1Char('$') ) {
194  int nEndPos = nDollarPos+1;
195  // the next character is not $
196  QString aVarName;
197  if ( aValue[nEndPos] == QLatin1Char('{') ) {
198  while ( (nEndPos <= aValue.length()) && (aValue[nEndPos] != QLatin1Char('}')) )
199  nEndPos++;
200  nEndPos++;
201  aVarName = aValue.mid( nDollarPos+2, nEndPos-nDollarPos-3 );
202  } else {
203  while ( nEndPos <= aValue.length() &&
204  (aValue[nEndPos].isNumber() ||
205  aValue[nEndPos].isLetter() ||
206  aValue[nEndPos] == QLatin1Char('_') ) )
207  nEndPos++;
208  aVarName = aValue.mid( nDollarPos+1, nEndPos-nDollarPos-1 );
209  }
210  QString env;
211  if (!aVarName.isEmpty()) {
212 #ifdef Q_OS_WIN
213  if (aVarName == QLatin1String("HOME"))
214  env = QDir::homePath();
215  else
216 #endif
217  {
218  QByteArray pEnv = qgetenv( aVarName.toLatin1() );
219  if( !pEnv.isEmpty() )
220  // !!! Sergey A. Sukiyazov <corwin@micom.don.ru> !!!
221  // An environment variable may contain values in 8bit
222  // locale specified encoding or UTF8 encoding
223  env = KStringHandler::from8Bit( pEnv );
224  }
225  aValue.replace(nDollarPos, nEndPos-nDollarPos, env);
226  nDollarPos += env.length();
227  } else
228  aValue.remove( nDollarPos, nEndPos-nDollarPos );
229  } else {
230  // remove one of the dollar signs
231  aValue.remove( nDollarPos, 1 );
232  nDollarPos++;
233  }
234  nDollarPos = aValue.indexOf( QLatin1Char('$'), nDollarPos );
235  }
236 
237  return aValue;
238 }
239 
240 
241 KConfig::KConfig( const QString& file, OpenFlags mode,
242  const char* resourceType)
243  : d_ptr(new KConfigPrivate(KGlobal::mainComponent(), mode, resourceType))
244 {
245  d_ptr->changeFileName(file, resourceType); // set the local file name
246 
247  // read initial information off disk
248  reparseConfiguration();
249 }
250 
251 KConfig::KConfig( const KComponentData& componentData, const QString& file, OpenFlags mode,
252  const char* resourceType)
253  : d_ptr(new KConfigPrivate(componentData, mode, resourceType))
254 {
255  d_ptr->changeFileName(file, resourceType); // set the local file name
256 
257  // read initial information off disk
258  reparseConfiguration();
259 }
260 
261 KConfig::KConfig(const QString& file, const QString& backend, const char* resourceType)
262  : d_ptr(new KConfigPrivate(KGlobal::mainComponent(), SimpleConfig, resourceType))
263 {
264  d_ptr->mBackend = KConfigBackend::create(d_ptr->componentData, file, backend);
265  d_ptr->bDynamicBackend = false;
266  d_ptr->changeFileName(file, ""); // set the local file name
267 
268  // read initial information off disk
269  reparseConfiguration();
270 }
271 
272 KConfig::KConfig(KConfigPrivate &d)
273  : d_ptr(&d)
274 {
275 }
276 
277 KConfig::~KConfig()
278 {
279  Q_D(KConfig);
280  if (d->bDirty && d->mBackend.isUnique())
281  sync();
282  delete d;
283 }
284 
285 const KComponentData& KConfig::componentData() const
286 {
287  Q_D(const KConfig);
288  return d->componentData;
289 }
290 
291 QStringList KConfig::groupList() const
292 {
293  Q_D(const KConfig);
294  QSet<QString> groups;
295 
296  for (KEntryMap::ConstIterator entryMapIt( d->entryMap.constBegin() ); entryMapIt != d->entryMap.constEnd(); ++entryMapIt) {
297  const KEntryKey& key = entryMapIt.key();
298  const QByteArray group = key.mGroup;
299  if (key.mKey.isNull() && !group.isEmpty() && group != "<default>" && group != "$Version") {
300  const QString groupname = QString::fromUtf8(group);
301  groups << groupname.left(groupname.indexOf(QLatin1Char('\x1d')));
302  }
303  }
304 
305  return groups.toList();
306 }
307 
308 QStringList KConfigPrivate::groupList(const QByteArray& group) const
309 {
310  QByteArray theGroup = group + '\x1d';
311  QSet<QString> groups;
312 
313  for (KEntryMap::ConstIterator entryMapIt( entryMap.constBegin() ); entryMapIt != entryMap.constEnd(); ++entryMapIt) {
314  const KEntryKey& key = entryMapIt.key();
315  if (key.mKey.isNull() && key.mGroup.startsWith(theGroup)) {
316  const QString groupname = QString::fromUtf8(key.mGroup.mid(theGroup.length()));
317  groups << groupname.left(groupname.indexOf(QLatin1Char('\x1d')));
318  }
319  }
320 
321  return groups.toList();
322 }
323 
324 // List all sub groups, including subsubgroups
325 QSet<QByteArray> KConfigPrivate::allSubGroups(const QByteArray& parentGroup) const
326 {
327  QSet<QByteArray> groups;
328  QByteArray theGroup = parentGroup + '\x1d';
329  groups << parentGroup;
330 
331  for (KEntryMap::const_iterator entryMapIt = entryMap.begin(); entryMapIt != entryMap.end(); ++entryMapIt) {
332  const KEntryKey& key = entryMapIt.key();
333  if (key.mKey.isNull() && key.mGroup.startsWith(theGroup)) {
334  groups << key.mGroup;
335  }
336  }
337  return groups;
338 }
339 
340 bool KConfigPrivate::hasNonDeletedEntries(const QByteArray& group) const
341 {
342  const QSet<QByteArray> allGroups = allSubGroups(group);
343 
344  Q_FOREACH(const QByteArray& aGroup, allGroups) {
345  // Could be optimized, let's use the slow way for now
346  // Check for any non-deleted entry
347  if (!keyListImpl(aGroup).isEmpty())
348  return true;
349  }
350  return false;
351 }
352 
353 
354 QStringList KConfigPrivate::keyListImpl(const QByteArray& theGroup) const
355 {
356  QStringList keys;
357 
358  const KEntryMapConstIterator theEnd = entryMap.constEnd();
359  KEntryMapConstIterator it = entryMap.findEntry(theGroup);
360  if (it != theEnd) {
361  ++it; // advance past the special group entry marker
362 
363  QSet<QString> tmp;
364  for (; it != theEnd && it.key().mGroup == theGroup; ++it) {
365  const KEntryKey& key = it.key();
366  if (key.mGroup == theGroup && !key.mKey.isNull() && !it->bDeleted)
367  tmp << QString::fromUtf8(key.mKey);
368  }
369  keys = tmp.toList();
370  }
371 
372  return keys;
373 }
374 
375 QStringList KConfig::keyList(const QString& aGroup) const
376 {
377  Q_D(const KConfig);
378  const QByteArray theGroup(aGroup.isEmpty() ? "<default>" : aGroup.toUtf8());
379  return d->keyListImpl(theGroup);
380 }
381 
382 QMap<QString,QString> KConfig::entryMap(const QString& aGroup) const
383 {
384  Q_D(const KConfig);
385  QMap<QString, QString> theMap;
386  const QByteArray theGroup(aGroup.isEmpty() ? "<default>" : aGroup.toUtf8());
387 
388  const KEntryMapConstIterator theEnd = d->entryMap.constEnd();
389  KEntryMapConstIterator it = d->entryMap.findEntry(theGroup, 0, 0);
390  if (it != theEnd) {
391  ++it; // advance past the special group entry marker
392 
393  for (; it != theEnd && it.key().mGroup == theGroup; ++it) {
394  // leave the default values and deleted entries out
395  if (!it->bDeleted && !it.key().bDefault) {
396  const QString key = QString::fromUtf8(it.key().mKey.constData());
397  // the localized entry should come first, so don't overwrite it
398  // with the non-localized entry
399  if (!theMap.contains(key)) {
400  if (it->bExpand) {
401  theMap.insert(key,KConfigPrivate::expandString(QString::fromUtf8(it->mValue.constData())));
402  } else {
403  theMap.insert(key,QString::fromUtf8(it->mValue.constData()));
404  }
405  }
406  }
407  }
408  }
409 
410  return theMap;
411 }
412 
413 // TODO KDE5: return a bool value
414 void KConfig::sync()
415 {
416  Q_D(KConfig);
417 
418  if (isImmutable() || name().isEmpty()) {
419  // can't write to an immutable or anonymous file.
420  return;
421  }
422 
423  if (d->bDirty && d->mBackend) {
424  const QByteArray utf8Locale(locale().toUtf8());
425 
426  // Create the containing dir, maybe it wasn't there
427  d->mBackend->createEnclosing();
428 
429  // lock the local file
430  if (d->configState == ReadWrite && !d->lockLocal()) {
431  qWarning() << "couldn't lock local file";
432  return;
433  }
434 
435  // Rewrite global/local config only if there is a dirty entry in it.
436  bool writeGlobals = false;
437  bool writeLocals = false;
438  foreach (const KEntry& e, d->entryMap) {
439  if (e.bDirty) {
440  if (e.bGlobal) {
441  writeGlobals = true;
442  } else {
443  writeLocals = true;
444  }
445 
446  if (writeGlobals && writeLocals) {
447  break;
448  }
449  }
450  }
451 
452  d->bDirty = false; // will revert to true if a config write fails
453 
454  if (d->wantGlobals() && writeGlobals) {
455  KSharedPtr<KConfigBackend> tmp = KConfigBackend::create(componentData(), d->sGlobalFileName);
456  if (d->configState == ReadWrite && !tmp->lock(componentData())) {
457  qWarning() << "couldn't lock global file";
458  d->bDirty = true;
459  return;
460  }
461  if (!tmp->writeConfig(utf8Locale, d->entryMap, KConfigBackend::WriteGlobal, d->componentData)) {
462  d->bDirty = true;
463  // TODO KDE5: return false? (to tell the app that writing wasn't possible, e.g.
464  // config file is immutable or disk full)
465  }
466  if (tmp->isLocked()) {
467  tmp->unlock();
468  }
469  }
470 
471  if (writeLocals) {
472  if (!d->mBackend->writeConfig(utf8Locale, d->entryMap, KConfigBackend::WriteOptions(), d->componentData)) {
473  d->bDirty = true;
474  // TODO KDE5: return false? (to tell the app that writing wasn't possible, e.g.
475  // config file is immutable or disk full)
476  }
477  }
478  if (d->mBackend->isLocked()) {
479  d->mBackend->unlock();
480  }
481  }
482 }
483 
484 void KConfig::markAsClean()
485 {
486  Q_D(KConfig);
487  d->bDirty = false;
488 
489  // clear any dirty flags that entries might have set
490  const KEntryMapIterator theEnd = d->entryMap.end();
491  for (KEntryMapIterator it = d->entryMap.begin(); it != theEnd; ++it)
492  it->bDirty = false;
493 }
494 
495 void KConfig::checkUpdate(const QString &id, const QString &updateFile)
496 {
497  const KConfigGroup cg(this, "$Version");
498  const QString cfg_id = updateFile+QLatin1Char(':')+id;
499  const QStringList ids = cg.readEntry("update_info", QStringList());
500  if (!ids.contains(cfg_id)) {
501  KToolInvocation::kdeinitExecWait(QString::fromLatin1("kconf_update"), QStringList() << QString::fromLatin1("--check") << updateFile);
502  reparseConfiguration();
503  }
504 }
505 
506 KConfig* KConfig::copyTo(const QString &file, KConfig *config) const
507 {
508  Q_D(const KConfig);
509  if (!config)
510  config = new KConfig(componentData(), QString(), SimpleConfig);
511  config->d_func()->changeFileName(file, d->resourceType);
512  config->d_func()->entryMap = d->entryMap;
513  config->d_func()->bFileImmutable = false;
514 
515  const KEntryMapIterator theEnd = config->d_func()->entryMap.end();
516  for (KEntryMapIterator it = config->d_func()->entryMap.begin(); it != theEnd; ++it)
517  it->bDirty = true;
518  config->d_ptr->bDirty = true;
519 
520  return config;
521 }
522 
523 QString KConfig::name() const
524 {
525  Q_D(const KConfig);
526  return d->fileName;
527 }
528 
529 void KConfigPrivate::changeFileName(const QString& name, const char* type)
530 {
531  fileName = name;
532 
533  QString file;
534  if (name.isEmpty()) {
535  if (wantDefaults()) { // accessing default app-specific config "appnamerc"
536  const QString appName = componentData.aboutData()->appName();
537  if (!appName.isEmpty()) {
538  fileName = appName + QLatin1String("rc");
539  if (type && *type)
540  resourceType = type; // only change it if it's not empty
541  file = KStandardDirs::locateLocal(resourceType, fileName, false, componentData);
542  }
543  } else if (wantGlobals()) { // accessing "kdeglobals" - XXX used anywhere?
544  resourceType = "config";
545  fileName = QLatin1String("kdeglobals");
546  file = sGlobalFileName;
547  } // else anonymous config.
548  // KDE5: remove these magic overloads
549  } else if (QDir::isAbsolutePath(fileName)) {
550  fileName = KStandardDirs::realFilePath(fileName);
551  file = fileName;
552  } else {
553  if (type && *type)
554  resourceType = type; // only change it if it's not empty
555  file = KStandardDirs::locateLocal(resourceType, fileName, false, componentData);
556  }
557 
558  if (file.isEmpty()) {
559  openFlags = KConfig::SimpleConfig;
560  return;
561  }
562 
563  bSuppressGlobal = (file == sGlobalFileName);
564 
565  if (bDynamicBackend || !mBackend) // allow dynamic changing of backend
566  mBackend = KConfigBackend::create(componentData, file);
567  else
568  mBackend->setFilePath(file);
569 
570  configState = mBackend->accessMode();
571 }
572 
573 void KConfig::reparseConfiguration()
574 {
575  Q_D(KConfig);
576  if (d->fileName.isEmpty()) {
577  return;
578  }
579 
580  // Don't lose pending changes
581  if (!d->isReadOnly() && d->bDirty)
582  sync();
583 
584  d->entryMap.clear();
585 
586  d->bFileImmutable = false;
587 
588  // Parse all desired files from the least to the most specific.
589  if (d->wantGlobals())
590  d->parseGlobalFiles();
591 
592  d->parseConfigFiles();
593 }
594 
595 
596 QStringList KConfigPrivate::getGlobalFiles() const
597 {
598  const KStandardDirs *const dirs = componentData.dirs();
599  QStringList globalFiles;
600  foreach (const QString& dir1, dirs->findAllResources("config", QLatin1String("kdeglobals")))
601  globalFiles.push_front(dir1);
602  foreach (const QString& dir2, dirs->findAllResources("config", QLatin1String("system.kdeglobals")))
603  globalFiles.push_front(dir2);
604  if (!etc_kderc.isEmpty())
605  globalFiles.push_front(etc_kderc);
606  return globalFiles;
607 }
608 
609 void KConfigPrivate::parseGlobalFiles()
610 {
611  const QStringList globalFiles = getGlobalFiles();
612 // qDebug() << "parsing global files" << globalFiles;
613 
614  // TODO: can we cache the values in etc_kderc / other global files
615  // on a per-application basis?
616  const QByteArray utf8Locale = locale.toUtf8();
617  foreach(const QString& file, globalFiles) {
618  KConfigBackend::ParseOptions parseOpts = KConfigBackend::ParseGlobal|KConfigBackend::ParseExpansions;
619  if (file != sGlobalFileName)
620  parseOpts |= KConfigBackend::ParseDefaults;
621 
622  KSharedPtr<KConfigBackend> backend = KConfigBackend::create(componentData, file);
623  if ( backend->parseConfig( utf8Locale, entryMap, parseOpts) == KConfigBackend::ParseImmutable)
624  break;
625  }
626 }
627 
628 void KConfigPrivate::parseConfigFiles()
629 {
630  // can only read the file if there is a backend and a file name
631  if (mBackend && !fileName.isEmpty()) {
632 
633  bFileImmutable = false;
634 
635  QList<QString> files;
636  if (wantDefaults()) {
637  if (bSuppressGlobal) {
638  files = getGlobalFiles();
639  } else {
640  foreach (const QString& f, componentData.dirs()->findAllResources(
641  resourceType, fileName))
642  files.prepend(f);
643  }
644  } else {
645  files << mBackend->filePath();
646  }
647  if (!isSimple())
648  files = extraFiles.toList() + files;
649 
650 // qDebug() << "parsing local files" << files;
651 
652  const QByteArray utf8Locale = locale.toUtf8();
653  foreach(const QString& file, files) {
654  if (file == mBackend->filePath()) {
655  switch (mBackend->parseConfig(utf8Locale, entryMap, KConfigBackend::ParseExpansions)) {
656  case KConfigBackend::ParseOk:
657  break;
658  case KConfigBackend::ParseImmutable:
659  bFileImmutable = true;
660  break;
661  case KConfigBackend::ParseOpenError:
662  configState = KConfigBase::NoAccess;
663  break;
664  }
665  } else {
666  KSharedPtr<KConfigBackend> backend = KConfigBackend::create(componentData, file);
667  bFileImmutable = (backend->parseConfig(utf8Locale, entryMap,
668  KConfigBackend::ParseDefaults|KConfigBackend::ParseExpansions)
669  == KConfigBackend::ParseImmutable);
670  }
671 
672  if (bFileImmutable)
673  break;
674  }
675  if (componentData.dirs()->isRestrictedResource(resourceType, fileName))
676  bFileImmutable = true;
677  }
678 }
679 
680 KConfig::AccessMode KConfig::accessMode() const
681 {
682  Q_D(const KConfig);
683  return d->configState;
684 }
685 
686 void KConfig::addConfigSources(const QStringList& files)
687 {
688  Q_D(KConfig);
689  foreach(const QString& file, files) {
690  d->extraFiles.push(file);
691  }
692 
693  if (!files.isEmpty()) {
694  reparseConfiguration();
695  }
696 }
697 
698 QString KConfig::locale() const
699 {
700  Q_D(const KConfig);
701  return d->locale;
702 }
703 
704 bool KConfigPrivate::setLocale(const QString& aLocale)
705 {
706  if (aLocale != locale) {
707  locale = aLocale;
708  return true;
709  }
710  return false;
711 }
712 
713 bool KConfig::setLocale(const QString& locale)
714 {
715  Q_D(KConfig);
716  if (d->setLocale(locale)) {
717  reparseConfiguration();
718  return true;
719  }
720  return false;
721 }
722 
723 void KConfig::setReadDefaults(bool b)
724 {
725  Q_D(KConfig);
726  d->bReadDefaults = b;
727 }
728 
729 bool KConfig::readDefaults() const
730 {
731  Q_D(const KConfig);
732  return d->bReadDefaults;
733 }
734 
735 bool KConfig::isImmutable() const
736 {
737  Q_D(const KConfig);
738  return d->bFileImmutable;
739 }
740 
741 bool KConfig::isGroupImmutableImpl(const QByteArray& aGroup) const
742 {
743  Q_D(const KConfig);
744  return isImmutable() || d->entryMap.getEntryOption(aGroup, 0, 0, KEntryMap::EntryImmutable);
745 }
746 
747 #ifndef KDE_NO_DEPRECATED
748 void KConfig::setForceGlobal(bool b)
749 {
750  Q_D(KConfig);
751  d->bForceGlobal = b;
752 }
753 #endif
754 
755 #ifndef KDE_NO_DEPRECATED
756 bool KConfig::forceGlobal() const
757 {
758  Q_D(const KConfig);
759  return d->bForceGlobal;
760 }
761 #endif
762 
763 KConfigGroup KConfig::groupImpl(const QByteArray &group)
764 {
765  return KConfigGroup(this, group.constData());
766 }
767 
768 const KConfigGroup KConfig::groupImpl(const QByteArray &group) const
769 {
770  return KConfigGroup(this, group.constData());
771 }
772 
773 KEntryMap::EntryOptions convertToOptions(KConfig::WriteConfigFlags flags)
774 {
775  KEntryMap::EntryOptions options=0;
776 
777  if (flags&KConfig::Persistent)
778  options |= KEntryMap::EntryDirty;
779  if (flags&KConfig::Global)
780  options |= KEntryMap::EntryGlobal;
781  if (flags&KConfig::Localized)
782  options |= KEntryMap::EntryLocalized;
783  return options;
784 }
785 
786 void KConfig::deleteGroupImpl(const QByteArray &aGroup, WriteConfigFlags flags)
787 {
788  Q_D(KConfig);
789  KEntryMap::EntryOptions options = convertToOptions(flags)|KEntryMap::EntryDeleted;
790 
791  const QSet<QByteArray> groups = d->allSubGroups(aGroup);
792  foreach (const QByteArray& group, groups) {
793  const QStringList keys = d->keyListImpl(group);
794  foreach (const QString& _key, keys) {
795  const QByteArray &key = _key.toUtf8();
796  if (d->canWriteEntry(group, key.constData())) {
797  d->entryMap.setEntry(group, key, QByteArray(), options);
798  d->bDirty = true;
799  }
800  }
801  }
802 }
803 
804 bool KConfig::isConfigWritable(bool warnUser)
805 {
806  Q_D(KConfig);
807  bool allWritable = (d->mBackend.isNull()? false: d->mBackend->isWritable());
808 
809  if (warnUser && !allWritable) {
810  QString errorMsg;
811  if (!d->mBackend.isNull()) // TODO how can be it be null? Set errorMsg appropriately
812  errorMsg = d->mBackend->nonWritableErrorMessage();
813 
814  // Note: We don't ask the user if we should not ask this question again because we can't save the answer.
815  errorMsg += i18n("Please contact your system administrator.");
816  QString cmdToExec = KStandardDirs::findExe(QString::fromLatin1("kdialog"));
817  if (!cmdToExec.isEmpty() && componentData().isValid())
818  {
819  QProcess::execute(cmdToExec, QStringList()
820  << QString::fromLatin1("--title") << componentData().componentName()
821  << QString::fromLatin1("--msgbox") << errorMsg);
822  }
823  }
824 
825  d->configState = allWritable ? ReadWrite : ReadOnly; // update the read/write status
826 
827  return allWritable;
828 }
829 
830 bool KConfig::hasGroupImpl(const QByteArray& aGroup) const
831 {
832  Q_D(const KConfig);
833 
834  // No need to look for the actual group entry anymore, or for subgroups:
835  // a group exists if it contains any non-deleted entry.
836 
837  return d->hasNonDeletedEntries(aGroup);
838 }
839 
840 bool KConfigPrivate::canWriteEntry(const QByteArray& group, const char* key, bool isDefault) const
841 {
842  if (bFileImmutable ||
843  entryMap.getEntryOption(group, key, KEntryMap::SearchLocalized, KEntryMap::EntryImmutable))
844  return isDefault;
845  return true;
846 }
847 
848 void KConfigPrivate::putData( const QByteArray& group, const char* key,
849  const QByteArray& value, KConfigBase::WriteConfigFlags flags, bool expand)
850 {
851  KEntryMap::EntryOptions options = convertToOptions(flags);
852 
853  if (bForceGlobal)
854  options |= KEntryMap::EntryGlobal;
855  if (expand)
856  options |= KEntryMap::EntryExpansion;
857 
858  if (value.isNull()) // deleting entry
859  options |= KEntryMap::EntryDeleted;
860 
861  bool dirtied = entryMap.setEntry(group, key, value, options);
862  if (dirtied && (flags & KConfigBase::Persistent))
863  bDirty = true;
864 }
865 
866 QByteArray KConfigPrivate::lookupData(const QByteArray& group, const char* key,
867  KEntryMap::SearchFlags flags) const
868 {
869  if (bReadDefaults)
870  flags |= KEntryMap::SearchDefaults;
871  const KEntryMapConstIterator it = entryMap.findEntry(group, key, flags);
872  if (it == entryMap.constEnd())
873  return QByteArray();
874  return it->mValue;
875 }
876 
877 QString KConfigPrivate::lookupData(const QByteArray& group, const char* key,
878  KEntryMap::SearchFlags flags, bool *expand) const
879 {
880  if (bReadDefaults)
881  flags |= KEntryMap::SearchDefaults;
882  return entryMap.getEntry(group, key, QString(), flags, expand);
883 }
884 
885 void KConfig::virtual_hook(int /*id*/, void* /*data*/)
886 {
887  /* nothing */
888 }
889 
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Sat Jun 1 2013 12:05:01 by doxygen 1.8.1.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

Skip menu "KDECore"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.10.4 API Reference

Skip menu "kdelibs-4.10.4 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal