Coverage Report

Created: 2026-03-12 07:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/kconfig/src/core/kconfiggroup.cpp
Line
Count
Source
1
/*
2
    This file is part of the KDE libraries
3
    SPDX-FileCopyrightText: 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
4
    SPDX-FileCopyrightText: 1999 Preston Brown <pbrown@kde.org>
5
    SPDX-FileCopyrightText: 1997 Matthias Kalle Dalheimer <kalle@kde.org>
6
7
    SPDX-License-Identifier: LGPL-2.0-or-later
8
*/
9
10
#include "kconfiggroup.h"
11
#include "kconfiggroup_p.h"
12
13
#include "kconfig.h"
14
#include "kconfig_core_log_settings.h"
15
#include "kconfig_p.h"
16
#include "kconfigdata_p.h"
17
#include "ksharedconfig.h"
18
19
#include <QDate>
20
#include <QDir>
21
#include <QFile>
22
#include <QPoint>
23
#include <QRect>
24
#include <QSharedData>
25
#include <QString>
26
#include <QTextStream>
27
#include <QUrl>
28
#include <QUuid>
29
30
#include <algorithm>
31
#include <array>
32
#include <math.h>
33
#include <stdlib.h>
34
35
class KConfigGroupPrivate : public QSharedData
36
{
37
public:
38
    KConfigGroupPrivate(KConfig *owner, bool isImmutable, bool isConst, const QString &name)
39
38.8k
        : mOwner(owner)
40
38.8k
        , mName(name)
41
38.8k
        , bImmutable(isImmutable)
42
38.8k
        , bConst(isConst)
43
38.8k
    {
44
38.8k
        if (Q_UNLIKELY(!mOwner->name().isEmpty() && mOwner->accessMode() == KConfigBase::NoAccess)) {
45
0
            qCWarning(KCONFIG_CORE_LOG) << "Created a KConfigGroup on an inaccessible config location" << mOwner->name() << name;
46
0
        }
47
38.8k
    }
48
49
    KConfigGroupPrivate(const KSharedConfigPtr &owner, const QString &name)
50
135k
        : sOwner(owner)
51
135k
        , mOwner(sOwner.data())
52
135k
        , mName(name)
53
135k
        , bImmutable(name.isEmpty() ? owner->isImmutable() : owner->isGroupImmutable(name))
54
135k
        , bConst(false)
55
135k
    {
56
135k
        if (Q_UNLIKELY(!mOwner->name().isEmpty() && mOwner->accessMode() == KConfigBase::NoAccess)) {
57
0
            qCWarning(KCONFIG_CORE_LOG) << "Created a KConfigGroup on an inaccessible config location" << mOwner->name() << name;
58
0
        }
59
135k
    }
60
61
    KConfigGroupPrivate(KConfigGroup *parent, bool isImmutable, bool isConst, const QString &name)
62
0
        : sOwner(parent->d->sOwner)
63
0
        , mOwner(parent->d->mOwner)
64
0
        , mName(name)
65
0
        , bImmutable(isImmutable)
66
0
        , bConst(isConst)
67
0
    {
68
0
        if (!parent->d->mName.isEmpty()) {
69
0
            mParent = parent->d;
70
0
        }
71
0
    }
72
73
    KConfigGroupPrivate(const KConfigGroupPrivate *other, bool isImmutable, const QString &name)
74
        : sOwner(other->sOwner)
75
        , mOwner(other->mOwner)
76
        , mName(name)
77
        , bImmutable(isImmutable)
78
        , bConst(other->bConst)
79
0
    {
80
0
        if (!other->mName.isEmpty()) {
81
0
            mParent = const_cast<KConfigGroupPrivate *>(other);
82
0
        }
83
0
    }
84
85
    KSharedConfig::Ptr sOwner;
86
    KConfig *mOwner;
87
    QExplicitlySharedDataPointer<KConfigGroupPrivate> mParent;
88
    QString mName;
89
90
    /* bitfield */
91
    const bool bImmutable : 1; // is this group immutable?
92
    const bool bConst : 1; // is this group read-only?
93
94
    QString fullName() const
95
213k
    {
96
213k
        if (!mParent) {
97
213k
            return name();
98
213k
        }
99
0
        return mParent->fullName(mName);
100
213k
    }
101
102
    QString name() const
103
213k
    {
104
213k
        if (mName.isEmpty()) {
105
0
            return QStringLiteral("<default>");
106
0
        }
107
213k
        return mName;
108
213k
    }
109
110
    QString fullName(const QString &aGroup) const
111
0
    {
112
0
        if (mName.isEmpty()) {
113
0
            return aGroup;
114
0
        }
115
0
        return fullName() + QLatin1Char('\x1d') + aGroup;
116
0
    }
117
118
    static QExplicitlySharedDataPointer<KConfigGroupPrivate> create(KConfigBase *master, const QString &name, bool isImmutable, bool isConst)
119
38.8k
    {
120
38.8k
        QExplicitlySharedDataPointer<KConfigGroupPrivate> data;
121
38.8k
        if (dynamic_cast<KConfigGroup *>(master)) {
122
0
            data = new KConfigGroupPrivate(static_cast<KConfigGroup *>(master), isImmutable, isConst, name);
123
38.8k
        } else {
124
38.8k
            data = new KConfigGroupPrivate(dynamic_cast<KConfig *>(master), isImmutable, isConst, name);
125
38.8k
        }
126
38.8k
        return data;
127
38.8k
    }
128
129
    static QByteArray serializeList(const QList<QByteArray> &list);
130
    static QStringList deserializeList(const QString &data);
131
};
132
133
QByteArray KConfigGroupPrivate::serializeList(const QList<QByteArray> &list)
134
0
{
135
0
    QByteArray value;
136
137
0
    if (!list.isEmpty()) {
138
0
        auto it = list.cbegin();
139
0
        const auto end = list.cend();
140
141
0
        value = QByteArray(*it).replace('\\', QByteArrayLiteral("\\\\")).replace(',', QByteArrayLiteral("\\,"));
142
143
0
        while (++it != end) {
144
            // In the loop, so it is not done when there is only one element.
145
            // Doing it repeatedly is a pretty cheap operation.
146
0
            value.reserve(4096);
147
148
0
            value += ',';
149
0
            value += QByteArray(*it).replace('\\', QByteArrayLiteral("\\\\")).replace(',', QByteArrayLiteral("\\,"));
150
0
        }
151
152
        // To be able to distinguish an empty list from a list with one empty element.
153
0
        if (value.isEmpty()) {
154
0
            value = QByteArrayLiteral("\\0");
155
0
        }
156
0
    }
157
158
0
    return value;
159
0
}
160
161
QStringList KConfigGroupPrivate::deserializeList(const QString &data)
162
0
{
163
0
    if (data.isEmpty()) {
164
0
        return QStringList();
165
0
    }
166
0
    if (data == QLatin1String("\\0")) {
167
0
        return QStringList(QString());
168
0
    }
169
0
    QStringList value;
170
0
    QString val;
171
0
    val.reserve(data.size());
172
0
    bool quoted = false;
173
0
    for (int p = 0; p < data.length(); p++) {
174
0
        if (quoted) {
175
0
            val += data[p];
176
0
            quoted = false;
177
0
        } else if (data[p].unicode() == '\\') {
178
0
            quoted = true;
179
0
        } else if (data[p].unicode() == ',') {
180
0
            val.squeeze(); // release any unused memory
181
0
            value.append(val);
182
0
            val.clear();
183
0
            val.reserve(data.size() - p);
184
0
        } else {
185
0
            val += data[p];
186
0
        }
187
0
    }
188
0
    value.append(val);
189
0
    return value;
190
0
}
191
192
static QVarLengthArray<int, 8> asIntList(QByteArrayView string)
193
0
{
194
0
    int start = 0;
195
0
    int next = start;
196
0
    QVarLengthArray<int, 8> ret;
197
0
    while ((next = string.indexOf(',', start)) != -1) {
198
0
        ret.push_back(string.sliced(start, next - start).toInt());
199
0
        start = next + 1;
200
0
    }
201
0
    ret.push_back(string.sliced(start, string.size() - start).toInt());
202
0
    return ret;
203
0
}
204
205
static QVarLengthArray<qreal, 8> asRealList(QByteArrayView string)
206
0
{
207
0
    int start = 0;
208
0
    int next = start;
209
0
    QVarLengthArray<qreal, 8> ret;
210
0
    while ((next = string.indexOf(',', start)) != -1) {
211
0
        ret.push_back(string.sliced(start, next - start).toDouble());
212
0
        start = next + 1;
213
0
    }
214
0
    ret.push_back(string.sliced(start, string.size() - start).toDouble());
215
0
    return ret;
216
0
}
217
218
static QString errString(const char *pKey, const QByteArray &value, const QVariant &aDefault)
219
0
{
220
0
    return QStringLiteral("\"%1\" - conversion of \"%3\" to %2 failed")
221
0
        .arg(QString::fromLatin1(pKey), QString::fromLatin1(aDefault.typeName()), QString::fromLatin1(value));
222
0
}
223
224
static QString formatError(int expected, int got)
225
0
{
226
0
    return QStringLiteral(" (wrong format: expected %1 items, got %2)").arg(expected).arg(got);
227
0
}
228
229
QVariant KConfigGroup::convertToQVariant(const char *pKey, const QByteArray &value, const QVariant &aDefault)
230
13.9k
{
231
    // if a type handler is added here you must add a QVConversions definition
232
    // to kconfigconversioncheck_p.h, or KConfigConversionCheck::to_QVariant will not allow
233
    // readEntry<T> to convert to QVariant.
234
13.9k
    switch (static_cast<QMetaType::Type>(aDefault.userType())) {
235
0
    case QMetaType::UnknownType:
236
0
        return QVariant();
237
0
    case QMetaType::QString:
238
        // this should return the raw string not the dollar expanded string.
239
        // imho if processed string is wanted should call
240
        // readEntry(key, QString) not readEntry(key, QVariant)
241
0
        return QString::fromUtf8(value);
242
0
    case QMetaType::QUuid:
243
0
        return QUuid::fromString(value);
244
0
    case QMetaType::QVariantList:
245
0
    case QMetaType::QStringList:
246
0
        return KConfigGroupPrivate::deserializeList(QString::fromUtf8(value));
247
0
    case QMetaType::QByteArray:
248
0
        return value;
249
0
    case QMetaType::Bool: {
250
0
        static const std::array<const char *, 4> negatives = {"false", "no", "off", "0"};
251
252
0
        return std::all_of(negatives.begin(), negatives.end(), [value](const char *negativeString) {
253
0
            return value.compare(negativeString, Qt::CaseInsensitive) != 0;
254
0
        });
255
0
    }
256
0
    case QMetaType::Double:
257
0
    case QMetaType::Float:
258
0
    case QMetaType::Int:
259
0
    case QMetaType::UInt:
260
0
    case QMetaType::LongLong:
261
13.9k
    case QMetaType::ULongLong:
262
13.9k
    case QMetaType::Long:
263
13.9k
    case QMetaType::ULong: {
264
13.9k
        QVariant tmp = value;
265
13.9k
        if (!tmp.convert(aDefault.metaType())) {
266
0
            tmp = aDefault;
267
0
        }
268
13.9k
        return tmp;
269
13.9k
    }
270
0
    case QMetaType::QPoint: {
271
0
        const auto list = asIntList(value);
272
273
0
        if (list.count() != 2) {
274
0
            qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault) << formatError(2, list.count());
275
0
            return aDefault;
276
0
        }
277
0
        return QPoint(list.at(0), list.at(1));
278
0
    }
279
0
    case QMetaType::QPointF: {
280
0
        const auto list = asRealList(value);
281
282
0
        if (list.count() != 2) {
283
0
            qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault) << formatError(2, list.count());
284
0
            return aDefault;
285
0
        }
286
0
        return QPointF(list.at(0), list.at(1));
287
0
    }
