aboutsummaryrefslogtreecommitdiff
path: root/tier1/kconfig/src/core/kconfiggroup.cpp
diff options
context:
space:
mode:
authorJenkins CI <null@kde.org>2013-12-18 00:45:18 +0000
committerJenkins CI <null@kde.org>2013-12-18 00:45:18 +0000
commitc38b88497a833e482e6892b72c8f52adec6de857 (patch)
tree8c2d4b788cf54ab2179ffe53515d276feaeba2d1 /tier1/kconfig/src/core/kconfiggroup.cpp
downloadkconfig-c38b88497a833e482e6892b72c8f52adec6de857.tar.gz
kconfig-c38b88497a833e482e6892b72c8f52adec6de857.tar.bz2
Initial import from the monolithic kdelibs.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the techbase wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://community.kde.org/Frameworks/GitOldHistory If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, kdelibs frameworks branch, at commit 162066dbbecde401a7347a1cff4fe72a9c919f58
Diffstat (limited to 'tier1/kconfig/src/core/kconfiggroup.cpp')
-rw-r--r--tier1/kconfig/src/core/kconfiggroup.cpp1243
1 files changed, 1243 insertions, 0 deletions
diff --git a/tier1/kconfig/src/core/kconfiggroup.cpp b/tier1/kconfig/src/core/kconfiggroup.cpp
new file mode 100644
index 00000000..ab7d494f
--- /dev/null
+++ b/tier1/kconfig/src/core/kconfiggroup.cpp
@@ -0,0 +1,1243 @@
+/*
+ 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 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 "kconfiggroup.h"
+#include "kconfiggroup_p.h"
+
+#include "kconfig.h"
+#include "kconfig_p.h"
+#include "ksharedconfig.h"
+#include "kconfigdata.h"
+
+#include <QtCore/QDate>
+#include <QtCore/QSharedData>
+#include <QtCore/QFile>
+#include <QtCore/QPoint>
+#include <QtCore/QRect>
+#include <QtCore/QString>
+#include <QtCore/QTextStream>
+#include <QtCore/QDir>
+#include <QtCore/QUrl>
+
+#include <stdlib.h>
+
+class KConfigGroupPrivate : public QSharedData
+{
+ public:
+ KConfigGroupPrivate(KConfig* owner, bool isImmutable, bool isConst, const QByteArray &name)
+ : mOwner(owner), mName(name), bImmutable(isImmutable), bConst(isConst)
+ {
+ }
+
+ KConfigGroupPrivate(const KSharedConfigPtr &owner, const QByteArray& name)
+ : sOwner(owner), mOwner(sOwner.data()), mName(name),
+ bImmutable(name.isEmpty()? owner->isImmutable(): owner->isGroupImmutable(name)), bConst(false)
+ {
+ }
+
+ KConfigGroupPrivate(KConfigGroup* parent, bool isImmutable, bool isConst, const QByteArray& name)
+ : sOwner(parent->d->sOwner), mOwner(parent->d->mOwner), mName(name),
+ bImmutable(isImmutable), bConst(isConst)
+ {
+ if (!parent->d->mName.isEmpty())
+ mParent = parent->d;
+ }
+
+ KConfigGroupPrivate(const KConfigGroupPrivate* other, bool isImmutable, const QByteArray &name)
+ : sOwner(other->sOwner), mOwner(other->mOwner), mName(name),
+ bImmutable(isImmutable), bConst(other->bConst)
+ {
+ if (!other->mName.isEmpty())
+ mParent = const_cast<KConfigGroupPrivate *>(other);
+ }
+
+ KSharedConfig::Ptr sOwner;
+ KConfig *mOwner;
+ QExplicitlySharedDataPointer<KConfigGroupPrivate> mParent;
+ QByteArray mName;
+
+ /* bitfield */
+ const bool bImmutable:1; // is this group immutable?
+ const bool bConst:1; // is this group read-only?
+
+ QByteArray fullName() const
+ {
+ if (!mParent) {
+ return name();
+ }
+ return mParent->fullName(mName);
+ }
+
+ QByteArray name() const
+ {
+ if (mName.isEmpty())
+ return "<default>";
+ return mName;
+ }
+
+ QByteArray fullName(const QByteArray& aGroup) const
+ {
+ if (mName.isEmpty())
+ return aGroup;
+ return fullName() + '\x1d' + aGroup;
+ }
+
+ static QExplicitlySharedDataPointer<KConfigGroupPrivate> create(KConfigBase *master,
+ const QByteArray &name,
+ bool isImmutable,
+ bool isConst)
+ {
+ QExplicitlySharedDataPointer<KConfigGroupPrivate> data;
+ if (dynamic_cast<KConfigGroup*>(master))
+ data = new KConfigGroupPrivate(dynamic_cast<KConfigGroup*>(master), isImmutable, isConst, name);
+ else
+ data = new KConfigGroupPrivate(dynamic_cast<KConfig*>(master), isImmutable, isConst, name);
+ return data;
+ }
+
+ static QByteArray serializeList(const QList<QByteArray> &list);
+ static QStringList deserializeList(const QString &data);
+};
+
+QByteArray KConfigGroupPrivate::serializeList(const QList<QByteArray> &list)
+{
+ QByteArray value = "";
+
+ if (!list.isEmpty()) {
+ QList<QByteArray>::ConstIterator it = list.constBegin();
+ const QList<QByteArray>::ConstIterator end = list.constEnd();
+
+ value = QByteArray(*it).replace('\\', "\\\\").replace(',', "\\,");
+
+ while (++it != end) {
+ // In the loop, so it is not done when there is only one element.
+ // Doing it repeatedly is a pretty cheap operation.
+ value.reserve(4096);
+
+ value += ',';
+ value += QByteArray(*it).replace('\\', "\\\\").replace(',', "\\,");
+ }
+
+ // To be able to distinguish an empty list from a list with one empty element.
+ if (value.isEmpty())
+ value = "\\0";
+ }
+
+ return value;
+}
+
+QStringList KConfigGroupPrivate::deserializeList(const QString &data)
+{
+ if (data.isEmpty())
+ return QStringList();
+ if (data == QLatin1String("\\0"))
+ return QStringList(QString());
+ QStringList value;
+ QString val;
+ val.reserve(data.size());
+ bool quoted = false;
+ for (int p = 0; p < data.length(); p++) {
+ if (quoted) {
+ val += data[p];
+ quoted = false;
+ } else if (data[p].unicode() == '\\') {
+ quoted = true;
+ } else if (data[p].unicode() == ',') {
+ val.squeeze(); // release any unused memory
+ value.append(val);
+ val.clear();
+ val.reserve(data.size() - p);
+ } else {
+ val += data[p];
+ }
+ }
+ value.append(val);
+ return value;
+}
+
+static QList<int> asIntList(const QByteArray& string)
+{
+ QList<int> list;
+ Q_FOREACH(const QByteArray& s, string.split(','))
+ list << s.toInt();
+ return list;
+}
+
+static QList<qreal> asRealList(const QByteArray& string)
+{
+ QList<qreal> list;
+ Q_FOREACH(const QByteArray& s, string.split(','))
+ list << s.toDouble();
+ return list;
+}
+
+static QString errString( const char * pKey, const QByteArray & value, const QVariant & aDefault ) {
+ return QString::fromLatin1("\"%1\" - conversion of \"%3\" to %2 failed")
+ .arg(QString::fromLatin1(pKey))
+ .arg(QString::fromLatin1(QVariant::typeToName(aDefault.type())))
+ .arg(QString::fromLatin1(value));
+}
+
+static QString formatError( int expected, int got ) {
+ return QString::fromLatin1(" (wrong format: expected %1 items, got %2)").arg( expected ).arg( got );
+}
+
+QVariant KConfigGroup::convertToQVariant(const char *pKey, const QByteArray& value, const QVariant& aDefault)
+{
+ // if a type handler is added here you must add a QVConversions definition
+ // to conversion_check.h, or ConversionCheck::to_QVariant will not allow
+ // readEntry<T> to convert to QVariant.
+ switch( aDefault.type() ) {
+ case QVariant::Invalid:
+ return QVariant();
+ case QVariant::String:
+ // this should return the raw string not the dollar expanded string.
+ // imho if processed string is wanted should call
+ // readEntry(key, QString) not readEntry(key, QVariant)
+ return QString::fromUtf8(value);
+ case QVariant::List:
+ case QVariant::StringList:
+ return KConfigGroupPrivate::deserializeList(QString::fromUtf8(value));
+ case QVariant::ByteArray:
+ return value;
+ case QVariant::Bool: {
+ const QByteArray lower(value.toLower());
+ if (lower == "false" || lower == "no" || lower == "off" || lower == "0")
+ return false;
+ return true;
+ }
+ case QVariant::Double:
+ case QMetaType::Float:
+ case QVariant::Int:
+ case QVariant::UInt:
+ case QVariant::LongLong:
+ case QVariant::ULongLong: {
+ QVariant tmp = value;
+ if ( !tmp.convert(aDefault.type()) )
+ tmp = aDefault;
+ return tmp;
+ }
+ case QVariant::Point: {
+ const QList<int> list = asIntList(value);
+
+ if ( list.count() != 2 ) {
+ qWarning() << errString( pKey, value, aDefault )
+ << formatError( 2, list.count() );
+ return aDefault;
+ }
+ return QPoint(list.at( 0 ), list.at( 1 ));
+ }
+ case QVariant::PointF: {
+ const QList<qreal> list = asRealList(value);
+
+ if ( list.count() != 2 ) {
+ qWarning() << errString( pKey, value, aDefault )
+ << formatError( 2, list.count() );
+ return aDefault;
+ }
+ return QPointF(list.at( 0 ), list.at( 1 ));
+ }
+ case QVariant::Rect: {
+ const QList<int> list = asIntList(value);
+
+ if ( list.count() != 4 ) {
+ qWarning() << errString( pKey, value, aDefault )
+ << formatError( 4, list.count() );
+ return aDefault;
+ }
+ const QRect rect(list.at( 0 ), list.at( 1 ), list.at( 2 ), list.at( 3 ));
+ if ( !rect.isValid() ) {
+ qWarning() << errString( pKey, value, aDefault );
+ return aDefault;
+ }
+ return rect;
+ }
+ case QVariant::RectF: {
+ const QList<qreal> list = asRealList(value);
+
+ if ( list.count() != 4 ) {
+ qWarning() << errString( pKey, value, aDefault )
+ << formatError( 4, list.count() );
+ return aDefault;
+ }
+ const QRectF rect(list.at( 0 ), list.at( 1 ), list.at( 2 ), list.at( 3 ));
+ if ( !rect.isValid() ) {
+ qWarning() << errString( pKey, value, aDefault );
+ return aDefault;
+ }
+ return rect;
+ }
+ case QVariant::Size: {
+ const QList<int> list = asIntList(value);
+
+ if ( list.count() != 2 ) {
+ qWarning() << errString( pKey, value, aDefault )
+ << formatError( 2, list.count() );
+ return aDefault;
+ }
+ const QSize size(list.at( 0 ), list.at( 1 ));
+ if ( !size.isValid() ) {
+ qWarning() << errString( pKey, value, aDefault );
+ return aDefault;
+ }
+ return size;
+ }
+ case QVariant::SizeF: {
+ const QList<qreal> list = asRealList(value);
+
+ if ( list.count() != 2 ) {
+ qWarning() << errString( pKey, value, aDefault )
+ << formatError( 2, list.count() );
+ return aDefault;
+ }
+ const QSizeF size(list.at( 0 ), list.at( 1 ));
+ if ( !size.isValid() ) {
+ qWarning() << errString( pKey, value, aDefault );
+ return aDefault;
+ }
+ return size;
+ }
+ case QVariant::DateTime: {
+ const QList<int> list = asIntList(value);
+ if ( list.count() != 6 ) {
+ qWarning() << errString( pKey, value, aDefault )
+ << formatError( 6, list.count() );
+ return aDefault;
+ }
+ const QDate date( list.at( 0 ), list.at( 1 ), list.at( 2 ) );
+ const QTime time( list.at( 3 ), list.at( 4 ), list.at( 5 ) );
+ const QDateTime dt( date, time );
+ if ( !dt.isValid() ) {
+ qWarning() << errString( pKey, value, aDefault );
+ return aDefault;
+ }
+ return dt;
+ }
+ case QVariant::Date: {
+ QList<int> list = asIntList(value);
+ if ( list.count() == 6 )
+ list = list.mid(0, 3); // don't break config files that stored QDate as QDateTime
+ if ( list.count() != 3 ) {
+ qWarning() << errString( pKey, value, aDefault )
+ << formatError( 3, list.count() );
+ return aDefault;
+ }
+ const QDate date( list.at( 0 ), list.at( 1 ), list.at( 2 ) );
+ if ( !date.isValid() ) {
+ qWarning() << errString( pKey, value, aDefault );
+ return aDefault;
+ }
+ return date;
+ }
+ case QVariant::Color:
+ case QVariant::Font:
+ qWarning() << "KConfigGroup::readEntry was passed GUI type '"
+ << aDefault.typeName()
+ << "' but kdeui isn't linked! If it is linked to your program, "
+ "this is a platform bug. Please inform the KDE developers";
+ break;
+ case QVariant::Url:
+ return QUrl(QString::fromUtf8(value));
+
+ default:
+ break;
+ }
+
+ qWarning() << "unhandled type " << aDefault.typeName();
+ return QVariant();
+}
+
+#ifdef Q_OS_WIN
+# include <QtCore/QDir>
+#endif
+
+static bool cleanHomeDirPath( QString &path, const QString &homeDir )
+{
+#ifdef Q_OS_WIN //safer
+ if (!QDir::toNativeSeparators(path).startsWith(QDir::toNativeSeparators(homeDir)))
+ return false;
+#else
+ if (!path.startsWith(homeDir))
+ return false;
+#endif
+
+ int len = homeDir.length();
+ // replace by "$HOME" if possible
+ if (len && (path.length() == len || path[len] == QLatin1Char('/'))) {
+ path.replace(0, len, QString::fromLatin1("$HOME"));
+ return true;
+ } else
+ return false;
+}
+
+static QString translatePath( QString path ) // krazy:exclude=passbyvalue
+{
+ if (path.isEmpty())
+ return path;
+
+ // only "our" $HOME should be interpreted
+ path.replace(QLatin1Char('$'), QLatin1String("$$"));
+
+ bool startsWithFile = path.startsWith(QLatin1String("file:"), Qt::CaseInsensitive);
+
+ // return original path, if it refers to another type of URL (e.g. http:/), or
+ // if the path is already relative to another directory
+ if ((!startsWithFile && QFileInfo(path).isRelative()) ||
+ (startsWithFile && QFileInfo(path.mid(5)).isRelative()))
+ return path;
+
+ if (startsWithFile)
+ path.remove(0,5); // strip leading "file:/" off the string
+
+ // keep only one single '/' at the beginning - needed for cleanHomeDirPath()
+ while (path[0] == QLatin1Char('/') && path[1] == QLatin1Char('/'))
+ path.remove(0,1);
+
+ // we can not use KGlobal::dirs()->relativeLocation("home", path) here,
+ // since it would not recognize paths without a trailing '/'.
+ // All of the 3 following functions to return the user's home directory
+ // can return different paths. We have to test all them.
+ const QString homeDir0 = QFile::decodeName(qgetenv("HOME"));
+ const QString homeDir1 = QDir::homePath();
+ const QString homeDir2 = QDir(homeDir1).canonicalPath();
+ if (cleanHomeDirPath(path, homeDir0) ||
+ cleanHomeDirPath(path, homeDir1) ||
+ cleanHomeDirPath(path, homeDir2) ) {
+ // qDebug() << "Path was replaced\n";
+ }
+
+ if (startsWithFile)
+ path.prepend(QString::fromLatin1("file://"));
+
+ return path;
+}
+
+
+KConfigGroup::KConfigGroup() : d(0)
+{
+}
+
+bool KConfigGroup::isValid() const
+{
+ return 0 != d.constData();
+}
+
+KConfigGroupGui _kde_internal_KConfigGroupGui;
+static inline bool readEntryGui(const QByteArray& data, const char* key, const QVariant &input,
+ QVariant &output)
+{
+ if (_kde_internal_KConfigGroupGui.readEntryGui)
+ return _kde_internal_KConfigGroupGui.readEntryGui(data, key, input, output);
+ return false;
+}
+
+static inline bool writeEntryGui(KConfigGroup *cg, const char* key, const QVariant &input,
+ KConfigGroup::WriteConfigFlags flags)
+{
+ if (_kde_internal_KConfigGroupGui.writeEntryGui)
+ return _kde_internal_KConfigGroupGui.writeEntryGui(cg, key, input, flags);
+ return false;
+}
+
+KConfigGroup::KConfigGroup(KConfigBase *master, const QString &_group)
+ : d(KConfigGroupPrivate::create(master, _group.toUtf8(), master->isGroupImmutable(_group), false))
+{
+}
+
+KConfigGroup::KConfigGroup(KConfigBase *master, const char *_group)
+ : d(KConfigGroupPrivate::create(master, _group, master->isGroupImmutable(_group), false))
+{
+}
+
+KConfigGroup::KConfigGroup(const KConfigBase *master, const QString &_group)
+ : d(KConfigGroupPrivate::create(const_cast<KConfigBase*>(master), _group.toUtf8(), master->isGroupImmutable(_group), true))
+{
+}
+
+KConfigGroup::KConfigGroup(const KConfigBase *master, const char * _group)
+ : d(KConfigGroupPrivate::create(const_cast<KConfigBase*>(master), _group, master->isGroupImmutable(_group), true))
+{
+}
+
+KConfigGroup::KConfigGroup(const KSharedConfigPtr &master, const QString &_group)
+ : d(new KConfigGroupPrivate(master, _group.toUtf8()))
+{
+}
+
+KConfigGroup::KConfigGroup(const KSharedConfigPtr &master, const char * _group)
+ : d(new KConfigGroupPrivate(master, _group))
+{
+}
+
+KConfigGroup &KConfigGroup::operator=(const KConfigGroup &rhs)
+{
+ d = rhs.d;
+ return *this;
+}
+
+KConfigGroup::KConfigGroup(const KConfigGroup &rhs)
+ : KConfigBase(), d(rhs.d)
+{
+}
+
+KConfigGroup::~KConfigGroup()
+{
+ d = 0;
+}
+
+KConfigGroup KConfigGroup::groupImpl(const QByteArray& aGroup)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::groupImpl", "accessing an invalid group");
+ Q_ASSERT_X(!aGroup.isEmpty(), "KConfigGroup::groupImpl", "can not have an unnamed child group");
+
+ KConfigGroup newGroup;
+
+ newGroup.d = new KConfigGroupPrivate(this, isGroupImmutableImpl(aGroup), d->bConst, aGroup);
+
+ return newGroup;
+}
+
+const KConfigGroup KConfigGroup::groupImpl(const QByteArray& aGroup) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::groupImpl", "accessing an invalid group");
+ Q_ASSERT_X(!aGroup.isEmpty(), "KConfigGroup::groupImpl", "can not have an unnamed child group");
+
+ KConfigGroup newGroup;
+
+ newGroup.d = new KConfigGroupPrivate(const_cast<KConfigGroup*>(this), isGroupImmutableImpl(aGroup),
+ true, aGroup);
+
+ return newGroup;
+}
+
+KConfigGroup KConfigGroup::parent() const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::parent", "accessing an invalid group");
+
+ KConfigGroup parentGroup;
+
+ if (d->mParent) {
+ parentGroup.d = d->mParent;
+ } else {
+ parentGroup.d = new KConfigGroupPrivate(d->mOwner, d->mOwner->isImmutable(), d->bConst, "");
+ // make sure we keep the refcount up on the KConfig object
+ parentGroup.d->sOwner = d->sOwner;
+ }
+
+ return parentGroup;
+}
+
+void KConfigGroup::deleteGroup(WriteConfigFlags flags)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::deleteGroup", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::deleteGroup", "deleting a read-only group");
+
+ config()->deleteGroup(d->fullName(), flags);
+}
+
+#ifndef KDE_NO_DEPRECATED
+void KConfigGroup::changeGroup( const QString &group )
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::changeGroup", "accessing an invalid group");
+ d.detach();
+ d->mName = group.toUtf8();
+}
+#endif
+
+#ifndef KDE_NO_DEPRECATED
+void KConfigGroup::changeGroup( const char *group )
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::changeGroup", "accessing an invalid group");
+ d.detach();
+ d->mName = group;
+}
+#endif
+
+QString KConfigGroup::name() const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::name", "accessing an invalid group");
+
+ return QString::fromUtf8(d->name());
+}
+
+bool KConfigGroup::exists() const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::exists", "accessing an invalid group");
+
+ return config()->hasGroup( d->fullName() );
+}
+
+bool KConfigGroup::sync()
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::sync", "accessing an invalid group");
+
+ if (!d->bConst)
+ return config()->sync();
+
+ return false;
+}
+
+QMap<QString, QString> KConfigGroup::entryMap() const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::entryMap", "accessing an invalid group");
+
+ return config()->entryMap(QString::fromUtf8(d->fullName()));
+}
+
+KConfig* KConfigGroup::config()
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::config", "accessing an invalid group");
+
+ return d->mOwner;
+}
+
+const KConfig* KConfigGroup::config() const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::config", "accessing an invalid group");
+
+ return d->mOwner;
+}
+
+bool KConfigGroup::isEntryImmutable(const char* key) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::isEntryImmutable", "accessing an invalid group");
+
+ return (isImmutable() ||
+ !config()->d_func()->canWriteEntry(d->fullName(), key, config()->readDefaults()));
+}
+
+bool KConfigGroup::isEntryImmutable(const QString& key) const
+{
+ return isEntryImmutable(key.toUtf8().constData());
+}
+
+QString KConfigGroup::readEntryUntranslated(const QString& pKey, const QString& aDefault) const
+{
+ return readEntryUntranslated(pKey.toUtf8().constData(), aDefault);
+}
+
+QString KConfigGroup::readEntryUntranslated(const char *key, const QString& aDefault) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::readEntryUntranslated", "accessing an invalid group");
+
+ QString result = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchFlags(), 0);
+ if (result.isNull())
+ return aDefault;
+ return result;
+}
+
+QString KConfigGroup::readEntry(const char *key, const char* aDefault) const
+{
+ return readEntry(key, QString::fromUtf8(aDefault));
+}
+
+QString KConfigGroup::readEntry(const QString &key, const char* aDefault) const
+{
+ return readEntry(key.toUtf8().constData(), aDefault);
+}
+
+QString KConfigGroup::readEntry(const char* key, const QString& aDefault) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
+
+ bool expand = false;
+
+ // read value from the entry map
+ QString aValue = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchLocalized,
+ &expand);
+ if (aValue.isNull())
+ aValue = aDefault;
+
+ if (expand)
+ return KConfigPrivate::expandString(aValue);
+
+ return aValue;
+}
+
+QString KConfigGroup::readEntry(const QString &key, const QString& aDefault) const
+{
+ return readEntry(key.toUtf8().constData(), aDefault);
+}
+
+QStringList KConfigGroup::readEntry(const char* key, const QStringList& aDefault) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
+
+ const QString data = readEntry(key, QString());
+ if (data.isNull())
+ return aDefault;
+
+ return KConfigGroupPrivate::deserializeList(data);
+}
+
+QStringList KConfigGroup::readEntry( const QString& key, const QStringList& aDefault) const
+{
+ return readEntry( key.toUtf8().constData(), aDefault );
+}
+
+QVariant KConfigGroup::readEntry( const char* key, const QVariant &aDefault ) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
+
+ const QByteArray data = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchLocalized);
+ if (data.isNull())
+ return aDefault;
+
+ QVariant value;
+ if (!readEntryGui( data, key, aDefault, value ))
+ return convertToQVariant(key, data, aDefault);
+
+ return value;
+}
+
+QVariant KConfigGroup::readEntry( const QString& key, const QVariant& aDefault) const
+{
+ return readEntry( key.toUtf8().constData(), aDefault );
+}
+
+QVariantList KConfigGroup::readEntry( const char* key, const QVariantList& aDefault) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
+
+ const QString data = readEntry(key, QString());
+ if (data.isNull())
+ return aDefault;
+
+ QVariantList value;
+ Q_FOREACH(const QString& v, KConfigGroupPrivate::deserializeList(data))
+ value << v;
+
+ return value;
+}
+
+QVariantList KConfigGroup::readEntry( const QString& key, const QVariantList& aDefault) const
+{
+ return readEntry( key.toUtf8().constData(), aDefault );
+}
+
+QStringList KConfigGroup::readXdgListEntry(const QString& key, const QStringList& aDefault) const
+{
+ return readXdgListEntry(key.toUtf8().constData(), aDefault);
+}
+
+QStringList KConfigGroup::readXdgListEntry(const char *key, const QStringList& aDefault) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::readXdgListEntry", "accessing an invalid group");
+
+ const QString data = readEntry(key, QString());
+ if (data.isNull())
+ return aDefault;
+
+ QStringList value;
+ QString val;
+ val.reserve(data.size());
+ // XXX List serialization being a separate layer from low-level parsing is
+ // probably a bug. No affected entries are defined, though.
+ bool quoted = false;
+ for (int p = 0; p < data.length(); p++) {
+ if (quoted) {
+ val += data[p];
+ quoted = false;
+ } else if (data[p] == QLatin1Char('\\')) {
+ quoted = true;
+ } else if (data[p] == QLatin1Char(';')) {
+ value.append(val);
+ val.clear();
+ val.reserve(data.size() - p);
+ } else {
+ val += data[p];
+ }
+ }
+ if (!val.isEmpty()) {
+ qWarning() << "List entry" << key << "in" << config()->name() << "is not compliant with XDG standard (missing trailing semicolon).";
+ value.append(val);
+ }
+ return value;
+}
+
+QString KConfigGroup::readPathEntry(const QString& pKey, const QString & aDefault) const
+{
+ return readPathEntry(pKey.toUtf8().constData(), aDefault);
+}
+
+QString KConfigGroup::readPathEntry(const char *key, const QString & aDefault) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::readPathEntry", "accessing an invalid group");
+
+ bool expand = false;
+
+ QString aValue = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchLocalized,
+ &expand);
+ if (aValue.isNull())
+ aValue = aDefault;
+
+ return KConfigPrivate::expandString(aValue);
+}
+
+QStringList KConfigGroup::readPathEntry(const QString& pKey, const QStringList& aDefault) const
+{
+ return readPathEntry(pKey.toUtf8().constData(), aDefault);
+}
+
+QStringList KConfigGroup::readPathEntry(const char *key, const QStringList& aDefault) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::readPathEntry", "accessing an invalid group");
+
+ const QString data = readPathEntry(key, QString());
+ if (data.isNull())
+ return aDefault;
+
+ return KConfigGroupPrivate::deserializeList(data);
+}
+
+void KConfigGroup::writeEntry( const char* key, const QString& value, WriteConfigFlags flags )
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
+
+ writeEntry(key, value.toUtf8(), flags);
+}
+
+void KConfigGroup::writeEntry( const QString& key, const QString& value, WriteConfigFlags flags )
+{
+ writeEntry(key.toUtf8().constData(), value, flags);
+}
+
+void KConfigGroup::writeEntry(const QString &key, const char *value, WriteConfigFlags pFlags)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
+
+ writeEntry(key.toUtf8().constData(), QVariant(QString::fromLatin1(value)), pFlags);
+}
+
+void KConfigGroup::writeEntry(const char *key, const char *value, WriteConfigFlags pFlags)
+{
+ writeEntry(key, QVariant(QString::fromLatin1(value)), pFlags);
+}
+
+void KConfigGroup::writeEntry( const char* key, const QByteArray& value,
+ WriteConfigFlags flags )
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
+
+ config()->d_func()->putData(d->fullName(), key, value.isNull()? QByteArray(""): value, flags);
+}
+
+void KConfigGroup::writeEntry(const QString& key, const QByteArray& value,
+ WriteConfigFlags pFlags)
+{
+ writeEntry(key.toUtf8().constData(), value, pFlags);
+}
+
+void KConfigGroup::writeEntry(const char* key, const QStringList &list, WriteConfigFlags flags)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
+
+ QList<QByteArray> balist;
+
+ Q_FOREACH(const QString &entry, list)
+ balist.append(entry.toUtf8());
+
+ writeEntry(key, KConfigGroupPrivate::serializeList(balist), flags);
+}
+
+void KConfigGroup::writeEntry(const QString& key, const QStringList &list, WriteConfigFlags flags)
+{
+ writeEntry(key.toUtf8().constData(), list, flags);
+}
+
+void KConfigGroup::writeEntry( const char* key, const QVariantList& list, WriteConfigFlags flags )
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
+
+ QList<QByteArray> data;
+
+ Q_FOREACH(const QVariant& v, list) {
+ if (v.type() == QVariant::ByteArray)
+ data << v.toByteArray();
+ else
+ data << v.toString().toUtf8();
+ }
+
+ writeEntry(key, KConfigGroupPrivate::serializeList(data), flags);
+}
+
+void KConfigGroup::writeEntry( const char* key, const QVariant &value,
+ WriteConfigFlags flags )
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
+
+ if ( writeEntryGui( this, key, value, flags ) )
+ return; // GUI type that was handled
+
+ QByteArray data;
+ // if a type handler is added here you must add a QVConversions definition
+ // to conversion_check.h, or ConversionCheck::to_QVariant will not allow
+ // writeEntry<T> to convert to QVariant.
+ switch( value.type() ) {
+ case QVariant::Invalid:
+ data = "";
+ break;
+ case QVariant::ByteArray:
+ data = value.toByteArray();
+ break;
+ case QVariant::String:
+ case QVariant::Int:
+ case QVariant::UInt:
+ case QVariant::Double:
+ case QMetaType::Float:
+ case QVariant::Bool:
+ case QVariant::LongLong:
+ case QVariant::ULongLong:
+ data = value.toString().toUtf8();
+ break;
+ case QVariant::List:
+ if (!value.canConvert(QVariant::StringList))
+ qWarning() << "not all types in \"" << key << "\" can convert to QString,"
+ " information will be lost";
+ case QVariant::StringList:
+ writeEntry( key, value.toList(), flags );
+ return;
+ case QVariant::Point: {
+ QVariantList list;
+ const QPoint rPoint = value.toPoint();
+ list.insert( 0, rPoint.x() );
+ list.insert( 1, rPoint.y() );
+
+ writeEntry( key, list, flags );
+ return;
+ }
+ case QVariant::PointF: {
+ QVariantList list;
+ const QPointF point = value.toPointF();
+ list.insert( 0, point.x() );
+ list.insert( 1, point.y() );
+
+ writeEntry( key, list, flags );
+ return;
+ }
+ case QVariant::Rect:{
+ QVariantList list;
+ const QRect rRect = value.toRect();
+ list.insert( 0, rRect.left() );
+ list.insert( 1, rRect.top() );
+ list.insert( 2, rRect.width() );
+ list.insert( 3, rRect.height() );
+
+ writeEntry( key, list, flags );
+ return;
+ }
+ case QVariant::RectF:{
+ QVariantList list;
+ const QRectF rRectF = value.toRectF();
+ list.insert(0, rRectF.left());
+ list.insert(1, rRectF.top());
+ list.insert(2, rRectF.width());
+ list.insert(3, rRectF.height());
+
+ writeEntry(key, list, flags);
+ return;
+ }
+ case QVariant::Size:{
+ QVariantList list;
+ const QSize rSize = value.toSize();
+ list.insert( 0, rSize.width() );
+ list.insert( 1, rSize.height() );
+
+ writeEntry( key, list, flags );
+ return;
+ }
+ case QVariant::SizeF:{
+ QVariantList list;
+ const QSizeF rSizeF = value.toSizeF();
+ list.insert(0, rSizeF.width());
+ list.insert(1, rSizeF.height());
+
+ writeEntry(key, list, flags);
+ return;
+ }
+ case QVariant::Date: {
+ QVariantList list;
+ const QDate date = value.toDate();
+
+ list.insert( 0, date.year() );
+ list.insert( 1, date.month() );
+ list.insert( 2, date.day() );
+
+ writeEntry( key, list, flags );
+ return;
+ }
+ case QVariant::DateTime: {
+ QVariantList list;
+ const QDateTime rDateTime = value.toDateTime();
+
+ const QTime time = rDateTime.time();
+ const QDate date = rDateTime.date();
+
+ list.insert( 0, date.year() );
+ list.insert( 1, date.month() );
+ list.insert( 2, date.day() );
+
+ list.insert( 3, time.hour() );
+ list.insert( 4, time.minute() );
+ list.insert( 5, time.second() );
+
+ writeEntry( key, list, flags );
+ return;
+ }
+
+ case QVariant::Color:
+ case QVariant::Font:
+ qWarning() << "KConfigGroup::writeEntry was passed GUI type '"
+ << value.typeName()
+ << "' but kdeui isn't linked! If it is linked to your program, this is a platform bug. "
+ "Please inform the KDE developers";
+ break;
+ case QVariant::Url:
+ data = QUrl(value.toUrl()).toString().toUtf8();
+ break;
+ default:
+ qWarning() << "KConfigGroup::writeEntry - unhandled type" << value.typeName() << "in group" << name();
+ }
+
+ writeEntry(key, data, flags);
+}
+
+void KConfigGroup::writeEntry( const QString& key, const QVariant& value, WriteConfigFlags flags )
+{
+ writeEntry(key.toUtf8().constData(), value, flags);
+}
+
+void KConfigGroup::writeEntry(const QString& key, const QVariantList &list, WriteConfigFlags flags)
+{
+ writeEntry(key.toUtf8().constData(), list, flags);
+}
+
+void KConfigGroup::writeXdgListEntry(const QString& key, const QStringList &value, WriteConfigFlags pFlags)
+{
+ writeXdgListEntry(key.toUtf8().constData(), value, pFlags);
+}
+
+void KConfigGroup::writeXdgListEntry(const char *key, const QStringList &list, WriteConfigFlags flags)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::writeXdgListEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::writeXdgListEntry", "writing to a read-only group");
+
+ QString value;
+ value.reserve(4096);
+
+ // XXX List serialization being a separate layer from low-level escaping is
+ // probably a bug. No affected entries are defined, though.
+ QStringList::ConstIterator it = list.constBegin();
+ const QStringList::ConstIterator end = list.constEnd();
+ for (; it != end; ++it) {
+ QString val(*it);
+ val.replace(QLatin1Char('\\'), QLatin1String("\\\\")).replace(QLatin1Char(';'), QLatin1String("\\;"));
+ value += val;
+ value += QLatin1Char(';');
+ }
+
+ writeEntry(key, value, flags);
+}
+
+void KConfigGroup::writePathEntry(const QString& pKey, const QString & path, WriteConfigFlags pFlags)
+{
+ writePathEntry(pKey.toUtf8().constData(), path, pFlags);
+}
+
+void KConfigGroup::writePathEntry(const char *pKey, const QString & path, WriteConfigFlags pFlags)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::writePathEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::writePathEntry", "writing to a read-only group");
+
+ config()->d_func()->putData(d->fullName(), pKey, translatePath(path).toUtf8(), pFlags, true);
+}
+
+void KConfigGroup::writePathEntry(const QString& pKey, const QStringList &value, WriteConfigFlags pFlags)
+{
+ writePathEntry(pKey.toUtf8().constData(), value, pFlags);
+}
+
+void KConfigGroup::writePathEntry(const char *pKey, const QStringList &value, WriteConfigFlags pFlags)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::writePathEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::writePathEntry", "writing to a read-only group");
+
+ QList<QByteArray> list;
+ Q_FOREACH(const QString& path, value)
+ list << translatePath(path).toUtf8();
+
+ config()->d_func()->putData(d->fullName(), pKey, KConfigGroupPrivate::serializeList(list), pFlags, true);
+}
+
+void KConfigGroup::deleteEntry( const char *key, WriteConfigFlags flags)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::deleteEntry", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::deleteEntry", "deleting from a read-only group");
+
+ config()->d_func()->putData(d->fullName(), key, QByteArray(), flags);
+}
+
+void KConfigGroup::deleteEntry( const QString& key, WriteConfigFlags flags)
+{
+ deleteEntry(key.toUtf8().constData(), flags);
+}
+
+void KConfigGroup::revertToDefault(const char *key)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::revertToDefault", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::revertToDefault", "writing to a read-only group");
+
+ config()->d_func()->revertEntry(d->fullName(), key);
+}
+
+void KConfigGroup::revertToDefault(const QString &key)
+{
+ revertToDefault(key.toUtf8().constData());
+}
+
+bool KConfigGroup::hasDefault(const char *key) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::hasDefault", "accessing an invalid group");
+
+ KEntryMap::SearchFlags flags = KEntryMap::SearchDefaults|KEntryMap::SearchLocalized;
+
+ return !config()->d_func()->lookupData(d->fullName(), key, flags).isNull();
+}
+
+bool KConfigGroup::hasDefault(const QString &key) const
+{
+ return hasDefault(key.toUtf8().constData());
+}
+
+bool KConfigGroup::hasKey(const char *key) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::hasKey", "accessing an invalid group");
+
+ KEntryMap::SearchFlags flags = KEntryMap::SearchLocalized;
+ if ( config()->readDefaults() )
+ flags |= KEntryMap::SearchDefaults;
+
+ return !config()->d_func()->lookupData(d->fullName(), key, flags).isNull();
+}
+
+bool KConfigGroup::hasKey(const QString &key) const
+{
+ return hasKey(key.toUtf8().constData());
+}
+
+bool KConfigGroup::isImmutable() const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::isImmutable", "accessing an invalid group");
+
+ return d->bImmutable;
+}
+
+QStringList KConfigGroup::groupList() const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::groupList", "accessing an invalid group");
+
+ return config()->d_func()->groupList(d->fullName());
+}
+
+QStringList KConfigGroup::keyList() const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::keyList", "accessing an invalid group");
+
+ return entryMap().keys();
+}
+
+void KConfigGroup::markAsClean()
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::markAsClean", "accessing an invalid group");
+
+ config()->markAsClean();
+}
+
+KConfigGroup::AccessMode KConfigGroup::accessMode() const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::accessMode", "accessing an invalid group");
+
+ return config()->accessMode();
+}
+
+bool KConfigGroup::hasGroupImpl(const QByteArray & b) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::hasGroupImpl", "accessing an invalid group");
+
+ return config()->hasGroup(d->fullName(b));
+}
+
+void KConfigGroup::deleteGroupImpl(const QByteArray &b, WriteConfigFlags flags)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::deleteGroupImpl", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst,"KConfigGroup::deleteGroupImpl", "deleting from a read-only group");
+
+ config()->deleteGroup(d->fullName(b), flags);
+}
+
+bool KConfigGroup::isGroupImmutableImpl(const QByteArray& b) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::isGroupImmutableImpl", "accessing an invalid group");
+
+ if (!hasGroupImpl(b)) // group doesn't exist yet
+ return d->bImmutable; // child groups are immutable if the parent is immutable.
+
+ return config()->isGroupImmutable(d->fullName(b));
+}
+
+void KConfigGroup::copyTo(KConfigBase* other, WriteConfigFlags pFlags) const
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::copyTo", "accessing an invalid group");
+ Q_ASSERT(other != 0);
+
+ if (KConfigGroup *otherGroup = dynamic_cast<KConfigGroup*>(other)) {
+ config()->d_func()->copyGroup(d->fullName(), otherGroup->d->fullName(), otherGroup, pFlags);
+ } else if (KConfig* otherConfig = dynamic_cast<KConfig*>(other)) {
+ KConfigGroup newGroup = otherConfig->group(d->fullName());
+ otherConfig->d_func()->copyGroup(d->fullName(), d->fullName(), &newGroup, pFlags);
+ } else {
+ Q_ASSERT_X(false, "KConfigGroup::copyTo", "unknown type of KConfigBase");
+ }
+}
+
+void KConfigGroup::reparent(KConfigBase* parent, WriteConfigFlags pFlags)
+{
+ Q_ASSERT_X(isValid(), "KConfigGroup::reparent", "accessing an invalid group");
+ Q_ASSERT_X(!d->bConst, "KConfigGroup::reparent", "reparenting a read-only group");
+ Q_ASSERT_X(!d->bImmutable, "KConfigGroup::reparent", "reparenting an immutable group");
+ Q_ASSERT(parent != 0);
+
+ KConfigGroup oldGroup(*this);
+
+ d = KConfigGroupPrivate::create(parent, d->mName, false, false);
+ oldGroup.copyTo(this, pFlags);
+ oldGroup.deleteGroup(); // so that the entries with the old group name are deleted on sync
+}