You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdelibs/kdecore/kconfig.cpp

368 lines
9.5 KiB

/*
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 <tqfileinfo.h>
#include <kapplication.h>
#include "kconfigbackend.h"
#include "kconfig.h"
#include "kglobal.h"
#include "kstandarddirs.h"
#include "kstaticdeleter.h"
#include <tqtimer.h>
KConfig::KConfig( const TQString& 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;
}
TQStringList KConfig::groupList() const
{
TQStringList retList;
KEntryMapConstIterator aIt = aEntryMap.begin();
KEntryMapConstIterator aEnd = aEntryMap.end();
for (; aIt != aEnd; ++aIt)
{
while(aIt.key().mKey.isEmpty())
{
TQCString 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(TQString::fromUtf8(group));
break; // Group is non-empty, added, next group
}
++aIt;
}
}
}
return retList;
}
TQMap<TQString, TQString> KConfig::entryMap(const TQString &pGroup) const
{
TQCString pGroup_utf = pGroup.utf8();
KEntryKey groupKey( pGroup_utf, 0 );
TQMap<TQString, TQString> 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(TQString::fromUtf8(aIt.key().mKey), TQString::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 TQString &pGroup) const
{
TQCString 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 TQCString &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 TQString &id, const TQString &updateFile)
{
TQString oldGroup = group();
setGroup("$Version");
TQString cfg_id = updateFile+":"+id;
TQStringList ids = readListEntry("update_info");
if (!ids.contains(cfg_id))
{
TQStringList args;
args << "--check" << updateFile;
KApplication::tdeinitExecWait("kconf_update", args);
reparseConfiguration();
}
setGroup(oldGroup);
}
KConfig* KConfig::copyTo(const TQString &file, KConfig *config) const
{
if (!config)
config = new KConfig(TQString::null, false, false);
config->backEnd->changeFileName(file, "config", false);
config->setReadOnly(false);
config->bFileImmutable = false;
config->backEnd->mConfigState = ReadWrite;
TQStringList groups = groupList();
for(TQStringList::ConstIterator it = groups.begin();
it != groups.end(); ++it)
{
TQMap<TQString, TQString> map = entryMap(*it);
config->setGroup(*it);
for (TQMap<TQString,TQString>::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< TQValueList<KSharedConfig*> > sd;
TQValueList<KSharedConfig*> *KSharedConfig::s_list = 0;
KSharedConfig::Ptr KSharedConfig::openConfig(const TQString& fileName, bool readOnly, bool useKDEGlobals )
{
if (s_list)
{
for(TQValueList<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 TQString& fileName, bool readonly, bool usekdeglobals)
: KConfig(fileName, readonly, usekdeglobals)
{
if (!s_list)
{
sd.setObject(s_list, new TQValueList<KSharedConfig*>);
}
s_list->append(this);
}
KSharedConfig::~KSharedConfig()
{
if ( s_list )
s_list->remove(this);
}
#include "kconfig.moc"