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 }