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 */ +} | 
