File indexing completed on 2024-05-12 15:34:10

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
0004     SPDX-FileCopyrightText: 1999 Preston Brown <pbrown@kde.org>
0005     SPDX-FileCopyrightText: 1997 Matthias Kalle Dalheimer <kalle@kde.org>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #include "kconfiggroup.h"
0011 #include "kconfiggroup_p.h"
0012 
0013 #include "kconfig.h"
0014 #include "kconfig_core_log_settings.h"
0015 #include "kconfig_p.h"
0016 #include "kconfigdata_p.h"
0017 #include "ksharedconfig.h"
0018 
0019 #include <QDate>
0020 #include <QDir>
0021 #include <QFile>
0022 #include <QPoint>
0023 #include <QRect>
0024 #include <QSharedData>
0025 #include <QString>
0026 #include <QTextStream>
0027 #include <QUrl>
0028 #include <QUuid>
0029 
0030 #include <algorithm>
0031 #include <array>
0032 #include <math.h>
0033 #include <stdlib.h>
0034 
0035 class KConfigGroupPrivate : public QSharedData
0036 {
0037 public:
0038     KConfigGroupPrivate(KConfig *owner, bool isImmutable, bool isConst, const QByteArray &name)
0039         : mOwner(owner)
0040         , mName(name)
0041         , bImmutable(isImmutable)
0042         , bConst(isConst)
0043     {
0044         if (Q_UNLIKELY(!mOwner->name().isEmpty() && mOwner->accessMode() == KConfigBase::NoAccess)) {
0045             qCWarning(KCONFIG_CORE_LOG) << "Created a KConfigGroup on an inaccessible config location" << mOwner->name() << name;
0046         }
0047     }
0048 
0049     KConfigGroupPrivate(const KSharedConfigPtr &owner, const QByteArray &name)
0050         : sOwner(owner)
0051         , mOwner(sOwner.data())
0052         , mName(name)
0053         , bImmutable(name.isEmpty() ? owner->isImmutable() : owner->isGroupImmutable(name))
0054         , bConst(false)
0055     {
0056         if (Q_UNLIKELY(!mOwner->name().isEmpty() && mOwner->accessMode() == KConfigBase::NoAccess)) {
0057             qCWarning(KCONFIG_CORE_LOG) << "Created a KConfigGroup on an inaccessible config location" << mOwner->name() << name;
0058         }
0059     }
0060 
0061     KConfigGroupPrivate(KConfigGroup *parent, bool isImmutable, bool isConst, const QByteArray &name)
0062         : sOwner(parent->d->sOwner)
0063         , mOwner(parent->d->mOwner)
0064         , mName(name)
0065         , bImmutable(isImmutable)
0066         , bConst(isConst)
0067     {
0068         if (!parent->d->mName.isEmpty()) {
0069             mParent = parent->d;
0070         }
0071     }
0072 
0073     KConfigGroupPrivate(const KConfigGroupPrivate *other, bool isImmutable, const QByteArray &name)
0074         : sOwner(other->sOwner)
0075         , mOwner(other->mOwner)
0076         , mName(name)
0077         , bImmutable(isImmutable)
0078         , bConst(other->bConst)
0079     {
0080         if (!other->mName.isEmpty()) {
0081             mParent = const_cast<KConfigGroupPrivate *>(other);
0082         }
0083     }
0084 
0085     KSharedConfig::Ptr sOwner;
0086     KConfig *mOwner;
0087     QExplicitlySharedDataPointer<KConfigGroupPrivate> mParent;
0088     QByteArray mName;
0089 
0090     /* bitfield */
0091     const bool bImmutable : 1; // is this group immutable?
0092     const bool bConst : 1; // is this group read-only?
0093 
0094     QByteArray fullName() const
0095     {
0096         if (!mParent) {
0097             return name();
0098         }
0099         return mParent->fullName(mName);
0100     }
0101 
0102     QByteArray name() const
0103     {
0104         if (mName.isEmpty()) {
0105             return QByteArrayLiteral("<default>");
0106         }
0107         return mName;
0108     }
0109 
0110     QByteArray fullName(const QByteArray &aGroup) const
0111     {
0112         if (mName.isEmpty()) {
0113             return aGroup;
0114         }
0115         return fullName() + '\x1d' + aGroup;
0116     }
0117 
0118     static QExplicitlySharedDataPointer<KConfigGroupPrivate> create(KConfigBase *master, const QByteArray &name, bool isImmutable, bool isConst)
0119     {
0120         QExplicitlySharedDataPointer<KConfigGroupPrivate> data;
0121         if (dynamic_cast<KConfigGroup *>(master)) {
0122             data = new KConfigGroupPrivate(static_cast<KConfigGroup *>(master), isImmutable, isConst, name);
0123         } else {
0124             data = new KConfigGroupPrivate(dynamic_cast<KConfig *>(master), isImmutable, isConst, name);
0125         }
0126         return data;
0127     }
0128 
0129     static QByteArray serializeList(const QList<QByteArray> &list);
0130     static QStringList deserializeList(const QString &data);
0131 };
0132 
0133 QByteArray KConfigGroupPrivate::serializeList(const QList<QByteArray> &list)
0134 {
0135     QByteArray value;
0136 
0137     if (!list.isEmpty()) {
0138         auto it = list.cbegin();
0139         const auto end = list.cend();
0140 
0141         value = QByteArray(*it).replace('\\', QByteArrayLiteral("\\\\")).replace(',', QByteArrayLiteral("\\,"));
0142 
0143         while (++it != end) {
0144             // In the loop, so it is not done when there is only one element.
0145             // Doing it repeatedly is a pretty cheap operation.
0146             value.reserve(4096);
0147 
0148             value += ',';
0149             value += QByteArray(*it).replace('\\', QByteArrayLiteral("\\\\")).replace(',', QByteArrayLiteral("\\,"));
0150         }
0151 
0152         // To be able to distinguish an empty list from a list with one empty element.
0153         if (value.isEmpty()) {
0154             value = QByteArrayLiteral("\\0");
0155         }
0156     }
0157 
0158     return value;
0159 }
0160 
0161 QStringList KConfigGroupPrivate::deserializeList(const QString &data)
0162 {
0163     if (data.isEmpty()) {
0164         return QStringList();
0165     }
0166     if (data == QLatin1String("\\0")) {
0167         return QStringList(QString());
0168     }
0169     QStringList value;
0170     QString val;
0171     val.reserve(data.size());
0172     bool quoted = false;
0173     for (int p = 0; p < data.length(); p++) {
0174         if (quoted) {
0175             val += data[p];
0176             quoted = false;
0177         } else if (data[p].unicode() == '\\') {
0178             quoted = true;
0179         } else if (data[p].unicode() == ',') {
0180             val.squeeze(); // release any unused memory
0181             value.append(val);
0182             val.clear();
0183             val.reserve(data.size() - p);
0184         } else {
0185             val += data[p];
0186         }
0187     }
0188     value.append(val);
0189     return value;
0190 }
0191 
0192 static QVector<int> asIntList(const QByteArray &string)
0193 {
0194     const auto &splitString = string.split(',');
0195 
0196     QVector<int> list;
0197     list.reserve(splitString.count());
0198     for (const QByteArray &s : splitString) {
0199         list << s.toInt();
0200     }
0201     return list;
0202 }
0203 
0204 static QVector<qreal> asRealList(const QByteArray &string)
0205 {
0206     const auto &splitString = string.split(',');
0207 
0208     QVector<qreal> list;
0209     list.reserve(splitString.count());
0210     for (const QByteArray &s : splitString) {
0211         list << s.toDouble();
0212     }
0213     return list;
0214 }
0215 
0216 static QString errString(const char *pKey, const QByteArray &value, const QVariant &aDefault)
0217 {
0218     return QStringLiteral("\"%1\" - conversion of \"%3\" to %2 failed")
0219         .arg(QString::fromLatin1(pKey), QString::fromLatin1(QVariant::typeToName(aDefault.type())), QString::fromLatin1(value));
0220 }
0221 
0222 static QString formatError(int expected, int got)
0223 {
0224     return QStringLiteral(" (wrong format: expected %1 items, got %2)").arg(expected).arg(got);
0225 }
0226 
0227 QVariant KConfigGroup::convertToQVariant(const char *pKey, const QByteArray &value, const QVariant &aDefault)
0228 {
0229     // if a type handler is added here you must add a QVConversions definition
0230     // to conversioncheck.h, or ConversionCheck::to_QVariant will not allow
0231     // readEntry<T> to convert to QVariant.
0232     switch (static_cast<QMetaType::Type>(aDefault.type())) {
0233     case QMetaType::UnknownType:
0234         return QVariant();
0235     case QMetaType::QString:
0236         // this should return the raw string not the dollar expanded string.
0237         // imho if processed string is wanted should call
0238         // readEntry(key, QString) not readEntry(key, QVariant)
0239         return QString::fromUtf8(value);
0240     case QMetaType::QUuid:
0241         return QUuid::fromString(QString::fromUtf8(value));
0242     case QMetaType::QVariantList:
0243     case QMetaType::QStringList:
0244         return KConfigGroupPrivate::deserializeList(QString::fromUtf8(value));
0245     case QMetaType::QByteArray:
0246         return value;
0247     case QMetaType::Bool: {
0248         static const std::array<const char *, 4> negatives = {"false", "no", "off", "0"};
0249 
0250         return std::all_of(negatives.begin(), negatives.end(), [value](const char *negativeString) {
0251             return value.compare(negativeString, Qt::CaseInsensitive) != 0;
0252         });
0253     }
0254     case QMetaType::Double:
0255     case QMetaType::Float:
0256     case QMetaType::Int:
0257     case QMetaType::UInt:
0258     case QMetaType::LongLong:
0259     case QMetaType::ULongLong: {
0260         QVariant tmp = value;
0261         if (!tmp.convert(aDefault.type())) {
0262             tmp = aDefault;
0263         }
0264         return tmp;
0265     }
0266     case QMetaType::QPoint: {
0267         const auto list = asIntList(value);
0268 
0269         if (list.count() != 2) {
0270             qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault) << formatError(2, list.count());
0271             return aDefault;
0272         }
0273         return QPoint(list.at(0), list.at(1));
0274     }
0275     case QMetaType::QPointF: {
0276         const auto list = asRealList(value);
0277 
0278         if (list.count() != 2) {
0279             qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault) << formatError(2, list.count());
0280             return aDefault;
0281         }
0282         return QPointF(list.at(0), list.at(1));
0283     }
0284     case QMetaType::QRect: {
0285         const auto list = asIntList(value);
0286 
0287         if (list.count() != 4) {
0288             qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault) << formatError(4, list.count());
0289             return aDefault;
0290         }
0291         const QRect rect(list.at(0), list.at(1), list.at(2), list.at(3));
0292         if (!rect.isValid()) {
0293             qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault);
0294             return aDefault;
0295         }
0296         return rect;
0297     }
0298     case QMetaType::QRectF: {
0299         const auto list = asRealList(value);
0300 
0301         if (list.count() != 4) {
0302             qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault) << formatError(4, list.count());
0303             return aDefault;
0304         }
0305         const QRectF rect(list.at(0), list.at(1), list.at(2), list.at(3));
0306         if (!rect.isValid()) {
0307             qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault);
0308             return aDefault;
0309         }
0310         return rect;
0311     }
0312     case QMetaType::QSize: {
0313         const auto list = asIntList(value);
0314 
0315         if (list.count() != 2) {
0316             qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault) << formatError(2, list.count());
0317             return aDefault;
0318         }
0319         const QSize size(list.at(0), list.at(1));
0320         if (!size.isValid()) {
0321             qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault);
0322             return aDefault;
0323         }
0324         return size;
0325     }
0326     case QMetaType::QSizeF: {
0327         const auto list = asRealList(value);
0328 
0329         if (list.count() != 2) {
0330             qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault) << formatError(2, list.count());
0331             return aDefault;
0332         }
0333         const QSizeF size(list.at(0), list.at(1));
0334         if (!size.isValid()) {
0335             qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault);
0336             return aDefault;
0337         }
0338         return size;
0339     }
0340     case QMetaType::QDateTime: {
0341         const auto list = asRealList(value);
0342         if (list.count() < 6) {
0343             qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault) << formatError(6, list.count());
0344             return aDefault;
0345         }
0346         const QDate date(list.at(0), list.at(1), list.at(2));
0347         const qreal totalSeconds = list.at(5);
0348         qreal seconds;
0349         const qreal fractional = modf(totalSeconds, &seconds);
0350         const qreal milliseconds = round(fractional * 1000.0);
0351         const QTime time(list.at(3), list.at(4), seconds, milliseconds);
0352         const QDateTime dt(date, time);
0353         if (!dt.isValid()) {
0354             qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault);
0355             return aDefault;
0356         }
0357         return dt;
0358     }
0359     case QMetaType::QDate: {
0360         auto list = asIntList(value);
0361         if (list.count() == 6) {
0362             list = list.mid(0, 3); // don't break config files that stored QDate as QDateTime
0363         }
0364         if (list.count() != 3) {
0365             qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault) << formatError(3, list.count());
0366             return aDefault;
0367         }
0368         const QDate date(list.at(0), list.at(1), list.at(2));
0369         if (!date.isValid()) {
0370             qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault);
0371             return aDefault;
0372         }
0373         return date;
0374     }
0375     case QMetaType::QColor:
0376     case QMetaType::QFont:
0377         qCWarning(KCONFIG_CORE_LOG) << "KConfigGroup::readEntry was passed GUI type '" << aDefault.typeName()
0378                                     << "' but KConfigGui isn't linked! If it is linked to your program, "
0379                                        "this is a platform bug. Please inform the KDE developers";
0380         break;
0381     case QMetaType::QUrl:
0382         return QUrl(QString::fromUtf8(value));
0383 
0384     default:
0385         break;
0386     }
0387 
0388     qCWarning(KCONFIG_CORE_LOG) << "unhandled type " << aDefault.typeName();
0389     return QVariant();
0390 }
0391 
0392 #ifdef Q_OS_WIN
0393 #include <QDir>
0394 #endif
0395 
0396 static bool cleanHomeDirPath(QString &path, const QString &homeDir)
0397 {
0398 #ifdef Q_OS_WIN // safer
0399     if (!QDir::toNativeSeparators(path).startsWith(QDir::toNativeSeparators(homeDir))) {
0400         return false;
0401     }
0402 #else
0403     if (!path.startsWith(homeDir)) {
0404         return false;
0405     }
0406 #endif
0407 
0408     int len = homeDir.length();
0409     // replace by "$HOME" if possible
0410     if (len && (path.length() == len || path[len] == QLatin1Char('/'))) {
0411         path.replace(0, len, QStringLiteral("$HOME"));
0412         return true;
0413     }
0414 
0415     return false;
0416 }
0417 
0418 static QString translatePath(QString path) // krazy:exclude=passbyvalue
0419 {
0420     if (path.isEmpty()) {
0421         return path;
0422     }
0423 
0424     // only "our" $HOME should be interpreted
0425     path.replace(QLatin1Char('$'), QLatin1String("$$"));
0426 
0427     const bool startsWithFile = path.startsWith(QLatin1String("file:"), Qt::CaseInsensitive);
0428     path = startsWithFile ? QUrl(path).toLocalFile() : path;
0429 
0430     if (QDir::isRelativePath(path)) {
0431         return path;
0432     }
0433 
0434     // Use the same thing as what expandString() will do, to keep data intact
0435 #ifdef Q_OS_WIN
0436     const QString homeDir = QDir::homePath();
0437 #else
0438     const QString homeDir = QFile::decodeName(qgetenv("HOME"));
0439 #endif
0440     (void)cleanHomeDirPath(path, homeDir);
0441 
0442     if (startsWithFile) {
0443         path = QUrl::fromLocalFile(path).toString();
0444     }
0445 
0446     return path;
0447 }
0448 
0449 KConfigGroup::KConfigGroup()
0450     : d()
0451 {
0452 }
0453 
0454 bool KConfigGroup::isValid() const
0455 {
0456     return bool(d);
0457 }
0458 
0459 KConfigGroupGui _kde_internal_KConfigGroupGui;
0460 static inline bool readEntryGui(const QByteArray &data, const char *key, const QVariant &input, QVariant &output)
0461 {
0462     if (_kde_internal_KConfigGroupGui.readEntryGui) {
0463         return _kde_internal_KConfigGroupGui.readEntryGui(data, key, input, output);
0464     }
0465     return false;
0466 }
0467 
0468 static inline bool writeEntryGui(KConfigGroup *cg, const char *key, const QVariant &input, KConfigGroup::WriteConfigFlags flags)
0469 {
0470     if (_kde_internal_KConfigGroupGui.writeEntryGui) {
0471         return _kde_internal_KConfigGroupGui.writeEntryGui(cg, key, input, flags);
0472     }
0473     return false;
0474 }
0475 
0476 KConfigGroup::KConfigGroup(KConfigBase *master, const QString &_group)
0477     : d(KConfigGroupPrivate::create(master, _group.toUtf8(), master->isGroupImmutable(_group), false))
0478 {
0479 }
0480 
0481 KConfigGroup::KConfigGroup(KConfigBase *master, const char *_group)
0482     : d(KConfigGroupPrivate::create(master, _group, master->isGroupImmutable(_group), false))
0483 {
0484 }
0485 
0486 KConfigGroup::KConfigGroup(const KConfigBase *master, const QString &_group)
0487     : d(KConfigGroupPrivate::create(const_cast<KConfigBase *>(master), _group.toUtf8(), master->isGroupImmutable(_group), true))
0488 {
0489 }
0490 
0491 KConfigGroup::KConfigGroup(const KConfigBase *master, const char *_group)
0492     : d(KConfigGroupPrivate::create(const_cast<KConfigBase *>(master), _group, master->isGroupImmutable(_group), true))
0493 {
0494 }
0495 
0496 KConfigGroup::KConfigGroup(const KSharedConfigPtr &master, const QString &_group)
0497     : d(new KConfigGroupPrivate(master, _group.toUtf8()))
0498 {
0499 }
0500 
0501 KConfigGroup::KConfigGroup(const KSharedConfigPtr &master, const char *_group)
0502     : d(new KConfigGroupPrivate(master, _group))
0503 {
0504 }
0505 
0506 KConfigGroup &KConfigGroup::operator=(const KConfigGroup &rhs)
0507 {
0508     d = rhs.d;
0509     return *this;
0510 }
0511 
0512 KConfigGroup::KConfigGroup(const KConfigGroup &rhs)
0513     : d(rhs.d)
0514 {
0515 }
0516 
0517 KConfigGroup::~KConfigGroup()
0518 {
0519     d.reset();
0520 }
0521 
0522 KConfigGroup KConfigGroup::groupImpl(const QByteArray &aGroup)
0523 {
0524     Q_ASSERT_X(isValid(), "KConfigGroup::groupImpl", "accessing an invalid group");
0525     Q_ASSERT_X(!aGroup.isEmpty(), "KConfigGroup::groupImpl", "can not have an unnamed child group");
0526 
0527     KConfigGroup newGroup;
0528 
0529     newGroup.d = new KConfigGroupPrivate(this, isGroupImmutableImpl(aGroup), d->bConst, aGroup);
0530 
0531     return newGroup;
0532 }
0533 
0534 const KConfigGroup KConfigGroup::groupImpl(const QByteArray &aGroup) const
0535 {
0536     Q_ASSERT_X(isValid(), "KConfigGroup::groupImpl", "accessing an invalid group");
0537     Q_ASSERT_X(!aGroup.isEmpty(), "KConfigGroup::groupImpl", "can not have an unnamed child group");
0538 
0539     KConfigGroup newGroup;
0540 
0541     newGroup.d = new KConfigGroupPrivate(const_cast<KConfigGroup *>(this), isGroupImmutableImpl(aGroup), true, aGroup);
0542 
0543     return newGroup;
0544 }
0545 
0546 KConfigGroup KConfigGroup::parent() const
0547 {
0548     Q_ASSERT_X(isValid(), "KConfigGroup::parent", "accessing an invalid group");
0549 
0550     KConfigGroup parentGroup;
0551 
0552     if (d->mParent) {
0553         parentGroup.d = d->mParent;
0554     } else {
0555         parentGroup.d = new KConfigGroupPrivate(d->mOwner, d->mOwner->isImmutable(), d->bConst, "");
0556         // make sure we keep the refcount up on the KConfig object
0557         parentGroup.d->sOwner = d->sOwner;
0558     }
0559 
0560     return parentGroup;
0561 }
0562 
0563 void KConfigGroup::deleteGroup(WriteConfigFlags flags)
0564 {
0565     Q_ASSERT_X(isValid(), "KConfigGroup::deleteGroup", "accessing an invalid group");
0566     Q_ASSERT_X(!d->bConst, "KConfigGroup::deleteGroup", "deleting a read-only group");
0567 
0568     config()->deleteGroup(d->fullName(), flags);
0569 }
0570 
0571 #if KCONFIGCORE_BUILD_DEPRECATED_SINCE(5, 0)
0572 void KConfigGroup::changeGroup(const QString &group)
0573 {
0574     Q_ASSERT_X(isValid(), "KConfigGroup::changeGroup", "accessing an invalid group");
0575     d.detach();
0576     d->mName = group.toUtf8();
0577 }
0578 #endif
0579 
0580 #if KCONFIGCORE_BUILD_DEPRECATED_SINCE(5, 0)
0581 void KConfigGroup::changeGroup(const char *group)
0582 {
0583     Q_ASSERT_X(isValid(), "KConfigGroup::changeGroup", "accessing an invalid group");
0584     d.detach();
0585     d->mName = group;
0586 }
0587 #endif
0588 
0589 QString KConfigGroup::name() const
0590 {
0591     Q_ASSERT_X(isValid(), "KConfigGroup::name", "accessing an invalid group");
0592 
0593     return QString::fromUtf8(d->name());
0594 }
0595 
0596 bool KConfigGroup::exists() const
0597 {
0598     Q_ASSERT_X(isValid(), "KConfigGroup::exists", "accessing an invalid group");
0599 
0600     return config()->hasGroup(d->fullName());
0601 }
0602 
0603 bool KConfigGroup::sync()
0604 {
0605     Q_ASSERT_X(isValid(), "KConfigGroup::sync", "accessing an invalid group");
0606 
0607     if (!d->bConst) {
0608         return config()->sync();
0609     }
0610 
0611     return false;
0612 }
0613 
0614 QMap<QString, QString> KConfigGroup::entryMap() const
0615 {
0616     Q_ASSERT_X(isValid(), "KConfigGroup::entryMap", "accessing an invalid group");
0617 
0618     return config()->entryMap(QString::fromUtf8(d->fullName()));
0619 }
0620 
0621 KConfig *KConfigGroup::config()
0622 {
0623     Q_ASSERT_X(isValid(), "KConfigGroup::config", "accessing an invalid group");
0624 
0625     return d->mOwner;
0626 }
0627 
0628 const KConfig *KConfigGroup::config() const
0629 {
0630     Q_ASSERT_X(isValid(), "KConfigGroup::config", "accessing an invalid group");
0631 
0632     return d->mOwner;
0633 }
0634 
0635 bool KConfigGroup::isEntryImmutable(const char *key) const
0636 {
0637     Q_ASSERT_X(isValid(), "KConfigGroup::isEntryImmutable", "accessing an invalid group");
0638 
0639     return (isImmutable() || !config()->d_func()->canWriteEntry(d->fullName(), key, config()->readDefaults()));
0640 }
0641 
0642 bool KConfigGroup::isEntryImmutable(const QString &key) const
0643 {
0644     return isEntryImmutable(key.toUtf8().constData());
0645 }
0646 
0647 QString KConfigGroup::readEntryUntranslated(const QString &pKey, const QString &aDefault) const
0648 {
0649     return readEntryUntranslated(pKey.toUtf8().constData(), aDefault);
0650 }
0651 
0652 QString KConfigGroup::readEntryUntranslated(const char *key, const QString &aDefault) const
0653 {
0654     Q_ASSERT_X(isValid(), "KConfigGroup::readEntryUntranslated", "accessing an invalid group");
0655 
0656     QString result = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchFlags(), nullptr);
0657     if (result.isNull()) {
0658         return aDefault;
0659     }
0660     return result;
0661 }
0662 
0663 QString KConfigGroup::readEntry(const char *key, const char *aDefault) const
0664 {
0665     return readEntry(key, QString::fromUtf8(aDefault));
0666 }
0667 
0668 QString KConfigGroup::readEntry(const QString &key, const char *aDefault) const
0669 {
0670     return readEntry(key.toUtf8().constData(), aDefault);
0671 }
0672 
0673 QString KConfigGroup::readEntry(const char *key, const QString &aDefault) const
0674 {
0675     Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
0676 
0677     bool expand = false;
0678 
0679     // read value from the entry map
0680     QString aValue = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchLocalized, &expand);
0681     if (aValue.isNull()) {
0682         aValue = aDefault;
0683     }
0684 
0685     if (expand) {
0686         return KConfigPrivate::expandString(aValue);
0687     }
0688 
0689     return aValue;
0690 }
0691 
0692 QString KConfigGroup::readEntry(const QString &key, const QString &aDefault) const
0693 {
0694     return readEntry(key.toUtf8().constData(), aDefault);
0695 }
0696 
0697 QStringList KConfigGroup::readEntry(const char *key, const QStringList &aDefault) const
0698 {
0699     Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
0700 
0701     const QString data = readEntry(key, QString());
0702     if (data.isNull()) {
0703         return aDefault;
0704     }
0705 
0706     return KConfigGroupPrivate::deserializeList(data);
0707 }
0708 
0709 QStringList KConfigGroup::readEntry(const QString &key, const QStringList &aDefault) const
0710 {
0711     return readEntry(key.toUtf8().constData(), aDefault);
0712 }
0713 
0714 QVariant KConfigGroup::readEntry(const char *key, const QVariant &aDefault) const
0715 {
0716     Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
0717 
0718     const QByteArray data = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchLocalized);
0719     if (data.isNull()) {
0720         return aDefault;
0721     }
0722 
0723     QVariant value;
0724     if (!readEntryGui(data, key, aDefault, value)) {
0725         return convertToQVariant(key, data, aDefault);
0726     }
0727 
0728     return value;
0729 }
0730 
0731 QVariant KConfigGroup::readEntry(const QString &key, const QVariant &aDefault) const
0732 {
0733     return readEntry(key.toUtf8().constData(), aDefault);
0734 }
0735 
0736 QVariantList KConfigGroup::readEntry(const char *key, const QVariantList &aDefault) const
0737 {
0738     Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
0739 
0740     const QString data = readEntry(key, QString());
0741     if (data.isNull()) {
0742         return aDefault;
0743     }
0744 
0745     const auto &list = KConfigGroupPrivate::deserializeList(data);
0746 
0747     QVariantList value;
0748     value.reserve(list.count());
0749     for (const QString &v : list) {
0750         value << v;
0751     }
0752 
0753     return value;
0754 }
0755 
0756 QVariantList KConfigGroup::readEntry(const QString &key, const QVariantList &aDefault) const
0757 {
0758     return readEntry(key.toUtf8().constData(), aDefault);
0759 }
0760 
0761 QStringList KConfigGroup::readXdgListEntry(const QString &key, const QStringList &aDefault) const
0762 {
0763     return readXdgListEntry(key.toUtf8().constData(), aDefault);
0764 }
0765 
0766 QStringList KConfigGroup::readXdgListEntry(const char *key, const QStringList &aDefault) const
0767 {
0768     Q_ASSERT_X(isValid(), "KConfigGroup::readXdgListEntry", "accessing an invalid group");
0769 
0770     const QString data = readEntry(key, QString());
0771     if (data.isNull()) {
0772         return aDefault;
0773     }
0774 
0775     QStringList value;
0776     QString val;
0777     val.reserve(data.size());
0778     // XXX List serialization being a separate layer from low-level parsing is
0779     // probably a bug. No affected entries are defined, though.
0780     bool quoted = false;
0781     for (int p = 0; p < data.length(); p++) {
0782         if (quoted) {
0783             val += data[p];
0784             quoted = false;
0785         } else if (data[p] == QLatin1Char('\\')) {
0786             quoted = true;
0787         } else if (data[p] == QLatin1Char(';')) {
0788             value.append(val);
0789             val.clear();
0790             val.reserve(data.size() - p);
0791         } else {
0792             val += data[p];
0793         }
0794     }
0795     if (!val.isEmpty()) {
0796         value.append(val);
0797     }
0798     return value;
0799 }
0800 
0801 QString KConfigGroup::readPathEntry(const QString &pKey, const QString &aDefault) const
0802 {
0803     return readPathEntry(pKey.toUtf8().constData(), aDefault);
0804 }
0805 
0806 QString KConfigGroup::readPathEntry(const char *key, const QString &aDefault) const
0807 {
0808     Q_ASSERT_X(isValid(), "KConfigGroup::readPathEntry", "accessing an invalid group");
0809 
0810     bool expand = false;
0811 
0812     QString aValue = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchLocalized, &expand);
0813     if (aValue.isNull()) {
0814         aValue = aDefault;
0815     }
0816 
0817     return KConfigPrivate::expandString(aValue);
0818 }
0819 
0820 QStringList KConfigGroup::readPathEntry(const QString &pKey, const QStringList &aDefault) const
0821 {
0822     return readPathEntry(pKey.toUtf8().constData(), aDefault);
0823 }
0824 
0825 QStringList KConfigGroup::readPathEntry(const char *key, const QStringList &aDefault) const
0826 {
0827     Q_ASSERT_X(isValid(), "KConfigGroup::readPathEntry", "accessing an invalid group");
0828 
0829     const QString data = readPathEntry(key, QString());
0830     if (data.isNull()) {
0831         return aDefault;
0832     }
0833 
0834     return KConfigGroupPrivate::deserializeList(data);
0835 }
0836 
0837 void KConfigGroup::writeEntry(const char *key, const QString &value, WriteConfigFlags flags)
0838 {
0839     Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
0840     Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
0841 
0842     writeEntry(key, value.toUtf8(), flags);
0843 }
0844 
0845 void KConfigGroup::writeEntry(const QString &key, const QString &value, WriteConfigFlags flags)
0846 {
0847     writeEntry(key.toUtf8().constData(), value, flags);
0848 }
0849 
0850 void KConfigGroup::writeEntry(const QString &key, const char *value, WriteConfigFlags pFlags)
0851 {
0852     Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
0853     Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
0854 
0855     writeEntry(key.toUtf8().constData(), QVariant(QString::fromLatin1(value)), pFlags);
0856 }
0857 
0858 void KConfigGroup::writeEntry(const char *key, const char *value, WriteConfigFlags pFlags)
0859 {
0860     writeEntry(key, QVariant(QString::fromLatin1(value)), pFlags);
0861 }
0862 
0863 void KConfigGroup::writeEntry(const char *key, const QByteArray &value, WriteConfigFlags flags)
0864 {
0865     Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
0866     Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
0867 
0868     config()->d_func()->putData(d->fullName(), key, value.isNull() ? QByteArray("") : value, flags);
0869 }
0870 
0871 void KConfigGroup::writeEntry(const QString &key, const QByteArray &value, WriteConfigFlags pFlags)
0872 {
0873     writeEntry(key.toUtf8().constData(), value, pFlags);
0874 }
0875 
0876 void KConfigGroup::writeEntry(const char *key, const QStringList &list, WriteConfigFlags flags)
0877 {
0878     Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
0879     Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
0880 
0881     QList<QByteArray> balist;
0882     balist.reserve(list.count());
0883 
0884     for (const QString &entry : list) {
0885         balist.append(entry.toUtf8());
0886     }
0887 
0888     writeEntry(key, KConfigGroupPrivate::serializeList(balist), flags);
0889 }
0890 
0891 void KConfigGroup::writeEntry(const QString &key, const QStringList &list, WriteConfigFlags flags)
0892 {
0893     writeEntry(key.toUtf8().constData(), list, flags);
0894 }
0895 
0896 void KConfigGroup::writeEntry(const char *key, const QVariantList &list, WriteConfigFlags flags)
0897 {
0898     Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
0899     Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
0900 
0901     QList<QByteArray> data;
0902     data.reserve(list.count());
0903 
0904     for (const QVariant &v : list) {
0905         if (v.type() == QVariant::ByteArray) {
0906             data << v.toByteArray();
0907         } else {
0908             data << v.toString().toUtf8();
0909         }
0910     }
0911 
0912     writeEntry(key, KConfigGroupPrivate::serializeList(data), flags);
0913 }
0914 
0915 void KConfigGroup::writeEntry(const char *key, const QVariant &value, WriteConfigFlags flags)
0916 {
0917     Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
0918     Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
0919 
0920     if (writeEntryGui(this, key, value, flags)) {
0921         return; // GUI type that was handled
0922     }
0923 
0924     QByteArray data;
0925     // if a type handler is added here you must add a QVConversions definition
0926     // to conversioncheck.h, or ConversionCheck::to_QVariant will not allow
0927     // writeEntry<T> to convert to QVariant.
0928     switch (static_cast<QMetaType::Type>(value.type())) {
0929     case QMetaType::UnknownType:
0930         data = "";
0931         break;
0932     case QMetaType::QByteArray:
0933         data = value.toByteArray();
0934         break;
0935     case QMetaType::QString:
0936     case QMetaType::Int:
0937     case QMetaType::UInt:
0938     case QMetaType::Double:
0939     case QMetaType::Float:
0940     case QMetaType::Bool:
0941     case QMetaType::LongLong:
0942     case QMetaType::ULongLong:
0943         data = value.toString().toUtf8();
0944         break;
0945     case QMetaType::QVariantList:
0946         if (!value.canConvert(QMetaType::QStringList)) {
0947             qCWarning(KCONFIG_CORE_LOG) << "not all types in \"" << key
0948                                         << "\" can convert to QString,"
0949                                            " information will be lost";
0950         }
0951         Q_FALLTHROUGH();
0952     case QMetaType::QStringList:
0953         writeEntry(key, value.toList(), flags);
0954         return;
0955     case QMetaType::QPoint: {
0956         const QPoint rPoint = value.toPoint();
0957 
0958         const QVariantList list{rPoint.x(), rPoint.y()};
0959 
0960         writeEntry(key, list, flags);
0961         return;
0962     }
0963     case QMetaType::QPointF: {
0964         const QPointF point = value.toPointF();
0965 
0966         const QVariantList list{point.x(), point.y()};
0967 
0968         writeEntry(key, list, flags);
0969         return;
0970     }
0971     case QMetaType::QRect: {
0972         const QRect rRect = value.toRect();
0973 
0974         const QVariantList list{rRect.left(), rRect.top(), rRect.width(), rRect.height()};
0975 
0976         writeEntry(key, list, flags);
0977         return;
0978     }
0979     case QMetaType::QRectF: {
0980         const QRectF rRectF = value.toRectF();
0981 
0982         const QVariantList list{rRectF.left(), rRectF.top(), rRectF.width(), rRectF.height()};
0983 
0984         writeEntry(key, list, flags);
0985         return;
0986     }
0987     case QMetaType::QSize: {
0988         const QSize rSize = value.toSize();
0989 
0990         const QVariantList list{rSize.width(), rSize.height()};
0991 
0992         writeEntry(key, list, flags);
0993         return;
0994     }
0995     case QMetaType::QUuid: {
0996         writeEntry(key, value.toString(), flags);
0997         return;
0998     }
0999     case QMetaType::QSizeF: {
1000         const QSizeF rSizeF = value.toSizeF();
1001 
1002         const QVariantList list{rSizeF.width(), rSizeF.height()};
1003 
1004         writeEntry(key, list, flags);
1005         return;
1006     }
1007     case QMetaType::QDate: {
1008         const QDate date = value.toDate();
1009 
1010         const QVariantList list{date.year(), date.month(), date.day()};
1011 
1012         writeEntry(key, list, flags);
1013         return;
1014     }
1015     case QMetaType::QDateTime: {
1016         const QDateTime rDateTime = value.toDateTime();
1017 
1018         const QTime time = rDateTime.time();
1019         const QDate date = rDateTime.date();
1020 
1021         const QVariantList list{
1022             date.year(),
1023             date.month(),
1024             date.day(),
1025 
1026             time.hour(),
1027             time.minute(),
1028             time.second() + time.msec() / 1000.0,
1029         };
1030 
1031         writeEntry(key, list, flags);
1032         return;
1033     }
1034 
1035     case QMetaType::QColor:
1036     case QMetaType::QFont:
1037         qCWarning(KCONFIG_CORE_LOG) << "KConfigGroup::writeEntry was passed GUI type '" << value.typeName()
1038                                     << "' but KConfigGui isn't linked! If it is linked to your program, this is a platform bug. "
1039                                        "Please inform the KDE developers";
1040         break;
1041     case QMetaType::QUrl:
1042         data = QUrl(value.toUrl()).toString().toUtf8();
1043         break;
1044     default:
1045         qCWarning(KCONFIG_CORE_LOG) << "KConfigGroup::writeEntry - unhandled type" << value.typeName() << "in group" << name();
1046     }
1047 
1048     writeEntry(key, data, flags);
1049 }
1050 
1051 void KConfigGroup::writeEntry(const QString &key, const QVariant &value, WriteConfigFlags flags)
1052 {
1053     writeEntry(key.toUtf8().constData(), value, flags);
1054 }
1055 
1056 void KConfigGroup::writeEntry(const QString &key, const QVariantList &list, WriteConfigFlags flags)
1057 {
1058     writeEntry(key.toUtf8().constData(), list, flags);
1059 }
1060 
1061 void KConfigGroup::writeXdgListEntry(const QString &key, const QStringList &value, WriteConfigFlags pFlags)
1062 {
1063     writeXdgListEntry(key.toUtf8().constData(), value, pFlags);
1064 }
1065 
1066 void KConfigGroup::writeXdgListEntry(const char *key, const QStringList &list, WriteConfigFlags flags)
1067 {
1068     Q_ASSERT_X(isValid(), "KConfigGroup::writeXdgListEntry", "accessing an invalid group");
1069     Q_ASSERT_X(!d->bConst, "KConfigGroup::writeXdgListEntry", "writing to a read-only group");
1070 
1071     QString value;
1072     value.reserve(4096);
1073 
1074     // XXX List serialization being a separate layer from low-level escaping is
1075     // probably a bug. No affected entries are defined, though.
1076     for (QString val : list) { // clazy:exclude=range-loop
1077         val.replace(QLatin1Char('\\'), QLatin1String("\\\\")).replace(QLatin1Char(';'), QLatin1String("\\;"));
1078         value += val + QLatin1Char(';');
1079     }
1080 
1081     writeEntry(key, value, flags);
1082 }
1083 
1084 void KConfigGroup::writePathEntry(const QString &pKey, const QString &path, WriteConfigFlags pFlags)
1085 {
1086     writePathEntry(pKey.toUtf8().constData(), path, pFlags);
1087 }
1088 
1089 void KConfigGroup::writePathEntry(const char *pKey, const QString &path, WriteConfigFlags pFlags)
1090 {
1091     Q_ASSERT_X(isValid(), "KConfigGroup::writePathEntry", "accessing an invalid group");
1092     Q_ASSERT_X(!d->bConst, "KConfigGroup::writePathEntry", "writing to a read-only group");
1093 
1094     config()->d_func()->putData(d->fullName(), pKey, translatePath(path).toUtf8(), pFlags, true);
1095 }
1096 
1097 void KConfigGroup::writePathEntry(const QString &pKey, const QStringList &value, WriteConfigFlags pFlags)
1098 {
1099     writePathEntry(pKey.toUtf8().constData(), value, pFlags);
1100 }
1101 
1102 void KConfigGroup::writePathEntry(const char *pKey, const QStringList &value, WriteConfigFlags pFlags)
1103 {
1104     Q_ASSERT_X(isValid(), "KConfigGroup::writePathEntry", "accessing an invalid group");
1105     Q_ASSERT_X(!d->bConst, "KConfigGroup::writePathEntry", "writing to a read-only group");
1106 
1107     QList<QByteArray> list;
1108     list.reserve(value.length());
1109     for (const QString &path : value) {
1110         list << translatePath(path).toUtf8();
1111     }
1112 
1113     config()->d_func()->putData(d->fullName(), pKey, KConfigGroupPrivate::serializeList(list), pFlags, true);
1114 }
1115 
1116 void KConfigGroup::deleteEntry(const char *key, WriteConfigFlags flags)
1117 {
1118     Q_ASSERT_X(isValid(), "KConfigGroup::deleteEntry", "accessing an invalid group");
1119     Q_ASSERT_X(!d->bConst, "KConfigGroup::deleteEntry", "deleting from a read-only group");
1120 
1121     config()->d_func()->putData(d->fullName(), key, QByteArray(), flags);
1122 }
1123 
1124 void KConfigGroup::deleteEntry(const QString &key, WriteConfigFlags flags)
1125 {
1126     deleteEntry(key.toUtf8().constData(), flags);
1127 }
1128 
1129 void KConfigGroup::revertToDefault(const char *key)
1130 {
1131     revertToDefault(key, WriteConfigFlags());
1132 }
1133 
1134 void KConfigGroup::revertToDefault(const char *key, WriteConfigFlags flags)
1135 {
1136     Q_ASSERT_X(isValid(), "KConfigGroup::revertToDefault", "accessing an invalid group");
1137     Q_ASSERT_X(!d->bConst, "KConfigGroup::revertToDefault", "writing to a read-only group");
1138 
1139     config()->d_func()->revertEntry(d->fullName(), key, flags);
1140 }
1141 
1142 void KConfigGroup::revertToDefault(const QString &key)
1143 {
1144     revertToDefault(key, WriteConfigFlags());
1145 }
1146 
1147 void KConfigGroup::revertToDefault(const QString &key, WriteConfigFlags flags)
1148 {
1149     revertToDefault(key.toUtf8().constData(), flags);
1150 }
1151 
1152 bool KConfigGroup::hasDefault(const char *key) const
1153 {
1154     Q_ASSERT_X(isValid(), "KConfigGroup::hasDefault", "accessing an invalid group");
1155 
1156     KEntryMap::SearchFlags flags = KEntryMap::SearchDefaults | KEntryMap::SearchLocalized;
1157 
1158     return !config()->d_func()->lookupData(d->fullName(), key, flags).isNull();
1159 }
1160 
1161 bool KConfigGroup::hasDefault(const QString &key) const
1162 {
1163     return hasDefault(key.toUtf8().constData());
1164 }
1165 
1166 bool KConfigGroup::hasKey(const char *key) const
1167 {
1168     Q_ASSERT_X(isValid(), "KConfigGroup::hasKey", "accessing an invalid group");
1169 
1170     KEntryMap::SearchFlags flags = KEntryMap::SearchLocalized;
1171     if (config()->readDefaults()) {
1172         flags |= KEntryMap::SearchDefaults;
1173     }
1174 
1175     return !config()->d_func()->lookupData(d->fullName(), key, flags).isNull();
1176 }
1177 
1178 bool KConfigGroup::hasKey(const QString &key) const
1179 {
1180     return hasKey(key.toUtf8().constData());
1181 }
1182 
1183 bool KConfigGroup::isImmutable() const
1184 {
1185     Q_ASSERT_X(isValid(), "KConfigGroup::isImmutable", "accessing an invalid group");
1186 
1187     return d->bImmutable;
1188 }
1189 
1190 QStringList KConfigGroup::groupList() const
1191 {
1192     Q_ASSERT_X(isValid(), "KConfigGroup::groupList", "accessing an invalid group");
1193 
1194     return config()->d_func()->groupList(d->fullName());
1195 }
1196 
1197 QStringList KConfigGroup::keyList() const
1198 {
1199     Q_ASSERT_X(isValid(), "KConfigGroup::keyList", "accessing an invalid group");
1200 
1201     return entryMap().keys();
1202 }
1203 
1204 void KConfigGroup::markAsClean()
1205 {
1206     Q_ASSERT_X(isValid(), "KConfigGroup::markAsClean", "accessing an invalid group");
1207 
1208     config()->markAsClean();
1209 }
1210 
1211 KConfigGroup::AccessMode KConfigGroup::accessMode() const
1212 {
1213     Q_ASSERT_X(isValid(), "KConfigGroup::accessMode", "accessing an invalid group");
1214 
1215     return config()->accessMode();
1216 }
1217 
1218 bool KConfigGroup::hasGroupImpl(const QByteArray &b) const
1219 {
1220     Q_ASSERT_X(isValid(), "KConfigGroup::hasGroupImpl", "accessing an invalid group");
1221 
1222     return config()->hasGroup(d->fullName(b));
1223 }
1224 
1225 void KConfigGroup::deleteGroupImpl(const QByteArray &b, WriteConfigFlags flags)
1226 {
1227     Q_ASSERT_X(isValid(), "KConfigGroup::deleteGroupImpl", "accessing an invalid group");
1228     Q_ASSERT_X(!d->bConst, "KConfigGroup::deleteGroupImpl", "deleting from a read-only group");
1229 
1230     config()->deleteGroup(d->fullName(b), flags);
1231 }
1232 
1233 bool KConfigGroup::isGroupImmutableImpl(const QByteArray &b) const
1234 {
1235     Q_ASSERT_X(isValid(), "KConfigGroup::isGroupImmutableImpl", "accessing an invalid group");
1236 
1237     if (!hasGroupImpl(b)) { // group doesn't exist yet
1238         return d->bImmutable; // child groups are immutable if the parent is immutable.
1239     }
1240 
1241     return config()->isGroupImmutable(d->fullName(b));
1242 }
1243 
1244 void KConfigGroup::copyTo(KConfigBase *other, WriteConfigFlags pFlags) const
1245 {
1246     Q_ASSERT_X(isValid(), "KConfigGroup::copyTo", "accessing an invalid group");
1247     Q_ASSERT(other != nullptr);
1248 
1249     if (KConfigGroup *otherGroup = dynamic_cast<KConfigGroup *>(other)) {
1250         config()->d_func()->copyGroup(d->fullName(), otherGroup->d->fullName(), otherGroup, pFlags);
1251     } else if (KConfig *otherConfig = dynamic_cast<KConfig *>(other)) {
1252         KConfigGroup newGroup = otherConfig->group(d->fullName());
1253         otherConfig->d_func()->copyGroup(d->fullName(), d->fullName(), &newGroup, pFlags);
1254     } else {
1255         Q_ASSERT_X(false, "KConfigGroup::copyTo", "unknown type of KConfigBase");
1256     }
1257 }
1258 
1259 void KConfigGroup::reparent(KConfigBase *parent, WriteConfigFlags pFlags)
1260 {
1261     Q_ASSERT_X(isValid(), "KConfigGroup::reparent", "accessing an invalid group");
1262     Q_ASSERT_X(!d->bConst, "KConfigGroup::reparent", "reparenting a read-only group");
1263     Q_ASSERT_X(!d->bImmutable, "KConfigGroup::reparent", "reparenting an immutable group");
1264     Q_ASSERT(parent != nullptr);
1265 
1266     KConfigGroup oldGroup(*this);
1267 
1268     d = KConfigGroupPrivate::create(parent, d->mName, false, false);
1269     oldGroup.copyTo(this, pFlags);
1270     oldGroup.deleteGroup(); // so that the entries with the old group name are deleted on sync
1271 }
1272 
1273 void KConfigGroup::moveValuesTo(const QList<const char *> &keys, KConfigGroup &other, WriteConfigFlags pFlags)
1274 {
1275     Q_ASSERT(isValid());
1276     Q_ASSERT(other.isValid());
1277 
1278     for (const auto key : keys) {
1279         const QByteArray groupName = name().toLocal8Bit();
1280         const auto entry = config()->d_ptr->lookupInternalEntry(groupName, key, KEntryMap::SearchLocalized);
1281 
1282         // Only write the entry if it is not null, if it is a global enry there is no point in moving it
1283         if (!entry.mValue.isNull() && !entry.bGlobal) {
1284             deleteEntry(key, pFlags);
1285             KEntryMap::EntryOptions options = KEntryMap::EntryOption::EntryDirty;
1286             if (entry.bDeleted) {
1287                 options |= KEntryMap::EntryDeleted;
1288             }
1289 
1290             if (entry.bExpand) {
1291                 options |= KEntryMap::EntryExpansion;
1292             }
1293 
1294             other.config()->d_ptr->setEntryData(other.name().toLocal8Bit(), key, entry.mValue, options);
1295         }
1296     }
1297 }