diff options
Diffstat (limited to 'kdecore/kconfig.cpp')
-rw-r--r-- | kdecore/kconfig.cpp | 367 |
1 files changed, 367 insertions, 0 deletions
diff --git a/kdecore/kconfig.cpp b/kdecore/kconfig.cpp new file mode 100644 index 000000000..4712415f4 --- /dev/null +++ b/kdecore/kconfig.cpp @@ -0,0 +1,367 @@ +/* + This file is part of the KDE libraries + 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. +*/ + +// $Id$ + +#include <config.h> + +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + +#include <stdlib.h> +#include <unistd.h> + +#include <qfileinfo.h> + +#include <kapplication.h> +#include "kconfigbackend.h" + +#include "kconfig.h" +#include "kglobal.h" +#include "kstandarddirs.h" +#include "kstaticdeleter.h" +#include <qtimer.h> + +KConfig::KConfig( const QString& fileName, + bool bReadOnly, bool bUseKderc, const char *resType ) + : KConfigBase(), bGroupImmutable(false), bFileImmutable(false), + bForceGlobal(false) +{ + // set the object's read-only status. + setReadOnly(bReadOnly); + + // for right now we will hardcode that we are using the INI + // back end driver. In the future this should be converted over to + // a object factory of some sorts. + KConfigINIBackEnd *aBackEnd = new KConfigINIBackEnd(this, + fileName, + resType, + bUseKderc); + + // set the object's back end pointer to this new backend + backEnd = aBackEnd; + + // read initial information off disk + reparseConfiguration(); + + // we let KStandardDirs add custom user config files. It will do + // this only once. So only the first call ever to this constructor + // will anything else than return here We have to reparse here as + // configuration files may appear after customized directories have + // been added. and the info they contain needs to be inserted into the + // config object. + // Since this makes only sense for config directories, addCustomized + // returns true only if new config directories appeared. + if (KGlobal::dirs()->addCustomized(this)) + reparseConfiguration(); +} + +KConfig::KConfig(KConfigBackEnd *aBackEnd, bool bReadOnly) + : bGroupImmutable(false), bFileImmutable(false), + bForceGlobal(false) +{ + setReadOnly(bReadOnly); + backEnd = aBackEnd; + reparseConfiguration(); +} + +KConfig::~KConfig() +{ + sync(); + + delete backEnd; +} + +void KConfig::rollback(bool bDeep) +{ + KConfigBase::rollback(bDeep); + + if (!bDeep) + return; // object's bDeep flag is set in KConfigBase method + + // clear any dirty flags that entries might have set + for (KEntryMapIterator aIt = aEntryMap.begin(); + aIt != aEntryMap.end(); ++aIt) + (*aIt).bDirty = false; +} + +QStringList KConfig::groupList() const +{ + QStringList retList; + + KEntryMapConstIterator aIt = aEntryMap.begin(); + KEntryMapConstIterator aEnd = aEntryMap.end(); + for (; aIt != aEnd; ++aIt) + { + while(aIt.key().mKey.isEmpty()) + { + QCString group = aIt.key().mGroup; + ++aIt; + while (true) + { + if (aIt == aEnd) + return retList; // done + + if (aIt.key().mKey.isEmpty()) + break; // Group is empty, next group + + if (!aIt.key().bDefault && !(*aIt).bDeleted) + { + if (group != "$Version") // Special case! + retList.append(QString::fromUtf8(group)); + break; // Group is non-empty, added, next group + } + ++aIt; + } + } + } + + return retList; +} + +QMap<QString, QString> KConfig::entryMap(const QString &pGroup) const +{ + QCString pGroup_utf = pGroup.utf8(); + KEntryKey groupKey( pGroup_utf, 0 ); + QMap<QString, QString> tmpMap; + + KEntryMapConstIterator aIt = aEntryMap.find(groupKey); + if (aIt == aEntryMap.end()) + return tmpMap; + ++aIt; // advance past special group entry marker + for (; aIt.key().mGroup == pGroup_utf && aIt != aEntryMap.end(); ++aIt) + { + // Leave the default values out && leave deleted entries out + if (!aIt.key().bDefault && !(*aIt).bDeleted) + tmpMap.insert(QString::fromUtf8(aIt.key().mKey), QString::fromUtf8((*aIt).mValue.data(), (*aIt).mValue.length())); + } + + return tmpMap; +} + +void KConfig::reparseConfiguration() +{ + // Don't lose pending changes + if (!isReadOnly() && backEnd && bDirty) + backEnd->sync(); + + aEntryMap.clear(); + + // add the "default group" marker to the map + KEntryKey groupKey("<default>", 0); + aEntryMap.insert(groupKey, KEntry()); + + bFileImmutable = false; + parseConfigFiles(); + bFileImmutable = bReadOnly; +} + +KEntryMap KConfig::internalEntryMap(const QString &pGroup) const +{ + QCString pGroup_utf = pGroup.utf8(); + KEntry aEntry; + KEntryMapConstIterator aIt; + KEntryKey aKey(pGroup_utf, 0); + KEntryMap tmpEntryMap; + + aIt = aEntryMap.find(aKey); + if (aIt == aEntryMap.end()) { + // the special group key is not in the map, + // so it must be an invalid group. Return + // an empty map. + return tmpEntryMap; + } + // we now have a pointer to the nodes we want to copy. + for (; aIt.key().mGroup == pGroup_utf && aIt != aEntryMap.end(); ++aIt) + { + tmpEntryMap.insert(aIt.key(), *aIt); + } + + return tmpEntryMap; +} + +void KConfig::putData(const KEntryKey &_key, const KEntry &_data, bool _checkGroup) +{ + if (bFileImmutable && !_key.bDefault) + return; + + // check to see if the special group key is present, + // and if not, put it in. + if (_checkGroup) + { + KEntryKey groupKey( _key.mGroup, 0); + KEntry &entry = aEntryMap[groupKey]; + bGroupImmutable = entry.bImmutable; + } + if (bGroupImmutable && !_key.bDefault) + return; + + // now either add or replace the data + KEntry &entry = aEntryMap[_key]; + bool immutable = entry.bImmutable; + if (immutable && !_key.bDefault) + return; + + entry = _data; + entry.bImmutable |= immutable; + entry.bGlobal |= bForceGlobal; // force to kdeglobals + + if (_key.bDefault) + { + // We have added the data as default value, + // add it as normal value as well. + KEntryKey key(_key); + key.bDefault = false; + aEntryMap[key] = _data; + } +} + +KEntry KConfig::lookupData(const KEntryKey &_key) const +{ + KEntryMapConstIterator aIt = aEntryMap.find(_key); + if (aIt != aEntryMap.end()) + { + const KEntry &entry = *aIt; + if (entry.bDeleted) + return KEntry(); + else + return entry; + } + else { + return KEntry(); + } +} + +bool KConfig::internalHasGroup(const QCString &group) const +{ + KEntryKey groupKey( group, 0); + + KEntryMapConstIterator aIt = aEntryMap.find(groupKey); + KEntryMapConstIterator aEnd = aEntryMap.end(); + + if (aIt == aEnd) + return false; + ++aIt; + for(; (aIt != aEnd); ++aIt) + { + if (aIt.key().mKey.isEmpty()) + break; + + if (!aIt.key().bDefault && !(*aIt).bDeleted) + return true; + } + return false; +} + +void KConfig::setFileWriteMode(int mode) +{ + backEnd->setFileWriteMode(mode); +} + +KLockFile::Ptr KConfig::lockFile(bool bGlobal) +{ + KConfigINIBackEnd *aBackEnd = dynamic_cast<KConfigINIBackEnd*>(backEnd); + if (!aBackEnd) return 0; + return aBackEnd->lockFile(bGlobal); +} + +void KConfig::checkUpdate(const QString &id, const QString &updateFile) +{ + QString oldGroup = group(); + setGroup("$Version"); + QString cfg_id = updateFile+":"+id; + QStringList ids = readListEntry("update_info"); + if (!ids.contains(cfg_id)) + { + QStringList args; + args << "--check" << updateFile; + KApplication::kdeinitExecWait("kconf_update", args); + reparseConfiguration(); + } + setGroup(oldGroup); +} + +KConfig* KConfig::copyTo(const QString &file, KConfig *config) const +{ + if (!config) + config = new KConfig(QString::null, false, false); + config->backEnd->changeFileName(file, "config", false); + config->setReadOnly(false); + config->bFileImmutable = false; + config->backEnd->mConfigState = ReadWrite; + + QStringList groups = groupList(); + for(QStringList::ConstIterator it = groups.begin(); + it != groups.end(); ++it) + { + QMap<QString, QString> map = entryMap(*it); + config->setGroup(*it); + for (QMap<QString,QString>::Iterator it2 = map.begin(); + it2 != map.end(); ++it2) + { + config->writeEntry(it2.key(), it2.data()); + } + + } + return config; +} + +void KConfig::virtual_hook( int id, void* data ) +{ KConfigBase::virtual_hook( id, data ); } + +static KStaticDeleter< QValueList<KSharedConfig*> > sd; +QValueList<KSharedConfig*> *KSharedConfig::s_list = 0; + +KSharedConfig::Ptr KSharedConfig::openConfig(const QString& fileName, bool readOnly, bool useKDEGlobals ) +{ + if (s_list) + { + for(QValueList<KSharedConfig*>::ConstIterator it = s_list->begin(); + it != s_list->end(); ++it) + { + if ((*it)->backEnd->fileName() == fileName && + (*it)->bReadOnly == readOnly && + (*it)->backEnd->useKDEGlobals == useKDEGlobals ) + return (*it); + } + } + return new KSharedConfig(fileName, readOnly, useKDEGlobals); +} + +KSharedConfig::KSharedConfig( const QString& fileName, bool readonly, bool usekdeglobals) + : KConfig(fileName, readonly, usekdeglobals) +{ + if (!s_list) + { + sd.setObject(s_list, new QValueList<KSharedConfig*>); + } + + s_list->append(this); +} + +KSharedConfig::~KSharedConfig() +{ + if ( s_list ) + s_list->remove(this); +} + +#include "kconfig.moc" |