288
0
    case QMetaType::QRect: {
289
0
        const auto list = asIntList(value);
290
291
0
        if (list.count() != 4) {
292
0
            qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault) << formatError(4, list.count());
293
0
            return aDefault;
294
0
        }
295
0
        const QRect rect(list.at(0), list.at(1), list.at(2), list.at(3));
296
0
        if (!rect.isValid()) {
297
0
            qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault);
298
0
            return aDefault;
299
0
        }
300
0
        return rect;
301
0
    }
302
0
    case QMetaType::QRectF: {
303
0
        const auto list = asRealList(value);
304
305
0
        if (list.count() != 4) {
306
0
            qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault) << formatError(4, list.count());
307
0
            return aDefault;
308
0
        }
309
0
        const QRectF rect(list.at(0), list.at(1), list.at(2), list.at(3));
310
0
        if (!rect.isValid()) {
311
0
            qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault);
312
0
            return aDefault;
313
0
        }
314
0
        return rect;
315
0
    }
316
0
    case QMetaType::QSize: {
317
0
        const auto list = asIntList(value);
318
319
0
        if (list.count() != 2) {
320
0
            qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault) << formatError(2, list.count());
321
0
            return aDefault;
322
0
        }
323
0
        const QSize size(list.at(0), list.at(1));
324
0
        if (!size.isValid()) {
325
0
            qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault);
