aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt53
-rw-r--r--src/core/bufferfragment_p.h181
-rw-r--r--src/core/conversion_check.h120
-rw-r--r--src/core/kauthorized.cpp393
-rw-r--r--src/core/kauthorized.h73
-rw-r--r--src/core/kconfig.cpp931
-rw-r--r--src/core/kconfig.h397
-rw-r--r--src/core/kconfig_p.h110
-rw-r--r--src/core/kconfigbackend.cpp123
-rw-r--r--src/core/kconfigbackend.desktop86
-rw-r--r--src/core/kconfigbackend.h211
-rw-r--r--src/core/kconfigbase.cpp112
-rw-r--r--src/core/kconfigbase.h184
-rw-r--r--src/core/kconfigbase_p.h30
-rw-r--r--src/core/kconfigdata.cpp317
-rw-r--r--src/core/kconfigdata.h237
-rw-r--r--src/core/kconfiggroup.cpp1243
-rw-r--r--src/core/kconfiggroup.h767
-rw-r--r--src/core/kconfiggroup_p.h42
-rw-r--r--src/core/kconfigini.cpp770
-rw-r--r--src/core/kconfigini_p.h81
-rw-r--r--src/core/kcoreconfigskeleton.cpp1343
-rw-r--r--src/core/kcoreconfigskeleton.h1407
-rw-r--r--src/core/kcoreconfigskeleton_p.h64
-rw-r--r--src/core/kdesktopfile.cpp366
-rw-r--r--src/core/kdesktopfile.h252
-rw-r--r--src/core/kemailsettings.cpp269
-rw-r--r--src/core/kemailsettings.h176
-rw-r--r--src/core/ksharedconfig.cpp122
-rw-r--r--src/core/ksharedconfig.h88
30 files changed, 10548 insertions, 0 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
new file mode 100644
index 00000000..ea272d31
--- /dev/null
+++ b/src/core/CMakeLists.txt
@@ -0,0 +1,53 @@
+
+find_package(Qt5Core 5.2.0 REQUIRED NO_MODULE)
+
+set(libkconfigcore_SRCS
+ kconfig.cpp
+ kconfigbase.cpp
+ kconfigdata.cpp
+ kconfiggroup.cpp
+ kconfigbackend.cpp
+ kconfigini.cpp
+ kdesktopfile.cpp
+ ksharedconfig.cpp
+ kcoreconfigskeleton.cpp
+ kauthorized.cpp
+ kemailsettings.cpp
+)
+
+add_library(KF5ConfigCore ${libkconfigcore_SRCS})
+generate_export_header(KF5ConfigCore BASE_NAME KConfigCore)
+add_library(KF5::ConfigCore ALIAS KF5ConfigCore)
+
+target_link_libraries(KF5ConfigCore PUBLIC Qt5::Core)
+if(WIN32)
+ target_link_libraries(KF5ConfigCore PRIVATE ${KDEWIN_LIBRARIES})
+endif()
+
+if(IS_ABSOLUTE "${INCLUDE_INSTALL_DIR}")
+ target_include_directories(KF5ConfigCore INTERFACE "$<INSTALL_INTERFACE:${INCLUDE_INSTALL_DIR}>" )
+else()
+ target_include_directories(KF5ConfigCore INTERFACE "$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/${INCLUDE_INSTALL_DIR}>" )
+endif()
+
+set_target_properties(KF5ConfigCore PROPERTIES VERSION ${KCONFIG_VERSION_STRING}
+ SOVERSION ${KCONFIG_SOVERSION}
+ EXPORT_NAME ConfigCore
+)
+
+install(TARGETS KF5ConfigCore EXPORT KF5ConfigTargets ${INSTALL_TARGETS_DEFAULT_ARGS})
+
+install( FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/kconfigcore_export.h
+ conversion_check.h
+ kconfig.h
+ #kconfigbackend.h re-enable post-API review and implementation (4.2?)
+ kconfigbase.h
+ kconfiggroup.h
+ kdesktopfile.h
+ ksharedconfig.h
+ kcoreconfigskeleton.h
+ kauthorized.h
+ kemailsettings.h
+ DESTINATION ${INCLUDE_INSTALL_DIR} COMPONENT Devel
+)
diff --git a/src/core/bufferfragment_p.h b/src/core/bufferfragment_p.h
new file mode 100644
index 00000000..5a753ad4
--- /dev/null
+++ b/src/core/bufferfragment_p.h
@@ -0,0 +1,181 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2008 Jakub Stachowski <qbast@go2.pl>
+
+ 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.
+*/
+
+#ifndef BUFFERFRAGMENT_H
+#define BUFFERFRAGMENT_H
+
+#define bf_isspace(str) ((str == ' ') || (str == '\t') || (str == '\r'))
+
+// This class provides wrapper around fragment of existing buffer (array of bytes).
+// If underlying buffer gets deleted, all BufferFragment objects referencing it become invalid.
+// Use toByteArray() to make deep copy of the buffer fragment.
+//
+// API is designed to subset of QByteArray methods with some changes:
+// - trim() is like QByteArray.trimmed(), but it modifies current object
+// - truncateLeft() provides way to cut off beginning of the buffer
+// - split() works more like strtok_r than QByteArray.split()
+// - truncateLeft() and mid() require position argument to be valid
+
+class KConfigIniBackend::BufferFragment
+{
+
+public:
+
+ BufferFragment() : d(0), len(0)
+ {
+ }
+
+ BufferFragment(char* buf, int size) : d(buf), len(size)
+ {
+ }
+
+ int length() const
+ {
+ return len;
+ }
+
+ char at(unsigned int i) const
+ {
+ Q_ASSERT(i < len);
+ return d[i];
+ }
+
+ void clear()
+ {
+ len = 0;
+ }
+
+ const char* constData() const
+ {
+ return d;
+ }
+
+ char* data() const
+ {
+ return d;
+ }
+
+ void trim()
+ {
+ while (bf_isspace(*d) && len > 0) {
+ d++;
+ len--;
+ }
+ while (len > 0 && bf_isspace(d[len - 1]))
+ len--;
+ }
+
+ // similar to strtok_r . On first call variable pointed by start should be set to 0.
+ // Each call will update *start to new starting position.
+ BufferFragment split(char c, unsigned int* start)
+ {
+ while (*start < len) {
+ int end = indexOf(c, *start);
+ if (end == -1) end = len;
+ BufferFragment line(d + (*start), end - (*start));
+ *start = end + 1;
+ return line;
+ }
+ return BufferFragment();
+ }
+
+ bool isEmpty() const
+ {
+ return (len == 0);
+ }
+
+ BufferFragment left(unsigned int size) const
+ {
+ return BufferFragment(d, qMin(size,len));
+ }
+
+ void truncateLeft(unsigned int size)
+ {
+ Q_ASSERT(size <= len);
+ d += size;
+ len -= size;
+ }
+
+ void truncate(unsigned int pos)
+ {
+ if (pos < len) len = pos;
+ }
+
+ bool isNull() const
+ {
+ return (d == 0);
+ }
+
+ BufferFragment mid(unsigned int pos, int length=-1) const
+ {
+ Q_ASSERT(pos < len);
+ int size = length;
+ if (length == -1 || (pos + length) > len)
+ size = len - pos;
+ return BufferFragment(d + pos, size);
+ }
+
+ bool operator==(const QByteArray& other) const
+ {
+ return (other.size() == (int)len && memcmp(d,other.constData(),len) == 0);
+ }
+
+ bool operator!=(const QByteArray& other) const
+ {
+ return (other.size() != (int)len || memcmp(d,other.constData(),len) != 0);
+ }
+
+ int indexOf(char c, unsigned int from = 0) const
+ {
+ const char* cursor = d + from - 1;
+ const char* end = d + len;
+ while ( ++cursor < end)
+ if (*cursor ==c )
+ return cursor - d;
+ return -1;
+ }
+
+ int lastIndexOf(char c) const
+ {
+ int from = len - 1;
+ while (from >= 0)
+ if (d[from] == c)
+ return from;
+ else
+ from--;
+ return -1;
+ }
+
+ QByteArray toByteArray() const {
+ return QByteArray(d,len);
+ }
+
+ // this is faster than toByteArray, but returned QByteArray becomes invalid
+ // when buffer for this BufferFragment disappears
+ QByteArray toVolatileByteArray() const {
+ return QByteArray::fromRawData(d, len);
+ }
+
+private:
+ char* d;
+ unsigned int len;
+};
+
+#endif
diff --git a/src/core/conversion_check.h b/src/core/conversion_check.h
new file mode 100644
index 00000000..23bdcf04
--- /dev/null
+++ b/src/core/conversion_check.h
@@ -0,0 +1,120 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006 Thomas Braxton <brax108@cox.net>
+
+ 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.
+*/
+
+
+#ifndef CONVERSION_CHECK_H
+#define CONVERSION_CHECK_H
+
+#include <QtCore/QString>
+#include <QtCore/QDate>
+#include <QtCore/QPoint>
+#include <QtCore/QSize>
+#include <QtCore/QRect>
+#include <QtCore/QVariant>
+
+class QColor;
+class QFont;
+
+namespace ConversionCheck {
+
+// used to distinguish between supported/unsupported types
+struct supported { };
+struct unsupported { };
+
+// traits type class to define support for constraints
+template <typename T>
+struct QVconvertible
+{
+ typedef unsupported toQString;
+ typedef unsupported toQVariant;
+};
+
+// constraint classes
+template <typename T>
+struct type_toQString
+{
+ void constraint() { supported x = y; Q_UNUSED(x); }
+ typename QVconvertible<T>::toQString y;
+};
+
+template <typename T>
+struct type_toQVariant
+{
+ void constraint() { supported x = y; Q_UNUSED(x); }
+ typename QVconvertible<T>::toQVariant y;
+};
+
+
+// check if T is convertible to QString thru QVariant
+// if not supported can't be used in QList<T> functions
+template <typename T>
+inline void to_QString()
+{
+ void (type_toQString<T>::*x)() = &type_toQString<T>::constraint;
+ Q_UNUSED(x);
+}
+
+// check if T is convertible to QVariant & supported in readEntry/writeEntry
+template <typename T>
+inline void to_QVariant()
+{
+ void (type_toQVariant<T>::*x)() = &type_toQVariant<T>::constraint;
+ Q_UNUSED(x);
+}
+
+// define for all types handled in readEntry/writeEntry
+// string_support - is supported by QVariant(type).toString(),
+// can be used in QList<T> functions
+// variant_support - has a QVariant constructor
+#define QVConversions(type, string_support, variant_support) \
+template <> struct QVconvertible<type> {\
+ typedef string_support toQString;\
+ typedef variant_support toQVariant;\
+}
+
+// The only types needed here are the types handled in readEntry/writeEntry
+// the default QVconvertible will take care of the rest.
+QVConversions(bool, supported, supported);
+QVConversions(int, supported, supported);
+QVConversions(unsigned int, supported, supported);
+QVConversions(long long, supported, supported);
+QVConversions(unsigned long long, supported, supported);
+QVConversions(float, supported, supported);
+QVConversions(double, supported, supported);
+QVConversions(QString, supported, supported);
+QVConversions(QColor, unsupported, supported);
+QVConversions(QFont, supported, supported);
+QVConversions(QDateTime, unsupported, supported);
+QVConversions(QDate, unsupported, supported);
+QVConversions(QSize, unsupported, supported);
+QVConversions(QRect, unsupported, supported);
+QVConversions(QPoint, unsupported, supported);
+QVConversions(QSizeF, unsupported, supported);
+QVConversions(QRectF, unsupported, supported);
+QVConversions(QPointF, unsupported, supported);
+QVConversions(QByteArray, supported, supported);
+QVConversions(QStringList, unsupported, supported);
+QVConversions(QVariantList, unsupported, supported);
+QVConversions(QUrl, supported, supported);
+QVConversions(QList<QUrl>, unsupported, supported);
+}
+
+#endif
+
diff --git a/src/core/kauthorized.cpp b/src/core/kauthorized.cpp
new file mode 100644
index 00000000..abf479ca
--- /dev/null
+++ b/src/core/kauthorized.cpp
@@ -0,0 +1,393 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
+ Copyright (C) 1998, 1999, 2000 Waldo Bastian <bastian@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.
+*/
+
+#include "kauthorized.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QRegExp>
+#include <QList>
+#include <QUrl>
+
+#include <QCoreApplication>
+#include <ksharedconfig.h>
+#include <stdlib.h> // srand(), rand()
+#ifndef Q_OS_WIN
+#include <unistd.h>
+#include <netdb.h>
+#endif
+
+#include <kconfiggroup.h>
+
+#include <QMutex>
+#include <QMutexLocker>
+
+extern bool kde_kiosk_exception;
+
+
+class URLActionRule
+{
+ public:
+#define checkExactMatch(s, b) \
+ if (s.isEmpty()) b = true; \
+ else if (s[s.length()-1] == QLatin1Char('!')) \
+ { b = false; s.truncate(s.length()-1); } \
+ else b = true;
+#define checkStartWildCard(s, b) \
+ if (s.isEmpty()) b = true; \
+ else if (s[0] == QLatin1Char('*')) \
+ { b = true; s = s.mid(1); } \
+ else b = false;
+#define checkEqual(s, b) \
+ b = (s == QString::fromLatin1("="));
+
+ URLActionRule(const QByteArray &act,
+ const QString &bProt, const QString &bHost, const QString &bPath,
+ const QString &dProt, const QString &dHost, const QString &dPath,
+ bool perm)
+ : action(act),
+ baseProt(bProt), baseHost(bHost), basePath(bPath),
+ destProt(dProt), destHost(dHost), destPath(dPath),
+ permission(perm)
+ {
+ checkExactMatch(baseProt, baseProtWildCard);
+ checkStartWildCard(baseHost, baseHostWildCard);
+ checkExactMatch(basePath, basePathWildCard);
+ checkExactMatch(destProt, destProtWildCard);
+ checkStartWildCard(destHost, destHostWildCard);
+ checkExactMatch(destPath, destPathWildCard);
+ checkEqual(destProt, destProtEqual);
+ checkEqual(destHost, destHostEqual);
+ }
+
+ bool baseMatch(const QUrl &url, const QString &protClass) const
+ {
+ if (baseProtWildCard)
+ {
+ if ( !baseProt.isEmpty() && !url.scheme().startsWith(baseProt) &&
+ (protClass.isEmpty() || (protClass != baseProt)) )
+ return false;
+ }
+ else
+ {
+ if ( (url.scheme() != baseProt) &&
+ (protClass.isEmpty() || (protClass != baseProt)) )
+ return false;
+ }
+ if (baseHostWildCard)
+ {
+ if (!baseHost.isEmpty() && !url.host().endsWith(baseHost))
+ return false;
+ }
+ else
+ {
+ if (url.host() != baseHost)
+ return false;
+ }
+ if (basePathWildCard)
+ {
+ if (!basePath.isEmpty() && !url.path().startsWith(basePath))
+ return false;
+ }
+ else
+ {
+ if (url.path() != basePath)
+ return false;
+ }
+ return true;
+ }
+
+ bool destMatch(const QUrl &url, const QString &protClass, const QUrl &base, const QString &baseClass) const
+ {
+ if (destProtEqual)
+ {
+ if ( (url.scheme() != base.scheme()) &&
+ (protClass.isEmpty() || baseClass.isEmpty() || protClass != baseClass) )
+ return false;
+ }
+ else if (destProtWildCard)
+ {
+ if ( !destProt.isEmpty() && !url.scheme().startsWith(destProt) &&
+ (protClass.isEmpty() || (protClass != destProt)) )
+ return false;
+ }
+ else
+ {
+ if ( (url.scheme() != destProt) &&
+ (protClass.isEmpty() || (protClass != destProt)) )
+ return false;
+ }
+ if (destHostWildCard)
+ {
+ if (!destHost.isEmpty() && !url.host().endsWith(destHost))
+ return false;
+ }
+ else if (destHostEqual)
+ {
+ if (url.host() != base.host())
+ return false;
+ }
+ else
+ {
+ if (url.host() != destHost)
+ return false;
+ }
+ if (destPathWildCard)
+ {
+ if (!destPath.isEmpty() && !url.path().startsWith(destPath))
+ return false;
+ }
+ else
+ {
+ if (url.path() != destPath)
+ return false;
+ }
+ return true;
+ }
+
+ QByteArray action;
+ QString baseProt;
+ QString baseHost;
+ QString basePath;
+ QString destProt;
+ QString destHost;
+ QString destPath;
+ bool baseProtWildCard : 1;
+ bool baseHostWildCard : 1;
+ bool basePathWildCard : 1;
+ bool destProtWildCard : 1;
+ bool destHostWildCard : 1;
+ bool destPathWildCard : 1;
+ bool destProtEqual : 1;
+ bool destHostEqual : 1;
+ bool permission;
+};
+
+class KAuthorizedPrivate {
+public:
+ KAuthorizedPrivate()
+ : actionRestrictions( false ), blockEverything(false),mutex(QMutex::Recursive)
+ {
+ Q_ASSERT_X(QCoreApplication::instance(),"KAuthorizedPrivate()","There has to be an existing QCoreApplication::instance() pointer");
+
+ KSharedConfig::Ptr config = KSharedConfig::openConfig();
+
+ Q_ASSERT_X(config,"KAuthorizedPrivate()","There has to be an existing KSharedConfig::openConfig() pointer");
+ if (!config) {
+ blockEverything=true;
+ return;
+ }
+ actionRestrictions = config->hasGroup("KDE Action Restrictions" ) && !kde_kiosk_exception;
+ }
+
+ ~KAuthorizedPrivate()
+ {
+ }
+
+ bool actionRestrictions : 1;
+ bool blockEverything : 1;
+ QList<URLActionRule> urlActionRestrictions;
+ QMutex mutex;
+};
+
+Q_GLOBAL_STATIC(KAuthorizedPrivate,authPrivate)
+#define MY_D KAuthorizedPrivate *d=authPrivate();
+
+
+bool KAuthorized::authorize(const QString &genericAction)
+{
+ MY_D
+ if (d->blockEverything) return false;
+
+ if (!d->actionRestrictions)
+ return true;
+
+ KConfigGroup cg(KSharedConfig::openConfig(), "KDE Action Restrictions");
+ return cg.readEntry(genericAction, true);
+}
+
+bool KAuthorized::authorizeKAction(const QString& action)
+{
+ MY_D
+ if (d->blockEverything) return false;
+ if (!d->actionRestrictions || action.isEmpty())
+ return true;
+
+ return authorize(QLatin1String("action/") + action);
+}
+
+bool KAuthorized::authorizeControlModule(const QString &menuId)
+{
+ if (menuId.isEmpty() || kde_kiosk_exception)
+ return true;
+ KConfigGroup cg(KSharedConfig::openConfig(), "KDE Control Module Restrictions");
+ return cg.readEntry(menuId, true);
+}
+
+QStringList KAuthorized::authorizeControlModules(const QStringList &menuIds)
+{
+ KConfigGroup cg(KSharedConfig::openConfig(), "KDE Control Module Restrictions");
+ QStringList result;
+ for(QStringList::ConstIterator it = menuIds.begin();
+ it != menuIds.end(); ++it)
+ {
+ if (cg.readEntry(*it, true))
+ result.append(*it);
+ }
+ return result;
+}
+
+static void initUrlActionRestrictions()
+{
+ MY_D
+ const QString Any;
+
+ d->urlActionRestrictions.clear();
+ d->urlActionRestrictions.append(
+ URLActionRule("open", Any, Any, Any, Any, Any, Any, true));
+ d->urlActionRestrictions.append(
+ URLActionRule("list", Any, Any, Any, Any, Any, Any, true));
+// TEST:
+// d->urlActionRestrictions.append(
+// URLActionRule("list", Any, Any, Any, Any, Any, Any, false));
+// d->urlActionRestrictions.append(
+// URLActionRule("list", Any, Any, Any, "file", Any, QDir::homePath(), true));
+ d->urlActionRestrictions.append(
+ URLActionRule("link", Any, Any, Any, QLatin1String(":internet"), Any, Any, true));
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", Any, Any, Any, QLatin1String(":internet"), Any, Any, true));
+
+ // We allow redirections to file: but not from internet protocols, redirecting to file:
+ // is very popular among io-slaves and we don't want to break them
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", Any, Any, Any, QLatin1String("file"), Any, Any, true));
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", QLatin1String(":internet"), Any, Any, QLatin1String("file"), Any, Any, false));
+
+ // local protocols may redirect everywhere
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", QLatin1String(":local"), Any, Any, Any, Any, Any, true));
+
+ // Anyone may redirect to about:
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", Any, Any, Any, QLatin1String("about"), Any, Any, true));
+
+ // Anyone may redirect to mailto:
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", Any, Any, Any, QLatin1String("mailto"), Any, Any, true));
+
+ // Anyone may redirect to itself, cq. within it's own group
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", Any, Any, Any, QLatin1String("="), Any, Any, true));
+
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", QLatin1String("about"), Any, Any, Any, Any, Any, true));
+
+
+ KConfigGroup cg(KSharedConfig::openConfig(), "KDE URL Restrictions");
+ int count = cg.readEntry("rule_count", 0);
+ QString keyFormat = QString::fromLatin1("rule_%1");
+ for(int i = 1; i <= count; i++)
+ {
+ QString key = keyFormat.arg(i);
+ const QStringList rule = cg.readEntry(key, QStringList());
+ if (rule.count() != 8)
+ continue;
+ const QByteArray action = rule[0].toLatin1();
+ QString refProt = rule[1];
+ QString refHost = rule[2];
+ QString refPath = rule[3];
+ QString urlProt = rule[4];
+ QString urlHost = rule[5];
+ QString urlPath = rule[6];
+ bool bEnabled = (rule[7].toLower() == QLatin1String("true"));
+
+ if (refPath.startsWith(QLatin1String("$HOME")))
+ refPath.replace(0, 5, QDir::homePath());
+ else if (refPath.startsWith(QLatin1Char('~')))
+ refPath.replace(0, 1, QDir::homePath());
+ if (urlPath.startsWith(QLatin1String("$HOME")))
+ urlPath.replace(0, 5, QDir::homePath());
+ else if (urlPath.startsWith(QLatin1Char('~')))
+ urlPath.replace(0, 1, QDir::homePath());
+
+ if (refPath.startsWith(QLatin1String("$TMP")))
+ refPath.replace(0, 4, QDir::tempPath());
+ if (urlPath.startsWith(QLatin1String("$TMP")))
+ urlPath.replace(0, 4, QDir::tempPath());
+
+ d->urlActionRestrictions.append(
+ URLActionRule( action, refProt, refHost, refPath, urlProt, urlHost, urlPath, bEnabled));
+ }
+}
+
+namespace KAuthorized
+{
+// Called by KAuthorized::allowUrlAction in KIO
+KCONFIGCORE_EXPORT void allowUrlActionInternal(const QString &action, const QUrl &_baseURL, const QUrl &_destURL)
+{
+ MY_D
+ QMutexLocker locker((&d->mutex));
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 3, 0)
+ const QString basePath = _baseURL.adjusted(QUrl::StripTrailingSlash).path();
+ const QString destPath = _destURL.adjusted(QUrl::StripTrailingSlash).path();
+#else
+ const QString basePath = QUrl(_baseURL.toString(QUrl::StripTrailingSlash)).path();
+ const QString destPath = QUrl(_destURL.toString(QUrl::StripTrailingSlash)).path();
+#endif
+
+ d->urlActionRestrictions.append( URLActionRule
+ ( action.toLatin1(), _baseURL.scheme(), _baseURL.host(), basePath,
+ _destURL.scheme(), _destURL.host(), destPath, true));
+}
+
+// Called by KAuthorized::authorizeUrlAction in KIO
+KCONFIGCORE_EXPORT bool authorizeUrlActionInternal(const QString& action, const QUrl &_baseURL, const QUrl &_destURL, const QString& baseClass, const QString& destClass)
+{
+ MY_D
+ QMutexLocker locker(&(d->mutex));
+ if (d->blockEverything) return false;
+
+ if (_destURL.isEmpty())
+ return true;
+
+ bool result = false;
+ if (d->urlActionRestrictions.isEmpty())
+ initUrlActionRestrictions();
+
+ QUrl baseURL(_baseURL);
+ baseURL.setPath(QDir::cleanPath(baseURL.path()));
+
+ QUrl destURL(_destURL);
+ destURL.setPath(QDir::cleanPath(destURL.path()));
+
+ Q_FOREACH(const URLActionRule &rule, d->urlActionRestrictions) {
+ if ((result != rule.permission) && // No need to check if it doesn't make a difference
+ (action == QLatin1String(rule.action.constData())) &&
+ rule.baseMatch(baseURL, baseClass) &&
+ rule.destMatch(destURL, destClass, baseURL, baseClass))
+ {
+ result = rule.permission;
+ }
+ }
+ return result;
+}
+
+} // namespace
diff --git a/src/core/kauthorized.h b/src/core/kauthorized.h
new file mode 100644
index 00000000..a16368a8
--- /dev/null
+++ b/src/core/kauthorized.h
@@ -0,0 +1,73 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
+ Copyright (c) 1998, 1999 Waldo Bastian <bastian@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.
+*/
+
+#ifndef KAUTHORIZED_H
+#define KAUTHORIZED_H
+
+#include <kconfigcore_export.h>
+
+class QUrl;
+class QString;
+class QStringList;
+
+/**
+* Kiosk authorization framework
+*
+* Core functionality, see kauthorized.h for authorizeUrlAction.
+*/
+namespace KAuthorized
+{
+ /**
+ * Returns whether a certain action is authorized
+ * @param genericAction The name of a generic action
+ * @return true if the action is authorized
+ * @todo what are the generic actions?
+ */
+ KCONFIGCORE_EXPORT bool authorize(const QString& genericAction);
+
+ /**
+ * Returns whether a certain KAction is authorized.
+ *
+ * @param action The name of a KAction action. The name is prepended
+ * with "action/" before being passed to authorize()
+ * @return true if the KAction is authorized
+ */
+ KCONFIGCORE_EXPORT bool authorizeKAction(const QString& action);
+
+ /**
+ * Returns whether access to a certain control module is authorized.
+ *
+ * @param menuId identifying the control module, e.g. kde-mouse.desktop
+ * @return true if access to the module is authorized, false otherwise.
+ */
+ KCONFIGCORE_EXPORT bool authorizeControlModule(const QString& menuId);
+
+ /**
+ * Returns which control modules from a given list are authorized for access.
+ *
+ * @param menuIds list of menu-ids of control modules;
+ * an example of a menu-id is kde-mouse.desktop.
+ * @return Those control modules for which access has been authorized.
+ */
+ KCONFIGCORE_EXPORT QStringList authorizeControlModules(const QStringList& menuIds);
+
+}
+
+#endif
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 */
+}
diff --git a/src/core/kconfig.h b/src/core/kconfig.h
new file mode 100644
index 00000000..6dbf1d26
--- /dev/null
+++ b/src/core/kconfig.h
@@ -0,0 +1,397 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
+ Copyright (c) 2001 Waldo Bastian <bastian@kde.org>
+ 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.
+*/
+
+#ifndef KCONFIG_H
+#define KCONFIG_H
+
+#include "kconfigbase.h"
+
+#include <kconfigcore_export.h>
+
+#include <QtCore/QString>
+#include <QtCore/QVariant>
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <qstandardpaths.h>
+
+class KConfigGroup;
+class KEntryMap;
+class KConfigPrivate;
+
+/**
+ * \class KConfig kconfig.h <KConfig>
+ *
+ * \brief The central class of the KDE configuration data system.
+ *
+ * Quickstart:
+ *
+ * Get the default application config object via KSharedConfig::openConfig().
+ *
+ * Load a specific configuration file:
+ * \code
+ * KConfig config( "/etc/kderc", KConfig::SimpleConfig );
+ * \endcode
+ *
+ * Load the configuration of a specific component:
+ * \code
+ * KConfig config( "pluginrc" );
+ * \endcode
+ *
+ * In general it is recommended to use KSharedConfig instead of
+ * creating multiple instances of KConfig to avoid the overhead of
+ * separate objects or concerns about synchronizing writes to disk
+ * even if the configuration object is updated from multiple code paths.
+ * KSharedConfig provides a set of open methods as counterparts for the
+ * KConfig constructors.
+ *
+ * \sa KSharedConfig, KConfigGroup, <a href="http://techbase.kde.org/index.php?title=Development/Tutorials/KConfig">the techbase HOWTO on KConfig</a>.
+ */
+class KCONFIGCORE_EXPORT KConfig : public KConfigBase
+{
+public:
+ /**
+ * Determines how the system-wide and user's global settings will affect
+ * the reading of the configuration.
+ *
+ * If CascadeConfig is selected, system-wide configuration sources are used
+ * to provide defaults for the settings accessed through this object, or
+ * possibly to override those settings in certain cases.
+ *
+ * IncludeGlobals does the same, but with the global settings sources.
+ *
+ * Note that the main configuration source overrides the cascaded sources,
+ * which override those provided to addConfigSources(), which override the
+ * global sources. The exception is that if a key or group is marked as
+ * being immutable, it will not be overridden.
+ *
+ * Note that all values other than IncludeGlobals and CascadeConfig are
+ * convenience definitions for the basic mode.
+ * Do @em not combine them with anything.
+ */
+ enum OpenFlag {
+ IncludeGlobals = 0x01, ///< Blend kdeglobals into the config object.
+ CascadeConfig = 0x02, ///< Cascade to system-wide config files.
+
+ SimpleConfig = 0x00, ///< Just a single config file.
+ NoCascade = IncludeGlobals, ///< Include user's globals, but omit system settings.
+ NoGlobals = CascadeConfig, ///< Cascade to system settings, but omit user's globals.
+ FullConfig = IncludeGlobals|CascadeConfig ///< Fully-fledged config, including globals and cascading to system settings
+ };
+ Q_DECLARE_FLAGS(OpenFlags, OpenFlag)
+
+ /**
+ * Creates a KConfig object to manipulate a configuration file for the
+ * current application.
+ *
+ * If an absolute path is specified for @p file, that file will be used
+ * as the store for the configuration settings. If a non-absolute path
+ * is provided, the file will be looked for in the standard directory
+ * specified by type. If no path is provided, a default
+ * configuration file will be used based on the name of the main
+ * application component.
+ *
+ * @p mode determines whether the user or global settings will be allowed
+ * to influence the values returned by this object. See OpenFlags for
+ * more details.
+ *
+ * @note You probably want to use KSharedConfig::openConfig instead.
+ *
+ * @param file the name of the file. If an empty string is passed in
+ * and SimpleConfig is passed in for the OpenFlags, then an in-memory
+ * KConfig object is created which will not write out to file nor which
+ * requires any file in the filesystem at all.
+ * @param mode how global settings should affect the configuration
+ * options exposed by this KConfig object
+ * @param type The standard directory to look for the configuration
+ * file in
+ *
+ * @sa KSharedConfig::openConfig(const QString&, OpenFlags, const char*)
+ */
+ explicit KConfig(const QString& file = QString(), OpenFlags mode = FullConfig,
+ QStandardPaths::StandardLocation type = QStandardPaths::GenericConfigLocation);
+
+ /**
+ * @internal
+ *
+ * Creates a KConfig object using the specified backend. If the backend can not
+ * be found or loaded, then the standard configuration parser is used as a fallback.
+ *
+ * @param file the file to be parsed
+ * @param backend the backend to load
+ * @param type where to look for the file if an absolute path is not provided
+ *
+ * @since 4.1
+ */
+ KConfig(const QString& file, const QString& backend, QStandardPaths::StandardLocation type = QStandardPaths::GenericConfigLocation);
+
+ virtual ~KConfig();
+
+ /**
+ * Returns the standard location enum passed to the constructor.
+ * Used by KSharedConfig.
+ * @since 5.0
+ */
+ QStandardPaths::StandardLocation locationType() const;
+
+ /**
+ * Returns the filename used to store the configuration.
+ */
+ QString name() const;
+
+ /// @reimp
+ bool sync() Q_DECL_OVERRIDE;
+
+ /// Returns true if sync has any changes to write out.
+ /// @since 4.12
+ bool isDirty() const;
+
+ /// @reimp
+ void markAsClean();
+
+ /// @{ configuration object state
+ /// @reimp
+ AccessMode accessMode() const;
+
+ /**
+ * Whether the configuration can be written to.
+ *
+ * If @p warnUser is true and the configuration cannot be
+ * written to (ie: this method returns @c false), a warning
+ * message box will be shown to the user telling them to
+ * contact their system administrator to get the problem fixed.
+ *
+ * The most likely cause for this method returning @c false
+ * is that the user does not have write permission for the
+ * configuration file.
+ *
+ * @param warnUser whether to show a warning message to the user
+ * if the configuration cannot be written to
+ *
+ * @returns true if the configuration can be written to, false
+ * if the configuration cannot be written to
+ */
+ bool isConfigWritable(bool warnUser);
+ /// @}
+
+ /**
+ * Copies all entries from this config object to a new config
+ * object that will save itself to @p file.
+ *
+ * The configuration will not actually be saved to @p file
+ * until the returned object is destroyed, or sync() is called
+ * on it.
+ *
+ * Do not forget to delete the returned KConfig object if
+ * @p config was 0.
+ *
+ * @param file the new config object will save itself to
+ * @param config if not 0, copy to the given KConfig object rather
+ * than creating a new one
+ *
+ * @return @p config if it was set, otherwise a new KConfig object
+ */
+ KConfig* copyTo(const QString &file, KConfig *config = 0) const;
+
+ /**
+ * Ensures that the configuration file contains a certain update.
+ *
+ * If the configuration file does not contain the update @p id
+ * as contained in @p updateFile, kconf_update is run to update
+ * the configuration file.
+ *
+ * If you install config update files with critical fixes
+ * you may wish to use this method to verify that a critical
+ * update has indeed been performed to catch the case where
+ * a user restores an old config file from backup that has
+ * not been updated yet.
+ *
+ * @param id the update to check
+ * @param updateFile the file containing the update
+ */
+ void checkUpdate(const QString &id, const QString &updateFile);
+
+ /**
+ * Updates the state of this object to match the persistent storage.
+ */
+ void reparseConfiguration();
+
+ /// @{ extra config files
+ /**
+ * Adds the list of configuration sources to the merge stack.
+ *
+ * Currently only files are accepted as configuration sources.
+ *
+ * The first entry in @p sources is treated as the most general and will
+ * be overridden by the second entry. The settings in the final entry
+ * in @p sources will override all the other sources provided in the list.
+ *
+ * The settings in @p sources will also be overridden by the sources
+ * provided by any previous calls to addConfigSources().
+ *
+ * The settings in the global configuration sources will be overridden by
+ * the sources provided to this method (@see IncludeGlobals).
+ * All the sources provided to any call to this method will be overridden
+ * by any files that cascade from the source provided to the constructor
+ * (@see CascadeConfig), which will in turn be
+ * overridden by the source provided to the constructor.
+ *
+ * Note that only the most specific file, ie: the file provided to the
+ * constructor, will be written to by this object.
+ *
+ * The state is automatically updated by this method, so there is no need to call
+ * reparseConfiguration().
+ *
+ * @param sources A list of extra config sources.
+ */
+ void addConfigSources(const QStringList &sources);
+
+ /// @}
+ /// @{ locales
+ /**
+ * Returns the current locale.
+ */
+ QString locale() const;
+ /**
+ * Sets the locale to @p aLocale.
+ *
+ * The global locale is used by default.
+ *
+ * @note If set to the empty string, @b no locale will be matched. This effectively disables
+ * reading translated entries.
+ *
+ * @return @c true if locale was changed, @c false if the call had no
+ * effect (eg: @p aLocale was already the current locale for this
+ * object)
+ */
+ bool setLocale(const QString& aLocale);
+ /// @}
+
+ /// @{ defaults
+ /**
+ * When set, all readEntry calls return the system-wide (default) values
+ * instead of the user's settings.
+ *
+ * This is off by default.
+ *
+ * @param b whether to read the system-wide defaults instead of the
+ * user's settings
+ */
+ void setReadDefaults(bool b);
+ /**
+ * @returns @c true if the system-wide defaults will be read instead of the
+ * user's settings
+ */
+ bool readDefaults() const;
+ /// @}
+
+ /// @{ immutability
+ /// @reimp
+ bool isImmutable() const;
+ /// @}
+
+ /// @{ global
+ /**
+ * @deprecated
+ *
+ * Forces all following write-operations to be performed on @c kdeglobals,
+ * independent of the @c Global flag in writeEntry().
+ *
+ * @param force true to force writing to kdeglobals
+ * @see forceGlobal
+ */
+#ifndef KDE_NO_DEPRECATED
+ KCONFIGCORE_DEPRECATED void setForceGlobal(bool force);
+#endif
+ /**
+ * @deprecated
+ *
+ * Returns whether all entries are being written to @c kdeglobals.
+ *
+ * @return @c true if all entries are being written to @c kdeglobals
+ * @see setForceGlobal
+ * @deprecated
+ */
+#ifndef KDE_NO_DEPRECATED
+ KCONFIGCORE_DEPRECATED bool forceGlobal() const;
+#endif
+ /// @}
+
+ /// @reimp
+ QStringList groupList() const;
+
+ /**
+ * Returns a map (tree) of entries in a particular group.
+ *
+ * The entries are all returned as strings.
+ *
+ * @param aGroup The group to get entries from.
+ *
+ * @return A map of entries in the group specified, indexed by key.
+ * The returned map may be empty if the group is empty, or not found.
+ * @see QMap
+ */
+ QMap<QString, QString> entryMap(const QString &aGroup=QString()) const;
+
+ /**
+ * Sets the name of the application config file.
+ * @since 5.0
+ */
+ static void setMainConfigName(const QString& str);
+
+protected:
+ virtual bool hasGroupImpl(const QByteArray &group) const;
+ virtual KConfigGroup groupImpl( const QByteArray &b);
+ virtual const KConfigGroup groupImpl(const QByteArray &b) const;
+ virtual void deleteGroupImpl(const QByteArray &group, WriteConfigFlags flags = Normal);
+ virtual bool isGroupImmutableImpl(const QByteArray& aGroup) const;
+
+ friend class KConfigGroup;
+ friend class KConfigGroupPrivate;
+ friend class KSharedConfig;
+
+ /** Virtual hook, used to add new "virtual" functions while maintaining
+ * binary compatibility. Unused in this class.
+ */
+ virtual void virtual_hook( int id, void* data );
+
+ KConfigPrivate *const d_ptr;
+
+ KConfig(KConfigPrivate &d);
+
+private:
+ friend class KConfigTest;
+
+ QStringList keyList(const QString& aGroup=QString()) const;
+
+ /**
+ * @internal for KSharedConfig. Could be made public if needed, though.
+ */
+ static QString mainConfigName();
+
+ Q_DISABLE_COPY(KConfig)
+
+ Q_DECLARE_PRIVATE(KConfig)
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS( KConfig::OpenFlags )
+
+#endif // KCONFIG_H
diff --git a/src/core/kconfig_p.h b/src/core/kconfig_p.h
new file mode 100644
index 00000000..e6fb1ca0
--- /dev/null
+++ b/src/core/kconfig_p.h
@@ -0,0 +1,110 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
+ Copyright (c) 2001 Waldo Bastian <bastian@kde.org>
+ 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.
+*/
+
+#ifndef KCONFIG_P_H
+#define KCONFIG_P_H
+
+#include "kconfigdata.h"
+#include "kconfigbackend.h"
+#include "kconfiggroup.h"
+
+#include <QtCore/QStringList>
+#include <QtCore/QStack>
+#include <QtCore/QFile>
+#include <QtCore/QDir>
+
+class KConfigPrivate
+{
+ friend class KConfig;
+public:
+ KConfig::OpenFlags openFlags;
+ QStandardPaths::StandardLocation resourceType;
+
+ void changeFileName(const QString& fileName);
+
+ // functions for KConfigGroup
+ bool canWriteEntry(const QByteArray& group, const char* key, bool isDefault=false) const;
+ QString lookupData(const QByteArray& group, const char* key, KEntryMap::SearchFlags flags,
+ bool* expand) const;
+ QByteArray lookupData(const QByteArray& group, const char* key, KEntryMap::SearchFlags flags) const;
+
+ void putData(const QByteArray& group, const char* key, const QByteArray& value,
+ KConfigBase::WriteConfigFlags flags, bool expand=false);
+ void revertEntry(const QByteArray& group, const char* key);
+ QStringList groupList(const QByteArray& group) const;
+ // copies the entries from @p source to @p otherGroup changing all occurrences
+ // of @p source with @p destination
+ void copyGroup(const QByteArray& source, const QByteArray& destination,
+ KConfigGroup *otherGroup, KConfigBase::WriteConfigFlags flags) const;
+ QStringList keyListImpl(const QByteArray& theGroup) const;
+ QSet<QByteArray> allSubGroups(const QByteArray& parentGroup) const;
+ bool hasNonDeletedEntries(const QByteArray& group) const;
+
+ static QString expandString(const QString& value);
+
+protected:
+ QExplicitlySharedDataPointer<KConfigBackend> mBackend;
+
+ KConfigPrivate(KConfig::OpenFlags flags,
+ QStandardPaths::StandardLocation type);
+
+ virtual ~KConfigPrivate()
+ {
+ }
+
+ bool bDynamicBackend:1; // do we own the backend?
+private:
+ bool bDirty:1;
+ bool bLocaleInitialized:1;
+ bool bReadDefaults:1;
+ bool bFileImmutable:1;
+ bool bForceGlobal:1;
+ bool bSuppressGlobal:1;
+
+ QString sGlobalFileName;
+ static bool mappingsRegistered;
+
+
+ KEntryMap entryMap;
+ QString backendType;
+ QStack<QString> extraFiles;
+
+ QString locale;
+ QString fileName;
+ QString etc_kderc;
+ KConfigBase::AccessMode configState;
+
+ bool wantGlobals() const { return openFlags&KConfig::IncludeGlobals && !bSuppressGlobal; }
+ bool wantDefaults() const { return openFlags&KConfig::CascadeConfig; }
+ bool isSimple() const { return openFlags == KConfig::SimpleConfig; }
+ bool isReadOnly() const { return configState == KConfig::ReadOnly; }
+
+ bool setLocale(const QString& aLocale);
+ QStringList getGlobalFiles() const;
+ void parseGlobalFiles();
+ void parseConfigFiles();
+ void initCustomized(KConfig*);
+ bool lockLocal();
+};
+
+#endif // KCONFIG_P_H
diff --git a/src/core/kconfigbackend.cpp b/src/core/kconfigbackend.cpp
new file mode 100644
index 00000000..eb92a964
--- /dev/null
+++ b/src/core/kconfigbackend.cpp
@@ -0,0 +1,123 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006 Thomas Braxton <brax108@cox.net>
+ 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.
+*/
+
+#include "kconfigbackend.h"
+
+#include <QtCore/QDateTime>
+#include <QtCore/QStringList>
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QtCore/QHash>
+#include <QtCore/QDebug>
+
+#include "kconfig.h"
+#include "kconfigini_p.h"
+#include "kconfigdata.h"
+
+typedef QExplicitlySharedDataPointer<KConfigBackend> BackendPtr;
+
+class KConfigBackend::Private
+{
+public:
+ qint64 size;
+ QDateTime lastModified;
+ QString localFileName;
+
+ static QString whatSystem(const QString& /*fileName*/)
+ {
+ return QLatin1String("INI");
+ }
+};
+
+
+void KConfigBackend::registerMappings(const KEntryMap& /*entryMap*/)
+{
+}
+
+BackendPtr KConfigBackend::create(const QString& file, const QString& sys)
+{
+ //qDebug() << "creating a backend for file" << file << "with system" << sys;
+ const QString system = (sys.isEmpty() ? Private::whatSystem(file) : sys);
+ KConfigBackend* backend = 0;
+
+#if 0 // TODO port to Qt5 plugin loading
+ if (system.compare(QLatin1String("INI"), Qt::CaseInsensitive) != 0) {
+ const QString constraint = QString::fromLatin1("[X-KDE-PluginInfo-Name] ~~ '%1'").arg(system);
+ KService::List offers = KServiceTypeTrader::self()->query(QLatin1String("KConfigBackend"), constraint);
+
+ //qDebug() << "found" << offers.count() << "offers for KConfigBackend plugins with name" << system;
+ foreach (const KService::Ptr& offer, offers) {
+ backend = offer->createInstance<KConfigBackend>(0);
+ if (backend) {
+ //qDebug() << "successfully created a backend for" << system;
+ backend->setFilePath(file);
+ return BackendPtr(backend);
+ }
+ } // foreach offers
+ }
+#endif
+
+ //qDebug() << "default creation of the Ini backend";
+ backend = new KConfigIniBackend;
+ backend->setFilePath(file);
+ return BackendPtr(backend);
+}
+
+KConfigBackend::KConfigBackend()
+ : d(new Private)
+{
+}
+
+KConfigBackend::~KConfigBackend()
+{
+ delete d;
+}
+
+QDateTime KConfigBackend::lastModified() const
+{
+ return d->lastModified;
+}
+
+void KConfigBackend::setLastModified(const QDateTime& dt)
+{
+ d->lastModified = dt;
+}
+
+qint64 KConfigBackend::size() const
+{
+ return d->size;
+}
+
+void KConfigBackend::setSize(qint64 sz)
+{
+ d->size = sz;
+}
+
+QString KConfigBackend::filePath() const
+{
+ return d->localFileName;
+}
+
+void KConfigBackend::setLocalFilePath(const QString& file)
+{
+ d->localFileName = file;
+}
diff --git a/src/core/kconfigbackend.desktop b/src/core/kconfigbackend.desktop
new file mode 100644
index 00000000..bebcbff6
--- /dev/null
+++ b/src/core/kconfigbackend.desktop
@@ -0,0 +1,86 @@
+[Desktop Entry]
+Type=ServiceType
+X-KDE-ServiceType=KConfigBackend
+
+Comment=Storage backend for KConfig
+Comment[ar]=خلفية الحفظ لـ KConfig
+Comment[as]=KConfig ৰ বাবে ভঁৰালৰ বেকএন্ড
+Comment[ast]=Infraestructura d'atroxamientu pa KConfig
+Comment[be@latin]=Słužba schovišča dla systemy „KConfig”
+Comment[bg]=Storage backend for KConfig
+Comment[bn]=KConfig-এর স্টোরেজ ব্যাকেন্ড
+Comment[bn_IN]=KConfig-র জন্য ব্যবহৃত ব্যাক-এন্ড সংগ্রহস্থল
+Comment[bs]=Skladišna pozadina za K‑konfig
+Comment[ca]=Dorsal d'emmagatzematge per al KConfig
+Comment[ca@valencia]=Dorsal d'emmagatzematge per al KConfig
+Comment[cs]=Úložiště pro KConfig
+Comment[csb]=Zôpisownô zbiérnica dlô KConfig
+Comment[da]=Lagringsmotor til KConfig
+Comment[de]=Speicher-Unterstützung für KConfig
+Comment[el]=Σύστημα υποστήριξης αποθήκευσης για το KConfig
+Comment[en_GB]=Storage backend for KConfig
+Comment[es]=Motor de almacenamiento para KConfig
+Comment[et]=KConfigi salvestamise taustaprogramm
+Comment[eu]=KConfig-en biltegiratze euskarria
+Comment[fi]=Asetusvaraston taustaosa
+Comment[fr]=Module de stockage pour KConfig
+Comment[fy]=Opslach efterein foar KConfig
+Comment[ga]=Inneall stórais KConfig
+Comment[gl]=Infraestrutura de almacenaxe para KConfig
+Comment[gu]=KConfig માટે સંગ્રહ પાશ્ર્વભાગ
+Comment[he]=מנוע שמירה עבור KConfig
+Comment[hne]=के-कानफिग बर भंडार बैकएण्ड
+Comment[hr]=Skladišna pozadina za KConfig
+Comment[hsb]=składowanski backend za KConfig
+Comment[hu]=Tároló a KConfighoz
+Comment[hy]=Բահեստի հետևի մասը KConfig-ի համար
+Comment[ia]=Retro-administration de immagazinage (storage) pro Kconfig
+Comment[id]=Backend penyimpanan untuk KConfig
+Comment[is]=Geymslubakendi fyrir KConfig
+Comment[it]=Backend di archiviazione per KConfig
+Comment[ja]=KConfig のストレージバックエンド
+Comment[kk]=KConfig үшін сақтау тетігі
+Comment[km]=កម្មវិធី​ខាងក្រោយ​ការ​ផ្ទុក​សម្រាប់ KConfig
+Comment[kn]=ಕೆಕಾನ್ಫಿಗ್ ಗೆ ಸಂಗ್ರಹಣಾ ಹಿಂಬದಿ (ಬಾಕೆಂಡ್)
+Comment[ko]=KConfig의 저장소 백엔드
+Comment[ku]=Embara ser-dawî ji bo KVeavakirin
+Comment[lt]=KConfig saugojimo sąsaja
+Comment[lv]=KConfig glabāšanas aizmugure
+Comment[mai]=KConfig क' लेल भंडारक बैकेंड
+Comment[ml]=കെകോണ്‍ഫിഗിനുളള സ്റ്റോറേജ് ബാക്കെന്‍ഡ്
+Comment[mr]=के-कॉन्फिग करिता संचयन बॅकएन्ड
+Comment[ms]=Storan belakang untuk KConfig
+Comment[nb]=Bakgrunnslagring for KConfig
+Comment[nds]=Spieker-Hülpprogramm för KConfig
+Comment[nl]=Opslagbackend voor KConfig
+Comment[nn]=Lagringsmotor for KConfig
+Comment[or]=KConfig ପାଇଁ ଭଣ୍ଡାର ପଛ ପାଖ
+Comment[pa]=KConfig ਲਈ ਸਟੋਰੇਜ਼ ਬੈਕਐਂਡ
+Comment[pl]=Przechowywanie danych dla KConfig
+Comment[pt]=Armazenamento da infra-estrutura do KConfig
+Comment[pt_BR]=Infraestrutura de armazenamento para o KConfig
+Comment[ro]=Suport de stocare pentru KConfig
+Comment[ru]=Модуль хранения параметров KConfig
+Comment[se]=KConfig vurkenduogáš
+Comment[si]=KConfig සඳහා ගබඩා පසුඈදුම
+Comment[sk]=Úložisko pre KConfig
+Comment[sl]=Zaledje za shranjevanje v KConfig
+Comment[sq]=Mbështetëse Ruajtëse për KConfig
+Comment[sr]=Складишна позадина за К‑конфиг
+Comment[sr@ijekavian]=Складишна позадина за К‑конфиг
+Comment[sr@ijekavianlatin]=Skladišna pozadina za KConfig
+Comment[sr@latin]=Skladišna pozadina za KConfig
+Comment[sv]=Lagringsgränssnitt för KConfig
+Comment[ta]=கேவடிவமைப்பிற்கான பின்னணி சேமிப்பகம்
+Comment[tg]=Пуштибонии захирагоҳ барои KConfig
+Comment[th]=โปรแกรมเบื้องหลังพื้นที่จัดเก็บข้อมูลสำหรับ KConfig
+Comment[tr]=KConfig için Depolama Arka Ucu
+Comment[tt]=KConfig өчен саклау бэкенды
+Comment[ug]=KConfig نىڭ ساقلاش ئارقا ئۇچى
+Comment[uk]=Засіб збереження для KConfig
+Comment[vi]=Hậu trường lưu trữ cho KConfig
+Comment[wa]=Bouye di fond di stocaedje po KConfig
+Comment[x-test]=xxStorage backend for KConfigxx
+Comment[zh_CN]=KConfig 存储后端
+Comment[zh_TW]=KConfig 儲存後端介面
+
diff --git a/src/core/kconfigbackend.h b/src/core/kconfigbackend.h
new file mode 100644
index 00000000..49239e66
--- /dev/null
+++ b/src/core/kconfigbackend.h
@@ -0,0 +1,211 @@
+/*
+ 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>
+ Portions 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.
+*/
+
+#ifndef KCONFIGBACKEND_H
+#define KCONFIGBACKEND_H
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QExplicitlySharedDataPointer>
+
+#include <kconfigcore_export.h>
+#include <kconfigbase.h>
+
+class KEntryMap;
+class QFile;
+class QByteArray;
+class QDateTime;
+
+/**
+ * \class KConfigBackend kconfigbackend.h <KConfigBackend>
+ *
+ * Provides the implementation for accessing configuration sources.
+ *
+ * KDELibs only provides an INI backend, but this class can be used
+ * to create plugins that allow access to other file formats and
+ * configuration systems.
+ */
+class KCONFIGCORE_EXPORT KConfigBackend : public QObject, public QSharedData
+{
+ Q_OBJECT
+ Q_FLAGS(ParseOption)
+ Q_FLAGS(WriteOption)
+
+public:
+ /**
+ * Creates a new KConfig backend.
+ *
+ * If no @p system is given, or the given @p system is unknown, this method tries
+ * to determine the correct backend to use.
+ *
+ * @param fileName the absolute file name of the configuration file
+ * @param system the configuration system to use
+ * @return a KConfigBackend object to be used with KConfig
+ */
+ static QExplicitlySharedDataPointer<KConfigBackend> create(const QString& fileName = QString(),
+ const QString& system = QString());
+
+ /**
+ * Registers mappings from directories/files to configuration systems
+ *
+ * Allows you to tell KConfigBackend that create() should use a particular
+ * backend for a particular file or directory.
+ *
+ * @warning currently does nothing
+ *
+ * @param entryMap the KEntryMap to build the mappings from
+ */
+ static void registerMappings(const KEntryMap& entryMap);
+
+ /** Destroys the backend */
+ virtual ~KConfigBackend();
+
+ /** Allows the behaviour of parseConfig() to be tuned */
+ enum ParseOption {
+ ParseGlobal = 1, /// entries should be marked as @em global
+ ParseDefaults = 2, /// entries should be marked as @em default
+ ParseExpansions = 4 /// entries are allowed to be marked as @em expandable
+ };
+ /// @typedef typedef QFlags<ParseOption> ParseOptions
+ Q_DECLARE_FLAGS(ParseOptions, ParseOption)
+
+ /** Allows the behaviour of writeConfig() to be tuned */
+ enum WriteOption {
+ WriteGlobal = 1 /// only write entries marked as "global"
+ };
+ /// @typedef typedef QFlags<WriteOption> WriteOptions
+ Q_DECLARE_FLAGS(WriteOptions, WriteOption)
+
+ /** Return value from parseConfig() */
+ enum ParseInfo {
+ ParseOk, /// the configuration was opened read/write
+ ParseImmutable, /// the configuration is @em immutable
+ ParseOpenError /// the configuration could not be opened
+ };
+
+ /**
+ * Read persistent storage
+ *
+ * @param locale the locale to read entries for (if the backend supports localized entries)
+ * @param pWriteBackMap the KEntryMap where the entries are placed
+ * @param options @see ParseOptions
+ * @return @see ParseInfo
+ */
+ virtual ParseInfo parseConfig(const QByteArray& locale,
+ KEntryMap& pWriteBackMap,
+ ParseOptions options = ParseOptions()) = 0;
+
+ /**
+ * Write the @em dirty entries to permanent storage
+ *
+ * @param locale the locale to write entries for (if the backend supports localized entries)
+ * @param entryMap the KEntryMap containing the config object's entries.
+ * @param options @see WriteOptions
+ *
+ * @return @c true if the write was successful, @c false if writing the configuration failed
+ */
+ virtual bool writeConfig(const QByteArray& locale, KEntryMap& entryMap,
+ WriteOptions options) = 0;
+
+ /**
+ * If isWritable() returns false, writeConfig() will always fail.
+ *
+ * @return @c true if the configuration is writable, @c false if it is immutable
+ */
+ virtual bool isWritable() const = 0;
+ /**
+ * When isWritable() returns @c false, return an error message to
+ * explain to the user why saving configuration will not work.
+ *
+ * The return value when isWritable() returns @c true is undefined.
+ *
+ * @returns a translated user-visible explanation for the configuration
+ * object not being writable
+ */
+ virtual QString nonWritableErrorMessage() const = 0;
+ /**
+ * @return the read/write status of the configuration object
+ *
+ * @see KConfigBase::AccessMode
+ */
+ virtual KConfigBase::AccessMode accessMode() const = 0;
+ /**
+ * Create the enclosing object of the configuration object
+ *
+ * For example, if the configuration object is a file, this should create
+ * the parent directory.
+ */
+ virtual void createEnclosing() = 0;
+
+ /**
+ * Set the file path.
+ *
+ * @note @p path @b MUST be @em absolute.
+ *
+ * @param path the absolute file path
+ */
+ virtual void setFilePath(const QString& path) = 0;
+
+ /**
+ * Lock the file
+ */
+ virtual bool lock() = 0;
+ /**
+ * Release the lock on the file
+ */
+ virtual void unlock() = 0;
+ /**
+ * @return @c true if the file is locked, @c false if it is not locked
+ */
+ virtual bool isLocked() const = 0;
+
+ /**
+ * @return the date and time when the object was last modified
+ */
+ QDateTime lastModified() const;
+ /** @return the absolute path to the object */
+ QString filePath() const;
+ /** @return the size of the object */
+ qint64 size() const;
+
+protected:
+ KConfigBackend();
+ void setLastModified(const QDateTime& dt);
+ void setSize(qint64 sz);
+ void setLocalFilePath(const QString& file);
+
+private:
+ class Private;
+ Private *const d;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(KConfigBackend::ParseOptions)
+Q_DECLARE_OPERATORS_FOR_FLAGS(KConfigBackend::WriteOptions)
+
+/**
+ * Register a KConfig backend when it is contained in a loadable module
+ */
+#define K_EXPORT_KCONFIGBACKEND(libname, classname) \
+K_PLUGIN_FACTORY(factory, registerPlugin<classname>();)
+
+
+#endif // KCONFIGBACKEND_H
diff --git a/src/core/kconfigbase.cpp b/src/core/kconfigbase.cpp
new file mode 100644
index 00000000..4be7ac23
--- /dev/null
+++ b/src/core/kconfigbase.cpp
@@ -0,0 +1,112 @@
+/*
+ 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.
+*/
+
+#include "kconfigbase.h"
+
+#include "kconfiggroup.h"
+
+#include <QtCore/QString>
+
+bool KConfigBase::hasGroup(const QString &group) const
+{
+ return hasGroupImpl(group.toUtf8());
+}
+
+bool KConfigBase::hasGroup(const char *group) const
+{
+ return hasGroupImpl(QByteArray(group));
+}
+
+bool KConfigBase::hasGroup(const QByteArray &group) const
+{
+ return hasGroupImpl(group);
+}
+
+KConfigGroup KConfigBase::group( const QByteArray &b)
+{
+ return groupImpl(b);
+}
+
+KConfigGroup KConfigBase::group( const QString &str)
+{
+ return groupImpl(str.toUtf8());
+}
+
+KConfigGroup KConfigBase::group( const char *str)
+{
+ return groupImpl(QByteArray(str));
+}
+
+const KConfigGroup KConfigBase::group( const QByteArray &b ) const
+{
+ return groupImpl(b);
+}
+
+const KConfigGroup KConfigBase::group( const QString &s ) const
+{
+ return groupImpl(s.toUtf8());
+}
+
+const KConfigGroup KConfigBase::group( const char *s ) const
+{
+ return groupImpl(QByteArray(s));
+}
+
+void KConfigBase::deleteGroup(const QByteArray &group, WriteConfigFlags flags)
+{
+ deleteGroupImpl(group, flags);
+}
+
+void KConfigBase::deleteGroup(const QString &group, WriteConfigFlags flags)
+{
+ deleteGroupImpl(group.toUtf8(), flags);
+}
+
+void KConfigBase::deleteGroup(const char *group, WriteConfigFlags flags)
+{
+ deleteGroupImpl(QByteArray(group), flags);
+}
+
+bool KConfigBase::isGroupImmutable(const QByteArray& aGroup) const
+{
+ return isGroupImmutableImpl(aGroup);
+}
+
+bool KConfigBase::isGroupImmutable(const QString& aGroup) const
+{
+ return isGroupImmutableImpl(aGroup.toUtf8());
+}
+
+
+bool KConfigBase::isGroupImmutable(const char *aGroup) const
+{
+ return isGroupImmutableImpl(QByteArray(aGroup));
+}
+
+KConfigBase::~KConfigBase()
+{}
+
+KConfigBase::KConfigBase()
+{}
+
+void KConfigBase::virtual_hook(int , void *)
+{}
diff --git a/src/core/kconfigbase.h b/src/core/kconfigbase.h
new file mode 100644
index 00000000..782ff4b6
--- /dev/null
+++ b/src/core/kconfigbase.h
@@ -0,0 +1,184 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
+ Copyright (c) 2001 Waldo Bastian <bastian@kde.org>
+ 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.
+*/
+
+#ifndef KCONFIGBASE_H
+#define KCONFIGBASE_H
+
+#include <kconfigcore_export.h>
+
+#include <QtCore/QtGlobal>
+
+class QStringList;
+class KConfigGroup;
+class KConfigBasePrivate;
+
+/**
+ * \class KConfigBase kconfigbase.h <KConfigBase>
+ */
+class KCONFIGCORE_EXPORT KConfigBase
+{
+public:
+ /**
+ * Flags to control write entry
+ */
+ enum WriteConfigFlag
+ {
+ Persistent = 0x01,
+ /**<
+ * Save this entry when saving the config object.
+ */
+ Global = 0x02,
+ /**<
+ * Save the entry to the global %KDE config file instead of the
+ * application specific config file.
+ */
+ Localized = 0x04,
+ /**<
+ * Add the locale tag to the key when writing it.
+ */
+ Normal=Persistent
+ /**<
+ * Save the entry to the application specific config file without
+ * a locale tag. This is the default.
+ */
+
+ };
+ Q_DECLARE_FLAGS(WriteConfigFlags, WriteConfigFlag)
+
+ /**
+ * Destructs the KConfigBase object.
+ */
+ virtual ~KConfigBase();
+
+ /**
+ * Returns a list of groups that are known about.
+ *
+ * @return The list of groups.
+ **/
+ virtual QStringList groupList() const = 0;
+
+ /**
+ * Returns true if the specified group is known about.
+ *
+ * @param group The group to search for.
+ * @return true if the group exists.
+ */
+ bool hasGroup(const QString &group) const;
+ bool hasGroup(const char *group) const;
+ bool hasGroup(const QByteArray &group) const;
+
+ /**
+ * Returns an object for the named subgroup.
+ *
+ * @param group the group to open. Pass a null string on to the KConfig
+ * object to obtain a handle on the root group.
+ * @return The list of groups.
+ **/
+ KConfigGroup group(const QByteArray &group);
+ KConfigGroup group(const QString &group);
+ KConfigGroup group(const char *group);
+
+ /**
+ * @overload
+ **/
+ const KConfigGroup group(const QByteArray &group) const;
+ const KConfigGroup group(const QString &group) const;
+ const KConfigGroup group(const char *group) const;
+
+ /**
+ * Delete @p aGroup. This marks @p aGroup as @em deleted in the config object. This effectively
+ * removes any cascaded values from config files earlier in the stack.
+ */
+ void deleteGroup(const QByteArray &group, WriteConfigFlags flags = Normal);
+ void deleteGroup(const QString &group, WriteConfigFlags flags = Normal);
+ void deleteGroup(const char *group, WriteConfigFlags flags = Normal);
+
+ /**
+ * Syncs the configuration object that this group belongs to.
+ * Unrelated concurrent changes to the same file are merged and thus
+ * not overwritten. Note however, that this object is @em not automatically
+ * updated with those changes.
+ */
+ virtual bool sync() = 0;
+
+ /**
+ * Reset the dirty flags of all entries in the entry map, so the
+ * values will not be written to disk on a later call to sync().
+ */
+ virtual void markAsClean() = 0;
+
+ /**
+ * Possible return values for accessMode().
+ */
+ enum AccessMode { NoAccess, ReadOnly, ReadWrite };
+
+ /**
+ * Returns the access mode of the app-config object.
+ *
+ * Possible return values
+ * are NoAccess (the application-specific config file could not be
+ * opened neither read-write nor read-only), ReadOnly (the
+ * application-specific config file is opened read-only, but not
+ * read-write) and ReadWrite (the application-specific config
+ * file is opened read-write).
+ *
+ * @return the access mode of the app-config object
+ */
+ virtual AccessMode accessMode() const = 0;
+
+ /**
+ * Checks whether this configuration object can be modified.
+ * @return whether changes may be made to this configuration object.
+ */
+ virtual bool isImmutable() const = 0;
+
+ /**
+ * Can changes be made to the entries in @p aGroup?
+ *
+ * @param aGroup The group to check for immutability.
+ * @return @c false if the entries in @p aGroup can be modified.
+ */
+ bool isGroupImmutable(const QByteArray& aGroup) const;
+ bool isGroupImmutable(const QString& aGroup) const;
+ bool isGroupImmutable(const char *aGroup) const;
+
+protected:
+ KConfigBase();
+
+ virtual bool hasGroupImpl(const QByteArray &group) const = 0;
+ virtual KConfigGroup groupImpl( const QByteArray &b) = 0;
+ virtual const KConfigGroup groupImpl(const QByteArray &b) const = 0;
+ virtual void deleteGroupImpl(const QByteArray &group, WriteConfigFlags flags = Normal) = 0;
+ virtual bool isGroupImmutableImpl(const QByteArray& aGroup) const = 0;
+
+ /** Virtual hook, used to add new "virtual" functions while maintaining
+ * binary compatibility. Unused in this class.
+ */
+ virtual void virtual_hook( int id, void* data );
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(KConfigBase::WriteConfigFlags)
+
+
+
+#endif // KCONFIG_H
diff --git a/src/core/kconfigbase_p.h b/src/core/kconfigbase_p.h
new file mode 100644
index 00000000..c1066267
--- /dev/null
+++ b/src/core/kconfigbase_p.h
@@ -0,0 +1,30 @@
+/*
+ This file is part of the KDE libraries
+ 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.
+*/
+
+#ifndef KCONFIGBASE_P_H
+#define KCONFIGBASE_P_H
+
+#include <QtCore/QSharedData>
+
+class KConfigBasePrivate : public QSharedData
+{
+};
+#endif
diff --git a/src/core/kconfigdata.cpp b/src/core/kconfigdata.cpp
new file mode 100644
index 00000000..74a068be
--- /dev/null
+++ b/src/core/kconfigdata.cpp
@@ -0,0 +1,317 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
+ Copyright (c) 1999-2000 Preston Brown <pbrown@kde.org>
+ Copyright (C) 1996-2000 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.
+*/
+
+#include <kconfigdata.h>
+
+QDebug operator<<(QDebug dbg, const KEntryKey& key)
+{
+ dbg.nospace() << "[" << key.mGroup << ", " << key.mKey << (key.bLocal?" localized":"") <<
+ (key.bDefault?" default":"") << (key.bRaw?" raw":"") << "]";
+ return dbg.space();
+}
+
+QDebug operator<<(QDebug dbg, const KEntry& entry)
+{
+ dbg.nospace() << "[" << entry.mValue << (entry.bDirty?" dirty":"") <<
+ (entry.bGlobal?" global":"") << (entry.bImmutable?" immutable":"") <<
+ (entry.bDeleted?" deleted":"") << (entry.bReverted?" reverted":"") <<
+ (entry.bExpand?" expand":"") << "]";
+
+ return dbg.space();
+}
+
+QMap< KEntryKey, KEntry >::Iterator KEntryMap::findExactEntry(const QByteArray& group, const QByteArray& key, KEntryMap::SearchFlags flags)
+{
+ KEntryKey theKey(group, key, bool(flags&SearchLocalized), bool(flags&SearchDefaults));
+ return find(theKey);
+}
+
+QMap< KEntryKey, KEntry >::Iterator KEntryMap::findEntry(const QByteArray& group, const QByteArray& key, KEntryMap::SearchFlags flags)
+{
+ KEntryKey theKey(group, key, false, bool(flags&SearchDefaults));
+
+ // try the localized key first
+ if (flags&SearchLocalized) {
+ theKey.bLocal = true;
+
+ Iterator it = find(theKey);
+ if (it != end())
+ return it;
+
+ theKey.bLocal = false;
+ }
+ return find(theKey);
+}
+
+QMap< KEntryKey, KEntry >::ConstIterator KEntryMap::findEntry(const QByteArray& group, const QByteArray& key, KEntryMap::SearchFlags flags) const
+{
+ KEntryKey theKey(group, key, false, bool(flags&SearchDefaults));
+
+ // try the localized key first
+ if (flags&SearchLocalized) {
+ theKey.bLocal = true;
+
+ ConstIterator it = find(theKey);
+ if (it != constEnd())
+ return it;
+
+ theKey.bLocal = false;
+ }
+ return find(theKey);
+}
+
+bool KEntryMap::setEntry(const QByteArray& group, const QByteArray& key, const QByteArray& value, KEntryMap::EntryOptions options)
+{
+ KEntryKey k;
+ KEntry e;
+ bool newKey = false;
+
+ const Iterator it = findExactEntry(group, key, SearchFlags(options>>16));
+
+ if (key.isEmpty()) { // inserting a group marker
+ k.mGroup = group;
+ e.bImmutable = (options&EntryImmutable);
+ if (options&EntryDeleted) {
+ qWarning("Internal KConfig error: cannot mark groups as deleted");
+ }
+ if(it == end()) {
+ insert(k, e);
+ return true;
+ } else if(it.value() == e) {
+ return false;
+ }
+
+ it.value() = e;
+ return true;
+ }
+
+
+ if (it != end()) {
+ if (it->bImmutable)
+ return false; // we cannot change this entry. Inherits group immutability.
+ k = it.key();
+ e = *it;
+ //qDebug() << "found existing entry for key" << k;
+ } else {
+ // make sure the group marker is in the map
+ KEntryMap const *that = this;
+ ConstIterator cit = that->findEntry(group);
+ if (cit == constEnd())
+ insert(KEntryKey(group), KEntry());
+ else if (cit->bImmutable)
+ return false; // this group is immutable, so we cannot change this entry.
+
+ k = KEntryKey(group, key);
+ newKey = true;
+ }
+
+ // set these here, since we may be changing the type of key from the one we found
+ k.bLocal = (options&EntryLocalized);
+ k.bDefault = (options&EntryDefault);
+ k.bRaw = (options&EntryRawKey);
+
+ e.mValue = value;
+ e.bDirty = e.bDirty || (options&EntryDirty);
+ e.bGlobal = (options&EntryGlobal); //we can't use || here, because changes to entries in
+ //kdeglobals would be written to kdeglobals instead
+ //of the local config file, regardless of the globals flag
+ e.bImmutable = e.bImmutable || (options&EntryImmutable);
+ if (value.isNull())
+ e.bDeleted = e.bDeleted || (options&EntryDeleted);
+ else
+ e.bDeleted = false; // setting a value to a previously deleted entry
+ e.bExpand = (options&EntryExpansion);
+ e.bReverted = false;
+
+ if(newKey)
+ {
+ //qDebug() << "inserting" << k << "=" << value;
+ insert(k, e);
+ if(k.bDefault)
+ {
+ k.bDefault = false;
+ //qDebug() << "also inserting" << k << "=" << value;
+ insert(k, e);
+ }
+ // TODO check for presence of unlocalized key
+ return true;
+ } else {
+// KEntry e2 = it.value();
+ if(it.value() != e)
+ {
+ //qDebug() << "changing" << k << "from" << e.mValue << "to" << value;
+ it.value() = e;
+ if(k.bDefault)
+ {
+ KEntryKey nonDefaultKey(k);
+ nonDefaultKey.bDefault = false;
+ insert(nonDefaultKey, e);
+ }
+ if (!(options & EntryLocalized)) {
+ KEntryKey theKey(group, key, true, false);
+ //qDebug() << "non-localized entry, remove localized one:" << theKey;
+ remove(theKey);
+ if (k.bDefault) {
+ theKey.bDefault = true;
+ remove(theKey);
+ }
+ }
+ return true;
+ } else {
+ //qDebug() << k << "was already set to" << e.mValue;
+ if (!(options & EntryLocalized)) {
+ //qDebug() << "unchanged non-localized entry, remove localized one.";
+ KEntryKey theKey(group, key, true, false);
+ bool ret = false;
+ Iterator cit = find(theKey);
+ if (cit != end()) {
+ erase(cit);
+ ret = true;
+ }
+ if (k.bDefault) {
+ theKey.bDefault = true;
+ Iterator cit = find(theKey);
+ if (cit != end()) {
+ erase(cit);
+ return true;
+ }
+ }
+ return ret;
+ }
+ //qDebug() << "localized entry, unchanged, return false";
+ // When we are writing a default, we know that the non-
+ // default is the same as the default, so we can simply
+ // use the same branch.
+ return false;
+ }
+ }
+}
+
+QString KEntryMap::getEntry(const QByteArray& group, const QByteArray& key, const QString& defaultValue, KEntryMap::SearchFlags flags, bool* expand) const
+{
+ const ConstIterator it = findEntry(group, key, flags);
+ QString theValue = defaultValue;
+
+ if (it != constEnd() && !it->bDeleted) {
+ if (!it->mValue.isNull()) {
+ const QByteArray data=it->mValue;
+ theValue = QString::fromUtf8(data.constData(), data.length());
+ if (expand)
+ *expand = it->bExpand;
+ }
+ }
+
+ return theValue;
+}
+
+bool KEntryMap::hasEntry(const QByteArray& group, const QByteArray& key, KEntryMap::SearchFlags flags) const
+{
+ const ConstIterator it = findEntry(group, key, flags);
+ if (it == constEnd())
+ return false;
+ if (it->bDeleted)
+ return false;
+ if (key.isNull()) { // looking for group marker
+ return it->mValue.isNull();
+ }
+ // if it->bReverted, we'll just return true; the real answer depends on lookup up with SearchDefaults, though.
+ return true;
+}
+
+bool KEntryMap::getEntryOption(const QMap< KEntryKey, KEntry >::ConstIterator& it, KEntryMap::EntryOption option) const
+{
+ if (it != constEnd()) {
+ switch (option) {
+ case EntryDirty:
+ return it->bDirty;
+ case EntryLocalized:
+ return it.key().bLocal;
+ case EntryGlobal:
+ return it->bGlobal;
+ case EntryImmutable:
+ return it->bImmutable;
+ case EntryDeleted:
+ return it->bDeleted;
+ case EntryExpansion:
+ return it->bExpand;
+ default:
+ break; // fall through
+ }
+ }
+
+ return false;
+}
+
+void KEntryMap::setEntryOption(QMap< KEntryKey, KEntry >::Iterator it, KEntryMap::EntryOption option, bool bf)
+{
+ if (it != end()) {
+ switch (option) {
+ case EntryDirty:
+ it->bDirty = bf;
+ break;
+ case EntryGlobal:
+ it->bGlobal = bf;
+ break;
+ case EntryImmutable:
+ it->bImmutable = bf;
+ break;
+ case EntryDeleted:
+ it->bDeleted = bf;
+ break;
+ case EntryExpansion:
+ it->bExpand = bf;
+ break;
+ default:
+ break; // fall through
+ }
+ }
+}
+
+bool KEntryMap::revertEntry(const QByteArray& group, const QByteArray& key, KEntryMap::SearchFlags flags)
+{
+ Q_ASSERT((flags & KEntryMap::SearchDefaults) == 0);
+ Iterator entry = findEntry(group, key, flags);
+ if (entry != end()) {
+ //qDebug() << "reverting" << entry.key() << " = " << entry->mValue;
+ if (entry->bReverted) { // already done before
+ return false;
+ }
+
+ KEntryKey defaultKey(entry.key());
+ defaultKey.bDefault = true;
+ //qDebug() << "looking up default entry with key=" << defaultKey;
+ const ConstIterator defaultEntry = constFind(defaultKey);
+ if (defaultEntry != constEnd()) {
+ Q_ASSERT(defaultEntry.key().bDefault);
+ //qDebug() << "found, update entry";
+ *entry = *defaultEntry; // copy default value, for subsequent lookups
+ } else {
+ entry->mValue = QByteArray();
+ }
+ entry->bDirty = true;
+ entry->bReverted = true; // skip it when writing out to disk
+
+ //qDebug() << "Here's what we have now:" << *this;
+ return true;
+ }
+ return false;
+}
diff --git a/src/core/kconfigdata.h b/src/core/kconfigdata.h
new file mode 100644
index 00000000..f7ad81b9
--- /dev/null
+++ b/src/core/kconfigdata.h
@@ -0,0 +1,237 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
+ Copyright (c) 1999-2000 Preston Brown <pbrown@kde.org>
+ Copyright (C) 1996-2000 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.
+*/
+
+#ifndef KCONFIGDATA_H
+#define KCONFIGDATA_H
+
+#include <QtCore/QByteArray>
+#include <QtCore/QString>
+#include <QtCore/QMap>
+#include <QtCore/QDebug>
+
+/**
+ * map/dict/list config node entry.
+ * @internal
+ */
+struct KEntry
+{
+ /** Constructor. @internal */
+ KEntry()
+ : mValue(), bDirty(false),
+ bGlobal(false), bImmutable(false), bDeleted(false), bExpand(false), bReverted(false) {}
+ /** @internal */
+ QByteArray mValue;
+ /**
+ * Must the entry be written back to disk?
+ */
+ bool bDirty :1;
+ /**
+ * Entry should be written to the global config file
+ */
+ bool bGlobal:1;
+ /**
+ * Entry can not be modified.
+ */
+ bool bImmutable:1;
+ /**
+ * Entry has been deleted.
+ */
+ bool bDeleted:1;
+ /**
+ * Whether to apply dollar expansion or not.
+ */
+ bool bExpand:1;
+ /**
+ * Entry has been reverted to its default value (from a more global file).
+ */
+ bool bReverted:1;
+};
+
+// These operators are used to check whether an entry which is about
+// to be written equals the previous value. As such, this intentionally
+// omits the dirty flag from the comparison.
+inline bool operator ==(const KEntry &k1, const KEntry &k2)
+{
+ return k1.bGlobal == k2.bGlobal && k1.bImmutable == k2.bImmutable
+ && k1.bDeleted == k2.bDeleted && k1.bExpand == k2.bExpand
+ && k1.mValue == k2.mValue;
+}
+
+inline bool operator !=(const KEntry &k1, const KEntry &k2)
+{
+ return !(k1 == k2);
+}
+
+/**
+ * key structure holding both the actual key and the group
+ * to which it belongs.
+ * @internal
+ */
+struct KEntryKey
+{
+ /** Constructor. @internal */
+ KEntryKey(const QByteArray& _group = QByteArray(),
+ const QByteArray& _key = QByteArray(), bool isLocalized=false, bool isDefault=false)
+ : mGroup(_group), mKey(_key), bLocal(isLocalized), bDefault(isDefault), bRaw(false)
+ { ; }
+ /**
+ * The "group" to which this EntryKey belongs
+ */
+ QByteArray mGroup;
+ /**
+ * The _actual_ key of the entry in question
+ */
+ QByteArray mKey;
+ /**
+ * Entry is localised or not
+ */
+ bool bLocal :1;
+ /**
+ * Entry indicates if this is a default value.
+ */
+ bool bDefault:1;
+ /** @internal
+ * Key is a raw unprocessed key.
+ * @warning this should only be set during merging, never for normal use.
+ */
+ bool bRaw:1;
+};
+
+/**
+ * Compares two KEntryKeys (needed for QMap). The order is localized, localized-default,
+ * non-localized, non-localized-default
+ * @internal
+ */
+inline bool operator <(const KEntryKey &k1, const KEntryKey &k2)
+{
+ int result = qstrcmp(k1.mGroup, k2.mGroup);
+ if (result != 0) {
+ return result < 0;
+ }
+
+ result = qstrcmp(k1.mKey, k2.mKey);
+ if (result != 0) {
+ return result < 0;
+ }
+
+ if (k1.bLocal != k2.bLocal)
+ return k1.bLocal;
+ return (!k1.bDefault && k2.bDefault);
+}
+
+
+QDebug operator<<(QDebug dbg, const KEntryKey& key);
+QDebug operator<<(QDebug dbg, const KEntry& entry);
+
+/**
+ * \relates KEntry
+ * type specifying a map of entries (key,value pairs).
+ * The keys are actually a key in a particular config file group together
+ * with the group name.
+ * @internal
+ */
+class KEntryMap : public QMap<KEntryKey, KEntry>
+{
+ public:
+ enum SearchFlag {
+ SearchDefaults=1,
+ SearchLocalized=2
+ };
+ Q_DECLARE_FLAGS(SearchFlags, SearchFlag)
+
+ enum EntryOption {
+ EntryDirty=1,
+ EntryGlobal=2,
+ EntryImmutable=4,
+ EntryDeleted=8,
+ EntryExpansion=16,
+ EntryRawKey=32,
+ EntryDefault=(SearchDefaults<<16),
+ EntryLocalized=(SearchLocalized<<16)
+ };
+ Q_DECLARE_FLAGS(EntryOptions, EntryOption)
+
+ Iterator findExactEntry(const QByteArray& group, const QByteArray& key = QByteArray(),
+ SearchFlags flags = SearchFlags());
+
+ Iterator findEntry(const QByteArray& group, const QByteArray& key = QByteArray(),
+ SearchFlags flags = SearchFlags());
+
+ ConstIterator findEntry(const QByteArray& group, const QByteArray& key = QByteArray(),
+ SearchFlags flags = SearchFlags()) const;
+
+ /**
+ * Returns true if the entry gets dirtied or false in other case
+ */
+ bool setEntry(const QByteArray& group, const QByteArray& key,
+ const QByteArray& value, EntryOptions options);
+
+ void setEntry(const QByteArray& group, const QByteArray& key,
+ const QString & value, EntryOptions options)
+ {
+ setEntry(group, key, value.toUtf8(), options);
+ }
+
+ QString getEntry(const QByteArray& group, const QByteArray& key,
+ const QString & defaultValue = QString(),
+ SearchFlags flags = SearchFlags(),
+ bool * expand=0) const;
+
+ bool hasEntry(const QByteArray& group, const QByteArray& key = QByteArray(),
+ SearchFlags flags = SearchFlags()) const;
+
+ bool getEntryOption(const ConstIterator& it, EntryOption option) const;
+ bool getEntryOption(const QByteArray& group, const QByteArray& key,
+ SearchFlags flags, EntryOption option) const
+ {
+ return getEntryOption(findEntry(group, key, flags), option);
+ }
+
+ void setEntryOption(Iterator it, EntryOption option, bool bf);
+ void setEntryOption(const QByteArray& group, const QByteArray& key, SearchFlags flags,
+ EntryOption option, bool bf)
+ {
+ setEntryOption(findEntry(group, key, flags), option, bf);
+ }
+
+ bool revertEntry(const QByteArray& group, const QByteArray& key, SearchFlags flags=SearchFlags());
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(KEntryMap::SearchFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(KEntryMap::EntryOptions)
+
+/**
+ * \relates KEntry
+ * type for iterating over keys in a KEntryMap in sorted order.
+ * @internal
+ */
+typedef QMap<KEntryKey, KEntry>::Iterator KEntryMapIterator;
+
+/**
+ * \relates KEntry
+ * type for iterating over keys in a KEntryMap in sorted order.
+ * It is const, thus you cannot change the entries in the iterator,
+ * only examine them.
+ * @internal
+ */
+typedef QMap<KEntryKey, KEntry>::ConstIterator KEntryMapConstIterator;
+
+#endif
diff --git a/src/core/kconfiggroup.cpp b/src/core/kconfiggroup.cpp
new file mode 100644
index 00000000..ab7d494f
--- /dev/null
+++ b/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
+}
diff --git a/src/core/kconfiggroup.h b/src/core/kconfiggroup.h
new file mode 100644
index 00000000..ce0330be
--- /dev/null
+++ b/src/core/kconfiggroup.h
@@ -0,0 +1,767 @@
+/*
+ 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>
+ Copyright (c) 2001 Waldo Bastian <bastian@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.
+*/
+
+#ifndef KCONFIGGROUP_H
+#define KCONFIGGROUP_H
+
+#include "kconfigbase.h"
+
+#include <kconfigcore_export.h>
+
+#include <QtCore/QExplicitlySharedDataPointer>
+#include <QtCore/QVariant>
+#include <QtCore/QStringList>
+
+class KConfig;
+class KConfigGroupPrivate;
+class KSharedConfig;
+typedef QExplicitlySharedDataPointer<KSharedConfig> KSharedConfigPtr;
+/**
+ * \class KConfigGroup kconfiggroup.h <KConfigGroup>
+ *
+ * A class for one specific group in a KConfig object.
+ *
+ * If you want to access the top-level entries of a KConfig
+ * object, which are not associated with any group, use an
+ * empty group name.
+ *
+ * A KConfigGroup will be read-only if it is constructed from a
+ * const config object or from another read-only group.
+ */
+class KCONFIGCORE_EXPORT KConfigGroup : public KConfigBase
+{
+public:
+ /**
+ * Constructs an invalid group.
+ *
+ * \see isValid
+ */
+ KConfigGroup();
+
+ /**
+ * Construct a config group corresponding to @p group in @p master.
+ *
+ * This allows the creation of subgroups by passing another
+ * group as @p master.
+ *
+ * @p group is the group name encoded in UTF-8.
+ */
+ KConfigGroup(KConfigBase *master, const QString &group);
+ /** Overload for KConfigGroup(KConfigBase*,const QString&) */
+ KConfigGroup(KConfigBase *master, const char *group);
+
+ /**
+ * Construct a read-only config group.
+ *
+ * A read-only group will silently ignore any attempts to write to it.
+ *
+ * This allows the creation of subgroups by passing an existing group
+ * as @p master.
+ */
+ KConfigGroup(const KConfigBase *master, const QString &group);
+ /** Overload for KConfigGroup(const KConfigBase*,const QString&) */
+ KConfigGroup(const KConfigBase *master, const char *group);
+
+ /** Overload for KConfigGroup(const KConfigBase*,const QString&) */
+ KConfigGroup(const KSharedConfigPtr &master, const QString &group);
+ /** Overload for KConfigGroup(const KConfigBase*,const QString&) */
+ KConfigGroup(const KSharedConfigPtr &master, const char *group);
+
+ /**
+ * Creates a read-only copy of a read-only group.
+ */
+ KConfigGroup(const KConfigGroup &);
+ KConfigGroup &operator=(const KConfigGroup &);
+
+ ~KConfigGroup();
+
+ /**
+ * Whether the group is valid.
+ *
+ * A group is invalid if it was constructed without arguments.
+ *
+ * You should not call any functions on an invalid group.
+ *
+ * @return @c true if the group is valid, @c false if it is invalid.
+ */
+ bool isValid() const;
+
+ /**
+ * The name of this group.
+ *
+ * The root group is named "<default>".
+ */
+ QString name() const;
+
+ /**
+ * Check whether the containing KConfig object acutally contains a
+ * group with this name.
+ */
+ bool exists() const;
+
+ /**
+ * @reimp
+ *
+ * Syncs the parent config.
+ */
+ bool sync() Q_DECL_OVERRIDE;
+
+ /// @reimp
+ void markAsClean();
+
+ /// @reimp
+ AccessMode accessMode() const;
+
+ /**
+ * Return the config object that this group belongs to
+ */
+ KConfig* config();
+ /**
+ * Return the config object that this group belongs to
+ */
+ const KConfig* config() const;
+
+ /**
+ * Changes the group of the object
+ *
+ * @deprecated
+ * Create another KConfigGroup from the parent of this group instead.
+ */
+#ifndef KDE_NO_DEPRECATED
+ KCONFIGCORE_DEPRECATED void changeGroup(const QString &group);
+#endif
+ /**
+ * Overload for changeGroup(const QString&)
+ *
+ * @deprecated
+ * Create another KConfigGroup from the parent of this group instead.
+ */
+#ifndef KDE_NO_DEPRECATED
+ KCONFIGCORE_DEPRECATED void changeGroup(const char *group);
+#endif
+
+ /**
+ * Copies the entries in this group to another configuration object
+ *
+ * @note @p other can be either another group or a different file.
+ *
+ * @param other the configuration object to copy this group's entries to
+ * @param pFlags the flags to use when writing the entries to the
+ * other configuration object
+ *
+ * @since 4.1
+ */
+ void copyTo(KConfigBase *other, WriteConfigFlags pFlags = Normal) const;
+
+ /**
+ * Changes the configuration object that this group belongs to
+ *
+ * @note @p other can be another group, the top-level KConfig object or
+ * a different KConfig object entirely.
+ *
+ * If @p parent is already the parent of this group, this method will have
+ * no effect.
+ *
+ * @param parent the config object to place this group under
+ * @param pFlags the flags to use in determining which storage source to
+ * write the data to
+ *
+ * @since 4.1
+ */
+ void reparent(KConfigBase *parent, WriteConfigFlags pFlags = Normal);
+
+ /**
+ * Returns the group that this group belongs to
+ *
+ * @return the parent group, or an invalid group if this is a top-level
+ * group
+ *
+ * @since 4.1
+ */
+ KConfigGroup parent() const;
+
+ /**
+ * @reimp
+ */
+ QStringList groupList() const;
+
+ /**
+ * Returns a list of keys this group contains
+ */
+ QStringList keyList() const;
+
+ /**
+ * Delete all entries in the entire group
+ *
+ * @param pFlags flags passed to KConfig::deleteGroup
+ *
+ * @see deleteEntry()
+ */
+ void deleteGroup(WriteConfigFlags pFlags = Normal);
+ using KConfigBase::deleteGroup;
+
+ /**
+ * Reads the value of an entry specified by @p pKey in the current group
+ *
+ * This template method makes it possible to write
+ * QString foo = readEntry("...", QString("default"));
+ * and the same with all other types supported by QVariant.
+ *
+ * The return type of the method is simply the same as the type of the default value.
+ *
+ * @note readEntry("...", Qt::white) will not compile because Qt::white is an enum.
+ * You must turn it into readEntry("...", QColor(Qt::white)).
+ *
+ * @note Only the following QVariant types are allowed : String,
+ * StringList, List, Font, Point, Rect, Size, Color, Int, UInt, Bool,
+ * Double, LongLong, ULongLong, DateTime and Date.
+ *
+ * @param key The key to search for
+ * @param aDefault A default value returned if the key was not found
+ * @return The value for this key, or @p aDefault.
+ *
+ * @see writeEntry(), deleteEntry(), hasKey()
+ */
+ template <typename T>
+ inline T readEntry(const QString &key, const T &aDefault) const
+ { return readCheck(key.toUtf8().constData(), aDefault); }
+ /** Overload for readEntry(const QString&, const T&) const */
+ template <typename T>
+ inline T readEntry(const char *key, const T &aDefault) const
+ { return readCheck(key, aDefault); }
+
+ /**
+ * Reads the value of an entry specified by @p key in the current group
+ *
+ * @param key the key to search for
+ * @param aDefault a default value returned if the key was not found
+ * @return the value for this key, or @p aDefault if the key was not found
+ *
+ * @see writeEntry(), deleteEntry(), hasKey()
+ */
+ QVariant readEntry(const QString &key, const QVariant &aDefault) const;
+ /** Overload for readEntry(const QString&, const QVariant&) */
+ QVariant readEntry(const char *key, const QVariant &aDefault) const;
+
+ /**
+ * Reads the string value of an entry specified by @p key in the current group
+ *
+ * If you want to read a path, please use readPathEntry().
+ *
+ * @param key the key to search for
+ * @param aDefault a default value returned if the key was not found
+ * @return the value for this key, or @p aDefault if the key was not found
+ *
+ * @see readPathEntry(), writeEntry(), deleteEntry(), hasKey()
+ */
+ QString readEntry(const QString &key, const QString &aDefault) const;
+ /** Overload for readEntry(const QString&, const QString&) */
+ QString readEntry(const char *key, const QString &aDefault) const;
+
+ /** Overload for readEntry(const QString&, const QString&) */
+ QString readEntry(const QString &key, const char *aDefault = 0) const;
+ /** Overload for readEntry(const QString&, const QString&) */
+ QString readEntry(const char *key, const char *aDefault = 0) const;
+
+ /**
+ * @copydoc readEntry(const char*, const QStringList&) const
+ *
+ * @warning This function doesn't convert the items returned
+ * to any type. It's actually a list of QVariant::String's. If you
+ * want the items converted to a specific type use
+ * readEntry(const char*, const QList<T>&) const
+ */
+ QVariantList readEntry(const QString &key, const QVariantList &aDefault) const;
+ /** Overload for readEntry(const QString&, const QVariantList&) */
+ QVariantList readEntry(const char *key, const QVariantList &aDefault) const;
+
+ /**
+ * Reads a list of strings from the config object
+ *
+ * @param key The key to search for
+ * @param aDefault The default value to use if the key does not exist
+ * @return The list, or @p aDefault if @p key does not exist
+ *
+ * @see readXdgListEntry(), writeEntry(), deleteEntry(), hasKey()
+ */
+ QStringList readEntry(const QString &key, const QStringList &aDefault) const;
+ /** Overload for readEntry(const QString&, const QStringList&) */
+ QStringList readEntry(const char *key, const QStringList &aDefault) const;
+
+ /**
+ * Reads a list of values from the config object
+ *
+ * @param key the key to search for
+ * @param aDefault the default value to use if the key does not exist
+ * @return the list, or @p aDefault if @p key does not exist
+ *
+ * @see readXdgListEntry(), writeEntry(), deleteEntry(), hasKey()
+ */
+ template<typename T>
+ inline QList<T> readEntry(const QString &key, const QList<T> &aDefault) const
+ { return readListCheck(key.toUtf8().constData(), aDefault); }
+ /** Overload for readEntry(const QString&, const QList<T>&) */
+ template<typename T>
+ inline QList<T> readEntry(const char *key, const QList<T> &aDefault) const
+ { return readListCheck(key, aDefault); }
+
+ /**
+ * Reads a list of strings from the config object, following XDG
+ * desktop entry spec separator semantics
+ *
+ * @param pKey the key to search for
+ * @param aDefault the default value to use if the key does not exist
+ * @return the list, or @p aDefault if @p pKey does not exist
+ *
+ * @see readEntry(const QString&, const QStringList&) const
+ */
+ QStringList readXdgListEntry(const QString &pKey, const QStringList &aDefault = QStringList()) const;
+ /** Overload for readXdgListEntry(const QString&, const QStringList&) */
+ QStringList readXdgListEntry(const char *pKey, const QStringList &aDefault = QStringList()) const;
+
+ /**
+ * Reads a path
+ *
+ * Read the value of an entry specified by @p pKey in the current group
+ * and interpret it as a path. This means, dollar expansion is activated
+ * for this value, so that e.g. $HOME gets expanded.
+ *
+ * @param pKey The key to search for.
+ * @param aDefault A default value returned if the key was not found.
+ * @return The value for this key. Can be QString() if @p aDefault is null.
+ */
+ QString readPathEntry(const QString &pKey, const QString &aDefault) const;
+ /** Overload for readPathEntry(const QString&, const QString&) */
+ QString readPathEntry(const char *key, const QString &aDefault) const;
+
+ /**
+ * Reads a list of paths
+ *
+ * Read the value of an entry specified by @p pKey in the current group
+ * and interpret it as a list of paths. This means, dollar expansion is activated
+ * for this value, so that e.g. $HOME gets expanded.
+ *
+ * @param pKey the key to search for
+ * @param aDefault a default value returned if the key was not found
+ * @return the list, or @p aDefault if the key does not exist
+ */
+ QStringList readPathEntry(const QString &pKey, const QStringList &aDefault) const;
+ /** Overload for readPathEntry(const QString&, const QStringList&) */
+ QStringList readPathEntry(const char *key, const QStringList &aDefault) const;
+
+ /**
+ * Reads an untranslated string entry
+ *
+ * You should not normally need to use this.
+ *
+ * @param pKey the key to search for
+ * @param aDefault a default value returned if the key was not found
+ * @return the value for this key, or @p aDefault if the key does not exist
+ */
+ QString readEntryUntranslated(const QString &pKey,
+ const QString &aDefault = QString()) const;
+ /** Overload for readEntryUntranslated(const QString&, const QString&) */
+ QString readEntryUntranslated(const char *key,
+ const QString &aDefault = QString()) const;
+
+ /**
+ * Writes a value to the configuration object.
+ *
+ * @param key the key to write to
+ * @param value the value to write
+ * @param pFlags the flags to use when writing this entry
+ *
+ * @see readEntry(), writeXdgListEntry(), deleteEntry()
+ */
+ void writeEntry(const QString &key, const QVariant &value,
+ WriteConfigFlags pFlags = Normal);
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const char *key, const QVariant &value,
+ WriteConfigFlags pFlags = Normal);
+
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const QString &key, const QString &value,
+ WriteConfigFlags pFlags = Normal);
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const char *key, const QString &value,
+ WriteConfigFlags pFlags = Normal);
+
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const QString &key, const QByteArray &value,
+ WriteConfigFlags pFlags = Normal);
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const char *key, const QByteArray &value,
+ WriteConfigFlags pFlags = Normal);
+
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const QString &key, const char *value, WriteConfigFlags pFlags = Normal);
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const char *key, const char *value, WriteConfigFlags pFlags = Normal);
+
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ template <typename T>
+ inline void writeEntry(const char *key, const T &value, WriteConfigFlags pFlags = Normal)
+ { writeCheck( key, value, pFlags ); }
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ template <typename T>
+ inline void writeEntry(const QString &key, const T &value, WriteConfigFlags pFlags = Normal)
+ { writeCheck( key.toUtf8().constData(), value, pFlags ); }
+
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const QString &key, const QStringList &value,
+ WriteConfigFlags pFlags = Normal);
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const char *key, const QStringList &value,
+ WriteConfigFlags pFlags = Normal);
+
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const QString &key, const QVariantList &value,
+ WriteConfigFlags pFlags = Normal);
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ void writeEntry(const char *key, const QVariantList &value,
+ WriteConfigFlags pFlags = Normal);
+
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ template <typename T>
+ inline void writeEntry(const QString &key, const QList<T> &value, WriteConfigFlags pFlags = Normal)
+ { writeListCheck( key.toUtf8().constData(), value, pFlags ); }
+ /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
+ template <typename T>
+ inline void writeEntry(const char *key, const QList<T> &value, WriteConfigFlags pFlags = Normal)
+ { writeListCheck( key, value, pFlags ); }
+
+ /**
+ * Writes a list of strings to the config object, following XDG
+ * desktop entry spec separator semantics
+ *
+ * @param pKey the key to write to
+ * @param value the list to write
+ * @param pFlags the flags to use when writing this entry
+ *
+ * @see writeEntry(), readXdgListEntry()
+ */
+ void writeXdgListEntry(const QString &pKey, const QStringList &value,
+ WriteConfigFlags pFlags = Normal);
+ /** Overload for writeXdgListEntry(const QString&, const QStringList&, WriteConfigFlags) */
+ void writeXdgListEntry(const char *pKey, const QStringList &value,
+ WriteConfigFlags pFlags = Normal);
+
+ /**
+ * Writes a file path to the configuration
+ *
+ * If the path is located under $HOME, the user's home directory
+ * is replaced with $HOME in the persistent storage.
+ * The path should therefore be read back with readPathEntry()
+ *
+ * @param pKey the key to write to
+ * @param path the path to write
+ * @param pFlags the flags to use when writing this entry
+ *
+ * @see writeEntry(), readPathEntry()
+ */
+ void writePathEntry(const QString &pKey, const QString &path,
+ WriteConfigFlags pFlags = Normal);
+ /** Overload for writePathEntry(const QString&, const QString&, WriteConfigFlags) */
+ void writePathEntry(const char *pKey, const QString &path,
+ WriteConfigFlags pFlags = Normal);
+
+ /**
+ * Writes a list of paths to the configuration
+ *
+ * If any of the paths are located under $HOME, the user's home directory
+ * is replaced with $HOME in the persistent storage.
+ * The paths should therefore be read back with readPathEntry()
+ *
+ * @param pKey the key to write to
+ * @param value the list to write
+ * @param pFlags the flags to use when writing this entry
+ *
+ * @see writeEntry(), readPathEntry()
+ */
+ void writePathEntry(const QString &pKey, const QStringList &value,
+ WriteConfigFlags pFlags = Normal);
+ /** Overload for writePathEntry(const QString&, const QStringList&, WriteConfigFlags) */
+ void writePathEntry(const char *pKey, const QStringList &value,
+ WriteConfigFlags pFlags = Normal);
+
+ /**
+ * Deletes the entry specified by @p pKey in the current group
+ *
+ * This also hides system wide defaults.
+ *
+ * @param pKey the key to delete
+ * @param pFlags the flags to use when deleting this entry
+ *
+ * @see deleteGroup(), readEntry(), writeEntry()
+ */
+ void deleteEntry(const QString &pKey, WriteConfigFlags pFlags = Normal);
+ /** Overload for deleteEntry(const QString&, WriteConfigFlags) */
+ void deleteEntry(const char *pKey, WriteConfigFlags pFlags = Normal);
+
+ /**
+ * Checks whether the key has an entry in this group
+ *
+ * Use this to determine if a key is not specified for the current
+ * group (hasKey() returns false).
+ *
+ * If this returns @c false for a key, readEntry() (and its variants)
+ * will return the default value passed to them.
+ *
+ * @param key the key to search for
+ * @return @c true if the key is defined in this group by any of the
+ * configuration sources, @c false otherwise
+ *
+ * @see readEntry()
+ */
+ bool hasKey(const QString &key) const;
+ /** Overload for hasKey(const QString&) const */
+ bool hasKey(const char *key) const;
+
+ /**
+ * Whether this group may be changed
+ *
+ * @return @c false if the group may be changed, @c true otherwise
+ */
+ bool isImmutable() const;
+
+ /**
+ * Checks if it is possible to change the given entry
+ *
+ * If isImmutable() returns @c true, then this method will return
+ * @c true for all inputs.
+ *
+ * @param key the key to check
+ * @return @c false if the key may be changed using this configuration
+ * group object, @c true otherwise
+ */
+ bool isEntryImmutable(const QString &key) const;
+ /** Overload for isEntryImmutable(const QString&) const */
+ bool isEntryImmutable(const char *key) const;
+
+ /**
+ * Reverts an entry to the default settings.
+ *
+ * Reverts the entry with key @p key in the current group in the
+ * application specific config file to either the system wide (default)
+ * value or the value specified in the global KDE config file.
+ *
+ * To revert entries in the global KDE config file, the global KDE config
+ * file should be opened explicitly in a separate config object.
+ *
+ * @note This is @em not the same as deleting the key, as instead the
+ * global setting will be copied to the configuration file that this
+ * object manipulates.
+ *
+ * @param key The key of the entry to revert.
+ */
+ void revertToDefault(const QString &key);
+ /** Overload for revertToDefault(const QString&) */
+ void revertToDefault(const char* key);
+
+ /**
+ * Whether a default is specified for an entry in either the
+ * system wide configuration file or the global KDE config file
+ *
+ * If an application computes a default value at runtime for
+ * a certain entry, e.g. like:
+ * \code
+ * QColor computedDefault = qApp->palette().color(QPalette::Active, QPalette::Text);
+ * QColor color = group.readEntry(key, computedDefault);
+ * \endcode
+ * then it may wish to make the following check before
+ * writing back changes:
+ * \code
+ * if ( (value == computedDefault) && !group.hasDefault(key) )
+ * group.revertToDefault(key);
+ * else
+ * group.writeEntry(key, value);
+ * \endcode
+ *
+ * This ensures that as long as the entry is not modified to differ from
+ * the computed default, the application will keep using the computed default
+ * and will follow changes the computed default makes over time.
+ *
+ * @param key the key of the entry to check
+ * @return @c true if the global or system settings files specify a default
+ * for @p key in this group, @c false otherwise
+ */
+ bool hasDefault(const QString &key) const;
+ /** Overload for hasDefault(const QString&) const */
+ bool hasDefault(const char *key) const;
+
+ /**
+ * Returns a map (tree) of entries for all entries in this group
+ *
+ * Only the actual entry string is returned, none of the
+ * other internal data should be included.
+ *
+ * @return a map of entries in this group, indexed by key
+ */
+ QMap<QString, QString> entryMap() const;
+
+protected:
+ bool hasGroupImpl(const QByteArray &group) const;
+ KConfigGroup groupImpl(const QByteArray &b);
+ const KConfigGroup groupImpl(const QByteArray &b) const;
+ void deleteGroupImpl(const QByteArray &group, WriteConfigFlags flags);
+ bool isGroupImmutableImpl(const QByteArray &aGroup) const;
+
+private:
+ QExplicitlySharedDataPointer<KConfigGroupPrivate> d;
+
+ template<typename T>
+ inline T readCheck(const char *key, const T &defaultValue) const;
+
+ template<typename T>
+ inline QList<T> readListCheck(const char *key, const QList<T> &defaultValue) const;
+
+ template<typename T>
+ inline void writeCheck(const char *key, const T &value, WriteConfigFlags pFlags);
+
+ template<typename T>
+ inline void writeListCheck(const char *key, const QList<T> &value, WriteConfigFlags pFlags);
+
+ friend class KConfigGroupPrivate;
+
+ /**
+ * Return the data in @p value converted to a QVariant
+ *
+ * @param pKey the name of the entry being converted, this is only used for error
+ * reporting
+ * @param value the UTF-8 data to be converted
+ * @param aDefault the default value if @p pKey is not found
+ * @return @p value converted to QVariant, or @p aDefault if @p value is invalid or cannot be converted.
+ */
+ static QVariant convertToQVariant(const char *pKey, const QByteArray &value, const QVariant &aDefault);
+ friend class KServicePrivate; // XXX yeah, ugly^5
+};
+
+#define KCONFIGGROUP_ENUMERATOR_ERROR(ENUM) \
+"The Qt MetaObject system does not seem to know about \"" ENUM \
+"\" please use Q_ENUMS or Q_FLAGS to register it."
+
+/**
+ * To add support for your own enums in KConfig, you can declare them with Q_ENUMS()
+ * in a QObject subclass (which will make moc generate the code to turn the
+ * enum into a string and vice-versa), and then (in the cpp code)
+ * use the macro
+ * <code>KCONFIGGROUP_DECLARE_ENUM_QOBJECT(MyClass, MyEnum)</code>
+ *
+ * After that, you can use readEntry(group, key, value) and writeEntry(group, key, value[, flags]).
+ * Note that those are global functions, NOT member functions of KConfigGroup.
+ *
+ */
+#define KCONFIGGROUP_DECLARE_ENUM_QOBJECT(Class, Enum) \
+inline Class::Enum readEntry(const KConfigGroup& group, const char* key, const Class::Enum& def) \
+{ \
+const QMetaObject* M_obj = &Class::staticMetaObject; \
+const int M_index = M_obj->indexOfEnumerator(#Enum); \
+if(M_index == -1) qFatal(KCONFIGGROUP_ENUMERATOR_ERROR(#Enum)); \
+const QMetaEnum M_enum = M_obj->enumerator(M_index); \
+const QByteArray M_data = group.readEntry(key, QByteArray(M_enum.valueToKey(def)));\
+return static_cast<Class::Enum>(M_enum.keyToValue(M_data.constData())); \
+} \
+inline void writeEntry(KConfigGroup& group, const char* key, const Class::Enum& value, KConfigBase::WriteConfigFlags flags = KConfigBase::Normal)\
+{ \
+const QMetaObject* M_obj = &Class::staticMetaObject; \
+const int M_index = M_obj->indexOfEnumerator(#Enum); \
+if(M_index == -1) qFatal(KCONFIGGROUP_ENUMERATOR_ERROR(#Enum)); \
+const QMetaEnum M_enum = M_obj->enumerator(M_index); \
+group.writeEntry(key, QByteArray(M_enum.valueToKey(value)), flags); \
+}
+
+/**
+ * Similar to KCONFIGGROUP_DECLARE_ENUM_QOBJECT but for flags declared with Q_FLAGS()
+ * (where multiple values can be set at the same time)
+ */
+#define KCONFIGGROUP_DECLARE_FLAGS_QOBJECT(Class, Flags) \
+inline Class::Flags readEntry(const KConfigGroup& group, const char* key, const Class::Flags& def) \
+{ \
+const QMetaObject* M_obj = &Class::staticMetaObject; \
+const int M_index = M_obj->indexOfEnumerator(#Flags); \
+if(M_index == -1) qFatal(KCONFIGGROUP_ENUMERATOR_ERROR(#Flags)); \
+const QMetaEnum M_enum = M_obj->enumerator(M_index); \
+const QByteArray M_data = group.readEntry(key, QByteArray(M_enum.valueToKeys(def)));\
+return static_cast<Class::Flags>(M_enum.keysToValue(M_data.constData())); \
+} \
+inline void writeEntry(KConfigGroup& group, const char* key, const Class::Flags& value, KConfigBase::WriteConfigFlags flags = KConfigBase::Normal)\
+{ \
+const QMetaObject* M_obj = &Class::staticMetaObject; \
+const int M_index = M_obj->indexOfEnumerator(#Flags); \
+if(M_index == -1) qFatal(KCONFIGGROUP_ENUMERATOR_ERROR(#Flags)); \
+const QMetaEnum M_enum = M_obj->enumerator(M_index); \
+group.writeEntry(key, QByteArray(M_enum.valueToKeys(value)), flags); \
+}
+
+#include "conversion_check.h"
+
+template <typename T>
+T KConfigGroup::readCheck(const char *key, const T &defaultValue) const
+{
+ ConversionCheck::to_QVariant<T>();
+ return qvariant_cast<T>(readEntry(key, qVariantFromValue(defaultValue)));
+}
+
+template <typename T>
+QList<T> KConfigGroup::readListCheck(const char *key, const QList<T> &defaultValue) const
+{
+ ConversionCheck::to_QVariant<T>();
+ ConversionCheck::to_QString<T>();
+
+ QVariantList data;
+
+ Q_FOREACH(const T& value, defaultValue)
+ data.append(qVariantFromValue(value));
+
+ QList<T> list;
+ Q_FOREACH (const QVariant &value, readEntry<QVariantList>(key, data)) {
+ Q_ASSERT(value.canConvert<T>());
+ list.append(qvariant_cast<T>(value));
+ }
+
+ return list;
+}
+
+template <typename T>
+void KConfigGroup::writeCheck(const char *key, const T &value,
+ WriteConfigFlags pFlags)
+{
+ ConversionCheck::to_QVariant<T>();
+ writeEntry(key, qVariantFromValue(value), pFlags);
+}
+
+template <typename T>
+void KConfigGroup::writeListCheck(const char *key, const QList<T> &list,
+ WriteConfigFlags pFlags)
+{
+ ConversionCheck::to_QVariant<T>();
+ ConversionCheck::to_QString<T>();
+ QVariantList data;
+ Q_FOREACH(const T &value, list) {
+ data.append(qVariantFromValue(value));
+ }
+
+ writeEntry(key, data, pFlags);
+}
+
+#endif // KCONFIGGROUP_H
diff --git a/src/core/kconfiggroup_p.h b/src/core/kconfiggroup_p.h
new file mode 100644
index 00000000..c5d4f150
--- /dev/null
+++ b/src/core/kconfiggroup_p.h
@@ -0,0 +1,42 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2007 Thiago Macieira <thiago@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.
+*/
+
+#ifndef KCONFIGGROUP_P_H
+#define KCONFIGGROUP_P_H
+
+#include <QtCore/QVariant>
+#include "kconfiggroup.h"
+
+class KConfigGroup;
+
+struct KConfigGroupGui
+{
+ typedef bool (*kReadEntryGui)(const QByteArray& data, const char* key, const QVariant &input,
+ QVariant &output);
+ typedef bool (*kWriteEntryGui)(KConfigGroup *, const char* key, const QVariant &input,
+ KConfigGroup::WriteConfigFlags flags);
+
+ kReadEntryGui readEntryGui;
+ kWriteEntryGui writeEntryGui;
+};
+
+extern KCONFIGCORE_EXPORT KConfigGroupGui _kde_internal_KConfigGroupGui;
+
+#endif
diff --git a/src/core/kconfigini.cpp b/src/core/kconfigini.cpp
new file mode 100644
index 00000000..f44b2c39
--- /dev/null
+++ b/src/core/kconfigini.cpp
@@ -0,0 +1,770 @@
+/*
+ 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.
+*/
+
+#include "kconfigini_p.h"
+
+#include "kconfig.h"
+#include "kconfigbackend.h"
+#include "bufferfragment_p.h"
+#include "kconfigdata.h"
+
+#include <qsavefile.h>
+#include <qlockfile.h>
+#include <qdatetime.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qdebug.h>
+#include <qplatformdefs.h>
+
+#ifndef Q_OS_WIN
+#include <unistd.h> // getuid, close
+#endif
+#include <sys/types.h> // uid_t
+#include <fcntl.h> // open
+
+KCONFIGCORE_EXPORT bool kde_kiosk_exception = false; // flag to disable kiosk restrictions
+
+QString KConfigIniBackend::warningProlog(const QFile &file, int line)
+{
+ return QString::fromLatin1("KConfigIni: In file %2, line %1: ")
+ .arg(line).arg(file.fileName());
+}
+
+KConfigIniBackend::KConfigIniBackend()
+ : KConfigBackend(), lockFile(NULL)
+{
+}
+
+KConfigIniBackend::~KConfigIniBackend()
+{
+}
+
+KConfigBackend::ParseInfo
+ KConfigIniBackend::parseConfig(const QByteArray& currentLocale, KEntryMap& entryMap,
+ ParseOptions options)
+{
+ return parseConfig(currentLocale, entryMap, options, false);
+}
+
+// merging==true is the merging that happens at the beginning of writeConfig:
+// merge changes in the on-disk file with the changes in the KConfig object.
+KConfigBackend::ParseInfo
+KConfigIniBackend::parseConfig(const QByteArray& currentLocale, KEntryMap& entryMap,
+ ParseOptions options, bool merging)
+{
+ if (filePath().isEmpty() || !QFile::exists(filePath()))
+ return ParseOk;
+
+ bool bDefault = options&ParseDefaults;
+ bool allowExecutableValues = options&ParseExpansions;
+
+ QByteArray currentGroup("<default>");
+
+ QFile file(filePath());
+ if (!file.open(QIODevice::ReadOnly|QIODevice::Text))
+ return ParseOpenError;
+
+ QList<QByteArray> immutableGroups;
+
+ bool fileOptionImmutable = false;
+ bool groupOptionImmutable = false;
+ bool groupSkip = false;
+
+ int lineNo = 0;
+ // on systems using \r\n as end of line, \r will be taken care of by
+ // trim() below
+ QByteArray buffer = file.readAll();
+ BufferFragment contents(buffer.data(), buffer.size());
+ unsigned int len = contents.length();
+ unsigned int startOfLine = 0;
+
+ while (startOfLine < len) {
+ BufferFragment line = contents.split('\n', &startOfLine);
+ line.trim();
+ lineNo++;
+
+ // skip empty lines and lines beginning with '#'
+ if (line.isEmpty() || line.at(0) == '#')
+ continue;
+
+ if (line.at(0) == '[') { // found a group
+ groupOptionImmutable = fileOptionImmutable;
+
+ QByteArray newGroup;
+ int start = 1, end;
+ do {
+ end = start;
+ for (;;) {
+ if (end == line.length()) {
+ qWarning() << warningProlog(file, lineNo) << "Invalid group header.";
+ // XXX maybe reset the current group here?
+ goto next_line;
+ }
+ if (line.at(end) == ']')
+ break;
+ end++;
+ }
+ if (end + 1 == line.length() && start + 2 == end &&
+ line.at(start) == '$' && line.at(start + 1) == 'i')
+ {
+ if (newGroup.isEmpty())
+ fileOptionImmutable = !kde_kiosk_exception;
+ else
+ groupOptionImmutable = !kde_kiosk_exception;
+ }
+ else {
+ if (!newGroup.isEmpty())
+ newGroup += '\x1d';
+ BufferFragment namePart=line.mid(start, end - start);
+ printableToString(&namePart, file, lineNo);
+ newGroup += namePart.toByteArray();
+ }
+ } while ((start = end + 2) <= line.length() && line.at(end + 1) == '[');
+ currentGroup = newGroup;
+
+ groupSkip = entryMap.getEntryOption(currentGroup, 0, 0, KEntryMap::EntryImmutable);
+
+ if (groupSkip && !bDefault)
+ continue;
+
+ if (groupOptionImmutable)
+ // Do not make the groups immutable until the entries from
+ // this file have been added.
+ immutableGroups.append(currentGroup);
+ } else {
+ if (groupSkip && !bDefault)
+ continue; // skip entry
+
+ BufferFragment aKey;
+ int eqpos = line.indexOf('=');
+ if (eqpos < 0) {
+ aKey = line;
+ line.clear();
+ } else {
+ BufferFragment temp = line.left(eqpos);
+ temp.trim();
+ aKey = temp;
+ line.truncateLeft(eqpos + 1);
+ }
+ if (aKey.isEmpty()) {
+ qWarning() << warningProlog(file, lineNo) << "Invalid entry (empty key)";
+ continue;
+ }
+
+ KEntryMap::EntryOptions entryOptions=0;
+ if (groupOptionImmutable)
+ entryOptions |= KEntryMap::EntryImmutable;
+
+ BufferFragment locale;
+ int start;
+ while ((start = aKey.lastIndexOf('[')) >= 0) {
+ int end = aKey.indexOf(']', start);
+ if (end < 0) {
+ qWarning() << warningProlog(file, lineNo)
+ << "Invalid entry (missing ']')";
+ goto next_line;
+ } else if (end > start + 1 && aKey.at(start + 1) == '$') { // found option(s)
+ int i = start + 2;
+ while (i < end) {
+ switch (aKey.at(i)) {
+ case 'i':
+ if (!kde_kiosk_exception)
+ entryOptions |= KEntryMap::EntryImmutable;
+ break;
+ case 'e':
+ if (allowExecutableValues)
+ entryOptions |= KEntryMap::EntryExpansion;
+ break;
+ case 'd':
+ entryOptions |= KEntryMap::EntryDeleted;
+ aKey = aKey.left(start);
+ printableToString(&aKey, file, lineNo);
+ entryMap.setEntry(currentGroup, aKey.toByteArray(), QByteArray(), entryOptions);
+ goto next_line;
+ default:
+ break;
+ }
+ i++;
+ }
+ } else { // found a locale
+ if (!locale.isNull()) {
+ qWarning() << warningProlog(file, lineNo)
+ << "Invalid entry (second locale!?)";
+ goto next_line;
+ }
+
+ locale = aKey.mid(start + 1,end - start - 1);
+ }
+ aKey.truncate(start);
+ }
+ if (eqpos < 0) { // Do this here after [$d] was checked
+ qWarning() << warningProlog(file, lineNo) << "Invalid entry (missing '=')";
+ continue;
+ }
+ printableToString(&aKey, file, lineNo);
+ if (!locale.isEmpty()) {
+ if (locale != currentLocale) {
+ // backward compatibility. C == en_US
+ if (locale.at(0) != 'C' || currentLocale != "en_US") {
+ if (merging)
+ entryOptions |= KEntryMap::EntryRawKey;
+ else
+ goto next_line; // skip this entry if we're not merging
+ }
+ }
+ }
+
+ if (!(entryOptions & KEntryMap::EntryRawKey))
+ printableToString(&aKey, file, lineNo);
+
+ if (options&ParseGlobal)
+ entryOptions |= KEntryMap::EntryGlobal;
+ if (bDefault)
+ entryOptions |= KEntryMap::EntryDefault;
+ if (!locale.isNull())
+ entryOptions |= KEntryMap::EntryLocalized;
+ printableToString(&line, file, lineNo);
+ if (entryOptions & KEntryMap::EntryRawKey) {
+ QByteArray rawKey;
+ rawKey.reserve(aKey.length() + locale.length() + 2);
+ rawKey.append(aKey.toVolatileByteArray());
+ rawKey.append('[').append(locale.toVolatileByteArray()).append(']');
+ entryMap.setEntry(currentGroup, rawKey, line.toByteArray(), entryOptions);
+ } else {
+ entryMap.setEntry(currentGroup, aKey.toByteArray(), line.toByteArray(), entryOptions);
+ }
+ }
+next_line:
+ continue;
+ }
+
+ // now make sure immutable groups are marked immutable
+ Q_FOREACH(const QByteArray& group, immutableGroups) {
+ entryMap.setEntry(group, QByteArray(), QByteArray(), KEntryMap::EntryImmutable);
+ }
+
+ return fileOptionImmutable ? ParseImmutable : ParseOk;
+}
+
+void KConfigIniBackend::writeEntries(const QByteArray& locale, QIODevice& file,
+ const KEntryMap& map, bool defaultGroup, bool &firstEntry)
+{
+ QByteArray currentGroup;
+ bool groupIsImmutable = false;
+ const KEntryMapConstIterator end = map.constEnd();
+ for (KEntryMapConstIterator it = map.constBegin(); it != end; ++it) {
+ const KEntryKey& key = it.key();
+
+ // Either process the default group or all others
+ if ((key.mGroup != "<default>") == defaultGroup)
+ continue; // skip
+
+ // the only thing we care about groups is, is it immutable?
+ if (key.mKey.isNull()) {
+ groupIsImmutable = it->bImmutable;
+ continue; // skip
+ }
+
+ const KEntry& currentEntry = *it;
+ if (!defaultGroup && currentGroup != key.mGroup) {
+ if (!firstEntry)
+ file.putChar('\n');
+ currentGroup = key.mGroup;
+ for (int start = 0, end;; start = end + 1) {
+ file.putChar('[');
+ end = currentGroup.indexOf('\x1d', start);
+ if (end < 0) {
+ int cgl = currentGroup.length();
+ if (currentGroup.at(start) == '$' && cgl - start <= 10) {
+ for (int i = start + 1; i < cgl; i++) {
+ char c = currentGroup.at(i);
+ if (c < 'a' || c > 'z')
+ goto nope;
+ }
+ file.write("\\x24");
+ start++;
+ }
+ nope:
+ file.write(stringToPrintable(currentGroup.mid(start), GroupString));
+ file.putChar(']');
+ if (groupIsImmutable) {
+ file.write("[$i]", 4);
+ }
+ file.putChar('\n');
+ break;
+ } else {
+ file.write(stringToPrintable(currentGroup.mid(start, end - start), GroupString));
+ file.putChar(']');
+ }
+ }
+ }
+
+ firstEntry = false;
+ // it is data for a group
+
+ if (key.bRaw) // unprocessed key with attached locale from merge
+ file.write(key.mKey);
+ else {
+ file.write(stringToPrintable(key.mKey, KeyString)); // Key
+ if (key.bLocal && locale != "C") { // 'C' locale == untranslated
+ file.putChar('[');
+ file.write(locale); // locale tag
+ file.putChar(']');
+ }
+ }
+ if (currentEntry.bDeleted) {
+ if (currentEntry.bImmutable)
+ file.write("[$di]", 5); // Deleted + immutable
+ else
+ file.write("[$d]", 4); // Deleted
+ } else {
+ if (currentEntry.bImmutable || currentEntry.bExpand) {
+ file.write("[$", 2);
+ if (currentEntry.bImmutable)
+ file.putChar('i');
+ if (currentEntry.bExpand)
+ file.putChar('e');
+ file.putChar(']');
+ }
+ file.putChar('=');
+ file.write(stringToPrintable(currentEntry.mValue, ValueString));
+ }
+ file.putChar('\n');
+ }
+}
+
+void KConfigIniBackend::writeEntries(const QByteArray& locale, QIODevice& file, const KEntryMap& map)
+{
+ bool firstEntry = true;
+
+ // write default group
+ writeEntries(locale, file, map, true, firstEntry);
+
+ // write all other groups
+ writeEntries(locale, file, map, false, firstEntry);
+}
+
+bool KConfigIniBackend::writeConfig(const QByteArray& locale, KEntryMap& entryMap,
+ WriteOptions options)
+{
+ Q_ASSERT(!filePath().isEmpty());
+
+ KEntryMap writeMap;
+ const bool bGlobal = options & WriteGlobal;
+
+ // First, reparse the file on disk, to merge our changes with the ones done by other apps
+ // Store the result into writeMap.
+ {
+ ParseOptions opts = ParseExpansions;
+ if (bGlobal)
+ opts |= ParseGlobal;
+ ParseInfo info = parseConfig(locale, writeMap, opts, true);
+ if (info != ParseOk) // either there was an error or the file became immutable
+ return false;
+ }
+
+ const KEntryMapIterator end = entryMap.end();
+ for (KEntryMapIterator it=entryMap.begin(); it != end; ++it) {
+ if (!it.key().mKey.isEmpty() && !it->bDirty) // not dirty, doesn't overwrite entry in writeMap. skips default entries, too.
+ continue;
+
+ const KEntryKey& key = it.key();
+
+ // only write entries that have the same "globality" as the file
+ if (it->bGlobal == bGlobal) {
+ if (it->bReverted) {
+ writeMap.remove(key);
+ } else if (!it->bDeleted) {
+ writeMap[key] = *it;
+ } else {
+ KEntryKey defaultKey = key;
+ defaultKey.bDefault = true;
+ if (!entryMap.contains(defaultKey)) {
+ writeMap.remove(key); // remove the deleted entry if there is no default
+ //qDebug() << "Detected as deleted=>removed:" << key.mGroup << key.mKey << "global=" << bGlobal;
+ } else {
+ writeMap[key] = *it; // otherwise write an explicitly deleted entry
+ //qDebug() << "Detected as deleted=>[$d]:" << key.mGroup << key.mKey << "global=" << bGlobal;
+ }
+ }
+ it->bDirty = false;
+ }
+ }
+
+ // now writeMap should contain only entries to be written
+ // so write it out to disk
+
+ // check if file exists
+ QFile::Permissions fileMode = QFile::ReadUser | QFile::WriteUser;
+ bool createNew = true;
+
+ QFileInfo fi(filePath());
+ if (fi.exists())
+ {
+#ifdef Q_OS_WIN
+ //TODO: getuid does not exist on windows, use GetSecurityInfo and GetTokenInformation instead
+ createNew = false;
+#else
+ if (fi.ownerId() == ::getuid())
+ {
+ // Preserve file mode if file exists and is owned by user.
+ fileMode = fi.permissions();
+ }
+ else
+ {
+ // File is not owned by user:
+ // Don't create new file but write to existing file instead.
+ createNew = false;
+ }
+#endif
+ }
+
+ if (createNew) {
+ QSaveFile file(filePath());
+ if (!file.open(QIODevice::WriteOnly)) {
+ return false;
+ }
+
+ file.setTextModeEnabled(true); // to get eol translation
+ writeEntries(locale, file, writeMap);
+
+ if (!file.size() && (fileMode == (QFile::ReadUser | QFile::WriteUser))) {
+ // File is empty and doesn't have special permissions: delete it.
+ file.cancelWriting();
+
+ if (fi.exists()) {
+ // also remove the old file in case it existed. this can happen
+ // when we delete all the entries in an existing config file.
+ // if we don't do this, then deletions and revertToDefault's
+ // will mysteriously fail
+ QFile::remove(filePath());
+ }
+ } else {
+ // Normal case: Close the file
+ if (file.commit()) {
+ QFile::setPermissions(filePath(), fileMode);
+ return true;
+ }
+ // Couldn't write. Disk full?
+ qWarning() << "Couldn't write" << filePath() << ". Disk full?";
+ return false;
+ }
+ } else {
+ // Open existing file. *DON'T* create it if it suddenly does not exist!
+#ifdef Q_OS_UNIX
+ int fd = QT_OPEN(QFile::encodeName(filePath()).constData(), O_WRONLY | O_TRUNC);
+ if (fd < 0) {
+ return false;
+ }
+ FILE *fp = ::fdopen(fd, "w");
+ if (!fp) {
+ QT_CLOSE(fd);
+ return false;
+ }
+ QFile f;
+ if (!f.open(fp, QIODevice::WriteOnly)) {
+ fclose(fp);
+ return false;
+ }
+ writeEntries(locale, f, writeMap);
+ f.close();
+ fclose(fp);
+#else
+ QFile f( filePath() );
+ // XXX This is broken - it DOES create the file if it is suddenly gone.
+ if (!f.open( QIODevice::WriteOnly | QIODevice::Truncate )) {
+ return false;
+ }
+ f.setTextModeEnabled(true);
+ writeEntries(locale, f, writeMap);
+#endif
+ }
+ return true;
+}
+
+
+bool KConfigIniBackend::isWritable() const
+{
+ const QString filePath = this->filePath();
+ if (!filePath.isEmpty()) {
+ QFileInfo file(filePath);
+ if (!file.exists()) {
+ // If the file does not exist, check if the deepest
+ // existing dir is writable.
+ QFileInfo dir(file.absolutePath());
+ while (!dir.exists()) {
+ QString parent = dir.absolutePath(); // Go up. Can't use cdUp() on non-existing dirs.
+ if (parent == dir.filePath()) {
+ // no parent
+ return false;
+ }
+ dir.setFile(parent);
+ }
+ return dir.isDir() && dir.isWritable();
+ } else {
+ return file.isWritable();
+ }
+ }
+
+ return false;
+}
+
+QString KConfigIniBackend::nonWritableErrorMessage() const
+{
+ return tr("Configuration file \"%1\" not writable.\n").arg(filePath());
+}
+
+void KConfigIniBackend::createEnclosing()
+{
+ const QString file = filePath();
+ if (file.isEmpty())
+ return; // nothing to do
+
+ // Create the containing dir, maybe it wasn't there
+ QDir dir;
+ dir.mkpath(QFileInfo(file).absolutePath());
+}
+
+void KConfigIniBackend::setFilePath(const QString& file)
+{
+ if (file.isEmpty())
+ return;
+
+ Q_ASSERT(QDir::isAbsolutePath(file));
+
+ const QFileInfo info(file);
+ if (info.exists()) {
+ setLocalFilePath(info.canonicalFilePath());
+ setLastModified(info.lastModified());
+ setSize(info.size());
+ } else {
+ setLocalFilePath(file);
+ setSize(0);
+ QDateTime dummy;
+ dummy.setTime_t(0);
+ setLastModified(dummy);
+ }
+}
+
+KConfigBase::AccessMode KConfigIniBackend::accessMode() const
+{
+ if (filePath().isEmpty())
+ return KConfigBase::NoAccess;
+
+ if (isWritable())
+ return KConfigBase::ReadWrite;
+
+ return KConfigBase::ReadOnly;
+}
+
+bool KConfigIniBackend::lock()
+{
+ Q_ASSERT(!filePath().isEmpty());
+
+ if (!lockFile) {
+ lockFile = new QLockFile(filePath() + QLatin1String(".lock"));
+ }
+
+ // This is a workaround for current QLockFilePrivate::tryLock_sys
+ // which might crash calling qAppName() if sync() is called after
+ // the QCoreApplication instance is gone. It might be the case with
+ // KSharedConfig instances cleanup.
+ if (!lockFile->tryLock(lockFile->staleLockTime())) {
+ lockFile->removeStaleLockFile();
+ lockFile->lock();
+ }
+ return lockFile->isLocked();
+}
+
+void KConfigIniBackend::unlock()
+{
+ lockFile->unlock();
+ delete lockFile;
+ lockFile = NULL;
+}
+
+bool KConfigIniBackend::isLocked() const
+{
+ return lockFile && lockFile->isLocked();
+}
+
+QByteArray KConfigIniBackend::stringToPrintable(const QByteArray& aString, StringType type)
+{
+ static const char nibbleLookup[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+
+ if (aString.isEmpty())
+ return aString;
+ const int l = aString.length();
+
+ QByteArray result; // Guesstimated that it's good to avoid data() initialization for a length of l*4
+ result.resize(l * 4); // Maximum 4x as long as source string due to \x<ab> escape sequences
+ register const char *s = aString.constData();
+ int i = 0;
+ char *data = result.data();
+ char *start = data;
+
+ // Protect leading space
+ if (s[0] == ' ' && type != GroupString) {
+ *data++ = '\\';
+ *data++ = 's';
+ i++;
+ }
+
+ for (; i < l; ++i/*, r++*/) {
+ switch (s[i]) {
+ default:
+ // The \n, \t, \r cases (all < 32) are handled below; we can ignore them here
+ if (((unsigned char)s[i]) < 32)
+ goto doEscape;
+ *data++ = s[i];
+ break;
+ case '\n':
+ *data++ = '\\';
+ *data++ = 'n';
+ break;
+ case '\t':
+ *data++ = '\\';
+ *data++ = 't';
+ break;
+ case '\r':
+ *data++ = '\\';
+ *data++ = 'r';
+ break;
+ case '\\':
+ *data++ = '\\';
+ *data++ = '\\';
+ break;
+ case '=':
+ if (type != KeyString) {
+ *data++ = s[i];
+ break;
+ }
+ goto doEscape;
+ case '[':
+ case ']':
+ // Above chars are OK to put in *value* strings as plaintext
+ if (type == ValueString) {
+ *data++ = s[i];
+ break;
+ }
+ doEscape:
+ *data++ = '\\';
+ *data++ = 'x';
+ *data++ = nibbleLookup[((unsigned char)s[i]) >> 4];
+ *data++ = nibbleLookup[((unsigned char)s[i]) & 0x0f];
+ break;
+ }
+ }
+ *data = 0;
+ result.resize(data - start);
+
+ // Protect trailing space
+ if (result.endsWith(' ') && type != GroupString) {
+ result.replace(result.length() - 1, 1, "\\s");
+ }
+ result.squeeze();
+
+ return result;
+}
+
+char KConfigIniBackend::charFromHex(const char *str, const QFile& file, int line)
+{
+ unsigned char ret = 0;
+ for (int i = 0; i < 2; i++) {
+ ret <<= 4;
+ quint8 c = quint8(str[i]);
+
+ if (c >= '0' && c <= '9') {
+ ret |= c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ ret |= c - 'a' + 0x0a;
+ } else if (c >= 'A' && c <= 'F') {
+ ret |= c - 'A' + 0x0a;
+ } else {
+ QByteArray e(str, 2);
+ e.prepend("\\x");
+ qWarning() << warningProlog(file, line) << "Invalid hex character " << c
+ << " in \\x<nn>-type escape sequence \"" << e.constData() << "\".";
+ return 'x';
+ }
+ }
+ return char(ret);
+}
+
+void KConfigIniBackend::printableToString(BufferFragment* aString, const QFile& file, int line)
+{
+ if (aString->isEmpty() || aString->indexOf('\\')==-1)
+ return;
+ aString->trim();
+ int l = aString->length();
+ char *r = aString->data();
+ char *str=r;
+
+ for(int i = 0; i < l; i++, r++) {
+ if (str[i]!= '\\') {
+ *r=str[i];
+ } else {
+ // Probable escape sequence
+ i++;
+ if (i >= l) { // Line ends after backslash - stop.
+ *r = '\\';
+ break;
+ }
+
+ switch(str[i]) {
+ case 's':
+ *r = ' ';
+ break;
+ case 't':
+ *r = '\t';
+ break;
+ case 'n':
+ *r = '\n';
+ break;
+ case 'r':
+ *r = '\r';
+ break;
+ case '\\':
+ *r = '\\';
+ break;
+ case 'x':
+ if (i + 2 < l) {
+ *r = charFromHex(str + i + 1, file, line);
+ i += 2;
+ } else {
+ *r = 'x';
+ i = l - 1;
+ }
+ break;
+ default:
+ *r = '\\';
+ qWarning() << warningProlog(file, line)
+ << QString::fromLatin1("Invalid escape sequence \"\\%1\".").arg(str[i]);
+ }
+ }
+ }
+ aString->truncate(r - aString->constData());
+}
diff --git a/src/core/kconfigini_p.h b/src/core/kconfigini_p.h
new file mode 100644
index 00000000..368a78fb
--- /dev/null
+++ b/src/core/kconfigini_p.h
@@ -0,0 +1,81 @@
+/*
+ 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>
+ Portions 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.
+*/
+
+#ifndef KCONFIGINI_P_H
+#define KCONFIGINI_P_H
+
+#include <kconfigcore_export.h>
+#include <kconfigbackend.h>
+
+class QLockFile;
+class QIODevice;
+
+class KConfigIniBackend : public KConfigBackend
+{
+private:
+ class BufferFragment;
+
+ QLockFile *lockFile;
+public:
+
+ KConfigIniBackend();
+ ~KConfigIniBackend();
+
+ ParseInfo parseConfig(const QByteArray& locale,
+ KEntryMap& entryMap,
+ ParseOptions options);
+ ParseInfo parseConfig(const QByteArray& locale,
+ KEntryMap& entryMap,
+ ParseOptions options,
+ bool merging);
+ bool writeConfig(const QByteArray& locale, KEntryMap& entryMap,
+ WriteOptions options);
+
+ bool isWritable() const;
+ QString nonWritableErrorMessage() const;
+ KConfigBase::AccessMode accessMode() const;
+ void createEnclosing();
+ void setFilePath(const QString& path);
+ bool lock();
+ void unlock();
+ bool isLocked() const;
+
+protected:
+
+ enum StringType {
+ GroupString = 0,
+ KeyString = 1,
+ ValueString = 2
+ };
+ // Warning: this modifies data in-place. Other BufferFragment objects referencing the same buffer
+ // fragment will get their data modified too.
+ static void printableToString(BufferFragment* aString, const QFile& file, int line);
+ static QByteArray stringToPrintable(const QByteArray& aString, StringType type);
+ static char charFromHex(const char *str, const QFile& file, int line);
+ static QString warningProlog(const QFile& file, int line);
+
+ void writeEntries(const QByteArray& locale, QIODevice& file, const KEntryMap& map);
+ void writeEntries(const QByteArray& locale, QIODevice& file, const KEntryMap& map,
+ bool defaultGroup, bool &firstEntry);
+};
+
+#endif // KCONFIGINI_P_H
diff --git a/src/core/kcoreconfigskeleton.cpp b/src/core/kcoreconfigskeleton.cpp
new file mode 100644
index 00000000..691e0b54
--- /dev/null
+++ b/src/core/kcoreconfigskeleton.cpp
@@ -0,0 +1,1343 @@
+/*
+ This file is part of KOrganizer.
+ Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
+ Copyright (c) 2003 Waldo Bastian <bastian@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.
+*/
+
+#include "kcoreconfigskeleton.h"
+#include "kcoreconfigskeleton_p.h"
+
+#include <QUrl>
+
+
+static QString obscuredString(const QString &str)
+{
+ QString result;
+ const QChar *unicode = str.unicode();
+ for ( int i = 0; i < str.length(); ++i )
+ // yes, no typo. can't encode ' ' or '!' because
+ // they're the unicode BOM. stupid scrambling. stupid.
+ result += ( unicode[ i ].unicode() <= 0x21 ) ? unicode[ i ]
+ : QChar( 0x1001F - unicode[ i ].unicode() );
+
+ return result;
+}
+
+KConfigSkeletonItem::KConfigSkeletonItem(const QString & _group,
+ const QString & _key)
+ : mGroup(_group)
+ , mKey(_key)
+ , d( new KConfigSkeletonItemPrivate )
+{
+}
+
+KConfigSkeletonItem::~KConfigSkeletonItem()
+{
+ delete d;
+}
+
+void KConfigSkeletonItem::setGroup( const QString &_group )
+{
+ mGroup = _group;
+}
+
+QString KConfigSkeletonItem::group() const
+{
+ return mGroup;
+}
+
+void KConfigSkeletonItem::setKey( const QString &_key )
+{
+ mKey = _key;
+}
+
+QString KConfigSkeletonItem::key() const
+{
+ return mKey;
+}
+
+void KConfigSkeletonItem::setName(const QString &_name)
+{
+ mName = _name;
+}
+
+QString KConfigSkeletonItem::name() const
+{
+ return mName;
+}
+
+void KConfigSkeletonItem::setLabel( const QString &l )
+{
+ d->mLabel = l;
+}
+
+QString KConfigSkeletonItem::label() const
+{
+ return d->mLabel;
+}
+
+void KConfigSkeletonItem::setToolTip( const QString &t )
+{
+ d->mToolTip = t;
+}
+
+QString KConfigSkeletonItem::toolTip() const
+{
+ return d->mToolTip;
+}
+
+void KConfigSkeletonItem::setWhatsThis( const QString &w )
+{
+ d->mWhatsThis = w;
+}
+
+QString KConfigSkeletonItem::whatsThis() const
+{
+ return d->mWhatsThis;
+}
+
+QVariant KConfigSkeletonItem::minValue() const
+{
+ return QVariant();
+}
+
+QVariant KConfigSkeletonItem::maxValue() const
+{
+ return QVariant();
+}
+
+bool KConfigSkeletonItem::isImmutable() const
+{
+ return d->mIsImmutable;
+}
+
+void KConfigSkeletonItem::readImmutability( const KConfigGroup &group )
+{
+ d->mIsImmutable = group.isEntryImmutable( mKey );
+}
+
+
+KCoreConfigSkeleton::ItemString::ItemString( const QString &_group, const QString &_key,
+ QString &reference,
+ const QString &defaultValue,
+ Type type )
+ : KConfigSkeletonGenericItem<QString>( _group, _key, reference, defaultValue ),
+ mType( type )
+{
+}
+
+void KCoreConfigSkeleton::ItemString::writeConfig( KConfig *config )
+{
+ if ( mReference != mLoadedValue ) // WABA: Is this test needed?
+ {
+ KConfigGroup cg(config, mGroup );
+ if ((mDefault == mReference) && !cg.hasDefault( mKey))
+ cg.revertToDefault( mKey );
+ else if ( mType == Path )
+ cg.writePathEntry( mKey, mReference );
+ else if ( mType == Password )
+ cg.writeEntry( mKey, obscuredString( mReference ) );
+ else
+ cg.writeEntry( mKey, mReference );
+ }
+}
+
+
+void KCoreConfigSkeleton::ItemString::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+
+ if ( mType == Path )
+ {
+ mReference = cg.readPathEntry( mKey, mDefault );
+ }
+ else if ( mType == Password )
+ {
+ QString val = cg.readEntry( mKey, obscuredString( mDefault ) );
+ mReference = obscuredString( val );
+ }
+ else
+ {
+ mReference = cg.readEntry( mKey, mDefault );
+ }
+
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemString::setProperty(const QVariant & p)
+{
+ mReference = p.toString();
+}
+
+bool KCoreConfigSkeleton::ItemString::isEqual(const QVariant &v) const
+{
+ return mReference == v.toString();
+}
+
+QVariant KCoreConfigSkeleton::ItemString::property() const
+{
+ return QVariant(mReference);
+}
+
+KCoreConfigSkeleton::ItemPassword::ItemPassword( const QString &_group, const QString &_key,
+ QString &reference,
+ const QString &defaultValue)
+ : ItemString( _group, _key, reference, defaultValue, Password )
+{
+}
+
+KCoreConfigSkeleton::ItemPath::ItemPath( const QString &_group, const QString &_key,
+ QString &reference,
+ const QString &defaultValue)
+ : ItemString( _group, _key, reference, defaultValue, Path )
+{
+}
+
+KCoreConfigSkeleton::ItemUrl::ItemUrl( const QString &_group, const QString &_key,
+ QUrl &reference,
+ const QUrl &defaultValue )
+ : KConfigSkeletonGenericItem<QUrl>( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemUrl::writeConfig( KConfig *config )
+{
+ if ( mReference != mLoadedValue ) // WABA: Is this test needed?
+ {
+ KConfigGroup cg(config, mGroup );
+ if ((mDefault == mReference) && !cg.hasDefault( mKey))
+ cg.revertToDefault( mKey );
+ else
+ cg.writeEntry<QString>( mKey, mReference.toString() );
+ }
+}
+
+void KCoreConfigSkeleton::ItemUrl::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+
+ mReference = QUrl( cg.readEntry<QString>( mKey, mDefault.toString() ) );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemUrl::setProperty(const QVariant & p)
+{
+ mReference = qvariant_cast<QUrl>(p);
+}
+
+bool KCoreConfigSkeleton::ItemUrl::isEqual(const QVariant &v) const
+{
+ return mReference == qvariant_cast<QUrl>(v);
+}
+
+QVariant KCoreConfigSkeleton::ItemUrl::property() const
+{
+ return qVariantFromValue<QUrl>(mReference);
+}
+
+KCoreConfigSkeleton::ItemProperty::ItemProperty( const QString &_group,
+ const QString &_key,
+ QVariant &reference,
+ const QVariant &defaultValue )
+ : KConfigSkeletonGenericItem<QVariant>( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemProperty::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemProperty::setProperty(const QVariant & p)
+{
+ mReference = p;
+}
+
+bool KCoreConfigSkeleton::ItemProperty::isEqual(const QVariant &v) const
+{
+ //this might cause problems if the QVariants are not of default types
+ return mReference == v;
+}
+
+QVariant KCoreConfigSkeleton::ItemProperty::property() const
+{
+ return mReference;
+}
+
+KCoreConfigSkeleton::ItemBool::ItemBool( const QString &_group, const QString &_key,
+ bool &reference, bool defaultValue )
+ : KConfigSkeletonGenericItem<bool>( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemBool::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemBool::setProperty(const QVariant & p)
+{
+ mReference = p.toBool();
+}
+
+bool KCoreConfigSkeleton::ItemBool::isEqual(const QVariant &v) const
+{
+ return mReference == v.toBool();
+}
+
+QVariant KCoreConfigSkeleton::ItemBool::property() const
+{
+ return QVariant( mReference );
+}
+
+
+KCoreConfigSkeleton::ItemInt::ItemInt( const QString &_group, const QString &_key,
+ qint32 &reference, qint32 defaultValue )
+ : KConfigSkeletonGenericItem<qint32>( _group, _key, reference, defaultValue )
+ ,mHasMin(false), mHasMax(false)
+{
+}
+
+void KCoreConfigSkeleton::ItemInt::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ if (mHasMin)
+ mReference = qMax(mReference, mMin);
+ if (mHasMax)
+ mReference = qMin(mReference, mMax);
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemInt::setProperty(const QVariant & p)
+{
+ mReference = p.toInt();
+}
+
+bool KCoreConfigSkeleton::ItemInt::isEqual(const QVariant &v) const
+{
+ return mReference == v.toInt();
+}
+
+QVariant KCoreConfigSkeleton::ItemInt::property() const
+{
+ return QVariant(mReference);
+}
+
+QVariant KCoreConfigSkeleton::ItemInt::minValue() const
+{
+ if (mHasMin)
+ return QVariant(mMin);
+ return QVariant();
+}
+
+QVariant KCoreConfigSkeleton::ItemInt::maxValue() const
+{
+ if (mHasMax)
+ return QVariant(mMax);
+ return QVariant();
+}
+
+void KCoreConfigSkeleton::ItemInt::setMinValue(qint32 v)
+{
+ mHasMin = true;
+ mMin = v;
+}
+
+void KCoreConfigSkeleton::ItemInt::setMaxValue(qint32 v)
+{
+ mHasMax = true;
+ mMax = v;
+}
+
+
+KCoreConfigSkeleton::ItemLongLong::ItemLongLong( const QString &_group, const QString &_key,
+ qint64 &reference, qint64 defaultValue )
+ : KConfigSkeletonGenericItem<qint64>( _group, _key, reference, defaultValue )
+ ,mHasMin(false), mHasMax(false)
+{
+}
+
+void KCoreConfigSkeleton::ItemLongLong::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ if (mHasMin)
+ mReference = qMax(mReference, mMin);
+ if (mHasMax)
+ mReference = qMin(mReference, mMax);
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemLongLong::setProperty(const QVariant & p)
+{
+ mReference = p.toLongLong();
+}
+
+bool KCoreConfigSkeleton::ItemLongLong::isEqual(const QVariant &v) const
+{
+ return mReference == v.toLongLong();
+}
+
+QVariant KCoreConfigSkeleton::ItemLongLong::property() const
+{
+ return QVariant(mReference);
+}
+
+QVariant KCoreConfigSkeleton::ItemLongLong::minValue() const
+{
+ if (mHasMin)
+ return QVariant(mMin);
+ return QVariant();
+}
+
+QVariant KCoreConfigSkeleton::ItemLongLong::maxValue() const
+{
+ if (mHasMax)
+ return QVariant(mMax);
+ return QVariant();
+}
+
+void KCoreConfigSkeleton::ItemLongLong::setMinValue(qint64 v)
+{
+ mHasMin = true;
+ mMin = v;
+}
+
+void KCoreConfigSkeleton::ItemLongLong::setMaxValue(qint64 v)
+{
+ mHasMax = true;
+ mMax = v;
+}
+
+KCoreConfigSkeleton::ItemEnum::ItemEnum( const QString &_group, const QString &_key,
+ qint32 &reference,
+ const QList<Choice> &choices,
+ qint32 defaultValue )
+ : ItemInt( _group, _key, reference, defaultValue ), mChoices(choices)
+{
+}
+
+void KCoreConfigSkeleton::ItemEnum::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ if (!cg.hasKey(mKey))
+ {
+ mReference = mDefault;
+ }
+ else
+ {
+ int i = 0;
+ mReference = -1;
+ QString tmp = cg.readEntry( mKey, QString() ).toLower();
+ for(QList<Choice>::ConstIterator it = mChoices.constBegin();
+ it != mChoices.constEnd(); ++it, ++i)
+ {
+ if ((*it).name.toLower() == tmp)
+ {
+ mReference = i;
+ break;
+ }
+ }
+ if (mReference == -1)
+ mReference = cg.readEntry( mKey, mDefault );
+ }
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemEnum::writeConfig( KConfig *config )
+{
+ if ( mReference != mLoadedValue ) // WABA: Is this test needed?
+ {
+ KConfigGroup cg(config, mGroup );
+ if ((mDefault == mReference) && !cg.hasDefault( mKey))
+ cg.revertToDefault( mKey );
+ else if ((mReference >= 0) && (mReference < (int) mChoices.count()))
+ cg.writeEntry( mKey, mChoices[mReference].name );
+ else
+ cg.writeEntry( mKey, mReference );
+ }
+}
+
+QList<KCoreConfigSkeleton::ItemEnum::Choice> KCoreConfigSkeleton::ItemEnum::choices() const
+{
+ return mChoices;
+}
+
+QList<KCoreConfigSkeleton::ItemEnum::Choice> KCoreConfigSkeleton::ItemEnum::choices2() const
+{
+ return mChoices;
+}
+
+KCoreConfigSkeleton::ItemUInt::ItemUInt( const QString &_group, const QString &_key,
+ quint32 &reference,
+ quint32 defaultValue )
+ : KConfigSkeletonGenericItem<quint32>( _group, _key, reference, defaultValue )
+ ,mHasMin(false), mHasMax(false)
+{
+}
+
+void KCoreConfigSkeleton::ItemUInt::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ if (mHasMin)
+ mReference = qMax(mReference, mMin);
+ if (mHasMax)
+ mReference = qMin(mReference, mMax);
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemUInt::setProperty(const QVariant & p)
+{
+ mReference = p.toUInt();
+}
+
+bool KCoreConfigSkeleton::ItemUInt::isEqual(const QVariant &v) const
+{
+ return mReference == v.toUInt();
+}
+
+QVariant KCoreConfigSkeleton::ItemUInt::property() const
+{
+ return QVariant(mReference);
+}
+
+QVariant KCoreConfigSkeleton::ItemUInt::minValue() const
+{
+ if (mHasMin)
+ return QVariant(mMin);
+ return QVariant();
+}
+
+QVariant KCoreConfigSkeleton::ItemUInt::maxValue() const
+{
+ if (mHasMax)
+ return QVariant(mMax);
+ return QVariant();
+}
+
+void KCoreConfigSkeleton::ItemUInt::setMinValue(quint32 v)
+{
+ mHasMin = true;
+ mMin = v;
+}
+
+void KCoreConfigSkeleton::ItemUInt::setMaxValue(quint32 v)
+{
+ mHasMax = true;
+ mMax = v;
+}
+
+
+KCoreConfigSkeleton::ItemULongLong::ItemULongLong( const QString &_group, const QString &_key,
+ quint64 &reference, quint64 defaultValue )
+ : KConfigSkeletonGenericItem<quint64>( _group, _key, reference, defaultValue )
+ ,mHasMin(false), mHasMax(false)
+{
+}
+
+void KCoreConfigSkeleton::ItemULongLong::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ if (mHasMin)
+ mReference = qMax(mReference, mMin);
+ if (mHasMax)
+ mReference = qMin(mReference, mMax);
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemULongLong::setProperty(const QVariant & p)
+{
+ mReference = p.toULongLong();
+}
+
+bool KCoreConfigSkeleton::ItemULongLong::isEqual(const QVariant &v) const
+{
+ return mReference == v.toULongLong();
+}
+
+QVariant KCoreConfigSkeleton::ItemULongLong::property() const
+{
+ return QVariant(mReference);
+}
+
+QVariant KCoreConfigSkeleton::ItemULongLong::minValue() const
+{
+ if (mHasMin)
+ return QVariant(mMin);
+ return QVariant();
+}
+
+QVariant KCoreConfigSkeleton::ItemULongLong::maxValue() const
+{
+ if (mHasMax)
+ return QVariant(mMax);
+ return QVariant();
+}
+
+void KCoreConfigSkeleton::ItemULongLong::setMinValue(quint64 v)
+{
+ mHasMin = true;
+ mMin = v;
+}
+
+void KCoreConfigSkeleton::ItemULongLong::setMaxValue(quint64 v)
+{
+ mHasMax = true;
+ mMax = v;
+}
+
+KCoreConfigSkeleton::ItemDouble::ItemDouble( const QString &_group, const QString &_key,
+ double &reference, double defaultValue )
+ : KConfigSkeletonGenericItem<double>( _group, _key, reference, defaultValue )
+ ,mHasMin(false), mHasMax(false)
+{
+}
+
+void KCoreConfigSkeleton::ItemDouble::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ if (mHasMin)
+ mReference = qMax(mReference, mMin);
+ if (mHasMax)
+ mReference = qMin(mReference, mMax);
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemDouble::setProperty(const QVariant & p)
+{
+ mReference = p.toDouble();
+}
+
+bool KCoreConfigSkeleton::ItemDouble::isEqual(const QVariant &v) const
+{
+ return mReference == v.toDouble();
+}
+
+QVariant KCoreConfigSkeleton::ItemDouble::property() const
+{
+ return QVariant(mReference);
+}
+
+QVariant KCoreConfigSkeleton::ItemDouble::minValue() const
+{
+ if (mHasMin)
+ return QVariant(mMin);
+ return QVariant();
+}
+
+QVariant KCoreConfigSkeleton::ItemDouble::maxValue() const
+{
+ if (mHasMax)
+ return QVariant(mMax);
+ return QVariant();
+}
+
+void KCoreConfigSkeleton::ItemDouble::setMinValue(double v)
+{
+ mHasMin = true;
+ mMin = v;
+}
+
+void KCoreConfigSkeleton::ItemDouble::setMaxValue(double v)
+{
+ mHasMax = true;
+ mMax = v;
+}
+
+
+KCoreConfigSkeleton::ItemRect::ItemRect( const QString &_group, const QString &_key,
+ QRect &reference,
+ const QRect &defaultValue )
+ : KConfigSkeletonGenericItem<QRect>( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemRect::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemRect::setProperty(const QVariant & p)
+{
+ mReference = p.toRect();
+}
+
+bool KCoreConfigSkeleton::ItemRect::isEqual(const QVariant &v) const
+{
+ return mReference == v.toRect();
+}
+
+QVariant KCoreConfigSkeleton::ItemRect::property() const
+{
+ return QVariant(mReference);
+}
+
+
+KCoreConfigSkeleton::ItemPoint::ItemPoint( const QString &_group, const QString &_key,
+ QPoint &reference,
+ const QPoint &defaultValue )
+ : KConfigSkeletonGenericItem<QPoint>( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemPoint::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemPoint::setProperty(const QVariant & p)
+{
+ mReference = p.toPoint();
+}
+
+bool KCoreConfigSkeleton::ItemPoint::isEqual(const QVariant &v) const
+{
+ return mReference == v.toPoint();
+}
+
+QVariant KCoreConfigSkeleton::ItemPoint::property() const
+{
+ return QVariant(mReference);
+}
+
+
+KCoreConfigSkeleton::ItemSize::ItemSize( const QString &_group, const QString &_key,
+ QSize &reference,
+ const QSize &defaultValue )
+ : KConfigSkeletonGenericItem<QSize>( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemSize::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemSize::setProperty(const QVariant & p)
+{
+ mReference = p.toSize();
+}
+
+bool KCoreConfigSkeleton::ItemSize::isEqual(const QVariant &v) const
+{
+ return mReference == v.toSize();
+}
+
+QVariant KCoreConfigSkeleton::ItemSize::property() const
+{
+ return QVariant(mReference);
+}
+
+
+KCoreConfigSkeleton::ItemDateTime::ItemDateTime( const QString &_group, const QString &_key,
+ QDateTime &reference,
+ const QDateTime &defaultValue )
+ : KConfigSkeletonGenericItem<QDateTime>( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemDateTime::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ mReference = cg.readEntry( mKey, mDefault );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemDateTime::setProperty(const QVariant & p)
+{
+ mReference = p.toDateTime();
+}
+
+bool KCoreConfigSkeleton::ItemDateTime::isEqual(const QVariant &v) const
+{
+ return mReference == v.toDateTime();
+}
+
+QVariant KCoreConfigSkeleton::ItemDateTime::property() const
+{
+ return QVariant(mReference);
+}
+
+
+KCoreConfigSkeleton::ItemStringList::ItemStringList( const QString &_group, const QString &_key,
+ QStringList &reference,
+ const QStringList &defaultValue )
+ : KConfigSkeletonGenericItem<QStringList>( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemStringList::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ if ( !cg.hasKey( mKey ) )
+ mReference = mDefault;
+ else
+ mReference = cg.readEntry( mKey, mDefault );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemStringList::setProperty(const QVariant & p)
+{
+ mReference = p.toStringList();
+}
+
+bool KCoreConfigSkeleton::ItemStringList::isEqual(const QVariant &v) const
+{
+ return mReference == v.toStringList();
+}
+
+QVariant KCoreConfigSkeleton::ItemStringList::property() const
+{
+ return QVariant(mReference);
+}
+
+
+KCoreConfigSkeleton::ItemPathList::ItemPathList( const QString &_group, const QString &_key,
+ QStringList &reference,
+ const QStringList &defaultValue )
+ : ItemStringList( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemPathList::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ if ( !cg.hasKey( mKey ) )
+ mReference = mDefault;
+ else
+ mReference = cg.readPathEntry( mKey, QStringList() );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemPathList::writeConfig( KConfig *config )
+{
+ if ( mReference != mLoadedValue ) // WABA: Is this test needed?
+ {
+ KConfigGroup cg(config, mGroup );
+ if ((mDefault == mReference) && !cg.hasDefault( mKey))
+ cg.revertToDefault( mKey );
+ else {
+ QStringList sl = mReference;
+ cg.writePathEntry( mKey, sl );
+ }
+ }
+}
+
+KCoreConfigSkeleton::ItemUrlList::ItemUrlList( const QString &_group, const QString &_key,
+ QList<QUrl> &reference,
+ const QList<QUrl> &defaultValue )
+ : KConfigSkeletonGenericItem<QList<QUrl> >( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemUrlList::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ if ( !cg.hasKey( mKey ) )
+ mReference = mDefault;
+ else {
+ QStringList strList;
+ Q_FOREACH (const QUrl& url, mDefault) {
+ strList.append(url.toString());
+ }
+ mReference.clear();
+ const QStringList readList = cg.readEntry<QStringList>(mKey, strList);
+ Q_FOREACH (const QString& str, readList) {
+ mReference.append(QUrl(str));
+ }
+ }
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemUrlList::writeConfig( KConfig *config )
+{
+ if ( mReference != mLoadedValue ) // WABA: Is this test needed?
+ {
+ KConfigGroup cg(config, mGroup );
+ if ((mDefault == mReference) && !cg.hasDefault( mKey))
+ cg.revertToDefault( mKey );
+ else {
+ QStringList strList;
+ Q_FOREACH (const QUrl& url, mReference) {
+ strList.append(url.toString());
+ }
+ cg.writeEntry<QStringList>(mKey, strList);
+ }
+ }
+}
+
+void KCoreConfigSkeleton::ItemUrlList::setProperty(const QVariant & p)
+{
+ mReference = qvariant_cast<QList<QUrl> >(p);
+}
+
+bool KCoreConfigSkeleton::ItemUrlList::isEqual(const QVariant &v) const
+{
+ return mReference == qvariant_cast<QList<QUrl> >(v);
+}
+
+QVariant KCoreConfigSkeleton::ItemUrlList::property() const
+{
+ return qVariantFromValue<QList<QUrl> >(mReference);
+}
+
+
+KCoreConfigSkeleton::ItemIntList::ItemIntList( const QString &_group, const QString &_key,
+ QList<int> &reference,
+ const QList<int> &defaultValue )
+ : KConfigSkeletonGenericItem<QList<int> >( _group, _key, reference, defaultValue )
+{
+}
+
+void KCoreConfigSkeleton::ItemIntList::readConfig( KConfig *config )
+{
+ KConfigGroup cg(config, mGroup );
+ if ( !cg.hasKey( mKey ) )
+ mReference = mDefault;
+ else
+ mReference = cg.readEntry( mKey , mDefault );
+ mLoadedValue = mReference;
+
+ readImmutability( cg );
+}
+
+void KCoreConfigSkeleton::ItemIntList::setProperty(const QVariant &p)
+{
+ mReference = qvariant_cast< QList<int> >(p);
+}
+
+bool KCoreConfigSkeleton::ItemIntList::isEqual(const QVariant &v) const
+{
+ return mReference == qvariant_cast< QList<int> >(v);
+}
+
+QVariant KCoreConfigSkeleton::ItemIntList::property() const
+{
+ return qVariantFromValue< QList<int> >(mReference);
+}
+
+//static int kCoreConfigSkeletionDebugArea() { static int s_area = KDebug::registerArea("kdecore (KConfigSkeleton)"); return s_area; }
+
+KCoreConfigSkeleton::KCoreConfigSkeleton(const QString &configname, QObject* parent)
+ : QObject(parent),
+ d( new Private )
+{
+ //qDebug() << "Creating KCoreConfigSkeleton (" << (void *)this << ")";
+
+ d->mConfig = KSharedConfig::openConfig( configname );
+}
+
+KCoreConfigSkeleton::KCoreConfigSkeleton(KSharedConfig::Ptr pConfig, QObject* parent)
+ : QObject(parent),
+ d( new Private )
+{
+ //qDebug() << "Creating KCoreConfigSkeleton (" << (void *)this << ")";
+ d->mConfig = pConfig;
+}
+
+
+KCoreConfigSkeleton::~KCoreConfigSkeleton()
+{
+ delete d;
+}
+
+void KCoreConfigSkeleton::setCurrentGroup( const QString &group )
+{
+ d->mCurrentGroup = group;
+}
+
+QString KCoreConfigSkeleton::currentGroup() const
+{
+ return d->mCurrentGroup;
+}
+
+KConfig *KCoreConfigSkeleton::config()
+{
+ return d->mConfig.data();
+}
+
+const KConfig *KCoreConfigSkeleton::config() const
+{
+ return d->mConfig.data();
+}
+
+void KCoreConfigSkeleton::setSharedConfig(KSharedConfig::Ptr pConfig)
+{
+ d->mConfig = pConfig;
+}
+
+KConfigSkeletonItem::List KCoreConfigSkeleton::items() const
+{
+ return d->mItems;
+}
+
+bool KCoreConfigSkeleton::useDefaults(bool b)
+{
+ if (b == d->mUseDefaults)
+ return d->mUseDefaults;
+
+ d->mUseDefaults = b;
+ KConfigSkeletonItem::List::ConstIterator it;
+ for( it = d->mItems.constBegin(); it != d->mItems.constEnd(); ++it )
+ {
+ (*it)->swapDefault();
+ }
+ usrUseDefaults(b);
+ return !d->mUseDefaults;
+}
+
+void KCoreConfigSkeleton::setDefaults()
+{
+ KConfigSkeletonItem::List::ConstIterator it;
+ for( it = d->mItems.constBegin(); it != d->mItems.constEnd(); ++it ) {
+ (*it)->setDefault();
+ }
+ usrSetDefaults();
+}
+
+void KCoreConfigSkeleton::readConfig()
+{
+ // qDebug();
+ d->mConfig->reparseConfiguration();
+ KConfigSkeletonItem::List::ConstIterator it;
+ for( it = d->mItems.constBegin(); it != d->mItems.constEnd(); ++it )
+ {
+ (*it)->readConfig( d->mConfig.data() );
+ }
+ usrReadConfig();
+}
+
+bool KCoreConfigSkeleton::writeConfig()
+{
+ //qDebug();
+ KConfigSkeletonItem::List::ConstIterator it;
+ for( it = d->mItems.constBegin(); it != d->mItems.constEnd(); ++it )
+ {
+ (*it)->writeConfig( d->mConfig.data() );
+ }
+ if (!usrWriteConfig())
+ return false;
+
+ if (d->mConfig->isDirty()) {
+ if (!d->mConfig->sync())
+ return false;
+ readConfig();
+ emit configChanged();
+ }
+ return true;
+}
+
+bool KCoreConfigSkeleton::usrUseDefaults(bool)
+{
+ return false;
+}
+
+void KCoreConfigSkeleton::usrSetDefaults()
+{
+}
+
+void KCoreConfigSkeleton::usrReadConfig()
+{
+}
+
+bool KCoreConfigSkeleton::usrWriteConfig()
+{
+ return true;
+}
+
+void KCoreConfigSkeleton::addItem( KConfigSkeletonItem *item, const QString &name )
+{
+ if (d->mItems.contains(item)) {
+ if (item->name() == name ||
+ (name.isEmpty() && item->name() == item->key())) {
+ // nothing to do -> it is already in our collection
+ // and the name isn't changing
+ return;
+ }
+
+ d->mItemDict.remove(item->name());
+ } else {
+ d->mItems.append( item );
+ }
+
+ item->setName(name.isEmpty() ? item->key() : name);
+ d->mItemDict.insert(item->name(), item);
+ item->readDefault(d->mConfig.data());
+ item->readConfig(d->mConfig.data());
+}
+
+void KCoreConfigSkeleton::removeItem(const QString &name)
+{
+ KConfigSkeletonItem *item = d->mItemDict.value(name);
+ if (item) {
+ d->mItems.removeAll(item);
+ d->mItemDict.remove(item->name());
+ delete item;
+ }
+}
+
+void KCoreConfigSkeleton::clearItems()
+{
+ KConfigSkeletonItem::List items = d->mItems;
+ d->mItems.clear();
+ d->mItemDict.clear();
+ qDeleteAll(items);
+}
+
+KCoreConfigSkeleton::ItemString *KCoreConfigSkeleton::addItemString( const QString &name, QString &reference,
+ const QString &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemString *item;
+ item = new KCoreConfigSkeleton::ItemString( d->mCurrentGroup, key.isEmpty() ? name : key,
+ reference, defaultValue,
+ KCoreConfigSkeleton::ItemString::Normal );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemPassword *KCoreConfigSkeleton::addItemPassword( const QString &name, QString &reference,
+ const QString &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemPassword *item;
+ item = new KCoreConfigSkeleton::ItemPassword( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemPath *KCoreConfigSkeleton::addItemPath( const QString &name, QString &reference,
+ const QString &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemPath *item;
+ item = new KCoreConfigSkeleton::ItemPath( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemProperty *KCoreConfigSkeleton::addItemProperty( const QString &name, QVariant &reference,
+ const QVariant &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemProperty *item;
+ item = new KCoreConfigSkeleton::ItemProperty( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemBool *KCoreConfigSkeleton::addItemBool( const QString &name, bool &reference,
+ bool defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemBool *item;
+ item = new KCoreConfigSkeleton::ItemBool( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemInt *KCoreConfigSkeleton::addItemInt( const QString &name, qint32 &reference,
+ qint32 defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemInt *item;
+ item = new KCoreConfigSkeleton::ItemInt( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemUInt *KCoreConfigSkeleton::addItemUInt( const QString &name, quint32 &reference,
+ quint32 defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemUInt *item;
+ item = new KCoreConfigSkeleton::ItemUInt( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemLongLong *KCoreConfigSkeleton::addItemLongLong( const QString &name, qint64 &reference,
+ qint64 defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemLongLong *item;
+ item = new KCoreConfigSkeleton::ItemLongLong( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+#ifndef KDE_NO_DEPRECATED
+KCoreConfigSkeleton::ItemLongLong *KCoreConfigSkeleton::addItemInt64(
+ const QString& name,
+ qint64 &reference,
+ qint64 defaultValue,
+ const QString & key)
+{
+ return addItemLongLong(name, reference, defaultValue, key);
+}
+#endif
+
+KCoreConfigSkeleton::ItemULongLong *KCoreConfigSkeleton::addItemULongLong( const QString &name, quint64 &reference,
+ quint64 defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemULongLong *item;
+ item = new KCoreConfigSkeleton::ItemULongLong( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+#ifndef KDE_NO_DEPRECATED
+KCoreConfigSkeleton::ItemULongLong *KCoreConfigSkeleton::addItemUInt64(
+ const QString & name,
+ quint64 &reference,
+ quint64 defaultValue,
+ const QString & key)
+{
+ return addItemULongLong(name, reference, defaultValue, key);
+}
+#endif
+
+KCoreConfigSkeleton::ItemDouble *KCoreConfigSkeleton::addItemDouble( const QString &name, double &reference,
+ double defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemDouble *item;
+ item = new KCoreConfigSkeleton::ItemDouble( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemRect *KCoreConfigSkeleton::addItemRect( const QString &name, QRect &reference,
+ const QRect &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemRect *item;
+ item = new KCoreConfigSkeleton::ItemRect( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemPoint *KCoreConfigSkeleton::addItemPoint( const QString &name, QPoint &reference,
+ const QPoint &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemPoint *item;
+ item = new KCoreConfigSkeleton::ItemPoint( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemSize *KCoreConfigSkeleton::addItemSize( const QString &name, QSize &reference,
+ const QSize &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemSize *item;
+ item = new KCoreConfigSkeleton::ItemSize( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemDateTime *KCoreConfigSkeleton::addItemDateTime( const QString &name, QDateTime &reference,
+ const QDateTime &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemDateTime *item;
+ item = new KCoreConfigSkeleton::ItemDateTime( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemStringList *KCoreConfigSkeleton::addItemStringList( const QString &name, QStringList &reference,
+ const QStringList &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemStringList *item;
+ item = new KCoreConfigSkeleton::ItemStringList( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+KCoreConfigSkeleton::ItemIntList *KCoreConfigSkeleton::addItemIntList( const QString &name, QList<int> &reference,
+ const QList<int> &defaultValue, const QString &key )
+{
+ KCoreConfigSkeleton::ItemIntList *item;
+ item = new KCoreConfigSkeleton::ItemIntList( d->mCurrentGroup, key.isNull() ? name : key,
+ reference, defaultValue );
+ addItem( item, name );
+ return item;
+}
+
+bool KCoreConfigSkeleton::isImmutable(const QString &name) const
+{
+ KConfigSkeletonItem *item = findItem(name);
+ return !item || item->isImmutable();
+}
+
+KConfigSkeletonItem *KCoreConfigSkeleton::findItem(const QString &name) const
+{
+ return d->mItemDict.value(name);
+}
+
diff --git a/src/core/kcoreconfigskeleton.h b/src/core/kcoreconfigskeleton.h
new file mode 100644
index 00000000..75f6fa28
--- /dev/null
+++ b/src/core/kcoreconfigskeleton.h
@@ -0,0 +1,1407 @@
+/*
+ * This file is part of KDE.
+ *
+ * Copyright (c) 2001,2002,2003 Cornelius Schumacher <schumacher@kde.org>
+ * Copyright (c) 2003 Waldo Bastian <bastian@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.
+ */
+
+#ifndef KCORECONFIGSKELETON_H
+#define KCORECONFIGSKELETON_H
+
+#include <kconfigcore_export.h>
+
+#include <ksharedconfig.h>
+#include <kconfiggroup.h>
+
+#include <QtCore/QDate>
+#include <QtCore/QHash>
+#include <QtCore/QRect>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+#include <QtCore/QUrl>
+
+ class KConfigSkeletonItemPrivate;
+ /**
+ * \class KConfigSkeletonItem kcoreconfigskeleton.h <KConfigSkeletonItem>
+ *
+ * @short Class for storing a preferences setting
+ * @author Cornelius Schumacher
+ * @see KCoreConfigSkeleton
+ *
+ * This class represents one preferences setting as used by @ref KCoreConfigSkeleton.
+ * Subclasses of KConfigSkeletonItem implement storage functions for a certain type of
+ * setting. Normally you don't have to use this class directly. Use the special
+ * addItem() functions of KCoreConfigSkeleton instead. If you subclass this class you will
+ * have to register instances with the function KCoreConfigSkeleton::addItem().
+ */
+ class KCONFIGCORE_EXPORT KConfigSkeletonItem
+ {
+ public:
+ typedef QList < KConfigSkeletonItem * >List;
+ typedef QHash < QString, KConfigSkeletonItem* > Dict;
+ typedef QHash < QString, KConfigSkeletonItem* >::Iterator DictIterator;
+
+ /**
+ * Constructor.
+ *
+ * @param _group Config file group.
+ * @param _key Config file key.
+ */
+ KConfigSkeletonItem(const QString & _group, const QString & _key);
+
+ /**
+ * Destructor.
+ */
+ virtual ~KConfigSkeletonItem();
+
+ /**
+ * Set config file group.
+ */
+ void setGroup( const QString &_group );
+
+ /**
+ * Return config file group.
+ */
+ QString group() const;
+
+ /**
+ * Set config file key.
+ */
+ void setKey( const QString &_key );
+
+ /**
+ * Return config file key.
+ */
+ QString key() const;
+
+ /**
+ * Set internal name of entry.
+ */
+ void setName(const QString &_name);
+
+ /**
+ * Return internal name of entry.
+ */
+ QString name() const;
+
+ /**
+ Set label providing a translated one-line description of the item.
+ */
+ void setLabel( const QString &l );
+
+ /**
+ Return label of item. See setLabel().
+ */
+ QString label() const;
+
+ /**
+ Set ToolTip description of item.
+ @since 4.2
+ */
+ void setToolTip( const QString &t );
+
+ /**
+ Return ToolTip description of item. See setToolTip().
+ @since 4.2
+ */
+ QString toolTip() const;
+
+ /**
+ Set WhatsThis description of item.
+ */
+ void setWhatsThis( const QString &w );
+
+ /**
+ Return WhatsThis description of item. See setWhatsThis().
+ */
+ QString whatsThis() const;
+
+ /**
+ * This function is called by @ref KCoreConfigSkeleton to read the value for this setting
+ * from a config file.
+ */
+ virtual void readConfig(KConfig *) = 0;
+
+ /**
+ * This function is called by @ref KCoreConfigSkeleton to write the value of this setting
+ * to a config file.
+ */
+ virtual void writeConfig(KConfig *) = 0;
+
+ /**
+ * Read global default value.
+ */
+ virtual void readDefault(KConfig *) = 0;
+
+ /**
+ * Set item to @p p
+ */
+ virtual void setProperty(const QVariant &p) = 0;
+
+ /**
+ * Check whether the item is equal to p.
+ *
+ * Use this function to compare items that use custom types,
+ * because QVariant::operator== will not work for those.
+ *
+ * @param p QVariant to compare to
+ * @return true if the item is equal to p, false otherwise
+ */
+ virtual bool isEqual(const QVariant &p) const = 0;
+
+ /**
+ * Return item as property
+ */
+ virtual QVariant property() const = 0;
+
+ /**
+ * Return minimum value of item or invalid if not specified
+ */
+ virtual QVariant minValue() const;
+
+ /**
+ * Return maximum value of item or invalid if not specified
+ */
+ virtual QVariant maxValue() const;
+
+ /**
+ * Sets the current value to the default value.
+ */
+ virtual void setDefault() = 0;
+
+ /**
+ * Exchanges the current value with the default value
+ * Used by KCoreConfigSkeleton::useDefaults(bool);
+ */
+ virtual void swapDefault() = 0;
+
+ /**
+ * Return if the entry can be modified.
+ */
+ bool isImmutable() const;
+
+ protected:
+ /**
+ * sets mIsImmutable to true if mKey in config is immutable
+ * @param group KConfigGroup to check if mKey is immutable in
+ */
+ void readImmutability(const KConfigGroup &group);
+
+ QString mGroup; ///< The group name for this item
+ QString mKey; ///< The config key for this item
+ QString mName; ///< The name of this item
+
+ private:
+ KConfigSkeletonItemPrivate * const d;
+ };
+
+
+/**
+ * \class KConfigSkeletonGenericItem kcoreconfigskeleton.h <KConfigSkeletonGenericItem>
+ */
+template < typename T > class KConfigSkeletonGenericItem:public KConfigSkeletonItem
+ {
+ public:
+ /** @copydoc KConfigSkeletonItem(const QString&, const QString&)
+ @param reference The initial value to hold in the item
+ @param defaultValue The default value for the item
+ */
+ KConfigSkeletonGenericItem(const QString & _group, const QString & _key, T & reference,
+ T defaultValue)
+ : KConfigSkeletonItem(_group, _key), mReference(reference),
+ mDefault(defaultValue), mLoadedValue(defaultValue)
+ {
+ }
+
+ /**
+ * Set value of this KConfigSkeletonItem.
+ */
+ void setValue(const T & v)
+ {
+ mReference = v;
+ }
+
+ /**
+ * Return value of this KConfigSkeletonItem.
+ */
+ T & value()
+ {
+ return mReference;
+ }
+
+ /**
+ * Return const value of this KConfigSkeletonItem.
+ */
+ const T & value() const
+ {
+ return mReference;
+ }
+
+ /**
+ Set default value for this item.
+ */
+ virtual void setDefaultValue( const T &v )
+ {
+ mDefault = v;
+ }
+
+ /**
+ Set the value for this item to the default value
+ */
+ virtual void setDefault()
+ {
+ mReference = mDefault;
+ }
+
+ /** @copydoc KConfigSkeletonItem::writeConfig(KConfig *) */
+ virtual void writeConfig(KConfig * config)
+ {
+ if ( mReference != mLoadedValue ) // Is this needed?
+ {
+ KConfigGroup cg(config, mGroup);
+ if ((mDefault == mReference) && !cg.hasDefault( mKey))
+ cg.revertToDefault( mKey );
+ else
+ cg.writeEntry(mKey, mReference);
+ }
+ }
+
+ /** @copydoc KConfigSkeletonItem::readDefault(KConfig*) */
+ void readDefault(KConfig * config)
+ {
+ config->setReadDefaults(true);
+ readConfig(config);
+ config->setReadDefaults(false);
+ mDefault = mReference;
+ }
+
+ /** @copydoc KConfigSkeletonItem::swapDefault() */
+ void swapDefault()
+ {
+ T tmp = mReference;
+ mReference = mDefault;
+ mDefault = tmp;
+ }
+
+ protected:
+ T & mReference; ///< Stores the value for this item
+ T mDefault; ///< The default value for this item
+ T mLoadedValue;
+ };
+
+ /**
+ * \class KCoreConfigSkeleton kcoreconfigskeleton.h <KCoreConfigSkeleton>
+ *
+ * @short Class for handling preferences settings for an application.
+ * @author Cornelius Schumacher
+ * @see KConfigSkeletonItem
+ *
+ * This class provides an interface to preferences settings. Preferences items
+ * can be registered by the addItem() function corresponding to the data type of
+ * the setting. KCoreConfigSkeleton then handles reading and writing of config files and
+ * setting of default values.
+ *
+ * Normally you will subclass KCoreConfigSkeleton, add data members for the preferences
+ * settings and register the members in the constructor of the subclass.
+ *
+ * Example:
+ * \code
+ * class MyPrefs : public KCoreConfigSkeleton
+ * {
+ * public:
+ * MyPrefs()
+ * {
+ * setCurrentGroup("MyGroup");
+ * addItemBool("MySetting1", mMyBool, false);
+ * addItemPoint("MySetting2", mMyPoint, QPoint(100, 200));
+ *
+ * setCurrentGroup("MyOtherGroup");
+ * addItemDouble("MySetting3", mMyDouble, 3.14);
+ * }
+ *
+ * bool mMyBool;
+ * QPoint mMyPoint;
+ * double mMyDouble;
+ * }
+ * \endcode
+ *
+ * It might be convenient in many cases to make this subclass of KCoreConfigSkeleton a
+ * singleton for global access from all over the application without passing
+ * references to the KCoreConfigSkeleton object around.
+ *
+ * You can write the data to the configuration file by calling @ref writeConfig()
+ * and read the data from the configuration file by calling @ref readConfig().
+ * If you want to watch for config changes, use @ref configChanged() signal.
+ *
+ * If you have items, which are not covered by the existing addItem() functions
+ * you can add customized code for reading, writing and default setting by
+ * implementing the functions @ref usrUseDefaults(), @ref usrReadConfig() and
+ * @ref usrWriteConfig().
+ *
+ * Internally preferences settings are stored in instances of subclasses of
+ * @ref KConfigSkeletonItem. You can also add KConfigSkeletonItem subclasses
+ * for your own types and call the generic @ref addItem() to register them.
+ *
+ * In many cases you don't have to write the specific KCoreConfigSkeleton
+ * subclasses yourself, but you can use \ref kconfig_compiler to automatically
+ * generate the C++ code from an XML description of the configuration options.
+ *
+ * Use KConfigSkeleton if you need GUI types as well.
+ */
+class KCONFIGCORE_EXPORT KCoreConfigSkeleton : public QObject
+{
+ Q_OBJECT
+public:
+ /**
+ * Class for handling a string preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemString:public KConfigSkeletonGenericItem < QString >
+ {
+ public:
+ enum Type { Normal, Password, Path };
+
+ /** @enum Type
+ The type of string that is held in this item
+
+ @var ItemString::Type ItemString::Normal
+ A normal string
+
+ @var ItemString::Type ItemString::Password
+ A password string
+
+ @var ItemString::Type ItemString::Path
+ A path to a file or directory
+ */
+
+
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem
+ @param type The type of string held by the item
+ */
+ ItemString(const QString & _group, const QString & _key,
+ QString & reference,
+ const QString & defaultValue = QLatin1String(""), // NOT QString() !!
+ Type type = Normal);
+
+ /** @copydoc KConfigSkeletonItem::writeConfig(KConfig*) */
+ void writeConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() const */
+ QVariant property() const;
+
+ private:
+ Type mType;
+ };
+
+ /**
+ * Class for handling a password preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemPassword:public ItemString
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemPassword(const QString & _group, const QString & _key,
+ QString & reference,
+ const QString & defaultValue = QLatin1String("")); // NOT QString() !!
+ };
+
+ /**
+ * Class for handling a path preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemPath:public ItemString
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemPath(const QString & _group, const QString & _key,
+ QString & reference,
+ const QString & defaultValue = QString());
+ };
+
+ /**
+ * Class for handling a url preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemUrl:public KConfigSkeletonGenericItem < QUrl >
+ {
+ public:
+
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem
+ */
+ ItemUrl(const QString & _group, const QString & _key,
+ QUrl & reference,
+ const QUrl & defaultValue = QUrl());
+
+ /** @copydoc KConfigSkeletonItem::writeConfig(KConfig*) */
+ void writeConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() const */
+ QVariant property() const;
+ };
+
+ /**
+ * Class for handling a QVariant preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemProperty:public KConfigSkeletonGenericItem < QVariant >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemProperty(const QString & _group, const QString & _key,
+ QVariant & reference, const QVariant & defaultValue = 0);
+
+ void readConfig(KConfig * config);
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() const */
+ QVariant property() const;
+ };
+
+
+ /**
+ * Class for handling a bool preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemBool:public KConfigSkeletonGenericItem < bool >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemBool(const QString & _group, const QString & _key, bool & reference,
+ bool defaultValue = true);
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() const */
+ QVariant property() const;
+ };
+
+
+ /**
+ * Class for handling a 32-bit integer preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemInt:public KConfigSkeletonGenericItem < qint32 >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemInt(const QString & _group, const QString & _key, qint32 &reference,
+ qint32 defaultValue = 0);
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+
+ /** Get the minimum value that is allowed to be stored in this item */
+ QVariant minValue() const;
+
+ /** Get the maximum value this is allowed to be stored in this item */
+ QVariant maxValue() const;
+
+ /** Set the minimum value for the item
+ @sa minValue()
+ */
+ void setMinValue(qint32);
+
+ /** Set the maximum value for the item
+ @sa maxValue
+ */
+ void setMaxValue(qint32);
+
+ private:
+ bool mHasMin : 1;
+ bool mHasMax : 1;
+ qint32 mMin;
+ qint32 mMax;
+ };
+
+ /**
+ * Class for handling a 64-bit integer preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemLongLong:public KConfigSkeletonGenericItem < qint64 >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemLongLong(const QString & _group, const QString & _key, qint64 &reference,
+ qint64 defaultValue = 0);
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+
+ /** @copydoc ItemInt::minValue() */
+ QVariant minValue() const;
+
+ /** @copydoc ItemInt::maxValue() */
+ QVariant maxValue() const;
+
+ /** @copydoc ItemInt::setMinValue(qint32) */
+ void setMinValue(qint64);
+
+ /** @copydoc ItemInt::setMaxValue(qint32) */
+ void setMaxValue(qint64);
+
+ private:
+ bool mHasMin : 1;
+ bool mHasMax : 1;
+ qint64 mMin;
+ qint64 mMax;
+ };
+#ifndef KDE_NO_DEPRECATED
+ typedef KCONFIGCORE_DEPRECATED ItemLongLong ItemInt64;
+#endif
+
+ /**
+ * Class for handling enums.
+ */
+ class KCONFIGCORE_EXPORT ItemEnum:public ItemInt
+ {
+ public:
+ struct Choice
+ {
+ QString name;
+ QString label;
+ QString toolTip;
+ QString whatsThis;
+ };
+
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem
+ @param choices The list of enums that can be stored in this item
+ */
+ ItemEnum(const QString & _group, const QString & _key, qint32 &reference,
+ const QList<Choice> &choices, qint32 defaultValue = 0);
+
+ QList<Choice> choices() const;
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::writeConfig(KConfig*) */
+ void writeConfig(KConfig * config);
+
+ // Source compatibility with 4.x
+ typedef Choice Choice2;
+ QList<Choice> choices2() const;
+
+ private:
+ QList<Choice> mChoices;
+ };
+
+
+ /**
+ * Class for handling an unsigned 32-bit integer preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemUInt:public KConfigSkeletonGenericItem < quint32 >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemUInt(const QString & _group, const QString & _key,
+ quint32 &reference, quint32 defaultValue = 0);
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+
+ /** @copydoc ItemInt::minValue() */
+ QVariant minValue() const;
+
+ /** @copydoc ItemInt::maxValue() */
+ QVariant maxValue() const;
+
+ /** @copydoc ItemInt::setMinValue(qint32) */
+ void setMinValue(quint32);
+
+ /** @copydoc ItemInt::setMaxValue(qint32) */
+ void setMaxValue(quint32);
+
+ private:
+ bool mHasMin : 1;
+ bool mHasMax : 1;
+ quint32 mMin;
+ quint32 mMax;
+ };
+
+ /**
+ * Class for handling unsigned 64-bit integer preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemULongLong:public KConfigSkeletonGenericItem < quint64 >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemULongLong(const QString & _group, const QString & _key, quint64 &reference,
+ quint64 defaultValue = 0);
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+
+ /** @copydoc ItemInt::minValue() */
+ QVariant minValue() const;
+
+ /** @copydoc ItemInt::maxValue() */
+ QVariant maxValue() const;
+
+ /** @copydoc ItemInt::setMinValue(qint32) */
+ void setMinValue(quint64);
+
+ /** @copydoc ItemInt::setMaxValue(qint32) */
+ void setMaxValue(quint64);
+
+ private:
+ bool mHasMin : 1;
+ bool mHasMax : 1;
+ quint64 mMin;
+ quint64 mMax;
+ };
+#ifndef KDE_NO_DEPRECATED
+ typedef KCONFIGCORE_DEPRECATED ItemULongLong ItemUInt64;
+#endif
+
+ /**
+ * Class for handling a floating point preference item.
+ */
+ class KCONFIGCORE_EXPORT ItemDouble:public KConfigSkeletonGenericItem < double >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemDouble(const QString & _group, const QString & _key,
+ double &reference, double defaultValue = 0);
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+
+ /** @copydoc ItemInt::minValue() */
+ QVariant minValue() const;
+
+ /** @copydoc ItemInt::maxValue() */
+ QVariant maxValue() const;
+
+ /** @copydoc ItemInt::setMinValue() */
+ void setMinValue(double);
+
+ /** @copydoc ItemInt::setMaxValue() */
+ void setMaxValue(double);
+
+ private:
+ bool mHasMin : 1;
+ bool mHasMax : 1;
+ double mMin;
+ double mMax;
+ };
+
+
+ /**
+ * Class for handling a QRect preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemRect:public KConfigSkeletonGenericItem < QRect >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemRect(const QString & _group, const QString & _key, QRect & reference,
+ const QRect & defaultValue = QRect());
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+ };
+
+
+ /**
+ * Class for handling a QPoint preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemPoint:public KConfigSkeletonGenericItem < QPoint >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemPoint(const QString & _group, const QString & _key, QPoint & reference,
+ const QPoint & defaultValue = QPoint());
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+ };
+
+
+ /**
+ * Class for handling a QSize preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemSize:public KConfigSkeletonGenericItem < QSize >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemSize(const QString & _group, const QString & _key, QSize & reference,
+ const QSize & defaultValue = QSize());
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+ };
+
+
+ /**
+ * Class for handling a QDateTime preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemDateTime:public KConfigSkeletonGenericItem < QDateTime >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemDateTime(const QString & _group, const QString & _key,
+ QDateTime & reference,
+ const QDateTime & defaultValue = QDateTime());
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+ };
+
+
+ /**
+ * Class for handling a string list preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemStringList:public KConfigSkeletonGenericItem < QStringList >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemStringList(const QString & _group, const QString & _key,
+ QStringList & reference,
+ const QStringList & defaultValue = QStringList());
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+ };
+
+
+ /**
+ * Class for handling a path list preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemPathList:public ItemStringList
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemPathList(const QString & _group, const QString & _key,
+ QStringList & reference,
+ const QStringList & defaultValue = QStringList());
+
+ /** @copydoc KConfigSkeletonItem::readConfig */
+ void readConfig(KConfig * config);
+ /** @copydoc KConfigSkeletonItem::writeConfig */
+ void writeConfig(KConfig * config);
+ };
+
+ /**
+ * Class for handling a url list preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemUrlList:public KConfigSkeletonGenericItem < QList<QUrl> >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemUrlList(const QString & _group, const QString & _key,
+ QList<QUrl> & reference,
+ const QList<QUrl> & defaultValue = QList<QUrl>());
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::writeConfig(KConfig*) */
+ void writeConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+ };
+
+ /**
+ * Class for handling an integer list preferences item.
+ */
+ class KCONFIGCORE_EXPORT ItemIntList:public KConfigSkeletonGenericItem < QList < int > >
+ {
+ public:
+ /** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
+ ItemIntList(const QString & _group, const QString & _key,
+ QList < int >&reference,
+ const QList < int >&defaultValue = QList < int >());
+
+ /** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
+ void readConfig(KConfig * config);
+
+ /** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
+ void setProperty(const QVariant & p);
+
+ /** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) const */
+ bool isEqual(const QVariant &p) const;
+
+ /** @copydoc KConfigSkeletonItem::property() */
+ QVariant property() const;
+ };
+
+
+public:
+ /**
+ * Constructor.
+ *
+ * @param configname name of config file. If no name is given, the default
+ * config file as returned by KSharedConfig::openConfig() is used
+ * @param parent the parent object (see QObject documentation)
+ */
+ explicit KCoreConfigSkeleton(const QString & configname = QString(), QObject* parent = 0);
+
+ /**
+ * Constructor.
+ *
+ * @param config configuration object to use
+ * @param parent the parent object (see QObject documentation)
+ */
+ explicit KCoreConfigSkeleton(KSharedConfig::Ptr config, QObject* parent = 0);
+
+ /**
+ * Destructor
+ */
+ virtual ~KCoreConfigSkeleton();
+
+ /**
+ * Set all registered items to their default values.
+ * This method calls usrSetDefaults() after setting the defaults for the
+ * registered items. You can overridde usrSetDefaults() in derived classes
+ * if you have special requirements.
+ * If you need more fine-grained control of setting the default values of
+ * the registered items you can override setDefaults() in a derived class.
+ */
+ virtual void setDefaults();
+
+ /**
+ * Read preferences from config file. All registered items are set to the
+ * values read from disk.
+ * This method calls usrReadConfig() after reading the settings of the
+ * registered items from the KConfig. You can overridde usrReadConfig()
+ * in derived classes if you have special requirements.
+ * If you need more fine-grained control of storing the settings from
+ * the registered items you can override readConfig() in a derived class.
+ */
+ virtual void readConfig();
+
+ /**
+ * Set the config file group for subsequent addItem() calls. It is valid
+ * until setCurrentGroup() is called with a new argument. Call this before
+ * you add any items. The default value is "No Group".
+ */
+ void setCurrentGroup(const QString & group);
+
+ /**
+ * Returns the current group used for addItem() calls.
+ */
+ QString currentGroup() const;
+
+ /**
+ * Register a custom @ref KConfigSkeletonItem with a given name.
+ *
+ * If the name parameter is null, take the name from KConfigSkeletonItem::key().
+ * Note that all names must be unique but that multiple entries can have
+ * the same key if they reside in different groups.
+ *
+ * KCoreConfigSkeleton takes ownership of the KConfigSkeletonItem.
+ */
+ void addItem(KConfigSkeletonItem *, const QString & name = QString() );
+
+ /**
+ * Register an item of type QString.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemString *addItemString(const QString & name, QString & reference,
+ const QString & defaultValue = QLatin1String(""), // NOT QString() !!
+ const QString & key = QString());
+
+ /**
+ * Register a password item of type QString. The string value is written
+ * encrypted to the config file. Note that the current encryption scheme
+ * is very weak.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemPassword *addItemPassword(const QString & name, QString & reference,
+ const QString & defaultValue = QLatin1String(""),
+ const QString & key = QString());
+
+ /**
+ * Register a path item of type QString. The string value is interpreted
+ * as a path. This means, dollar expension is activated for this value, so
+ * that e.g. $HOME gets expanded.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemPath *addItemPath(const QString & name, QString & reference,
+ const QString & defaultValue = QLatin1String(""),
+ const QString & key = QString());
+
+ /**
+ * Register a property item of type QVariant. Note that only the following
+ * QVariant types are allowed: String, StringList, Font, Point, Rect, Size,
+ * Color, Int, UInt, Bool, Double, DateTime and Date.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemProperty *addItemProperty(const QString & name, QVariant & reference,
+ const QVariant & defaultValue = QVariant(),
+ const QString & key = QString());
+ /**
+ * Register an item of type bool.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemBool *addItemBool(const QString & name, bool & reference,
+ bool defaultValue = false,
+ const QString & key = QString());
+
+ /**
+ * Register an item of type qint32.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemInt *addItemInt(const QString & name, qint32 &reference, qint32 defaultValue = 0,
+ const QString & key = QString());
+
+ /**
+ * Register an item of type quint32.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemUInt *addItemUInt(const QString & name, quint32 &reference,
+ quint32 defaultValue = 0,
+ const QString & key = QString());
+
+ /**
+ * Register an item of type qint64.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemLongLong *addItemLongLong(const QString & name, qint64 &reference,
+ qint64 defaultValue = 0,
+ const QString & key = QString());
+
+ /**
+ * @deprecated
+ * Use addItemLongLong().
+ */
+#ifndef KDE_NO_DEPRECATED
+ KCONFIGCORE_DEPRECATED ItemLongLong *addItemInt64( const QString& name, qint64 &reference,
+ qint64 defaultValue = 0,
+ const QString & key = QString());
+#endif
+
+ /**
+ * Register an item of type quint64
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemULongLong *addItemULongLong(const QString & name, quint64 &reference,
+ quint64 defaultValue = 0,
+ const QString & key = QString());
+
+ /**
+ * @deprecated
+ * Use addItemULongLong().
+ */
+#ifndef KDE_NO_DEPRECATED
+ KCONFIGCORE_DEPRECATED ItemULongLong *addItemUInt64(const QString & name, quint64 &reference,
+ quint64 defaultValue = 0,
+ const QString & key = QString());
+#endif
+
+ /**
+ * Register an item of type double.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemDouble *addItemDouble(const QString & name, double &reference,
+ double defaultValue = 0.0,
+ const QString & key = QString());
+
+ /**
+ * Register an item of type QRect.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemRect *addItemRect(const QString & name, QRect & reference,
+ const QRect & defaultValue = QRect(),
+ const QString & key = QString());
+
+ /**
+ * Register an item of type QPoint.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemPoint *addItemPoint(const QString & name, QPoint & reference,
+ const QPoint & defaultValue = QPoint(),
+ const QString & key = QString());
+
+ /**
+ * Register an item of type QSize.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemSize *addItemSize(const QString & name, QSize & reference,
+ const QSize & defaultValue = QSize(),
+ const QString & key = QString());
+
+ /**
+ * Register an item of type QDateTime.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemDateTime *addItemDateTime(const QString & name, QDateTime & reference,
+ const QDateTime & defaultValue = QDateTime(),
+ const QString & key = QString());
+
+ /**
+ * Register an item of type QStringList.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemStringList *addItemStringList(const QString & name, QStringList & reference,
+ const QStringList & defaultValue = QStringList(),
+ const QString & key = QString());
+
+ /**
+ * Register an item of type QList<int>.
+ *
+ * @param name Name used to identify this setting. Names must be unique.
+ * @param reference Pointer to the variable, which is set by readConfig()
+ * calls and read by writeConfig() calls.
+ * @param defaultValue Default value, which is used when the config file
+ * does not yet contain the key of this item.
+ * @param key Key used in config file. If key is null, name is used as key.
+ * @return The created item
+ */
+ ItemIntList *addItemIntList(const QString & name, QList < int >&reference,
+ const QList < int >&defaultValue =
+ QList < int >(),
+ const QString & key = QString());
+
+ /**
+ * Return the @ref KConfig object used for reading and writing the settings.
+ */
+ KConfig *config();
+
+ /**
+ * Return the @ref KConfig object used for reading and writing the settings.
+ */
+ const KConfig *config() const;
+
+ /**
+ * Set the @ref KSharedConfig object used for reading and writing the settings.
+ */
+ void setSharedConfig(KSharedConfig::Ptr pConfig);
+
+ /**
+ * Return list of items managed by this KCoreConfigSkeleton object.
+ */
+ KConfigSkeletonItem::List items() const;
+
+ /**
+ * Removes and deletes an item by name
+ * @arg name the name of the item to remove
+ */
+ void removeItem(const QString &name);
+
+ /**
+ * Removes and deletes all items
+ */
+ void clearItems();
+
+ /**
+ * Return whether a certain item is immutable
+ * @since 4.4
+ */
+ bool isImmutable(const QString & name) const;
+
+ /**
+ * Lookup item by name
+ * @since 4.4
+ */
+ KConfigSkeletonItem * findItem(const QString & name) const;
+
+ /**
+ * Specify whether this object should reflect the actual values or the
+ * default values.
+ * This method is implemented by usrUseDefaults(), which can be overridden
+ * in derived classes if you have special requirements and can call
+ * usrUseDefaults() directly.
+ * If you don't have control whether useDefaults() or usrUseDefaults() is
+ * called override useDefaults() directly.
+ * @param b true to make this object reflect the default values,
+ * false to make it reflect the actual values.
+ * @return The state prior to this call
+ */
+ virtual bool useDefaults(bool b);
+
+public Q_SLOTS:
+ /**
+ * Write preferences to config file. The values of all registered items are
+ * written to disk.
+ * This method calls usrWriteConfig() after writing the settings from the
+ * registered items to the KConfig. You can overridde usrWriteConfig()
+ * in derived classes if you have special requirements.
+ * If you need more fine-grained control of storing the settings from
+ * the registered items you can override writeConfig() in a derived class.
+ */
+ virtual bool writeConfig();
+
+Q_SIGNALS:
+ /**
+ * This signal is emitted when the configuration change.
+ */
+ void configChanged();
+
+protected:
+ /**
+ * Implemented by subclasses that use special defaults.
+ * It replaces the default values with the actual values and
+ * vice versa. Called from @ref useDefaults()
+ * @param b true to make this object reflect the default values,
+ * false to make it reflect the actual values.
+ * @return The state prior to this call
+ */
+ virtual bool usrUseDefaults(bool b);
+
+ /**
+ * Perform the actual setting of default values.
+ * Override in derived classes to set special default values.
+ * Called from @ref setDefaults()
+ */
+ virtual void usrSetDefaults();
+
+ /**
+ * Perform the actual reading of the configuration file.
+ * Override in derived classes to read special config values.
+ * Called from @ref readConfig()
+ */
+ virtual void usrReadConfig();
+
+ /**
+ * Perform the actual writing of the configuration file.
+ * Override in derived classes to write special config values.
+ * Called from @ref writeConfig()
+ */
+ virtual bool usrWriteConfig();
+
+private:
+ class Private;
+ Private * const d;
+ friend class KConfigSkeleton;
+
+};
+
+#endif
diff --git a/src/core/kcoreconfigskeleton_p.h b/src/core/kcoreconfigskeleton_p.h
new file mode 100644
index 00000000..0912019c
--- /dev/null
+++ b/src/core/kcoreconfigskeleton_p.h
@@ -0,0 +1,64 @@
+/*
+ This file is part of KOrganizer.
+ Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
+ Copyright (c) 2003 Waldo Bastian <bastian@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.
+*/
+
+#ifndef KCORECONFIGSKELETON_P_H
+#define KCORECONFIGSKELETON_P_H
+
+#include "kcoreconfigskeleton.h"
+
+class KCoreConfigSkeleton::Private
+{
+public:
+ Private()
+ : mCurrentGroup( QLatin1String("No Group") ), mUseDefaults( false )
+ {}
+ ~Private()
+ {
+ KConfigSkeletonItem::List::ConstIterator it;
+ for( it = mItems.constBegin(); it != mItems.constEnd(); ++it )
+ {
+ delete *it;
+ }
+ }
+ QString mCurrentGroup;
+
+ KSharedConfig::Ptr mConfig; // pointer to KConfig object
+
+ KConfigSkeletonItem::List mItems;
+ KConfigSkeletonItem::Dict mItemDict;
+
+ bool mUseDefaults;
+};
+
+class KConfigSkeletonItemPrivate
+{
+public:
+ KConfigSkeletonItemPrivate()
+ : mIsImmutable(true)
+ {}
+ bool mIsImmutable; ///< Indicates this item is immutable
+
+ QString mLabel; ///< The label for this item
+ QString mToolTip; ///< The ToolTip text for this item
+ QString mWhatsThis; ///< The What's This text for this item
+};
+
+#endif
diff --git a/src/core/kdesktopfile.cpp b/src/core/kdesktopfile.cpp
new file mode 100644
index 00000000..0ebbb4b0
--- /dev/null
+++ b/src/core/kdesktopfile.cpp
@@ -0,0 +1,366 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 1999 Pietro Iglio <iglio@kde.org>
+ Copyright (c) 1999 Preston Brown <pbrown@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 "kdesktopfile.h"
+
+#ifndef Q_OS_WIN
+#include <unistd.h>
+#endif
+
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QUrl>
+#include <qstandardpaths.h>
+
+#include "kauthorized.h"
+#include "kconfig_p.h"
+#include "kconfiggroup.h"
+#include "kconfigini_p.h"
+
+class KDesktopFilePrivate : public KConfigPrivate
+{
+ public:
+ KDesktopFilePrivate(QStandardPaths::StandardLocation resourceType, const QString &fileName);
+ KConfigGroup desktopGroup;
+};
+
+KDesktopFilePrivate::KDesktopFilePrivate(QStandardPaths::StandardLocation resourceType, const QString &fileName)
+ : KConfigPrivate(KConfig::NoGlobals, resourceType)
+{
+ mBackend = new KConfigIniBackend();
+ bDynamicBackend = false;
+ changeFileName(fileName);
+}
+
+KDesktopFile::KDesktopFile(QStandardPaths::StandardLocation resourceType, const QString &fileName)
+ : KConfig(*new KDesktopFilePrivate(resourceType, fileName))
+{
+ Q_D(KDesktopFile);
+ reparseConfiguration();
+ d->desktopGroup = KConfigGroup(this, "Desktop Entry");
+}
+
+KDesktopFile::KDesktopFile(const QString &fileName)
+ : KConfig(*new KDesktopFilePrivate(QStandardPaths::ApplicationsLocation, fileName))
+{
+ Q_D(KDesktopFile);
+ reparseConfiguration();
+ d->desktopGroup = KConfigGroup(this, "Desktop Entry");
+}
+
+KDesktopFile::~KDesktopFile()
+{
+}
+
+KConfigGroup KDesktopFile::desktopGroup() const
+{
+ Q_D(const KDesktopFile);
+ return d->desktopGroup;
+}
+
+QString KDesktopFile::locateLocal(const QString &path)
+{
+ QString relativePath;
+ // Relative to config? (e.g. for autostart)
+ Q_FOREACH(const QString& dir, QStandardPaths::standardLocations(QStandardPaths::GenericConfigLocation)) {
+ if (path.startsWith(dir) + '/') {
+ relativePath = dir.mid(path.length() + 1);
+ return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1Char('/') + relativePath;
+ }
+ }
+ // Relative to xdg data dir? (much more common)
+ Q_FOREACH(const QString& dir, QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation)) {
+ if (path.startsWith(dir) + '/')
+ relativePath = dir.mid(path.length() + 1);
+ }
+ if (relativePath.isEmpty()) {
+ // What now? The desktop file doesn't come from XDG_DATA_DIRS. Use filename only and hope for the best.
+ relativePath = path.mid(path.lastIndexOf(QLatin1Char('/'))+1);
+ }
+ return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Char('/') + relativePath;
+}
+
+bool KDesktopFile::isDesktopFile(const QString& path)
+{
+ return (path.length() > 8
+ && path.endsWith(QLatin1String(".desktop")));
+}
+
+bool KDesktopFile::isAuthorizedDesktopFile(const QString& path)
+{
+ if (path.isEmpty())
+ return false; // Empty paths are not ok.
+
+ if (QDir::isRelativePath(path))
+ return true; // Relative paths are ok.
+
+ const QString realPath = QFileInfo(path).canonicalFilePath();
+ if (realPath.isEmpty())
+ return false; // File doesn't exist.
+
+#ifndef Q_OS_WIN
+ const Qt::CaseSensitivity sensitivity = Qt::CaseSensitive;
+#else
+ const Qt::CaseSensitivity sensitivity = Qt::CaseInsensitive;
+#endif
+
+ // Check if the .desktop file is installed as part of KDE or XDG.
+ const QStringList appsDirs = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation);
+ Q_FOREACH (const QString &prefix, appsDirs) {
+ if (QDir(prefix).exists() && realPath.startsWith(QFileInfo(prefix).canonicalFilePath(), sensitivity))
+ return true;
+ }
+ const QString servicesDir = QLatin1String("kde5/services/"); // KGlobal::dirs()->xdgDataRelativePath("services")
+ Q_FOREACH (const QString &xdgDataPrefix, QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation)) {
+ if (QDir(xdgDataPrefix).exists()) {
+ const QString prefix = QFileInfo(xdgDataPrefix).canonicalFilePath();
+ if (realPath.startsWith(prefix + QLatin1Char('/') + servicesDir, sensitivity))
+ return true;
+ }
+ }
+ const QString autostartDir = QLatin1String("autostart/");
+ Q_FOREACH (const QString &xdgDataPrefix, QStandardPaths::standardLocations(QStandardPaths::GenericConfigLocation)) {
+ if (QDir(xdgDataPrefix).exists()) {
+ const QString prefix = QFileInfo(xdgDataPrefix).canonicalFilePath();
+ if (realPath.startsWith(prefix + QLatin1Char('/') + autostartDir, sensitivity))
+ return true;
+ }
+ }
+
+ // Forbid desktop files outside of standard locations if kiosk is set so
+ if (!KAuthorized::authorize(QLatin1String("run_desktop_files"))) {
+ qWarning() << "Access to '" << path << "' denied because of 'run_desktop_files' restriction." << endl;
+ return false;
+ }
+
+ // Not otherwise permitted, so only allow if the file is executable, or if
+ // owned by root (uid == 0)
+ QFileInfo entryInfo( path );
+ if (entryInfo.isExecutable() || entryInfo.ownerId() == 0)
+ return true;
+
+ qWarning() << "Access to '" << path << "' denied, not owned by root, executable flag not set." << endl;
+ return false;
+}
+
+QString KDesktopFile::readType() const
+{
+ Q_D(const KDesktopFile);
+ return d->desktopGroup.readEntry("Type", QString());
+}
+
+QString KDesktopFile::readIcon() const
+{
+ Q_D(const KDesktopFile);
+ return d->desktopGroup.readEntry("Icon", QString());
+}
+
+QString KDesktopFile::readName() const
+{
+ Q_D(const KDesktopFile);
+ return d->desktopGroup.readEntry("Name", QString());
+}
+
+QString KDesktopFile::readComment() const
+{
+ Q_D(const KDesktopFile);
+ return d->desktopGroup.readEntry("Comment", QString());
+}
+
+QString KDesktopFile::readGenericName() const
+{
+ Q_D(const KDesktopFile);
+ return d->desktopGroup.readEntry("GenericName", QString());
+}
+
+QString KDesktopFile::readPath() const
+{
+ Q_D(const KDesktopFile);
+ // NOT readPathEntry, it is not XDG-compliant. Path entries written by
+ // KDE4 will be still treated as such, though.
+ return d->desktopGroup.readEntry("Path", QString());
+}
+
+QString KDesktopFile::readDevice() const
+{
+ Q_D(const KDesktopFile);
+ return d->desktopGroup.readEntry("Dev", QString());
+}
+
+QString KDesktopFile::readUrl() const
+{
+ Q_D(const KDesktopFile);
+ if (hasDeviceType()) {
+ return d->desktopGroup.readEntry("MountPoint", QString());
+ } else {
+ // NOT readPathEntry (see readPath())
+ QString url = d->desktopGroup.readEntry("URL", QString());
+ if ( !url.isEmpty() && !QDir::isRelativePath(url) )
+ {
+ // Handle absolute paths as such (i.e. we need to escape them)
+ return QUrl::fromLocalFile(url).toString();
+ }
+ return url;
+ }
+}
+
+QStringList KDesktopFile::readActions() const
+{
+ Q_D(const KDesktopFile);
+ return d->desktopGroup.readXdgListEntry("Actions");
+}
+
+KConfigGroup KDesktopFile::actionGroup(const QString &group)
+{
+ return KConfigGroup(this, QLatin1String("Desktop Action ") + group);
+}
+
+const KConfigGroup KDesktopFile::actionGroup(const QString& group) const
+{
+ return const_cast<KDesktopFile*>(this)->actionGroup(group);
+}
+
+bool KDesktopFile::hasActionGroup(const QString &group) const
+{
+ return hasGroup(QString(QLatin1String("Desktop Action ") + group).toUtf8().constData());
+}
+
+bool KDesktopFile::hasLinkType() const
+{
+ return readType() == QLatin1String("Link");
+}
+
+bool KDesktopFile::hasApplicationType() const
+{
+ return readType() == QLatin1String("Application");
+}
+
+bool KDesktopFile::hasDeviceType() const
+{
+ return readType() == QLatin1String("FSDevice");
+}
+
+bool KDesktopFile::tryExec() const
+{
+ Q_D(const KDesktopFile);
+ // Test for TryExec and "X-KDE-AuthorizeAction"
+ // NOT readPathEntry (see readPath())
+ QString te = d->desktopGroup.readEntry("TryExec", QString());
+
+ if (!te.isEmpty()) {
+ return !QStandardPaths::findExecutable(te).isEmpty();
+ }
+ const QStringList list = d->desktopGroup.readEntry("X-KDE-AuthorizeAction", QStringList());
+ if (!list.isEmpty())
+ {
+ for(QStringList::ConstIterator it = list.begin();
+ it != list.end();
+ ++it)
+ {
+ if (!KAuthorized::authorize((*it).trimmed()))
+ return false;
+ }
+ }
+
+ // See also KService::username()
+ bool su = d->desktopGroup.readEntry("X-KDE-SubstituteUID", false);
+ if (su)
+ {
+ QString user = d->desktopGroup.readEntry("X-KDE-Username", QString());
+ if (user.isEmpty())
+ user = QString::fromLocal8Bit(qgetenv("ADMIN_ACCOUNT"));
+ if (user.isEmpty())
+ user = QString::fromLatin1("root");
+ if (!KAuthorized::authorize(QString::fromLatin1("user/")+user))
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * @return the filename as passed to the constructor.
+ */
+//QString KDesktopFile::fileName() const { return backEnd->fileName(); }
+
+/**
+ * @return the resource type as passed to the constructor.
+ */
+//QString
+//KDesktopFile::resource() const { return backEnd->resource(); }
+
+QStringList
+KDesktopFile::sortOrder() const
+{
+ Q_D(const KDesktopFile);
+ return d->desktopGroup.readEntry("SortOrder", QStringList());
+}
+
+//void KDesktopFile::virtual_hook( int id, void* data )
+//{ KConfig::virtual_hook( id, data ); }
+
+QString KDesktopFile::readDocPath() const
+{
+ Q_D(const KDesktopFile);
+ //legacy entry in kde3 apps
+ if(d->desktopGroup.hasKey( "DocPath" ))
+ return d->desktopGroup.readPathEntry( "DocPath", QString() );
+ return d->desktopGroup.readPathEntry( "X-DocPath", QString() );
+}
+
+KDesktopFile* KDesktopFile::copyTo(const QString &file) const
+{
+ KDesktopFile *config = new KDesktopFile(QString());
+ this->KConfig::copyTo(file, config);
+// config->setDesktopGroup();
+ return config;
+}
+
+QStandardPaths::StandardLocation KDesktopFile::resource() const
+{
+ Q_D(const KDesktopFile);
+ return d->resourceType;
+}
+
+QString KDesktopFile::fileName() const
+{
+ return name();
+}
+
+bool KDesktopFile::noDisplay() const
+{
+ Q_D(const KDesktopFile);
+ if (d->desktopGroup.readEntry("NoDisplay", false)) {
+ return true;
+ }
+ if (d->desktopGroup.hasKey("OnlyShowIn")) {
+ if (!d->desktopGroup.readXdgListEntry("OnlyShowIn").contains(QLatin1String("KDE")))
+ return true;
+ }
+ if (d->desktopGroup.hasKey("NotShowIn")) {
+ if (d->desktopGroup.readXdgListEntry("NotShowIn").contains(QLatin1String("KDE")))
+ return true;
+ }
+ return false;
+}
diff --git a/src/core/kdesktopfile.h b/src/core/kdesktopfile.h
new file mode 100644
index 00000000..f3c5fe8f
--- /dev/null
+++ b/src/core/kdesktopfile.h
@@ -0,0 +1,252 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 1999 Pietro Iglio <iglio@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.
+*/
+#ifndef KDESKTOPFILE_H
+#define KDESKTOPFILE_H
+
+#include <kconfig.h>
+
+class KConfigGroup;
+class KDesktopFilePrivate;
+
+/**
+ * \class KDesktopFile kdesktopfile.h <KDesktopFile>
+ *
+ * %KDE Desktop File Management.
+ * This class implements %KDE's support for the freedesktop.org
+ * <em>Desktop Entry Spec</em>.
+ *
+ * @author Pietro Iglio <iglio@kde.org>
+ * @see KConfigBase KConfig
+ * @see <a href="http://standards.freedesktop.org/desktop-entry-spec/latest/">Desktop Entry Spec</a>
+ */
+class KCONFIGCORE_EXPORT KDesktopFile : public KConfig
+{
+public:
+ /**
+ * Constructs a KDesktopFile object.
+ *
+ * See QStandardPaths for more information on resources.
+ *
+ * @param resourceType Allows you to change what sort of resource
+ * to search for if @p fileName is not absolute.
+ * For instance, you might want to specify GenericConfigLocation.
+ * @param fileName The name or path of the desktop file. If it
+ * is not absolute, it will be located
+ * using the resource type @p resType.
+ */
+ explicit KDesktopFile(QStandardPaths::StandardLocation resourceType, const QString &fileName);
+
+ /**
+ * Constructs a KDesktopFile object.
+ *
+ * See QStandardPaths for more information on resources.
+ *
+ * @param fileName The name or path of the desktop file. If it
+ * is not absolute, it will be located
+ * using the resource type ApplicationsLocation
+ */
+ explicit KDesktopFile(const QString &fileName);
+
+ /**
+ * Destructs the KDesktopFile object.
+ *
+ * Writes back any dirty configuration entries.
+ */
+ virtual ~KDesktopFile();
+
+ /**
+ * Checks whether this is really a desktop file.
+ *
+ * The check is performed looking at the file extension (the file is not
+ * opened).
+ * Currently, the only valid extension is ".desktop".
+ * @param path the path of the file to check
+ * @return true if the file appears to be a desktop file.
+ */
+ static bool isDesktopFile(const QString& path);
+
+ /**
+ * Checks whether the user is authorized to run this desktop file.
+ * By default users are authorized to run all desktop files but
+ * the KIOSK framework can be used to activate certain restrictions.
+ * See README.kiosk for more information.
+ *
+ * Note: Since KDE 4.3, there are more restrictions on authorized
+ * desktop files to prevent users from inadvertently running trojan
+ * desktop files. Your application launchers should have the executable
+ * bit set to prevent issues. To see if a restriction is due to
+ * KIOSK, see KAuthorized.
+ *
+ * @param path the file to check
+ * @return true if the user is authorized to run the file
+ */
+ static bool isAuthorizedDesktopFile(const QString& path);
+
+ /**
+ * Returns the location where changes for the .desktop file @p path
+ * should be written to.
+ */
+ static QString locateLocal(const QString &path);
+
+ KConfigGroup desktopGroup() const;
+
+ /**
+ * Returns the value of the "Type=" entry.
+ * @return the type or QString() if not specified
+ */
+ QString readType() const;
+
+ /**
+ * Returns the value of the "Icon=" entry.
+ * @return the icon or QString() if not specified
+ */
+ QString readIcon() const;
+
+ /**
+ * Returns the value of the "Name=" entry.
+ * @return the name or QString() if not specified
+ */
+ QString readName() const;
+
+ /**
+ * Returns the value of the "Comment=" entry.
+ * @return the comment or QString() if not specified
+ */
+ QString readComment() const;
+
+ /**
+ * Returns the value of the "GenericName=" entry.
+ * @return the generic name or QString() if not specified
+ */
+ QString readGenericName() const;
+
+ /**
+ * Returns the value of the "Path=" entry.
+ * @return the path or QString() if not specified
+ */
+ QString readPath() const;
+
+ /**
+ * Returns the value of the "Dev=" entry.
+ * @return the device or QString() if not specified
+ */
+ QString readDevice() const;
+
+ /**
+ * Returns the value of the "URL=" entry.
+ * @return the URL or QString() if not specified
+ */
+ QString readUrl() const;
+
+ /**
+ * Returns a list of the "Actions=" entries.
+ * @return the list of actions
+ */
+ QStringList readActions() const;
+
+ /**
+ * Sets the desktop action group.
+ * @param group the new action group
+ */
+ KConfigGroup actionGroup(const QString &group);
+
+ const KConfigGroup actionGroup(const QString &group) const;
+
+ /**
+ * Returns true if the action group exists, false otherwise
+ * @param group the action group to test
+ * @return true if the action group exists
+ */
+ bool hasActionGroup(const QString &group) const;
+
+ /**
+ * Checks whether there is a "Type=Link" entry.
+ *
+ * The link points to the "URL=" entry.
+ * @return true if there is a "Type=Link" entry
+ */
+ bool hasLinkType() const;
+
+ /**
+ * Checks whether there is an entry "Type=Application".
+ * @return true if there is a "Type=Application" entry
+ */
+ bool hasApplicationType() const;
+
+ /**
+ * Checks whether there is an entry "Type=FSDevice".
+ * @return true if there is a "Type=FSDevice" entry
+ */
+ bool hasDeviceType() const;
+
+ /**
+ * Checks whether the TryExec field contains a binary
+ * which is found on the local system.
+ * @return true if TryExec contains an existing binary
+ */
+ bool tryExec() const;
+
+ /**
+ * Returns the value of the "X-DocPath=" Or "DocPath=" entry.
+ * @return The value of the "X-DocPath=" Or "DocPath=" entry.
+ */
+ QString readDocPath() const;
+
+ /**
+ * Returns the entry of the "SortOrder=" entry.
+ * @return the value of the "SortOrder=" entry.
+ */
+ QStringList sortOrder() const;
+
+ /**
+ * Whether the entry should be suppressed in menus.
+ * This handles the NoDisplay key, but also OnlyShowIn / NotShowIn.
+ * @return true to suppress this service
+ * @since 4.1
+ */
+ bool noDisplay() const;
+
+ /**
+ * Copies all entries from this config object to a new
+ * KDesktopFile object that will save itself to @p file.
+ *
+ * Actual saving to @p file happens when the returned object is
+ * destructed or when sync() is called upon it.
+ *
+ * @param file the new KDesktopFile object it will save itself to.
+ */
+ KDesktopFile* copyTo(const QString &file) const;
+
+ QString fileName() const;
+
+ QStandardPaths::StandardLocation resource() const;
+
+protected:
+ /** Virtual hook, used to add new "virtual" functions while maintaining
+ binary compatibility. Unused in this class.
+ */
+// virtual void virtual_hook( int id, void* data );
+private:
+
+ Q_DISABLE_COPY(KDesktopFile)
+
+ Q_DECLARE_PRIVATE(KDesktopFile)
+};
+
+#endif
diff --git a/src/core/kemailsettings.cpp b/src/core/kemailsettings.cpp
new file mode 100644
index 00000000..6a1f9448
--- /dev/null
+++ b/src/core/kemailsettings.cpp
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2000 Alex Zepeda <zipzippy@sonic.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "kemailsettings.h"
+
+#include <kconfig.h>
+#include <kconfiggroup.h>
+
+class KEMailSettingsPrivate {
+public:
+ KEMailSettingsPrivate() : m_pConfig( 0 ) {}
+ ~KEMailSettingsPrivate() { delete m_pConfig; }
+ KConfig *m_pConfig;
+ QStringList profiles;
+ QString m_sDefaultProfile, m_sCurrentProfile;
+};
+
+QString KEMailSettings::defaultProfileName() const
+{
+ return p->m_sDefaultProfile;
+}
+
+QString KEMailSettings::getSetting(KEMailSettings::Setting s) const
+{
+ KConfigGroup cg(p->m_pConfig, QStringLiteral("PROFILE_") + p->m_sCurrentProfile);
+ switch (s) {
+ case ClientProgram: {
+ return cg.readEntry("EmailClient");
+ break;
+ }
+ case ClientTerminal: {
+ return cg.readEntry("TerminalClient", QVariant(false)).toString();
+ break;
+ }
+ case RealName: {
+ return cg.readEntry("FullName");
+ break;
+ }
+ case EmailAddress: {
+ return cg.readEntry("EmailAddress");
+ break;
+ }
+ case ReplyToAddress: {
+ return cg.readEntry("ReplyAddr");
+ break;
+ }
+ case Organization: {
+ return cg.readEntry("Organization");
+ break;
+ }
+ case OutServer: {
+ return cg.readEntry("OutgoingServer");
+ break;
+ }
+ case OutServerLogin: {
+ return cg.readEntry("OutgoingUserName");
+ break;
+ }
+ case OutServerPass: {
+ return cg.readEntry("OutgoingPassword");
+ break;
+ }
+ case OutServerType: {
+ return cg.readEntry("OutgoingServerType");
+ break;
+ }
+ case OutServerCommand: {
+ return cg.readEntry("OutgoingCommand");
+ break;
+ }
+ case OutServerTLS: {
+ return cg.readEntry("OutgoingServerTLS", QVariant(false)).toString();
+ break;
+ }
+ case InServer: {
+ return cg.readEntry("IncomingServer");
+ break;
+ }
+ case InServerLogin: {
+ return cg.readEntry("IncomingUserName");
+ break;
+ }
+ case InServerPass: {
+ return cg.readEntry("IncomingPassword");
+ break;
+ }
+ case InServerType: {
+ return cg.readEntry("IncomingServerType");
+ break;
+ }
+ case InServerMBXType: {
+ return cg.readEntry("IncomingServerMBXType");
+ break;
+ }
+ case InServerTLS: {
+ return cg.readEntry("IncomingServerTLS", QVariant(false)).toString();
+ break;
+ }
+ };
+ return QString();
+}
+void KEMailSettings::setSetting(KEMailSettings::Setting s, const QString &v)
+{
+ KConfigGroup cg(p->m_pConfig, QStringLiteral("PROFILE_") + p->m_sCurrentProfile);
+ switch (s) {
+ case ClientProgram: {
+ cg.writePathEntry("EmailClient", v);
+ break;
+ }
+ case ClientTerminal: {
+ cg.writeEntry("TerminalClient", (v == QLatin1String("true")));
+ break;
+ }
+ case RealName: {
+ cg.writeEntry("FullName", v);
+ break;
+ }
+ case EmailAddress: {
+ cg.writeEntry("EmailAddress", v);
+ break;
+ }
+ case ReplyToAddress: {
+ cg.writeEntry("ReplyAddr", v);
+ break;
+ }
+ case Organization: {
+ cg.writeEntry("Organization", v);
+ break;
+ }
+ case OutServer: {
+ cg.writeEntry("OutgoingServer", v);
+ break;
+ }
+ case OutServerLogin: {
+ cg.writeEntry("OutgoingUserName", v);
+ break;
+ }
+ case OutServerPass: {
+ cg.writeEntry("OutgoingPassword", v);
+ break;
+ }
+ case OutServerType: {
+ cg.writeEntry("OutgoingServerType", v);
+ break;
+ }
+ case OutServerCommand: {
+ cg.writeEntry("OutgoingCommand", v);
+ break;
+ }
+ case OutServerTLS: {
+ cg.writeEntry("OutgoingServerTLS", (v == QLatin1String("true")));
+ break;
+ }
+ case InServer: {
+ cg.writeEntry("IncomingServer", v);
+ break;
+ }
+ case InServerLogin: {
+ cg.writeEntry("IncomingUserName", v);
+ break;
+ }
+ case InServerPass: {
+ cg.writeEntry("IncomingPassword", v);
+ break;
+ }
+ case InServerType: {
+ cg.writeEntry("IncomingServerType", v);
+ break;
+ }
+ case InServerMBXType: {
+ cg.writeEntry("IncomingServerMBXType", v);
+ break;
+ }
+ case InServerTLS: {
+ cg.writeEntry("IncomingServerTLS", (v == QLatin1String("true")));
+ break;
+ }
+ };
+ cg.sync();
+}
+
+void KEMailSettings::setDefault(const QString &s)
+{
+ p->m_pConfig->group("Defaults").writeEntry("Profile", s);
+ p->m_pConfig->sync();
+ p->m_sDefaultProfile=s;
+
+}
+
+void KEMailSettings::setProfile (const QString &s)
+{
+ QString groupname = QStringLiteral("PROFILE_");
+ groupname.append(s);
+ p->m_sCurrentProfile=s;
+ if (!p->m_pConfig->hasGroup(groupname)) { // Create a group if it doesn't exist
+ KConfigGroup cg(p->m_pConfig, groupname);
+ cg.writeEntry("ServerType", QString());
+ p->profiles+=s;
+ }
+}
+
+#ifndef KDE_NO_DEPRECATED
+QString KEMailSettings::currentProfileName() const
+{
+ return p->m_sCurrentProfile;
+}
+#endif
+
+QStringList KEMailSettings::profiles() const
+{
+ return p->profiles;
+}
+
+KEMailSettings::KEMailSettings()
+ :p(new KEMailSettingsPrivate())
+{
+ p->m_sCurrentProfile.clear();
+
+ p->m_pConfig = new KConfig(QStringLiteral("emaildefaults"));
+
+ const QStringList groups = p->m_pConfig->groupList();
+ for (QStringList::ConstIterator it = groups.begin(); it != groups.end(); ++it) {
+ if ( (*it).startsWith( QLatin1String( "PROFILE_" ) ) )
+ p->profiles+= (*it).mid(8, (*it).length());
+ }
+
+ KConfigGroup cg( p->m_pConfig, "Defaults");
+ p->m_sDefaultProfile = cg.readEntry("Profile", tr("Default"));
+ if (!p->m_sDefaultProfile.isNull()) {
+ if (!p->m_pConfig->hasGroup(QStringLiteral("PROFILE_") + p->m_sDefaultProfile))
+ setDefault(tr("Default"));
+ else
+ setDefault(p->m_sDefaultProfile);
+ } else {
+ if (p->profiles.count()) {
+ setDefault(p->profiles[0]);
+ } else
+ setDefault(tr("Default"));
+ }
+ setProfile(defaultProfileName());
+}
+
+KEMailSettings::~KEMailSettings()
+{
+ delete p;
+}
diff --git a/src/core/kemailsettings.h b/src/core/kemailsettings.h
new file mode 100644
index 00000000..32610d61
--- /dev/null
+++ b/src/core/kemailsettings.h
@@ -0,0 +1,176 @@
+/*-
+ * Copyright (c) 2000 Alex Zepeda <zipzippy@sonic.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _KEMAILSETTINGS_H
+#define _KEMAILSETTINGS_H
+
+#include <QtCore/QCoreApplication> // Q_DECLARE_TR_FUNCTIONS
+#include <QtCore/QStringList>
+
+#include <kconfigcore_export.h>
+
+class KEMailSettingsPrivate;
+
+
+/**
+ * This is just a small class to facilitate accessing e-mail settings in
+ * a sane way, and allowing any program to manage multiple e-mail
+ * profiles effortlessly
+ *
+ * The default profile is automatically selected in the constructor.
+ *
+ * @author Alex Zepeda zipzippy@sonic.net
+ **/
+class KCONFIGCORE_EXPORT KEMailSettings {
+ Q_DECLARE_TR_FUNCTIONS(KEMailSettings)
+public:
+ /**
+ * The list of settings that I thought of when I wrote this
+ * class. Any extra settings thought of later can be accessed
+ * easily with getExtendedSetting and setExtendedSetting.
+ * @see getSetting()
+ * @see setSetting()
+ * @see getExtendedSetting()
+ * @see setExtendedSetting()
+ **/
+ enum Setting {
+ ClientProgram,
+ ClientTerminal,
+ RealName,
+ EmailAddress,
+ ReplyToAddress,
+ Organization,
+ OutServer,
+ OutServerLogin,
+ OutServerPass,
+#ifndef KDE_NO_DEPRECATED
+ /**
+ * @deprecated since Frameworks 5.0
+ */
+ OutServerType,
+ /**
+ * @deprecated since Frameworks 5.0
+ */
+ OutServerCommand,
+ /**
+ * @deprecated since Frameworks 5.0
+ */
+ OutServerTLS,
+#endif
+ InServer,
+ InServerLogin,
+ InServerPass,
+#ifndef KDE_NO_DEPRECATED
+ /**
+ * @deprecated since Frameworks 5.0
+ */
+ InServerType,
+ /**
+ * @deprecated since Frameworks 5.0
+ */
+ InServerMBXType,
+ /**
+ * @deprecated since Frameworks 5.0
+ */
+ InServerTLS
+#endif
+ };
+
+ /**
+ * The various extensions allowed.
+ **/
+ enum Extension {
+ POP3,
+ SMTP,
+ OTHER
+ };
+
+ /**
+ * Default constructor, just sets things up and sets the default profile
+ * as the current profile
+ **/
+ KEMailSettings();
+
+ /**
+ * Default destructor, nothing to see here.
+ **/
+ ~KEMailSettings();
+
+ /**
+ * List of profiles available.
+ * @return the list of profiles
+ **/
+ QStringList profiles() const;
+
+#ifndef KDE_NO_DEPRECATED
+ /**
+ * @deprecated since Frameworks 5.0
+ * Returns the name of the current profile.
+ * @returns what profile we're currently using
+ **/
+ KCONFIGCORE_DEPRECATED QString currentProfileName() const;
+#endif
+
+ /**
+ * Change the current profile.
+ * @param s the name of the new profile
+ **/
+ void setProfile (const QString &s);
+
+ /**
+ * Returns the name of the default profile.
+ * @returns the name of the one that's currently default QString() if none
+ **/
+ QString defaultProfileName() const;
+
+ /**
+ * Sets a new default.
+ * @param def the new default
+ **/
+ void setDefault(const QString &def);
+
+ /**
+ * Get one of the predefined "basic" settings.
+ * @param s the setting to get
+ * @return the value of the setting, or QString() if not
+ * set
+ **/
+ QString getSetting(KEMailSettings::Setting s) const;
+
+ /**
+ * Set one of the predefined "basic" settings.
+ * @param s the setting to set
+ * @param v the new value of the setting, or QString() to
+ * unset
+ **/
+ void setSetting(KEMailSettings::Setting s, const QString &v);
+
+private:
+ KEMailSettingsPrivate* const p;
+};
+
+#endif
diff --git a/src/core/ksharedconfig.cpp b/src/core/ksharedconfig.cpp
new file mode 100644
index 00000000..0e5d1959
--- /dev/null
+++ b/src/core/ksharedconfig.cpp
@@ -0,0 +1,122 @@
+/*
+ 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.
+*/
+
+#include "ksharedconfig.h"
+#include "kconfigbackend.h"
+#include "kconfiggroup.h"
+#include "kconfig_p.h"
+#include <QCoreApplication>
+
+void _k_globalMainConfigSync();
+
+class GlobalSharedConfigList : public QList<KSharedConfig*>
+{
+public:
+ GlobalSharedConfigList()
+ {
+ // We want to force the sync() before the QCoreApplication
+ // instance is gone. Otherwise we trigger a QLockFile::lock()
+ // after QCoreApplication is gone, calling qAppName() for a non
+ // existent app...
+ qAddPostRoutine(&_k_globalMainConfigSync);
+ }
+
+ // in addition to the list, we need to hold the main config,
+ // so that it's not created and destroyed all the time.
+ KSharedConfigPtr mainConfig;
+};
+
+
+Q_GLOBAL_STATIC(GlobalSharedConfigList, globalSharedConfigList)
+
+void _k_globalMainConfigSync()
+{
+ if (globalSharedConfigList->mainConfig)
+ globalSharedConfigList->mainConfig->sync();
+}
+
+
+KSharedConfigPtr KSharedConfig::openConfig(const QString& _fileName,
+ OpenFlags flags,
+ QStandardPaths::StandardLocation resType)
+{
+ QString fileName(_fileName);
+ GlobalSharedConfigList *list = globalSharedConfigList();
+ if (fileName.isEmpty() && !flags.testFlag(KConfig::SimpleConfig)) {
+ // Determine the config file name that KConfig will make up (see KConfigPrivate::changeFileName)
+ fileName = KConfig::mainConfigName();
+ }
+
+ if (list) {
+ for(QList<KSharedConfig*>::ConstIterator it = list->constBegin(); it != list->constEnd(); ++it) {
+ if ( (*it)->name() == fileName &&
+ (*it)->d_ptr->openFlags == flags &&
+ (*it)->locationType() == resType
+// (*it)->backEnd()->type() == backEnd
+ ) {
+ return KSharedConfigPtr(*it);
+ }
+ }
+ }
+ KSharedConfigPtr ptr(new KSharedConfig(fileName, flags, resType));
+ if (_fileName.isEmpty() && flags == FullConfig && resType == QStandardPaths::GenericConfigLocation) {
+ list->mainConfig = ptr;
+
+ static bool userWarned = false;
+ if (!userWarned) {
+ userWarned = true;
+ QByteArray readOnly = qgetenv("KDE_HOME_READONLY");
+ if (readOnly.isEmpty() && QCoreApplication::applicationName() != QLatin1String("kdialog")) {
+ if (ptr->group("General").readEntry(QLatin1String("warn_unwritable_config"), true))
+ ptr->isConfigWritable(true);
+ }
+ }
+ }
+
+ return ptr;
+}
+
+
+KSharedConfig::KSharedConfig(const QString &fileName,
+ OpenFlags flags,
+ QStandardPaths::StandardLocation resType)
+ : KConfig(fileName, flags, resType)
+{
+ globalSharedConfigList()->append(this);
+}
+
+KSharedConfig::~KSharedConfig()
+{
+ if (!globalSharedConfigList.isDestroyed())
+ globalSharedConfigList()->removeAll(this);
+}
+
+KConfigGroup KSharedConfig::groupImpl(const QByteArray &groupName)
+{
+ KSharedConfigPtr ptr(this);
+ return KConfigGroup( ptr, groupName.constData());
+}
+
+const KConfigGroup KSharedConfig::groupImpl(const QByteArray &groupName) const
+{
+ const KSharedConfigPtr ptr(const_cast<KSharedConfig*>(this));
+ return KConfigGroup( ptr, groupName.constData());
+}
diff --git a/src/core/ksharedconfig.h b/src/core/ksharedconfig.h
new file mode 100644
index 00000000..42f7440e
--- /dev/null
+++ b/src/core/ksharedconfig.h
@@ -0,0 +1,88 @@
+/*
+ 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.
+*/
+
+#ifndef KSHAREDCONFIG_H
+#define KSHAREDCONFIG_H
+
+#include <kconfig.h>
+#include <QExplicitlySharedDataPointer>
+
+/**
+ * \class KSharedConfig ksharedconfig.h <KSharedConfig>
+ *
+ * KConfig variant using shared memory
+ *
+ * KSharedConfig provides a reference counted, shared memory variant
+ * of KConfig. This allows you to use manipulate the same configuration
+ * files from different places in your code without worrying about
+ * accidentally overwriting changes.
+ *
+ * Note that, as with most of kdelibs, this is @b NOT threadsafe.
+ */
+class KCONFIGCORE_EXPORT KSharedConfig : public KConfig, public QSharedData //krazy:exclude=dpointer (only for refcounting)
+{
+public:
+ typedef QExplicitlySharedDataPointer<KSharedConfig> Ptr;
+
+public:
+ /**
+ * Creates a KSharedConfig object to manipulate a configuration file
+ *
+ * If an absolute path is specified for @p fileName, that file will be used
+ * as the store for the configuration settings. If a non-absolute path
+ * is provided, the file will be looked for in the standard directory
+ * specified by resourceType. If no path is provided, a default
+ * configuration file will be used based on the name of the main
+ * application component.
+ *
+ * @p mode determines whether the user or global settings will be allowed
+ * to influence the values returned by this object. See KConfig::OpenFlags for
+ * more details.
+ *
+ * @param fileName the configuration file to open. If empty, it will be determined
+ * automatically (from --config on the command line, otherwise
+ * from the application name + "rc")
+ * @param mode how global settings should affect the configuration
+ * options exposed by this KConfig object
+ * @param resourceType The standard directory to look for the configuration
+ * file in (see KStandardDirs)
+ *
+ * @sa KConfig
+ */
+ static KSharedConfig::Ptr openConfig(const QString& fileName = QString(),
+ OpenFlags mode = FullConfig,
+ QStandardPaths::StandardLocation type = QStandardPaths::GenericConfigLocation);
+
+ virtual ~KSharedConfig();
+
+private:
+ Q_DISABLE_COPY(KSharedConfig)
+ virtual KConfigGroup groupImpl(const QByteArray& aGroup);
+ virtual const KConfigGroup groupImpl(const QByteArray& aGroup) const;
+
+ KSharedConfig(const QString& file, OpenFlags mode,
+ QStandardPaths::StandardLocation resourceType);
+
+};
+
+typedef KSharedConfig::Ptr KSharedConfigPtr;
+
+#endif // multiple inclusion guard