diff options
author | Jenkins CI <null@kde.org> | 2013-12-18 00:45:18 +0000 |
---|---|---|
committer | Jenkins CI <null@kde.org> | 2013-12-18 00:45:18 +0000 |
commit | 867e7a50e6396338ab4fe9aa22ad141e4cd344d2 (patch) | |
tree | 1d6f8d6c912fa04dc268b5580bcfe696fa538743 /src/core/kconfig.cpp | |
parent | c38b88497a833e482e6892b72c8f52adec6de857 (diff) | |
download | kconfig-867e7a50e6396338ab4fe9aa22ad141e4cd344d2.tar.gz kconfig-867e7a50e6396338ab4fe9aa22ad141e4cd344d2.tar.bz2 |
Move kconfig code to the root directory.
Diffstat (limited to 'src/core/kconfig.cpp')
-rw-r--r-- | src/core/kconfig.cpp | 931 |
1 files changed, 931 insertions, 0 deletions
diff --git a/src/core/kconfig.cpp b/src/core/kconfig.cpp new file mode 100644 index 00000000..b311a366 --- /dev/null +++ b/src/core/kconfig.cpp @@ -0,0 +1,931 @@ +/* + This file is part of the KDE libraries + Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com> + Copyright (c) 1999 Preston Brown <pbrown@kde.org> + Copyright (c) 1997-1999 Matthias Kalle Dalheimer <kalle@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// Qt5 TODO: re-enable. No point in doing it before, it breaks on QString::fromUtf8(QByteArray), which exists in qt5. +#undef QT_NO_CAST_FROM_BYTEARRAY + +#include "kconfig.h" +#include "kconfig_p.h" + +#include <cstdlib> +#include <fcntl.h> + +#ifdef Q_OS_WIN +static inline FILE* popen(const char *cmd, const char *mode) { return _popen(cmd, mode); } +static inline int pclose(FILE* stream) { return _pclose(stream); } +#else +#include <unistd.h> +#endif + +#include "kconfigbackend.h" +#include "kconfiggroup.h" + +#include <qcoreapplication.h> +#include <qprocess.h> +#include <qstandardpaths.h> +#include <qbytearray.h> +#include <qfile.h> +#include <qlocale.h> +#include <qdir.h> +#include <QtCore/QProcess> +#include <QtCore/QSet> + +bool KConfigPrivate::mappingsRegistered=false; + +KConfigPrivate::KConfigPrivate(KConfig::OpenFlags flags, + QStandardPaths::StandardLocation resourceType) + : openFlags(flags), resourceType(resourceType), mBackend(0), + bDynamicBackend(true), bDirty(false), bReadDefaults(false), + bFileImmutable(false), bForceGlobal(false), bSuppressGlobal(false), + configState(KConfigBase::NoAccess) +{ + sGlobalFileName = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1String("/kdeglobals"); + + static int use_etc_kderc = -1; + if (use_etc_kderc < 0) + use_etc_kderc = !qEnvironmentVariableIsSet("KDE_SKIP_KDERC"); // for unit tests + if (use_etc_kderc) { + + etc_kderc = +#ifdef Q_OS_WIN + QFile::decodeName( qgetenv("WINDIR") + "/kde4rc" ); +#else + QLatin1String("/etc/kde4rc"); +#endif + if (!QFileInfo(etc_kderc).isReadable()) { + etc_kderc.clear(); + } + } + +// if (!mappingsRegistered) { +// KEntryMap tmp; +// if (!etc_kderc.isEmpty()) { +// QExplicitlySharedDataPointer<KConfigBackend> backend = KConfigBackend::create(etc_kderc, QLatin1String("INI")); +// backend->parseConfig( "en_US", tmp, KConfigBackend::ParseDefaults); +// } +// const QString kde4rc(QDir::home().filePath(".kde4rc")); +// if (KStandardDirs::checkAccess(kde4rc, R_OK)) { +// QExplicitlySharedDataPointer<KConfigBackend> backend = KConfigBackend::create(kde4rc, QLatin1String("INI")); +// backend->parseConfig( "en_US", tmp, KConfigBackend::ParseOptions()); +// } +// KConfigBackend::registerMappings(tmp); +// mappingsRegistered = true; +// } + +#if 0 // KDE4 code + setLocale(KLocale::global()->language()); +#else + setLocale(QLocale::system().name()); +#endif +} + + +bool KConfigPrivate::lockLocal() +{ + if (mBackend) { + return mBackend->lock(); + } + // anonymous object - pretend we locked it + return true; +} + +void KConfigPrivate::copyGroup(const QByteArray& source, const QByteArray& destination, + KConfigGroup *otherGroup, KConfigBase::WriteConfigFlags flags) const +{ + KEntryMap& otherMap = otherGroup->config()->d_ptr->entryMap; + const int len = source.length(); + const bool sameName = (destination == source); + + // we keep this bool outside the foreach loop so that if + // the group is empty, we don't end up marking the other config + // as dirty erroneously + bool dirtied = false; + + for (KEntryMap::ConstIterator entryMapIt( entryMap.constBegin() ); entryMapIt != entryMap.constEnd(); ++entryMapIt) { + const QByteArray& group = entryMapIt.key().mGroup; + + if (!group.startsWith(source)) // nothing to do + continue; + + // don't copy groups that start with the same prefix, but are not sub-groups + if (group.length() > len && group[len] != '\x1d') + continue; + + KEntryKey newKey = entryMapIt.key(); + + if (flags & KConfigBase::Localized) { + newKey.bLocal = true; + } + + if (!sameName) + newKey.mGroup.replace(0, len, destination); + + KEntry entry = entryMap[ entryMapIt.key() ]; + dirtied = entry.bDirty = flags & KConfigBase::Persistent; + + if (flags & KConfigBase::Global) { + entry.bGlobal = true; + } + + otherMap[newKey] = entry; + } + + if (dirtied) { + otherGroup->config()->d_ptr->bDirty = true; + } +} + +QString KConfigPrivate::expandString(const QString& value) +{ + QString aValue = value; + + // check for environment variables and make necessary translations + int nDollarPos = aValue.indexOf( QLatin1Char('$') ); + while( nDollarPos != -1 && nDollarPos+1 < aValue.length()) { + // there is at least one $ + if( aValue[nDollarPos+1] == QLatin1Char('(') ) { + int nEndPos = nDollarPos+1; + // the next character is not $ + while ( (nEndPos <= aValue.length()) && (aValue[nEndPos]!=QLatin1Char(')')) ) + nEndPos++; + nEndPos++; + QString cmd = aValue.mid( nDollarPos+2, nEndPos-nDollarPos-3 ); + + QString result; +#if 0 // Removed in KDE Frameworks 5. No such concept anymore. Just set your PATH. + QByteArray oldpath = qgetenv( "PATH" ); + QByteArray newpath; + if (KComponentData::hasMainComponent()) { + newpath = QFile::encodeName(KGlobal::dirs()->resourceDirs("exe").join(QChar::fromLatin1(KPATH_SEPARATOR))); + if (!newpath.isEmpty() && !oldpath.isEmpty()) + newpath += KPATH_SEPARATOR; + } + newpath += oldpath; + qputenv( "PATH", newpath); +#endif + +// FIXME: wince does not have pipes +#ifndef _WIN32_WCE + FILE *fs = popen(QFile::encodeName(cmd).data(), "r"); + if (fs) { + QTextStream ts(fs, QIODevice::ReadOnly); + result = ts.readAll().trimmed(); + pclose(fs); + } +#endif +#if 0 // Removed in KDE Frameworks 5, see above. + qputenv( "PATH", oldpath); +#endif + aValue.replace( nDollarPos, nEndPos-nDollarPos, result ); + nDollarPos += result.length(); + } else if( aValue[nDollarPos+1] != QLatin1Char('$') ) { + int nEndPos = nDollarPos+1; + // the next character is not $ + QString aVarName; + if ( aValue[nEndPos] == QLatin1Char('{') ) { + while ( (nEndPos <= aValue.length()) && (aValue[nEndPos] != QLatin1Char('}')) ) + nEndPos++; + nEndPos++; + aVarName = aValue.mid( nDollarPos+2, nEndPos-nDollarPos-3 ); + } else { + while ( nEndPos <= aValue.length() && + (aValue[nEndPos].isNumber() || + aValue[nEndPos].isLetter() || + aValue[nEndPos] == QLatin1Char('_') ) ) + nEndPos++; + aVarName = aValue.mid( nDollarPos+1, nEndPos-nDollarPos-1 ); + } + QString env; + if (!aVarName.isEmpty()) { +#ifdef Q_OS_WIN + if (aVarName == QLatin1String("HOME")) + env = QDir::homePath(); + else +#endif + { + QByteArray pEnv = qgetenv(aVarName.toLatin1().constData()); + if( !pEnv.isEmpty() ) + env = QString::fromLocal8Bit(pEnv.constData()); + } + aValue.replace(nDollarPos, nEndPos-nDollarPos, env); + nDollarPos += env.length(); + } else + aValue.remove( nDollarPos, nEndPos-nDollarPos ); + } else { + // remove one of the dollar signs + aValue.remove( nDollarPos, 1 ); + nDollarPos++; + } + nDollarPos = aValue.indexOf( QLatin1Char('$'), nDollarPos ); + } + + return aValue; +} + + +KConfig::KConfig(const QString& file, OpenFlags mode, + QStandardPaths::StandardLocation resourceType) + : d_ptr(new KConfigPrivate(mode, resourceType)) +{ + d_ptr->changeFileName(file); // set the local file name + + // read initial information off disk + reparseConfiguration(); +} + +KConfig::KConfig(const QString& file, const QString& backend, QStandardPaths::StandardLocation resourceType) + : d_ptr(new KConfigPrivate(SimpleConfig, resourceType)) +{ + d_ptr->mBackend = KConfigBackend::create(file, backend); + d_ptr->bDynamicBackend = false; + d_ptr->changeFileName(file); // set the local file name + + // read initial information off disk + reparseConfiguration(); +} + +KConfig::KConfig(KConfigPrivate &d) + : d_ptr(&d) +{ +} + +KConfig::~KConfig() +{ + Q_D(KConfig); + if (d->bDirty && (d->mBackend && d->mBackend->ref.load() == 1)) + sync(); + delete d; +} + +QStringList KConfig::groupList() const +{ + Q_D(const KConfig); + QSet<QString> groups; + + for (KEntryMap::ConstIterator entryMapIt( d->entryMap.constBegin() ); entryMapIt != d->entryMap.constEnd(); ++entryMapIt) { + const KEntryKey& key = entryMapIt.key(); + const QByteArray group = key.mGroup; + if (key.mKey.isNull() && !group.isEmpty() && group != "<default>" && group != "$Version") { + const QString groupname = QString::fromUtf8(group); + groups << groupname.left(groupname.indexOf(QLatin1Char('\x1d'))); + } + } + + return groups.toList(); +} + +QStringList KConfigPrivate::groupList(const QByteArray& group) const +{ + QByteArray theGroup = group + '\x1d'; + QSet<QString> groups; + + for (KEntryMap::ConstIterator entryMapIt( entryMap.constBegin() ); entryMapIt != entryMap.constEnd(); ++entryMapIt) { + const KEntryKey& key = entryMapIt.key(); + if (key.mKey.isNull() && key.mGroup.startsWith(theGroup)) { + const QString groupname = QString::fromUtf8(key.mGroup.mid(theGroup.length())); + groups << groupname.left(groupname.indexOf(QLatin1Char('\x1d'))); + } + } + + return groups.toList(); +} + +// List all sub groups, including subsubgroups +QSet<QByteArray> KConfigPrivate::allSubGroups(const QByteArray& parentGroup) const +{ + QSet<QByteArray> groups; + QByteArray theGroup = parentGroup + '\x1d'; + groups << parentGroup; + + for (KEntryMap::const_iterator entryMapIt = entryMap.begin(); entryMapIt != entryMap.end(); ++entryMapIt) { + const KEntryKey& key = entryMapIt.key(); + if (key.mKey.isNull() && key.mGroup.startsWith(theGroup)) { + groups << key.mGroup; + } + } + return groups; +} + +bool KConfigPrivate::hasNonDeletedEntries(const QByteArray& group) const +{ + const QSet<QByteArray> allGroups = allSubGroups(group); + + Q_FOREACH(const QByteArray& aGroup, allGroups) { + // Could be optimized, let's use the slow way for now + // Check for any non-deleted entry + if (!keyListImpl(aGroup).isEmpty()) + return true; + } + return false; +} + + +QStringList KConfigPrivate::keyListImpl(const QByteArray& theGroup) const +{ + QStringList keys; + + const KEntryMapConstIterator theEnd = entryMap.constEnd(); + KEntryMapConstIterator it = entryMap.findEntry(theGroup); + if (it != theEnd) { + ++it; // advance past the special group entry marker + + QSet<QString> tmp; + for (; it != theEnd && it.key().mGroup == theGroup; ++it) { + const KEntryKey& key = it.key(); + if (key.mGroup == theGroup && !key.mKey.isNull() && !it->bDeleted) + tmp << QString::fromUtf8(key.mKey); + } + keys = tmp.toList(); + } + + return keys; +} + +QStringList KConfig::keyList(const QString& aGroup) const +{ + Q_D(const KConfig); + const QByteArray theGroup(aGroup.isEmpty() ? "<default>" : aGroup.toUtf8()); + return d->keyListImpl(theGroup); +} + +QMap<QString,QString> KConfig::entryMap(const QString& aGroup) const +{ + Q_D(const KConfig); + QMap<QString, QString> theMap; + const QByteArray theGroup(aGroup.isEmpty() ? "<default>" : aGroup.toUtf8()); + + const KEntryMapConstIterator theEnd = d->entryMap.constEnd(); + KEntryMapConstIterator it = d->entryMap.findEntry(theGroup, 0, 0); + if (it != theEnd) { + ++it; // advance past the special group entry marker + + for (; it != theEnd && it.key().mGroup == theGroup; ++it) { + // leave the default values and deleted entries out + if (!it->bDeleted && !it.key().bDefault) { + const QString key = QString::fromUtf8(it.key().mKey.constData()); + // the localized entry should come first, so don't overwrite it + // with the non-localized entry + if (!theMap.contains(key)) { + if (it->bExpand) { + theMap.insert(key,KConfigPrivate::expandString(QString::fromUtf8(it->mValue.constData()))); + } else { + theMap.insert(key,QString::fromUtf8(it->mValue.constData())); + } + } + } + } + } + + return theMap; +} + +bool KConfig::sync() +{ + Q_D(KConfig); + + if (isImmutable() || name().isEmpty()) { + // can't write to an immutable or anonymous file. + return false; + } + + if (d->bDirty && d->mBackend) { + const QByteArray utf8Locale(locale().toUtf8()); + + // Create the containing dir, maybe it wasn't there + d->mBackend->createEnclosing(); + + // lock the local file + if (d->configState == ReadWrite && !d->lockLocal()) { + qWarning() << "couldn't lock local file"; + return false; + } + + // Rewrite global/local config only if there is a dirty entry in it. + bool writeGlobals = false; + bool writeLocals = false; + Q_FOREACH (const KEntry& e, d->entryMap) { + if (e.bDirty) { + if (e.bGlobal) { + writeGlobals = true; + } else { + writeLocals = true; + } + + if (writeGlobals && writeLocals) { + break; + } + } + } + + d->bDirty = false; // will revert to true if a config write fails + + if (d->wantGlobals() && writeGlobals) { + QExplicitlySharedDataPointer<KConfigBackend> tmp = KConfigBackend::create(d->sGlobalFileName); + if (d->configState == ReadWrite && !tmp->lock()) { + qWarning() << "couldn't lock global file"; + d->bDirty = true; + return false; + } + if (!tmp->writeConfig(utf8Locale, d->entryMap, KConfigBackend::WriteGlobal)) { + d->bDirty = true; + } + if (tmp->isLocked()) { + tmp->unlock(); + } + } + + if (writeLocals) { + if (!d->mBackend->writeConfig(utf8Locale, d->entryMap, KConfigBackend::WriteOptions())) { + d->bDirty = true; + } + } + if (d->mBackend->isLocked()) { + d->mBackend->unlock(); + } + } + return !d->bDirty; +} + +void KConfig::markAsClean() +{ + Q_D(KConfig); + d->bDirty = false; + + // clear any dirty flags that entries might have set + const KEntryMapIterator theEnd = d->entryMap.end(); + for (KEntryMapIterator it = d->entryMap.begin(); it != theEnd; ++it) + it->bDirty = false; +} + +bool KConfig::isDirty() const +{ + Q_D(const KConfig); + return d->bDirty; +} + +void KConfig::checkUpdate(const QString &id, const QString &updateFile) +{ + const KConfigGroup cg(this, "$Version"); + const QString cfg_id = updateFile+QLatin1Char(':')+id; + const QStringList ids = cg.readEntry("update_info", QStringList()); + if (!ids.contains(cfg_id)) { +#if 0 + KToolInvocation::kdeinitExecWait(QString::fromLatin1("kconf_update"), QStringList() << QString::fromLatin1("--check") << updateFile); +#else + QProcess::execute(QString::fromLatin1("kconf_update"), QStringList() << QString::fromLatin1("--check") << updateFile); +#endif + reparseConfiguration(); + } +} + +KConfig* KConfig::copyTo(const QString &file, KConfig *config) const +{ + Q_D(const KConfig); + if (!config) + config = new KConfig(QString(), SimpleConfig, d->resourceType); + config->d_func()->changeFileName(file); + config->d_func()->entryMap = d->entryMap; + config->d_func()->bFileImmutable = false; + + const KEntryMapIterator theEnd = config->d_func()->entryMap.end(); + for (KEntryMapIterator it = config->d_func()->entryMap.begin(); it != theEnd; ++it) + it->bDirty = true; + config->d_ptr->bDirty = true; + + return config; +} + +QString KConfig::name() const +{ + Q_D(const KConfig); + return d->fileName; +} + +Q_GLOBAL_STATIC(QString, globalMainConfigName) + +void KConfig::setMainConfigName(const QString& str) +{ + *globalMainConfigName() = str; +} + +QString KConfig::mainConfigName() +{ + // --config on the command line overrides everything else + const QStringList args = QCoreApplication::arguments(); + for (int i = 1; i < args.count() ; ++i) { + if (args.at(i) == QLatin1String("--config") && i < args.count()-1) { + return args.at(i+1); + } + } + const QString globalName = *globalMainConfigName(); + if (!globalName.isEmpty()) + return globalName; + + QString appName = QCoreApplication::applicationName(); + return appName + QLatin1String("rc"); +} + +void KConfigPrivate::changeFileName(const QString& name) +{ + fileName = name; + + QString file; + if (name.isEmpty()) { + if (wantDefaults()) { // accessing default app-specific config "appnamerc" + fileName = KConfig::mainConfigName(); + file = QStandardPaths::writableLocation(resourceType) + QLatin1Char('/') + fileName; + } else if (wantGlobals()) { // accessing "kdeglobals" - XXX used anywhere? + resourceType = QStandardPaths::GenericConfigLocation; + fileName = QLatin1String("kdeglobals"); + file = sGlobalFileName; + } else { + // anonymous config + openFlags = KConfig::SimpleConfig; + return; + } + } else if (QDir::isAbsolutePath(fileName)) { + fileName = QFileInfo(fileName).canonicalFilePath(); + if (fileName.isEmpty()) // file doesn't exist (yet) + fileName = name; + file = fileName; + } else { + file = QStandardPaths::writableLocation(resourceType) + QLatin1Char('/') + fileName; + } + + Q_ASSERT(!file.isEmpty()); + +#ifndef Q_OS_WIN + bSuppressGlobal = (file == sGlobalFileName); +#else + bSuppressGlobal = (file.compare(sGlobalFileName, Qt::CaseInsensitive) == 0); +#endif + + if (bDynamicBackend || !mBackend) // allow dynamic changing of backend + mBackend = KConfigBackend::create(file); + else + mBackend->setFilePath(file); + + configState = mBackend->accessMode(); +} + +void KConfig::reparseConfiguration() +{ + Q_D(KConfig); + if (d->fileName.isEmpty()) { + return; + } + + // Don't lose pending changes + if (!d->isReadOnly() && d->bDirty) + sync(); + + d->entryMap.clear(); + + d->bFileImmutable = false; + + // Parse all desired files from the least to the most specific. + if (d->wantGlobals()) + d->parseGlobalFiles(); + + d->parseConfigFiles(); +} + + +QStringList KConfigPrivate::getGlobalFiles() const +{ + QStringList globalFiles; + Q_FOREACH (const QString& dir1, QStandardPaths::locateAll(QStandardPaths::GenericConfigLocation, QLatin1String("kdeglobals"))) + globalFiles.push_front(dir1); + Q_FOREACH (const QString& dir2, QStandardPaths::locateAll(QStandardPaths::GenericConfigLocation, QLatin1String("system.kdeglobals"))) + globalFiles.push_front(dir2); + if (!etc_kderc.isEmpty()) + globalFiles.push_front(etc_kderc); + return globalFiles; +} + +void KConfigPrivate::parseGlobalFiles() +{ + const QStringList globalFiles = getGlobalFiles(); +// qDebug() << "parsing global files" << globalFiles; + + // TODO: can we cache the values in etc_kderc / other global files + // on a per-application basis? + const QByteArray utf8Locale = locale.toUtf8(); + Q_FOREACH(const QString& file, globalFiles) { + KConfigBackend::ParseOptions parseOpts = KConfigBackend::ParseGlobal|KConfigBackend::ParseExpansions; +#ifndef Q_OS_WIN + if (file != sGlobalFileName) +#else + if (file.compare(sGlobalFileName, Qt::CaseInsensitive) != 0) +#endif + parseOpts |= KConfigBackend::ParseDefaults; + + QExplicitlySharedDataPointer<KConfigBackend> backend = KConfigBackend::create(file); + if ( backend->parseConfig( utf8Locale, entryMap, parseOpts) == KConfigBackend::ParseImmutable) + break; + } +} + +void KConfigPrivate::parseConfigFiles() +{ + // can only read the file if there is a backend and a file name + if (mBackend && !fileName.isEmpty()) { + + bFileImmutable = false; + + QList<QString> files; + if (wantDefaults()) { + if (bSuppressGlobal) { + files = getGlobalFiles(); + } else { + if (QDir::isAbsolutePath(fileName)) { + files << fileName; + } else { + Q_FOREACH (const QString& f, QStandardPaths::locateAll(resourceType, fileName)) + files.prepend(f); + } + } + } else { + files << mBackend->filePath(); + } + if (!isSimple()) + files = extraFiles.toList() + files; + +// qDebug() << "parsing local files" << files; + + const QByteArray utf8Locale = locale.toUtf8(); + foreach(const QString& file, files) { +#ifndef Q_OS_WIN + if (file == mBackend->filePath()) { +#else + if (file.compare(mBackend->filePath(), Qt::CaseInsensitive) == 0) { +#endif + switch (mBackend->parseConfig(utf8Locale, entryMap, KConfigBackend::ParseExpansions)) { + case KConfigBackend::ParseOk: + break; + case KConfigBackend::ParseImmutable: + bFileImmutable = true; + break; + case KConfigBackend::ParseOpenError: + configState = KConfigBase::NoAccess; + break; + } + } else { + QExplicitlySharedDataPointer<KConfigBackend> backend = KConfigBackend::create(file); + bFileImmutable = (backend->parseConfig(utf8Locale, entryMap, + KConfigBackend::ParseDefaults|KConfigBackend::ParseExpansions) + == KConfigBackend::ParseImmutable); + } + + if (bFileImmutable) + break; + } +#pragma message("TODO: enable kiosk feature again (resource restrictions), but without KStandardDirs... Needs a class in the kconfig framework.") +#if 0 + if (componentData.dirs()->isRestrictedResource(resourceType, fileName)) + bFileImmutable = true; +#endif + } +} + +KConfig::AccessMode KConfig::accessMode() const +{ + Q_D(const KConfig); + return d->configState; +} + +void KConfig::addConfigSources(const QStringList& files) +{ + Q_D(KConfig); + Q_FOREACH(const QString& file, files) { + d->extraFiles.push(file); + } + + if (!files.isEmpty()) { + reparseConfiguration(); + } +} + +QString KConfig::locale() const +{ + Q_D(const KConfig); + return d->locale; +} + +bool KConfigPrivate::setLocale(const QString& aLocale) +{ + if (aLocale != locale) { + locale = aLocale; + return true; + } + return false; +} + +bool KConfig::setLocale(const QString& locale) +{ + Q_D(KConfig); + if (d->setLocale(locale)) { + reparseConfiguration(); + return true; + } + return false; +} + +void KConfig::setReadDefaults(bool b) +{ + Q_D(KConfig); + d->bReadDefaults = b; +} + +bool KConfig::readDefaults() const +{ + Q_D(const KConfig); + return d->bReadDefaults; +} + +bool KConfig::isImmutable() const +{ + Q_D(const KConfig); + return d->bFileImmutable; +} + +bool KConfig::isGroupImmutableImpl(const QByteArray& aGroup) const +{ + Q_D(const KConfig); + return isImmutable() || d->entryMap.getEntryOption(aGroup, 0, 0, KEntryMap::EntryImmutable); +} + +#ifndef KDE_NO_DEPRECATED +void KConfig::setForceGlobal(bool b) +{ + Q_D(KConfig); + d->bForceGlobal = b; +} +#endif + +#ifndef KDE_NO_DEPRECATED +bool KConfig::forceGlobal() const +{ + Q_D(const KConfig); + return d->bForceGlobal; +} +#endif + +KConfigGroup KConfig::groupImpl(const QByteArray &group) +{ + return KConfigGroup(this, group.constData()); +} + +const KConfigGroup KConfig::groupImpl(const QByteArray &group) const +{ + return KConfigGroup(this, group.constData()); +} + +KEntryMap::EntryOptions convertToOptions(KConfig::WriteConfigFlags flags) +{ + KEntryMap::EntryOptions options=0; + + if (flags&KConfig::Persistent) + options |= KEntryMap::EntryDirty; + if (flags&KConfig::Global) + options |= KEntryMap::EntryGlobal; + if (flags&KConfig::Localized) + options |= KEntryMap::EntryLocalized; + return options; +} + +void KConfig::deleteGroupImpl(const QByteArray &aGroup, WriteConfigFlags flags) +{ + Q_D(KConfig); + KEntryMap::EntryOptions options = convertToOptions(flags)|KEntryMap::EntryDeleted; + + const QSet<QByteArray> groups = d->allSubGroups(aGroup); + Q_FOREACH (const QByteArray& group, groups) { + const QStringList keys = d->keyListImpl(group); + Q_FOREACH (const QString& _key, keys) { + const QByteArray &key = _key.toUtf8(); + if (d->canWriteEntry(group, key.constData())) { + d->entryMap.setEntry(group, key, QByteArray(), options); + d->bDirty = true; + } + } + } +} + +bool KConfig::isConfigWritable(bool warnUser) +{ + Q_D(KConfig); + bool allWritable = (d->mBackend ? d->mBackend->isWritable() : false); + + if (warnUser && !allWritable) { + QString errorMsg; + if (d->mBackend) // TODO how can be it be null? Set errorMsg appropriately + errorMsg = d->mBackend->nonWritableErrorMessage(); + + // Note: We don't ask the user if we should not ask this question again because we can't save the answer. + errorMsg += QCoreApplication::translate("KConfig", "Please contact your system administrator."); + QString cmdToExec = QStandardPaths::findExecutable(QString::fromLatin1("kdialog")); + if (!cmdToExec.isEmpty()) + { + QProcess::execute(cmdToExec, QStringList() + << QString::fromLatin1("--title") << QCoreApplication::applicationName() + << QString::fromLatin1("--msgbox") << errorMsg); + } + } + + d->configState = allWritable ? ReadWrite : ReadOnly; // update the read/write status + + return allWritable; +} + +bool KConfig::hasGroupImpl(const QByteArray& aGroup) const +{ + Q_D(const KConfig); + + // No need to look for the actual group entry anymore, or for subgroups: + // a group exists if it contains any non-deleted entry. + + return d->hasNonDeletedEntries(aGroup); +} + +bool KConfigPrivate::canWriteEntry(const QByteArray& group, const char* key, bool isDefault) const +{ + if (bFileImmutable || + entryMap.getEntryOption(group, key, KEntryMap::SearchLocalized, KEntryMap::EntryImmutable)) + return isDefault; + return true; +} + +void KConfigPrivate::putData( const QByteArray& group, const char* key, + const QByteArray& value, KConfigBase::WriteConfigFlags flags, bool expand) +{ + KEntryMap::EntryOptions options = convertToOptions(flags); + + if (bForceGlobal) + options |= KEntryMap::EntryGlobal; + if (expand) + options |= KEntryMap::EntryExpansion; + + if (value.isNull()) // deleting entry + options |= KEntryMap::EntryDeleted; + + bool dirtied = entryMap.setEntry(group, key, value, options); + if (dirtied && (flags & KConfigBase::Persistent)) + bDirty = true; +} + +void KConfigPrivate::revertEntry(const QByteArray& group, const char* key) +{ + bool dirtied = entryMap.revertEntry(group, key); + if (dirtied) + bDirty = true; +} + +QByteArray KConfigPrivate::lookupData(const QByteArray& group, const char* key, + KEntryMap::SearchFlags flags) const +{ + if (bReadDefaults) + flags |= KEntryMap::SearchDefaults; + const KEntryMapConstIterator it = entryMap.findEntry(group, key, flags); + if (it == entryMap.constEnd()) + return QByteArray(); + return it->mValue; +} + +QString KConfigPrivate::lookupData(const QByteArray& group, const char* key, + KEntryMap::SearchFlags flags, bool *expand) const +{ + if (bReadDefaults) + flags |= KEntryMap::SearchDefaults; + return entryMap.getEntry(group, key, QString(), flags, expand); +} + +QStandardPaths::StandardLocation KConfig::locationType() const +{ + Q_D(const KConfig); + return d->resourceType; +} + +void KConfig::virtual_hook(int /*id*/, void* /*data*/) +{ + /* nothing */ +} |