326
0
            return aDefault;
327
0
        }
328
0
        return size;
329
0
    }
330
0
    case QMetaType::QSizeF: {
331
0
        const auto list = asRealList(value);
332
333
0
        if (list.count() != 2) {
334
0
            qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault) << formatError(2, list.count());
335
0
            return aDefault;
336
0
        }
337
0
        const QSizeF size(list.at(0), list.at(1));
338
0
        if (!size.isValid()) {
339
0
            qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault);
340
0
            return aDefault;
341
0
        }
342
0
        return size;
343
0
    }
344
0
    case QMetaType::QDateTime: {
345
0
        const auto list = asRealList(value);
346
0
        if (list.count() < 6) {
347
0
            qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault) << formatError(6, list.count());
348
0
            return aDefault;
349
0
        }
350
0
        const QDate date(list.at(0), list.at(1), list.at(2));
351
0
        const qreal totalSeconds = list.at(5);
352
0
        qreal seconds;
353
0
        const qreal fractional = modf(totalSeconds, &seconds);
354
0
        const qreal milliseconds = round(fractional * 1000.0);
355
0
        const QTime time(list.at(3), list.at(4), seconds, milliseconds);
356
357
0
        QDateTime dt(date, time);
358
0
        if (list.count() == 7) { // Then the timezone, which was added later
359
0
            const auto id = value.mid(value.lastIndexOf(',') + 1);
360
0
            dt.setTimeZone(QTimeZone(id));
361
0
        }
362
0
        if (!dt.isValid()) {
363
0
            qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault);
364
0
            return aDefault;
365
0
        }
366
0
        return dt;
367
0
    }
368
0
    case QMetaType::QDate: {
369
0
        auto list = asIntList(value);
370
        // list.count == 6 -> don't break config files that stored QDate as QDateTime
371
0
        if (list.count() != 3 && list.count() != 6) {
372
0
            qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault) << formatError(3, list.count());
373
0
            return aDefault;
374
0
        }
375
0
        const QDate date(list.at(0), list.at(1), list.at(2));
376
0
        if (!date.isValid()) {
377
0
            qCWarning(KCONFIG_CORE_LOG) << errString(pKey, value, aDefault);
378
0
            return aDefault;
379
0
        }
380
0
        return date;
381
0
    }
382
0
    case QMetaType::QTime:
383
0
        return QTime::fromString(QString::fromUtf8(value));
384
0
    case QMetaType::QColor:
385
0
    case QMetaType::QFont:
386
0
        qCWarning(KCONFIG_CORE_LOG) << "KConfigGroup::readEntry was passed GUI type '" << aDefault.typeName()
387
0
                                    << "' but KConfigGui isn't linked! If it is linked to your program, "
388
0
                                       "this is a platform bug. Please inform the KDE developers";
389
0
        break;
390
0
    case QMetaType::QUrl:
391
0
        return QUrl(QString::fromUtf8(value));
392
393
0
    default:
394
0
        break;
395
13.9k
    }
396
397
13.9k
    qCWarning(KCONFIG_CORE_LOG) << "unhandled type " << aDefault.typeName();
398
0
    return QVariant();
399
13.9k
}
400
401
static bool cleanHomeDirPath(QString &path, const QString &homeDir)
402
0
{
403
#ifdef Q_OS_WIN // safer
404
    if (!QDir::toNativeSeparators(path).startsWith(QDir::toNativeSeparators(homeDir))) {
405
        return false;
406
    }
407
#else
408
0
    if (!path.startsWith(homeDir)) {
409
0
        return false;
410
0
    }
411
0
#endif
412
413
0
    int len = homeDir.length();
414
    // replace by "$HOME" if possible
415
0
    if (len && (path.length() == len || path[len] == QLatin1Char('/'))) {
416
0
        path.replace(0, len, QStringLiteral("$HOME"));
417
0
        return true;
418
0
    }
419
420
0
    return false;
421
0
}
422
423
static QString translatePath(QString path) // krazy:exclude=passbyvalue
424
0
{
425
0
    if (path.isEmpty()) {
426
0
        return path;
427
0
    }
428
429
    // only "our" $HOME should be interpreted
430
0
    path.replace(QLatin1Char('$'), QLatin1String("$$"));
431
432
0
    const bool startsWithFile = path.startsWith(QLatin1String("file:"), Qt::CaseInsensitive);
433
0
    path = startsWithFile ? QUrl(path).toLocalFile() : path;
434
435
0
    if (QDir::isRelativePath(path)) {
436
0
        return path;
437
0
    }
438
439
    // Use the same thing as what expandString() will do, to keep data intact
440
#ifdef Q_OS_WIN
441
    const QString homeDir = QDir::homePath();
442
#else
443
0
    const QString homeDir = QFile::decodeName(qgetenv("HOME"));
444
0
#endif
445
0
    (void)cleanHomeDirPath(path, homeDir);
446
447
0
    if (startsWithFile) {
448
0
        path = QUrl::fromLocalFile(path).toString();
449
0
    }
450
451
0
    return path;
452
0
}
453
454
KConfigGroup::KConfigGroup()
455
4
    : d()
456
4
{
457
4
}
458
459
bool KConfigGroup::isValid() const
460
665k
{
461
665k
    return bool(d);
462
665k
}
463
464
KConfigGroupGui _kde_internal_KConfigGroupGui;
465
static inline bool readEntryGui(const QByteArray &data, const char *key, const QVariant &input, QVariant &output)
466
13.9k
{
467
13.9k
    if (_kde_internal_KConfigGroupGui.readEntryGui) {
468
0
        return _kde_internal_KConfigGroupGui.readEntryGui(data, key, input, output);
469
0
    }
470
13.9k
    return false;
471
13.9k
}
472
473
static inline bool writeEntryGui(KConfigGroup *cg, const char *key, const QVariant &input, KConfigGroup::WriteConfigFlags flags)
474
121k
{
475
121k
    if (_kde_internal_KConfigGroupGui.writeEntryGui) {
476
19.3k
        return _kde_internal_KConfigGroupGui.writeEntryGui(cg, key, input, flags);
477
19.3k
    }
478
102k
    return false;
479
121k
}
480
481
KConfigGroup::KConfigGroup(KConfigBase *master, const QString &_group)
482
38.8k
    : d(KConfigGroupPrivate::create(master, _group, master->isGroupImmutable(_group), false))
483
38.8k
{
484
38.8k
}
485
486
KConfigGroup::KConfigGroup(const KConfigBase *master, const QString &_group)
487
0
    : d(KConfigGroupPrivate::create(const_cast<KConfigBase *>(master), _group, master->isGroupImmutable(_group), true))
488
0
{
489
0
}
490
491
KConfigGroup::KConfigGroup(const KSharedConfigPtr &master, const QString &_group)
492
135k
    : d(new KConfigGroupPrivate(master, _group))
493
135k
{
494
135k
}
495
496
KConfigGroup &KConfigGroup::operator=(const KConfigGroup &rhs)
497
0
{
498
0
    d = rhs.d;
499
0
    return *this;
500
0
}
501
502
KConfigGroup::KConfigGroup(const KConfigGroup &rhs)
503
0
    : d(rhs.d)
504
0
{
505
0
}
506
507
KConfigGroup::~KConfigGroup()
508
174k
{
509
174k
    d.reset();
510
174k
}
511
512
KConfigGroup KConfigGroup::groupImpl(const QString &aGroup)
513
0
{
514
0
    Q_ASSERT_X(isValid(), "KConfigGroup::groupImpl", "accessing an invalid group");
515
0
    Q_ASSERT_X(!aGroup.isEmpty(), "KConfigGroup::groupImpl", "can not have an unnamed child group");
516
517
0
    KConfigGroup newGroup;
518
519
0
    newGroup.d = new KConfigGroupPrivate(this, isGroupImmutableImpl(aGroup), d->bConst, aGroup);
520
521
0
    return newGroup;
522
0
}
523
524
const KConfigGroup KConfigGroup::groupImpl(const QString &aGroup) const
525
0
{
526
0
    Q_ASSERT_X(isValid(), "KConfigGroup::groupImpl", "accessing an invalid group");
527
0
    Q_ASSERT_X(!aGroup.isEmpty(), "KConfigGroup::groupImpl", "can not have an unnamed child group");
528
529
0
    KConfigGroup newGroup;
530
531
0
    newGroup.d = new KConfigGroupPrivate(const_cast<KConfigGroup *>(this), isGroupImmutableImpl(aGroup), true, aGroup);
532
533
0
    return newGroup;
534
0
}
535
536
KConfigGroup KConfigGroup::parent() const
537
0
{
538
0
    Q_ASSERT_X(isValid(), "KConfigGroup::parent", "accessing an invalid group");
539
540
0
    KConfigGroup parentGroup;
541
542
0
    if (d->mParent) {
543
0
        parentGroup.d = d->mParent;
544
0
    } else {
545
0
        parentGroup.d = new KConfigGroupPrivate(d->mOwner, d->mOwner->isImmutable(), d->bConst, QString());
546
        // make sure we keep the refcount up on the KConfig object
547
0
        parentGroup.d->sOwner = d->sOwner;
548
0
    }
549
550
0
    return parentGroup;
551
0
}
552
553
void KConfigGroup::deleteGroup(WriteConfigFlags flags)
554
0
{
555
0
    Q_ASSERT_X(isValid(), "KConfigGroup::deleteGroup", "accessing an invalid group");
556
0
    Q_ASSERT_X(!d->bConst, "KConfigGroup::deleteGroup", "deleting a read-only group");
557
558
0
    config()->deleteGroup(d->fullName(), flags);
559
0
}
560
561
QString KConfigGroup::name() const
562
0
{
563
0
    Q_ASSERT_X(isValid(), "KConfigGroup::name", "accessing an invalid group");
564
565
0
    return d->name();
566
0
}
567
568
bool KConfigGroup::exists() const
569
0
{
570
0
    Q_ASSERT_X(isValid(), "KConfigGroup::exists", "accessing an invalid group");
571
572
0
    return config()->hasGroup(d->fullName());
573
0
}
574
575
bool KConfigGroup::sync()
576
0
{
577
0
    Q_ASSERT_X(isValid(), "KConfigGroup::sync", "accessing an invalid group");
578
579
0
    if (!d->bConst) {
580
0
        return config()->sync();
581
0
    }
582
583
0
    return false;
584
0
}
585
586
QMap<QString, QString> KConfigGroup::entryMap() const
587
0
{
588
0
    Q_ASSERT_X(isValid(), "KConfigGroup::entryMap", "accessing an invalid group");
589
590
0
    return config()->entryMap(d->fullName());
591
0
}
592
593
KConfig *KConfigGroup::config()
594
121k
{
595
121k
    Q_ASSERT_X(isValid(), "KConfigGroup::config", "accessing an invalid group");
596
597
121k
    return d->mOwner;
598
121k
}
599
600
const KConfig *KConfigGroup::config() const
601
130k
{
602
130k
    Q_ASSERT_X(isValid(), "KConfigGroup::config", "accessing an invalid group");
603
604
130k
    return d->mOwner;
605
130k
}
606
607
bool KConfigGroup::isEntryImmutable(const char *key) const
608
38.8k
{
609
38.8k
    Q_ASSERT_X(isValid(), "KConfigGroup::isEntryImmutable", "accessing an invalid group");
610
611
38.8k
    return (isImmutable() || !config()->d_func()->canWriteEntry(d->fullName(), key, config()->readDefaults()));
612
38.8k
}
613
614
bool KConfigGroup::isEntryImmutable(const QString &key) const
615
38.8k
{
616
38.8k
    return isEntryImmutable(key.toUtf8().constData());
617
38.8k
}
618
619
QString KConfigGroup::readEntryUntranslated(const QString &pKey, const QString &aDefault) const
620
0
{
621
0
    return readEntryUntranslated(pKey.toUtf8().constData(), aDefault);
622
0
}
623
624
QString KConfigGroup::readEntryUntranslated(const char *key, const QString &aDefault) const
625
0
{
626
0
    Q_ASSERT_X(isValid(), "KConfigGroup::readEntryUntranslated", "accessing an invalid group");
627
628
0
    QString result = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchFlags(), nullptr);
629
0
    if (result.isNull()) {
630
0
        return aDefault;
631
0
    }
632
0
    return result;
633
0
}
634
635
QString KConfigGroup::readEntry(const char *key, const char *aDefault) const
636
0
{
637
0
    return readEntry(key, QString::fromUtf8(aDefault));
638
0
}
639
640
QString KConfigGroup::readEntry(const QString &key, const char *aDefault) const
641
0
{
642
0
    return readEntry(key.toUtf8().constData(), aDefault);
643
0
}
644
645
QString KConfigGroup::readEntry(const char *key, const QString &aDefault) const
646
0
{
647
0
    Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
648
649
0
    bool expand = false;
650
651
    // read value from the entry map
652
0
    QString aValue = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchLocalized, &expand);
653
0
    if (aValue.isNull()) {
654
0
        aValue = aDefault;
655
0
    }
656
657
0
    if (expand) {
658
0
        return KConfigPrivate::expandString(aValue);
659
0
    }
660
661
0
    return aValue;
662
0
}
663
664
QString KConfigGroup::readEntry(const QString &key, const QString &aDefault) const
665
0
{
666
0
    return readEntry(key.toUtf8().constData(), aDefault);
667
0
}
668
669
QStringList KConfigGroup::readEntry(const char *key, const QStringList &aDefault) const
670
0
{
671
0
    Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
672
673
0
    const QString data = readEntry(key, QString());
674
0
    if (data.isNull()) {
675
0
        return aDefault;
676
0
    }
677
678
0
    return KConfigGroupPrivate::deserializeList(data);
679
0
}
680
681
QStringList KConfigGroup::readEntry(const QString &key, const QStringList &aDefault) const
682
0
{
683
0
    return readEntry(key.toUtf8().constData(), aDefault);
684
0
}
685
686
QVariant KConfigGroup::readEntry(const char *key, const QVariant &aDefault) const
687
52.7k
{
688
52.7k
    Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
689
690
52.7k
    const QByteArray data = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchLocalized);
691
52.7k
    if (data.isNull()) {
692
38.8k
        return aDefault;
693
38.8k
    }
694
695
13.9k
    QVariant value;
696
13.9k
    if (!readEntryGui(data, key, aDefault, value)) {
697
13.9k
        return convertToQVariant(key, data, aDefault);
698
13.9k
    }
699
700
0
    return value;
701
13.9k
}
702
703
QVariant KConfigGroup::readEntry(const QString &key, const QVariant &aDefault) const
704
0
{
705
0
    return readEntry(key.toUtf8().constData(), aDefault);
706
0
}
707
708
QVariantList KConfigGroup::readEntry(const char *key, const QVariantList &aDefault) const
709
0
{
710
0
    Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
711
712
0
    const QString data = readEntry(key, QString());
713
0
    if (data.isNull()) {
714
0
        return aDefault;
715
0
    }
716
717
0
    const auto &list = KConfigGroupPrivate::deserializeList(data);
718
719
0
    QVariantList value;
720
0
    value.reserve(list.count());
721
0
    for (const QString &v : list) {
722
0
        value << v;
723
0
    }
724
725
0
    return value;
726
0
}
727
728
QVariantList KConfigGroup::readEntry(const QString &key, const QVariantList &aDefault) const
729
0
{
730
0
    return readEntry(key.toUtf8().constData(), aDefault);
731
0
}
732
733
QStringList KConfigGroup::readXdgListEntry(const QString &key, const QStringList &aDefault) const
734
0
{
735
0
    return readXdgListEntry(key.toUtf8().constData(), aDefault);
736
0
}
737
738
QStringList KConfigGroup::readXdgListEntry(const char *key, const QStringList &aDefault) const
739
0
{
740
0
    Q_ASSERT_X(isValid(), "KConfigGroup::readXdgListEntry", "accessing an invalid group");
741
742
0
    const QString data = readEntry(key, QString());
743
0
    if (data.isNull()) {
744
0
        return aDefault;
745
0
    }
746
747
0
    QStringList value;
748
0
    QString val;
749
0
    val.reserve(data.size());
750
    // XXX List serialization being a separate layer from low-level parsing is
751
    // probably a bug. No affected entries are defined, though.
752
0
    bool quoted = false;
753
0
    for (int p = 0; p < data.length(); p++) {
754
0
        if (quoted) {
755
0
            val += data[p];
756
0
            quoted = false;
757
0
        } else if (data[p] == QLatin1Char('\\')) {
758
0
            quoted = true;
759
0
        } else if (data[p] == QLatin1Char(';')) {
760
0
            value.append(val);
761
0
            val.clear();
762
0
            val.reserve(data.size() - p);
763
0
        } else {
764
0
            val += data[p];
765
0
        }
766
0
    }
767
0
    if (!val.isEmpty()) {
768
0
        value.append(val);
769
0
    }
770
0
    return value;
771
0
}
772
773
QString KConfigGroup::readPathEntry(const QString &pKey, const QString &aDefault) const
774
0
{
775
0
    return readPathEntry(pKey.toUtf8().constData(), aDefault);
776
0
}
777
778
QString KConfigGroup::readPathEntry(const char *key, const QString &aDefault) const
779
0
{
780
0
    Q_ASSERT_X(isValid(), "KConfigGroup::readPathEntry", "accessing an invalid group");
781
782
0
    bool expand = false;
783
784
0
    QString aValue = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchLocalized, &expand);
785
0
    if (aValue.isNull()) {
786
0
        aValue = aDefault;
787
0
    }
788
789
0
    return KConfigPrivate::expandString(aValue);
790
0
}
791
792
QStringList KConfigGroup::readPathEntry(const QString &pKey, const QStringList &aDefault) const
793
0
{
794
0
    return readPathEntry(pKey.toUtf8().constData(), aDefault);
795
0
}
796
797
QStringList KConfigGroup::readPathEntry(const char *key, const QStringList &aDefault) const
798
0
{
799
0
    Q_ASSERT_X(isValid(), "KConfigGroup::readPathEntry", "accessing an invalid group");
800
801
0
    const QString data = readPathEntry(key, QString());
802
0
    if (data.isNull()) {
803
0
        return aDefault;
804
0
    }
805
806
0
    return KConfigGroupPrivate::deserializeList(data);
807
0
}
808
809
void KConfigGroup::writeEntry(const char *key, const QString &value, WriteConfigFlags flags)
810
0
{
811
0
    Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
812
0
    Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
813
814
0
    writeEntry(key, value.toUtf8(), flags);
815
0
}
816
817
void KConfigGroup::writeEntry(const QString &key, const QString &value, WriteConfigFlags flags)
818
0
{
819
0
    writeEntry(key.toUtf8().constData(), value, flags);
820
0
}
821
822
void KConfigGroup::writeEntry(const QString &key, const char *value, WriteConfigFlags pFlags)
823
0
{
824
0
    Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
825
0
    Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
826
827
0
    writeEntry(key.toUtf8().constData(), QVariant(QString::fromLatin1(value)), pFlags);
828
0
}
829
830
void KConfigGroup::writeEntry(const char *key, const char *value, WriteConfigFlags pFlags)
831
0
{
832
0
    writeEntry(key, QVariant(QString::fromLatin1(value)), pFlags);
833
0
}
834
835
void KConfigGroup::writeEntry(const char *key, const QByteArray &value, WriteConfigFlags flags)
836
121k
{
837
121k
    Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
838
121k
    Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
839
840
121k
    config()->d_func()->putData(d->fullName(), key, value.isNull() ? QByteArray("") : value, flags);
841
121k
}
842
843
void KConfigGroup::writeEntry(const QString &key, const QByteArray &value, WriteConfigFlags pFlags)
844
0
{
845
0
    writeEntry(key.toUtf8().constData(), value, pFlags);
846
0
}
847
848
void KConfigGroup::writeEntry(const char *key, const QStringList &list, WriteConfigFlags flags)
849
0
{
850
0
    Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
851
0
    Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
852
853
0
    QList<QByteArray> balist;
854
0
    balist.reserve(list.count());
855
856
0
    for (const QString &entry : list) {
857
0
        balist.append(entry.toUtf8());
858
0
    }
859
860
0
    writeEntry(key, KConfigGroupPrivate::serializeList(balist), flags);
861
0
}
862
863
void KConfigGroup::writeEntry(const QString &key, const QStringList &list, WriteConfigFlags flags)
864
0
{
865
0
    writeEntry(key.toUtf8().constData(), list, flags);
866
0
}
867
868
void KConfigGroup::writeEntry(const char *key, const QVariantList &list, WriteConfigFlags flags)
869
0
{
870
0
    Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
871
0
    Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
872
873
0
    QList<QByteArray> data;
874
0
    data.reserve(list.count());
875
876
0
    for (const QVariant &v : list) {
877
0
        if (v.userType() == QMetaType::QByteArray) {
878
0
            data << v.toByteArray();
879
0
        } else {
880
0
            data << v.toString().toUtf8();
881
0
        }
882
0
    }
883
884
0
    writeEntry(key, KConfigGroupPrivate::serializeList(data), flags);
885
0
}
886
887
void KConfigGroup::writeEntry(const char *key, const QVariant &value, WriteConfigFlags flags)
888
121k
{
889
121k
    Q_ASSERT_X(isValid(), "KConfigGroup::writeEntry", "accessing an invalid group");
890
121k
    Q_ASSERT_X(!d->bConst, "KConfigGroup::writeEntry", "writing to a read-only group");
891
892
121k
    if (writeEntryGui(this, key, value, flags)) {
893
0
        return; // GUI type that was handled
894
0
    }
895
896
121k
    QByteArray data;
897
    // if a type handler is added here you must add a QVConversions definition
898
    // to kconfigconversioncheck_p.h, or KConfigConversionCheck::to_QVariant will not allow
899
    // writeEntry<T> to convert to QVariant.
900
121k
    switch (static_cast<QMetaType::Type>(value.userType())) {
901
0
    case QMetaType::UnknownType:
902
0
        data = "";
903
0
        break;
904
0
    case QMetaType::QByteArray:
905
0
        data = value.toByteArray();
906
0
        break;
907
0
    case QMetaType::QString:
908
0
    case QMetaType::Int:
909
0
    case QMetaType::UInt:
910
0
    case QMetaType::Double:
911
0
    case QMetaType::Float:
912
0
    case QMetaType::Bool:
913
0
    case QMetaType::LongLong:
914
121k
    case QMetaType::ULongLong:
915
121k
    case QMetaType::Long:
916
121k
    case QMetaType::ULong:
917
121k
        data = value.toString().toUtf8();
918
121k
        break;
919
0
    case QMetaType::QVariantList:
920
0
        if (!value.canConvert<QStringList>()) {
921
0
            qCWarning(KCONFIG_CORE_LOG) << "not all types in \"" << key
922
0
                                        << "\" can convert to QString,"
923
0
                                           " information will be lost";
924
0
        }
925
0
        Q_FALLTHROUGH();
926
0
    case QMetaType::QStringList:
927
0
        writeEntry(key, value.toList(), flags);
928
0
        return;
929
0
    case QMetaType::QPoint: {
930
0
        const QPoint rPoint = value.toPoint();
931
932
0
        const QVariantList list{rPoint.x(), rPoint.y()};
933
934
0
        writeEntry(key, list, flags);
935
0
        return;
936
0
    }
937
0
    case QMetaType::QPointF: {
938
0
        const QPointF point = value.toPointF();
939
940
0
        const QVariantList list{point.x(), point.y()};
941
942
0
        writeEntry(key, list, flags);
943
0
        return;
944
0
    }
945
0
    case QMetaType::QRect: {
946
0
        const QRect rRect = value.toRect();
947
948
0
        const QVariantList list{rRect.left(), rRect.top(), rRect.width(), rRect.height()};
949
950
0
        writeEntry(key, list, flags);
951
0
        return;
952
0
    }
953
0
    case QMetaType::QRectF: {
954
0
        const QRectF rRectF = value.toRectF();
955
956
0
        const QVariantList list{rRectF.left(), rRectF.top(), rRectF.width(), rRectF.height()};
957
958
0
        writeEntry(key, list, flags);
959
0
        return;
960
0
    }
961
0
    case QMetaType::QSize: {
962
0
        const QSize rSize = value.toSize();
963
964
0
        const QVariantList list{rSize.width(), rSize.height()};
965
966
0
        writeEntry(key, list, flags);
967
0
        return;
968
0
    }
969
0
    case QMetaType::QUuid: {
970
0
        writeEntry(key, value.toString(), flags);
971
0
        return;
972
0
    }
973
0
    case QMetaType::QSizeF: {
974
0
        const QSizeF rSizeF = value.toSizeF();
975
976
0
        const QVariantList list{rSizeF.width(), rSizeF.height()};
977
978
0
        writeEntry(key, list, flags);
979
0
        return;
980
0
    }
981
0
    case QMetaType::QDate: {
982
0
        const QDate date = value.toDate();
983
984
0
        const QVariantList list{date.year(), date.month(), date.day()};
985
986
0
        writeEntry(key, list, flags);
987
0
        return;
988
0
    }
989
0
    case QMetaType::QTime: {
990
0
        data = value.toTime().toString().toUtf8();
991
0
        break;
992
0
    }
993
0
    case QMetaType::QDateTime: {
994
0
        const QDateTime rDateTime = value.toDateTime();
995
996
0
        const QTime time = rDateTime.time();
997
0
        const QDate date = rDateTime.date();
998
999
0
        QVariantList list{
1000
0
            date.year(),
1001
0
            date.month(),
1002
0
            date.day(),
1003
1004
0
            time.hour(),
1005
0
            time.minute(),
1006
0
            time.second() + time.msec() / 1000.0,
1007
0
        };
1008
0
        if (rDateTime.timeRepresentation().timeSpec() != Qt::LocalTime) {
1009
0
            list.append(rDateTime.timeZone().id());
1010
0
        }
1011
1012
0
        writeEntry(key, list, flags);
1013
0
        return;
1014
0
    }
1015
1016
0
    case QMetaType::QColor:
1017
0
    case QMetaType::QFont:
1018
0
        qCWarning(KCONFIG_CORE_LOG) << "KConfigGroup::writeEntry was passed GUI type '" << value.typeName()
1019
0
                                    << "' but KConfigGui isn't linked! If it is linked to your program, this is a platform bug. "
1020
0
                                       "Please inform the KDE developers";
1021
0
        break;
1022
0
    case QMetaType::QUrl:
1023
0
        data = QUrl(value.toUrl()).toString().toUtf8();
1024
0
        break;
1025
0
    default:
1026
0
        qCWarning(KCONFIG_CORE_LOG) << "KConfigGroup::writeEntry - unhandled type" << value.typeName() << "in group" << name();
1027
121k
    }
1028
1029
121k
    writeEntry(key, data, flags);
1030
121k
}
1031
1032
void KConfigGroup::writeEntry(const QString &key, const QVariant &value, WriteConfigFlags flags)
1033
0
{
1034
0
    writeEntry(key.toUtf8().constData(), value, flags);
1035
0
}
1036
1037
void KConfigGroup::writeEntry(const QString &key, const QVariantList &list, WriteConfigFlags flags)
1038
0
{
1039
0
    writeEntry(key.toUtf8().constData(), list, flags);
1040
0
}
1041
1042
void KConfigGroup::writeXdgListEntry(const QString &key, const QStringList &value, WriteConfigFlags pFlags)
1043
0
{
1044
0
    writeXdgListEntry(key.toUtf8().constData(), value, pFlags);
1045
0
}
1046
1047
void KConfigGroup::writeXdgListEntry(const char *key, const QStringList &list, WriteConfigFlags flags)
1048
0
{
1049
0
    Q_ASSERT_X(isValid(), "KConfigGroup::writeXdgListEntry", "accessing an invalid group");
1050
0
    Q_ASSERT_X(!d->bConst, "KConfigGroup::writeXdgListEntry", "writing to a read-only group");
1051
1052
0
    QString value;
1053
0
    value.reserve(4096);
1054
1055
    // XXX List serialization being a separate layer from low-level escaping is
1056
    // probably a bug. No affected entries are defined, though.
1057
0
    for (QString val : list) { // clazy:exclude=range-loop
1058
0
        val.replace(QLatin1Char('\\'), QLatin1String("\\\\")).replace(QLatin1Char(';'), QLatin1String("\\;"));
1059
0
        value += val + QLatin1Char(';');
1060
0
    }
1061
1062
0
    writeEntry(key, value, flags);
1063
0
}
1064
1065
void KConfigGroup::writePathEntry(const QString &pKey, const QString &path, WriteConfigFlags pFlags)
1066
0
{
1067
0
    writePathEntry(pKey.toUtf8().constData(), path, pFlags);
1068
0
}
1069
1070
void KConfigGroup::writePathEntry(const char *pKey, const QString &path, WriteConfigFlags pFlags)
1071
0
{
1072
0
    Q_ASSERT_X(isValid(), "KConfigGroup::writePathEntry", "accessing an invalid group");
1073
0
    Q_ASSERT_X(!d->bConst, "KConfigGroup::writePathEntry", "writing to a read-only group");
1074
1075
0
    config()->d_func()->putData(d->fullName(), pKey, translatePath(path).toUtf8(), pFlags, true);
1076
0
}
1077
1078
void KConfigGroup::writePathEntry(const QString &pKey, const QStringList &value, WriteConfigFlags pFlags)
1079
0
{
1080
0
    writePathEntry(pKey.toUtf8().constData(), value, pFlags);
1081
0
}
1082
1083
void KConfigGroup::writePathEntry(const char *pKey, const QStringList &value, WriteConfigFlags pFlags)
1084
0
{
1085
0
    Q_ASSERT_X(isValid(), "KConfigGroup::writePathEntry", "accessing an invalid group");
1086
0
    Q_ASSERT_X(!d->bConst, "KConfigGroup::writePathEntry", "writing to a read-only group");
1087
1088
0
    QList<QByteArray> list;
1089
0
    list.reserve(value.length());
1090
0
    for (const QString &path : value) {
1091
0
        list << translatePath(path).toUtf8();
1092
0
    }
1093
1094
0
    config()->d_func()->putData(d->fullName(), pKey, KConfigGroupPrivate::serializeList(list), pFlags, true);
1095
0
}
1096
1097
void KConfigGroup::deleteEntry(const char *key, WriteConfigFlags flags)
1098
0
{
1099
0
    Q_ASSERT_X(isValid(), "KConfigGroup::deleteEntry", "accessing an invalid group");
1100
0
    Q_ASSERT_X(!d->bConst, "KConfigGroup::deleteEntry", "deleting from a read-only group");
1101
1102
0
    config()->d_func()->putData(d->fullName(), key, QByteArray(), flags);
1103
0
}
1104
1105
void KConfigGroup::deleteEntry(const QString &key, WriteConfigFlags flags)
1106
0
{
1107
0
    deleteEntry(key.toUtf8().constData(), flags);
1108
0
}
1109
1110
void KConfigGroup::revertToDefault(const char *key, WriteConfigFlags flags)
1111
0
{
1112
0
    Q_ASSERT_X(isValid(), "KConfigGroup::revertToDefault", "accessing an invalid group");
1113
0
    Q_ASSERT_X(!d->bConst, "KConfigGroup::revertToDefault", "writing to a read-only group");
1114
1115
0
    config()->d_func()->revertEntry(d->fullName(), key, flags);
1116
0
}
1117
1118
void KConfigGroup::revertToDefault(const QString &key, WriteConfigFlags flags)
1119
0
{
1120
0
    revertToDefault(key.toUtf8().constData(), flags);
1121
0
}
1122
1123
bool KConfigGroup::hasDefault(const char *key) const
1124
0
{
1125
0
    Q_ASSERT_X(isValid(), "KConfigGroup::hasDefault", "accessing an invalid group");
1126
1127
0
    KEntryMap::SearchFlags flags = KEntryMap::SearchDefaults | KEntryMap::SearchLocalized;
1128
1129
0
    return !config()->d_func()->lookupData(d->fullName(), key, flags).isNull();
1130
0
}
1131
1132
bool KConfigGroup::hasDefault(const QString &key) const
1133
0
{
1134
0
    return hasDefault(key.toUtf8().constData());
1135
0
}
1136
1137
bool KConfigGroup::hasKey(const char *key) const
1138
3
{
1139
3
    Q_ASSERT_X(isValid(), "KConfigGroup::hasKey", "accessing an invalid group");
1140
1141
3
    KEntryMap::SearchFlags flags = KEntryMap::SearchLocalized;
1142
3
    if (config()->readDefaults()) {
1143
1
        flags |= KEntryMap::SearchDefaults;
1144
1
    }
1145
1146
3
    return !config()->d_func()->lookupData(d->fullName(), key, flags).isNull();
1147
3
}
1148
1149
bool KConfigGroup::hasKey(const QString &key) const
1150
3
{
1151
3
    return hasKey(key.toUtf8().constData());
1152
3
}
1153
1154
bool KConfigGroup::isImmutable() const
1155
38.8k
{
1156
38.8k
    Q_ASSERT_X(isValid(), "KConfigGroup::isImmutable", "accessing an invalid group");
1157
1158
38.8k
    return d->bImmutable;
1159
38.8k
}
1160
1161
QStringList KConfigGroup::groupList() const
1162
0
{
1163
0
    Q_ASSERT_X(isValid(), "KConfigGroup::groupList", "accessing an invalid group");
1164
1165
0
    return config()->d_func()->groupList(d->fullName());
1166
0
}
1167
1168
QStringList KConfigGroup::keyList() const
1169
0
{
1170
0
    Q_ASSERT_X(isValid(), "KConfigGroup::keyList", "accessing an invalid group");
1171
1172
0
    return config()->d_func()->usedKeyList(d->fullName());
1173
0
}
1174
1175
void KConfigGroup::markAsClean()
1176
0
{
1177
0
    Q_ASSERT_X(isValid(), "KConfigGroup::markAsClean", "accessing an invalid group");
1178
1179
0
    config()->markAsClean();
1180
0
}
1181
1182
KConfigGroup::AccessMode KConfigGroup::accessMode() const
1183
0
{
1184
0
    Q_ASSERT_X(isValid(), "KConfigGroup::accessMode", "accessing an invalid group");
1185
1186
0
    return config()->accessMode();
1187
0
}
1188
1189
bool KConfigGroup::hasGroupImpl(const QString &b) const
1190
0
{
1191
0
    Q_ASSERT_X(isValid(), "KConfigGroup::hasGroupImpl", "accessing an invalid group");
1192
1193
0
    return config()->hasGroup(d->fullName(b));
1194
0
}
1195
1196
void KConfigGroup::deleteGroupImpl(const QString &b, WriteConfigFlags flags)
1197
0
{
1198
0
    Q_ASSERT_X(isValid(), "KConfigGroup::deleteGroupImpl", "accessing an invalid group");
1199
0
    Q_ASSERT_X(!d->bConst, "KConfigGroup::deleteGroupImpl", "deleting from a read-only group");
1200
1201
0
    config()->deleteGroup(d->fullName(b), flags);
1202
0
}
1203
1204
bool KConfigGroup::isGroupImmutableImpl(const QString &groupName) const
1205
0
{
1206
0
    Q_ASSERT_X(isValid(), "KConfigGroup::isGroupImmutableImpl", "accessing an invalid group");
1207
1208
0
    if (!hasGroupImpl(groupName)) { // group doesn't exist yet
1209
0
        return d->bImmutable; // child groups are immutable if the parent is immutable.
1210
0
    }
1211
1212
0
    return config()->isGroupImmutable(d->fullName(groupName));
1213
0
}
1214
1215
void KConfigGroup::copyTo(KConfigBase *other, WriteConfigFlags pFlags) const
1216
0
{
1217
0
    Q_ASSERT_X(isValid(), "KConfigGroup::copyTo", "accessing an invalid group");
1218
0
    Q_ASSERT(other != nullptr);
1219
1220
0
    if (KConfigGroup *otherGroup = dynamic_cast<KConfigGroup *>(other)) {
1221
0
        config()->d_func()->copyGroup(d->fullName(), otherGroup->d->fullName(), otherGroup, pFlags);
1222
0
    } else if (KConfig *otherConfig = dynamic_cast<KConfig *>(other)) {
1223
0
        KConfigGroup newGroup = otherConfig->group(d->fullName());
1224
0
        otherConfig->d_func()->copyGroup(d->fullName(), d->fullName(), &newGroup, pFlags);
1225
0
    } else {
1226
0
        Q_ASSERT_X(false, "KConfigGroup::copyTo", "unknown type of KConfigBase");
1227
0
    }
1228
0
}
1229
1230
void KConfigGroup::reparent(KConfigBase *parent, WriteConfigFlags pFlags)
1231
0
{
1232
0
    Q_ASSERT_X(isValid(), "KConfigGroup::reparent", "accessing an invalid group");
1233
0
    Q_ASSERT_X(!d->bConst, "KConfigGroup::reparent", "reparenting a read-only group");
1234
0
    Q_ASSERT_X(!d->bImmutable, "KConfigGroup::reparent", "reparenting an immutable group");
1235
0
    Q_ASSERT(parent != nullptr);
1236
1237
0
    KConfigGroup oldGroup(*this);
1238
1239
0
    d = KConfigGroupPrivate::create(parent, d->mName, false, false);
1240
0
    oldGroup.copyTo(this, pFlags);
1241
0
    oldGroup.deleteGroup(); // so that the entries with the old group name are deleted on sync
1242
0
}
1243
1244
void KConfigGroup::moveValue(const char *key, KConfigGroup &other, WriteConfigFlags pFlags)
1245
0
{
1246
0
    const QString groupName = d->fullName();
1247
0
    const auto entry = config()->d_ptr->lookupInternalEntry(groupName, key, KEntryMap::SearchLocalized);
1248
1249
    // Only write the entry if it is not null, if it is a global enry there is no point in moving it
1250
0
    if (!entry.mValue.isNull() && !entry.bGlobal) {
1251
0
        deleteEntry(key, pFlags);
1252
0
        KEntryMap::EntryOptions options = KEntryMap::EntryOption::EntryDirty;
1253
0
        if (entry.bDeleted) {
1254
0
            options |= KEntryMap::EntryDeleted;
1255
0
        }
1256
1257
0
        if (entry.bExpand) {
1258
0
            options |= KEntryMap::EntryExpansion;
1259
0
        }
1260
1261
0
        other.config()->d_ptr->setEntryData(other.d->fullName(), key, entry.mValue, options);
1262
0
    }
1263
0
}
1264
1265
void KConfigGroup::moveValuesTo(const QList<const char *> &keys, KConfigGroup &other, WriteConfigFlags pFlags)
1266
0
{
1267
0
    Q_ASSERT(isValid());
1268
0
    Q_ASSERT(other.isValid());
1269
1270
0
    for (const auto key : keys) {
1271
0
        moveValue(key, other, pFlags);
1272
0
    }
1273
0
}
1274
1275
void KConfigGroup::moveValuesTo(KConfigGroup &other, WriteConfigFlags pFlags)
1276
0
{
1277
0
    Q_ASSERT(isValid());
1278
0
    Q_ASSERT(other.isValid());
1279
1280
0
    const QStringList keys = keyList();
1281
0
    for (const QString &key : keys) {
1282
0
        moveValue(key.toUtf8().constData(), other, pFlags);
1283
0
    }
1284
0
}