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

KDECore

kconfig.cpp

Go to the documentation of this file.
00001 /*
00002    This file is part of the KDE libraries
00003    Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
00004    Copyright (c) 1999 Preston Brown <pbrown@kde.org>
00005    Copyright (c) 1997-1999 Matthias Kalle Dalheimer <kalle@kde.org>
00006 
00007    This library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Library General Public
00009    License as published by the Free Software Foundation; either
00010    version 2 of the License, or (at your option) any later version.
00011 
00012    This library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Library General Public License for more details.
00016 
00017    You should have received a copy of the GNU Library General Public License
00018    along with this library; see the file COPYING.LIB.  If not, write to
00019    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020    Boston, MA 02110-1301, USA.
00021 */
00022 
00023 #include "kconfig.h"
00024 #include "kconfig_p.h"
00025 
00026 #include <cstdlib>
00027 #include <fcntl.h>
00028 #include <unistd.h>
00029 
00030 #include "kconfigbackend.h"
00031 #include "kconfiggroup.h"
00032 #include <kstringhandler.h>
00033 #include <klocale.h>
00034 #include <kstandarddirs.h>
00035 #include <kurl.h>
00036 #include <kcomponentdata.h>
00037 #include <ktoolinvocation.h>
00038 #include <kaboutdata.h>
00039 #include <kdebug.h>
00040 
00041 #include <qbytearray.h>
00042 #include <qfile.h>
00043 #include <qdir.h>
00044 #include <qdatetime.h>
00045 #include <qrect.h>
00046 #include <qsize.h>
00047 #include <qcolor.h>
00048 #include <QtCore/QProcess>
00049 #include <QtCore/QPointer>
00050 #include <QtCore/QSet>
00051 #include <QtCore/QStack>
00052 
00053 bool KConfigPrivate::mappingsRegistered=false;
00054 
00055 KConfigPrivate::KConfigPrivate(const KComponentData &componentData_, KConfig::OpenFlags flags,
00056                                const char* resource)
00057     : openFlags(flags), resourceType(resource), mBackend(0),
00058       bDynamicBackend(true),  bDirty(false), bReadDefaults(false),
00059       bFileImmutable(false), bForceGlobal(false), bSuppressGlobal(false),
00060       componentData(componentData_), configState(KConfigBase::NoAccess)
00061 {
00062     sGlobalFileName = componentData.dirs()->saveLocation("config", QString(), false) + QLatin1String("kdeglobals");
00063 
00064     static int use_etc_kderc = -1;
00065     if (use_etc_kderc < 0)
00066         use_etc_kderc = getenv("KDE_SKIP_KDERC") != 0 ? 0 : 1; // for unit tests
00067     if (use_etc_kderc) {
00068 
00069         etc_kderc =
00070 #ifdef Q_WS_WIN
00071             QFile::decodeName( qgetenv("WINDIR") + "/kde4rc" );
00072 #else
00073             QLatin1String("/etc/kde4rc");
00074 #endif
00075         if (!KStandardDirs::checkAccess(etc_kderc, R_OK)) {
00076             etc_kderc.clear();
00077         }
00078     }
00079 
00080 //    if (!mappingsRegistered) {
00081 //        KEntryMap tmp;
00082 //        if (!etc_kderc.isEmpty()) {
00083 //            KSharedPtr<KConfigBackend> backend = KConfigBackend::create(componentData, etc_kderc, QLatin1String("INI"));
00084 //            backend->parseConfig( "en_US", tmp, KConfigBackend::ParseDefaults);
00085 //        }
00086 //        const QString kde4rc(QDir::home().filePath(".kde4rc"));
00087 //        if (KStandardDirs::checkAccess(kde4rc, R_OK)) {
00088 //            KSharedPtr<KConfigBackend> backend = KConfigBackend::create(componentData, kde4rc, QLatin1String("INI"));
00089 //            backend->parseConfig( "en_US", tmp, KConfigBackend::ParseOptions());
00090 //        }
00091 //        KConfigBackend::registerMappings(tmp);
00092 //        mappingsRegistered = true;
00093 //    }
00094 
00095     setLocale(KGlobal::hasLocale() ? KGlobal::locale()->language() : KLocale::defaultLanguage());
00096 }
00097 
00098 
00099 bool KConfigPrivate::lockLocal()
00100 {
00101     if (mBackend) {
00102         return mBackend->lock(componentData);
00103     }
00104     // anonymous object - pretend we locked it
00105     return true;
00106 }
00107 
00108 void KConfigPrivate::copyGroup(const QByteArray& source, const QByteArray& destination,
00109                                 KConfigGroup *otherGroup, KConfigBase::WriteConfigFlags flags) const
00110 {
00111     KEntryMap& otherMap = otherGroup->config()->d_ptr->entryMap;
00112     const int len = source.length();
00113     const bool sameName = (destination == source);
00114 
00115     // we keep this bool outside the foreach loop so that if
00116     // the group is empty, we don't end up marking the other config
00117     // as dirty erroneously
00118     bool dirtied = false;
00119 
00120     for (KEntryMap::ConstIterator entryMapIt( entryMap.constBegin() ); entryMapIt != entryMap.constEnd(); ++entryMapIt) {
00121         const QByteArray& group = entryMapIt.key().mGroup;
00122 
00123         if (!group.startsWith(source)) // nothing to do
00124             continue;
00125 
00126         // don't copy groups that start with the same prefix, but are not sub-groups
00127         if (group.length() > len && group[len] != '\x1d')
00128             continue;
00129 
00130         KEntryKey newKey = entryMapIt.key();
00131 
00132         if (flags & KConfigBase::Localized) {
00133             newKey.bLocal = true;
00134         }
00135 
00136         if (!sameName)
00137             newKey.mGroup.replace(0, len, destination);
00138 
00139         KEntry entry = entryMap[ entryMapIt.key() ];
00140         dirtied = entry.bDirty = flags & KConfigBase::Persistent;
00141 
00142         if (flags & KConfigBase::Global) {
00143             entry.bGlobal = true;
00144         }
00145 
00146         otherMap[newKey] = entry;
00147     }
00148 
00149     if (dirtied) {
00150         otherGroup->config()->d_ptr->bDirty = true;
00151     }
00152 }
00153 
00154 KConfig::KConfig( const QString& file, OpenFlags mode,
00155                   const char* resourceType)
00156   : d_ptr(new KConfigPrivate(KGlobal::mainComponent(), mode, resourceType))
00157 {
00158     d_ptr->changeFileName(file, resourceType); // set the local file name
00159 
00160     // read initial information off disk
00161     reparseConfiguration();
00162 }
00163 
00164 KConfig::KConfig( const KComponentData& componentData, const QString& file, OpenFlags mode,
00165                   const char* resourceType)
00166     : d_ptr(new KConfigPrivate(componentData, mode, resourceType))
00167 {
00168     d_ptr->changeFileName(file, resourceType); // set the local file name
00169 
00170     // read initial information off disk
00171     reparseConfiguration();
00172 }
00173 
00174 KConfig::KConfig(const QString& file, const QString& backend, const char* resourceType)
00175     : d_ptr(new KConfigPrivate(KGlobal::mainComponent(), SimpleConfig, resourceType))
00176 {
00177     d_ptr->mBackend = KConfigBackend::create(d_ptr->componentData, file, backend);
00178     d_ptr->bDynamicBackend = false;
00179     d_ptr->changeFileName(file, ""); // set the local file name
00180 
00181     // read initial information off disk
00182     reparseConfiguration();
00183 }
00184 
00185 KConfig::KConfig(KConfigPrivate &d)
00186     : d_ptr(&d)
00187 {
00188 }
00189 
00190 KConfig::~KConfig()
00191 {
00192     Q_D(KConfig);
00193     if (d->bDirty && d->mBackend.isUnique())
00194         sync();
00195     delete d;
00196 }
00197 
00198 const KComponentData& KConfig::componentData() const
00199 {
00200     Q_D(const KConfig);
00201     return d->componentData;
00202 }
00203 
00204 QStringList KConfig::groupList() const
00205 {
00206     Q_D(const KConfig);
00207     QSet<QString> groups;
00208 
00209     for (KEntryMap::ConstIterator entryMapIt( d->entryMap.constBegin() ); entryMapIt != d->entryMap.constEnd(); ++entryMapIt) {
00210         const KEntryKey& key = entryMapIt.key();    
00211         const QByteArray group = key.mGroup;
00212         if (key.mKey.isNull() && !group.isEmpty() && group != "<default>" && group != "$Version") {
00213             const QString groupname = QString::fromUtf8(group);
00214             groups << groupname.left(groupname.indexOf(QLatin1Char('\x1d')));
00215         }
00216     }
00217 
00218     return groups.toList();
00219 }
00220 
00221 QStringList KConfigPrivate::groupList(const QByteArray& group) const
00222 {
00223     QByteArray theGroup = group + '\x1d';
00224     QSet<QString> groups;
00225 
00226     for (KEntryMap::ConstIterator entryMapIt( entryMap.constBegin() ); entryMapIt != entryMap.constEnd(); ++entryMapIt) {
00227         const KEntryKey& key = entryMapIt.key();    
00228         if (key.mKey.isNull() && key.mGroup.startsWith(theGroup)) {
00229             const QString groupname = QString::fromUtf8(key.mGroup.mid(theGroup.length()));
00230             groups << groupname.left(groupname.indexOf(QLatin1Char('\x1d')));
00231         }
00232     }
00233 
00234     return groups.toList();
00235 }
00236 
00237 // List all sub groups, including subsubgroups
00238 QSet<QByteArray> KConfigPrivate::allSubGroups(const QByteArray& parentGroup) const
00239 {
00240     QSet<QByteArray> groups;
00241     QByteArray theGroup = parentGroup + '\x1d';
00242     groups << parentGroup;
00243 
00244     for (KEntryMap::const_iterator entryMapIt = entryMap.begin(); entryMapIt != entryMap.end(); ++entryMapIt) {
00245         const KEntryKey& key = entryMapIt.key();
00246         if (key.mKey.isNull() && key.mGroup.startsWith(theGroup)) {
00247             groups << key.mGroup;
00248         }
00249     }
00250     return groups;
00251 }
00252 
00253 bool KConfigPrivate::hasNonDeletedEntries(const QByteArray& group) const
00254 {
00255     const QSet<QByteArray> allGroups = allSubGroups(group);
00256 
00257     Q_FOREACH(const QByteArray& aGroup, allGroups) {
00258         // Could be optimized, let's use the slow way for now
00259         // Check for any non-deleted entry
00260         if (!keyListImpl(aGroup).isEmpty())
00261             return true;
00262     }
00263     return false;
00264 }
00265 
00266 
00267 QStringList KConfigPrivate::keyListImpl(const QByteArray& theGroup) const
00268 {
00269     QStringList keys;
00270 
00271     const KEntryMapConstIterator theEnd = entryMap.constEnd();
00272     KEntryMapConstIterator it = entryMap.findEntry(theGroup);
00273     if (it != theEnd) {
00274         ++it; // advance past the special group entry marker
00275 
00276         QSet<QString> tmp;
00277         for (; it != theEnd && it.key().mGroup == theGroup; ++it) {
00278             const KEntryKey& key = it.key();
00279             if (key.mGroup == theGroup && !key.mKey.isNull() && !it->bDeleted)
00280                 tmp << QString::fromUtf8(key.mKey);
00281         }
00282         keys = tmp.toList();
00283     }
00284 
00285     return keys;
00286 }
00287 
00288 QStringList KConfig::keyList(const QString& aGroup) const
00289 {
00290     Q_D(const KConfig);
00291     const QByteArray theGroup(aGroup.isEmpty() ? "<default>" : aGroup.toUtf8());
00292     return d->keyListImpl(theGroup);
00293 }
00294 
00295 QMap<QString,QString> KConfig::entryMap(const QString& aGroup) const
00296 {
00297     Q_D(const KConfig);
00298     QMap<QString, QString> theMap;
00299     const QByteArray theGroup(aGroup.isEmpty() ? "<default>" : aGroup.toUtf8());
00300 
00301     const KEntryMapConstIterator theEnd = d->entryMap.constEnd();
00302     KEntryMapConstIterator it = d->entryMap.findEntry(theGroup, 0, 0);
00303     if (it != theEnd) {
00304         ++it; // advance past the special group entry marker
00305 
00306         for (; it != theEnd && it.key().mGroup == theGroup; ++it) {
00307             // leave the default values and deleted entries out
00308             if (!it->bDeleted && !it.key().bDefault) {
00309                 const QString key = QString::fromUtf8(it.key().mKey.constData());
00310                 // the localized entry should come first, so don't overwrite it
00311                 // with the non-localized entry
00312                 if (!theMap.contains(key))
00313                     theMap.insert(key,QString::fromUtf8(it->mValue.constData()));
00314             }
00315         }
00316     }
00317 
00318     return theMap;
00319 }
00320 
00321 // TODO KDE5: return a bool value
00322 void KConfig::sync()
00323 {
00324     Q_D(KConfig);
00325 
00326     if (isImmutable() || name().isEmpty()) {
00327         // can't write to an immutable or anonymous file.
00328         return;
00329     }
00330 
00331     if (d->bDirty && d->mBackend) {
00332         const QByteArray utf8Locale(locale().toUtf8());
00333 
00334         // Create the containing dir, maybe it wasn't there
00335         d->mBackend->createEnclosing();
00336 
00337         // lock the local file
00338         if (d->configState == ReadWrite && !d->lockLocal()) {
00339             qWarning() << "couldn't lock local file";
00340             return;
00341         }
00342 
00343         // Rewrite global/local config only if there is a dirty entry in it.
00344         bool writeGlobals = false;
00345         bool writeLocals = false;
00346         foreach (const KEntry& e, d->entryMap) {
00347             if (e.bDirty) {
00348                 if (e.bGlobal) {
00349                     writeGlobals = true;
00350                 } else {
00351                     writeLocals = true;
00352                 }
00353 
00354                 if (writeGlobals && writeLocals) {
00355                     break;
00356                 }
00357             }
00358         }
00359 
00360         d->bDirty = false; // will revert to true if a config write fails
00361 
00362         if (d->wantGlobals() && writeGlobals) {
00363             KSharedPtr<KConfigBackend> tmp = KConfigBackend::create(componentData(), d->sGlobalFileName);
00364             if (d->configState == ReadWrite && !tmp->lock(componentData())) {
00365                 qWarning() << "couldn't lock global file";
00366                 return;
00367             }
00368             if (!tmp->writeConfig(utf8Locale, d->entryMap, KConfigBackend::WriteGlobal, d->componentData)) {
00369                 d->bDirty = true;
00370                 // TODO KDE5: return false? (to tell the app that writing wasn't possible, e.g.
00371                 // config file is immutable or disk full)
00372             }
00373             if (tmp->isLocked()) {
00374                 tmp->unlock();
00375             }
00376         }
00377 
00378         if (writeLocals) {
00379             if (!d->mBackend->writeConfig(utf8Locale, d->entryMap, KConfigBackend::WriteOptions(), d->componentData)) {
00380                 d->bDirty = true;
00381                 // TODO KDE5: return false? (to tell the app that writing wasn't possible, e.g.
00382                 // config file is immutable or disk full)
00383             }
00384         }
00385         if (d->mBackend->isLocked()) {
00386             d->mBackend->unlock();
00387         }
00388     }
00389 }
00390 
00391 void KConfig::markAsClean()
00392 {
00393     Q_D(KConfig);
00394     d->bDirty = false;
00395 
00396     // clear any dirty flags that entries might have set
00397     const KEntryMapIterator theEnd = d->entryMap.end();
00398     for (KEntryMapIterator it = d->entryMap.begin(); it != theEnd; ++it)
00399         it->bDirty = false;
00400 }
00401 
00402 void KConfig::checkUpdate(const QString &id, const QString &updateFile)
00403 {
00404     const KConfigGroup cg(this, "$Version");
00405     const QString cfg_id = updateFile+QLatin1Char(':')+id;
00406     const QStringList ids = cg.readEntry("update_info", QStringList());
00407     if (!ids.contains(cfg_id)) {
00408         KToolInvocation::kdeinitExecWait(QString::fromLatin1("kconf_update"), QStringList() << QString::fromLatin1("--check") << updateFile);
00409         reparseConfiguration();
00410     }
00411 }
00412 
00413 KConfig* KConfig::copyTo(const QString &file, KConfig *config) const
00414 {
00415     Q_D(const KConfig);
00416     if (!config)
00417         config = new KConfig(componentData(), QString(), SimpleConfig);
00418     config->d_func()->changeFileName(file, d->resourceType);
00419     config->d_func()->entryMap = d->entryMap;
00420     config->d_func()->bFileImmutable = false;
00421 
00422     const KEntryMapIterator theEnd = config->d_func()->entryMap.end();
00423     for (KEntryMapIterator it = config->d_func()->entryMap.begin(); it != theEnd; ++it)
00424         it->bDirty = true;
00425     config->d_ptr->bDirty = true;
00426 
00427     return config;
00428 }
00429 
00430 QString KConfig::name() const
00431 {
00432     Q_D(const KConfig);
00433     return d->fileName;
00434 }
00435 
00436 void KConfigPrivate::changeFileName(const QString& name, const char* type)
00437 {
00438     fileName = name;
00439 
00440     QString file;
00441     if (name.isEmpty()) {
00442         if (wantDefaults()) { // accessing default app-specific config "appnamerc"
00443             const QString appName = componentData.aboutData()->appName();
00444             if (!appName.isEmpty()) {
00445                 fileName = appName + QLatin1String("rc");
00446                 if (type && *type)
00447                     resourceType = type; // only change it if it's not empty
00448                 file = KStandardDirs::locateLocal(resourceType, fileName, false, componentData);
00449             }
00450         } else if (wantGlobals()) { // accessing "kdeglobals" - XXX used anywhere?
00451             resourceType = "config";
00452             fileName = QLatin1String("kdeglobals");
00453             file = sGlobalFileName;
00454         } // else anonymous config.
00455         // KDE5: remove these magic overloads
00456     } else if (QDir::isAbsolutePath(fileName)) {
00457         fileName = KStandardDirs::realFilePath(fileName);
00458         file = fileName;
00459     } else {
00460         if (type && *type)
00461             resourceType = type; // only change it if it's not empty
00462         file = KStandardDirs::locateLocal(resourceType, fileName, false, componentData);
00463     }
00464 
00465     if (file.isEmpty()) {
00466         openFlags = KConfig::SimpleConfig;
00467         return;
00468     }
00469 
00470     bSuppressGlobal = (file == sGlobalFileName);
00471 
00472     if (bDynamicBackend || !mBackend) // allow dynamic changing of backend
00473         mBackend = KConfigBackend::create(componentData, file);
00474     else
00475         mBackend->setFilePath(file);
00476 
00477     configState = mBackend->accessMode();
00478 }
00479 
00480 void KConfig::reparseConfiguration()
00481 {
00482     Q_D(KConfig);
00483     if (d->fileName.isEmpty()) {
00484         return;
00485     }
00486 
00487     // Don't lose pending changes
00488     if (!d->isReadOnly() && d->bDirty)
00489         sync();
00490 
00491     d->entryMap.clear();
00492 
00493     d->bFileImmutable = false;
00494 
00495     // Parse all desired files from the least to the most specific.
00496     if (d->wantGlobals())
00497         d->parseGlobalFiles();
00498 
00499     d->parseConfigFiles();
00500 }
00501 
00502 
00503 QStringList KConfigPrivate::getGlobalFiles() const
00504 {
00505     const KStandardDirs *const dirs = componentData.dirs();
00506     QStringList globalFiles;
00507     foreach (const QString& dir1, dirs->findAllResources("config", QLatin1String("kdeglobals")))
00508         globalFiles.push_front(dir1);
00509     foreach (const QString& dir2, dirs->findAllResources("config", QLatin1String("system.kdeglobals")))
00510         globalFiles.push_front(dir2);
00511     if (!etc_kderc.isEmpty())
00512         globalFiles.push_front(etc_kderc);
00513     return globalFiles;
00514 }
00515 
00516 void KConfigPrivate::parseGlobalFiles()
00517 {
00518     const QStringList globalFiles = getGlobalFiles();
00519 //    qDebug() << "parsing global files" << globalFiles;
00520 
00521     // TODO: can we cache the values in etc_kderc / other global files
00522     //       on a per-application basis?
00523     const QByteArray utf8Locale = locale.toUtf8();
00524     foreach(const QString& file, globalFiles) {
00525         KConfigBackend::ParseOptions parseOpts = KConfigBackend::ParseGlobal|KConfigBackend::ParseExpansions;
00526         if (file != sGlobalFileName)
00527             parseOpts |= KConfigBackend::ParseDefaults;
00528 
00529         KSharedPtr<KConfigBackend> backend = KConfigBackend::create(componentData, file);
00530         if ( backend->parseConfig( utf8Locale, entryMap, parseOpts) == KConfigBackend::ParseImmutable)
00531             break;
00532     }
00533 }
00534 
00535 void KConfigPrivate::parseConfigFiles()
00536 {
00537     // can only read the file if there is a backend and a file name
00538     if (mBackend && !fileName.isEmpty()) {
00539 
00540         bFileImmutable = false;
00541 
00542         QList<QString> files;
00543         if (wantDefaults()) {
00544             if (bSuppressGlobal) {
00545                 files = getGlobalFiles();
00546             } else {
00547                 foreach (const QString& f, componentData.dirs()->findAllResources(
00548                                                     resourceType, fileName))
00549                     files.prepend(f);
00550             }
00551         } else {
00552             files << mBackend->filePath();
00553         }
00554         if (!isSimple())
00555             files = extraFiles.toList() + files;
00556 
00557 //        qDebug() << "parsing local files" << files;
00558 
00559         const QByteArray utf8Locale = locale.toUtf8();
00560         foreach(const QString& file, files) {
00561             if (file == mBackend->filePath()) {
00562                 switch (mBackend->parseConfig(utf8Locale, entryMap, KConfigBackend::ParseExpansions)) {
00563                 case KConfigBackend::ParseOk:
00564                     break;
00565                 case KConfigBackend::ParseImmutable:
00566                     bFileImmutable = true;
00567                     break;
00568                 case KConfigBackend::ParseOpenError:
00569                     configState = KConfigBase::NoAccess;
00570                     break;
00571                 }
00572             } else {
00573                 KSharedPtr<KConfigBackend> backend = KConfigBackend::create(componentData, file);
00574                 bFileImmutable = (backend->parseConfig(utf8Locale, entryMap,
00575                                         KConfigBackend::ParseDefaults|KConfigBackend::ParseExpansions)
00576                                   == KConfigBackend::ParseImmutable);
00577             }
00578 
00579             if (bFileImmutable)
00580                 break;
00581         }
00582         if (componentData.dirs()->isRestrictedResource(resourceType, fileName))
00583             bFileImmutable = true;
00584     }
00585 }
00586 
00587 KConfig::AccessMode KConfig::accessMode() const
00588 {
00589     Q_D(const KConfig);
00590     return d->configState;
00591 }
00592 
00593 void KConfig::addConfigSources(const QStringList& files)
00594 {
00595     Q_D(KConfig);
00596     foreach(const QString& file, files) {
00597         d->extraFiles.push(file);
00598     }
00599 
00600     if (!files.isEmpty()) {
00601         reparseConfiguration();
00602     }
00603 }
00604 
00605 QString KConfig::locale() const
00606 {
00607     Q_D(const KConfig);
00608     return d->locale;
00609 }
00610 
00611 bool KConfigPrivate::setLocale(const QString& aLocale)
00612 {
00613     if (aLocale != locale) {
00614         locale = aLocale;
00615         return true;
00616     }
00617     return false;
00618 }
00619 
00620 bool KConfig::setLocale(const QString& locale)
00621 {
00622     Q_D(KConfig);
00623     if (d->setLocale(locale)) {
00624         reparseConfiguration();
00625         return true;
00626     }
00627     return false;
00628 }
00629 
00630 void KConfig::setReadDefaults(bool b)
00631 {
00632     Q_D(KConfig);
00633     d->bReadDefaults = b;
00634 }
00635 
00636 bool KConfig::readDefaults() const
00637 {
00638     Q_D(const KConfig);
00639     return d->bReadDefaults;
00640 }
00641 
00642 bool KConfig::isImmutable() const
00643 {
00644     Q_D(const KConfig);
00645     return d->bFileImmutable;
00646 }
00647 
00648 bool KConfig::isGroupImmutableImpl(const QByteArray& aGroup) const
00649 {
00650     Q_D(const KConfig);
00651     return isImmutable() || d->entryMap.getEntryOption(aGroup, 0, 0, KEntryMap::EntryImmutable);
00652 }
00653 
00654 #ifndef KDE_NO_DEPRECATED
00655 void KConfig::setForceGlobal(bool b)
00656 {
00657     Q_D(KConfig);
00658     d->bForceGlobal = b;
00659 }
00660 #endif
00661 
00662 #ifndef KDE_NO_DEPRECATED
00663 bool KConfig::forceGlobal() const
00664 {
00665     Q_D(const KConfig);
00666     return d->bForceGlobal;
00667 }
00668 #endif
00669 
00670 KConfigGroup KConfig::groupImpl(const QByteArray &group)
00671 {
00672     return KConfigGroup(this, group.constData());
00673 }
00674 
00675 const KConfigGroup KConfig::groupImpl(const QByteArray &group) const
00676 {
00677     return KConfigGroup(this, group.constData());
00678 }
00679 
00680 KEntryMap::EntryOptions convertToOptions(KConfig::WriteConfigFlags flags)
00681 {
00682     KEntryMap::EntryOptions options=0;
00683 
00684     if (flags&KConfig::Persistent)
00685         options |= KEntryMap::EntryDirty;
00686     if (flags&KConfig::Global)
00687         options |= KEntryMap::EntryGlobal;
00688     if (flags&KConfig::Localized)
00689         options |= KEntryMap::EntryLocalized;
00690     return options;
00691 }
00692 
00693 void KConfig::deleteGroupImpl(const QByteArray &aGroup, WriteConfigFlags flags)
00694 {
00695     Q_D(KConfig);
00696     KEntryMap::EntryOptions options = convertToOptions(flags)|KEntryMap::EntryDeleted;
00697 
00698     const QSet<QByteArray> groups = d->allSubGroups(aGroup);
00699     foreach (const QByteArray& group, groups) {
00700         const QStringList keys = d->keyListImpl(group);
00701         foreach (const QString& _key, keys) {
00702             const QByteArray &key = _key.toUtf8();
00703             if (d->canWriteEntry(group, key.constData())) {
00704                 d->entryMap.setEntry(group, key, QByteArray(), options);
00705                 d->bDirty = true;
00706             }
00707         }
00708     }
00709 }
00710 
00711 bool KConfig::isConfigWritable(bool warnUser)
00712 {
00713     Q_D(KConfig);
00714     bool allWritable = (d->mBackend.isNull()? false: d->mBackend->isWritable());
00715 
00716     if (warnUser && !allWritable) {
00717         QString errorMsg;
00718         if (!d->mBackend.isNull()) // TODO how can be it be null? Set errorMsg appropriately
00719             errorMsg = d->mBackend->nonWritableErrorMessage();
00720 
00721         // Note: We don't ask the user if we should not ask this question again because we can't save the answer.
00722         errorMsg += i18n("Please contact your system administrator.");
00723         QString cmdToExec = KStandardDirs::findExe(QString::fromLatin1("kdialog"));
00724         if (!cmdToExec.isEmpty() && componentData().isValid())
00725         {
00726             QProcess::execute(cmdToExec, QStringList()
00727                               << QString::fromLatin1("--title") << componentData().componentName()
00728                               << QString::fromLatin1("--msgbox") << errorMsg);
00729         }
00730     }
00731 
00732     d->configState = allWritable ?  ReadWrite : ReadOnly; // update the read/write status
00733 
00734     return allWritable;
00735 }
00736 
00737 bool KConfig::hasGroupImpl(const QByteArray& aGroup) const
00738 {
00739     Q_D(const KConfig);
00740 
00741     // No need to look for the actual group entry anymore, or for subgroups:
00742     // a group exists if it contains any non-deleted entry.
00743 
00744     return d->hasNonDeletedEntries(aGroup);
00745 }
00746 
00747 bool KConfigPrivate::canWriteEntry(const QByteArray& group, const char* key, bool isDefault) const
00748 {
00749     if (bFileImmutable ||
00750         entryMap.getEntryOption(group, key, KEntryMap::SearchLocalized, KEntryMap::EntryImmutable))
00751         return isDefault;
00752     return true;
00753 }
00754 
00755 void KConfigPrivate::putData( const QByteArray& group, const char* key,
00756                       const QByteArray& value, KConfigBase::WriteConfigFlags flags, bool expand)
00757 {
00758     KEntryMap::EntryOptions options = convertToOptions(flags);
00759 
00760     if (bForceGlobal)
00761         options |= KEntryMap::EntryGlobal;
00762     if (expand)
00763         options |= KEntryMap::EntryExpansion;
00764 
00765     if (value.isNull()) // deleting entry
00766         options |= KEntryMap::EntryDeleted;
00767 
00768     bool dirtied = entryMap.setEntry(group, key, value, options);
00769     if (dirtied && (flags & KConfigBase::Persistent))
00770         bDirty = true;
00771 }
00772 
00773 QByteArray KConfigPrivate::lookupData(const QByteArray& group, const char* key,
00774                                       KEntryMap::SearchFlags flags) const
00775 {
00776     if (bReadDefaults)
00777         flags |= KEntryMap::SearchDefaults;
00778     const KEntryMapConstIterator it = entryMap.findEntry(group, key, flags);
00779     if (it == entryMap.constEnd())
00780         return QByteArray();
00781     return it->mValue;
00782 }
00783 
00784 QString KConfigPrivate::lookupData(const QByteArray& group, const char* key,
00785                                    KEntryMap::SearchFlags flags, bool *expand) const
00786 {
00787     if (bReadDefaults)
00788         flags |= KEntryMap::SearchDefaults;
00789     return entryMap.getEntry(group, key, QString(), flags, expand);
00790 }
00791 
00792 void KConfig::virtual_hook(int /*id*/, void* /*data*/)
00793 {
00794     /* nothing */
00795 }
00796 

KDECore

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • 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
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal