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 SPDX-FileCopyrightText: 2001 Waldo Bastian <bastian@kde.org>
7
8 SPDX-License-Identifier: LGPL-2.0-or-later
9*/
10
11#ifndef KCONFIGGROUP_H
12#define KCONFIGGROUP_H
13
14#include "kconfigbase.h"
15
16#include <kconfigcore_export.h>
17
18#include <QExplicitlySharedDataPointer>
19#include <QStringList>
20#include <QVariant>
21
22class KConfig;
23class KConfigGroupPrivate;
24class KSharedConfig;
25
26/**
27 * \class KConfigGroup kconfiggroup.h <KConfigGroup>
28 *
29 * A class for one specific group in a KConfig object.
30 *
31 * If you want to access the top-level entries of a KConfig
32 * object, which are not associated with any group, use an
33 * empty group name.
34 *
35 * A KConfigGroup will be read-only if it is constructed from a
36 * const config object or from another read-only group.
37 */
38class KCONFIGCORE_EXPORT KConfigGroup : public KConfigBase
39{
40public:
41 /**
42 * Constructs an invalid group.
43 *
44 * \see isValid
45 */
46 KConfigGroup();
47
48 /**
49 * Construct a config group corresponding to @p group in @p master.
50 *
51 * This allows the creation of subgroups by passing another
52 * group as @p master.
53 *
54 * @param group name of group
55 */
56 KConfigGroup(KConfigBase *master, const QString &group);
57
58 /**
59 * Construct a read-only config group.
60 *
61 * A read-only group will silently ignore any attempts to write to it.
62 *
63 * This allows the creation of subgroups by passing an existing group
64 * as @p master.
65 */
66 KConfigGroup(const KConfigBase *master, const QString &group);
67
68 /** Overload for KConfigGroup(const KConfigBase*,const QString&) */
69 KConfigGroup(const QExplicitlySharedDataPointer<KSharedConfig> &master, const QString &group);
70
71 /**
72 * Creates a copy of a group.
73 */
74 KConfigGroup(const KConfigGroup &);
75 KConfigGroup &operator=(const KConfigGroup &);
76
77 ~KConfigGroup() override;
78
79 /**
80 * Whether the group is valid.
81 *
82 * A group is invalid if it was constructed without arguments.
83 *
84 * You should not call any functions on an invalid group.
85 *
86 * @return @c true if the group is valid, @c false if it is invalid.
87 */
88 bool isValid() const;
89
90 /**
91 * The name of this group.
92 *
93 * The root group is named "<default>".
94 */
95 QString name() const;
96
97 /**
98 * Check whether the containing KConfig object actually contains a
99 * group with this name.
100 */
101 bool exists() const;
102
103 /**
104 * @reimp
105 *
106 * Syncs the parent config.
107 */
108 bool sync() override;
109
110 /// @reimp
111 void markAsClean() override;
112
113 /// @reimp
114 AccessMode accessMode() const override;
115
116 /**
117 * Return the config object that this group belongs to
118 */
119 KConfig *config();
120 /**
121 * Return the config object that this group belongs to
122 */
123 const KConfig *config() const;
124
125 /**
126 * Copies the entries in this group to another configuration object
127 *
128 * @note @p other can be either another group or a different file.
129 *
130 * @param other the configuration object to copy this group's entries to
131 * @param pFlags the flags to use when writing the entries to the
132 * other configuration object
133 *
134 * @since 4.1
135 */
136 void copyTo(KConfigBase *other, WriteConfigFlags pFlags = Normal) const;
137
138 /**
139 * Changes the configuration object that this group belongs to
140 *
141 * @note @p other can be another group, the top-level KConfig object or
142 * a different KConfig object entirely.
143 *
144 * If @p parent is already the parent of this group, this method will have
145 * no effect.
146 *
147 * @param parent the config object to place this group under
148 * @param pFlags the flags to use in determining which storage source to
149 * write the data to
150 *
151 * @since 4.1
152 */
153 void reparent(KConfigBase *parent, WriteConfigFlags pFlags = Normal);
154
155 /**
156 * Moves the key-value pairs from one config group to the other.
157 * In case the entries do not exist the key is ignored.
158 *
159 * @since 5.88
160 */
161 void moveValuesTo(const QList<const char *> &keys, KConfigGroup &other, WriteConfigFlags pFlags = Normal);
162
163 /**
164 * Returns the group that this group belongs to
165 *
166 * @return the parent group, or an invalid group if this is a top-level
167 * group
168 *
169 * @since 4.1
170 */
171 KConfigGroup parent() const;
172
173 /**
174 * @reimp
175 */
176 QStringList groupList() const override;
177
178 /**
179 * Returns a list of keys this group contains
180 */
181 QStringList keyList() const;
182
183 /**
184 * Delete all entries in the entire group
185 *
186 * @param pFlags flags passed to KConfig::deleteGroup
187 *
188 * @see deleteEntry()
189 */
190 void deleteGroup(WriteConfigFlags pFlags = Normal);
191 using KConfigBase::deleteGroup;
192
193 /**
194 * Reads the value of an entry specified by @p pKey in the current group
195 *
196 * This template method makes it possible to write
197 * QString foo = readEntry("...", QString("default"));
198 * and the same with all other types supported by QVariant.
199 *
200 * The return type of the method is simply the same as the type of the default value.
201 *
202 * @note readEntry("...", Qt::white) will not compile because Qt::white is an enum.
203 * You must turn it into readEntry("...", QColor(Qt::white)).
204 *
205 * @note Only the following QVariant types are allowed : String,
206 * StringList, List, Font, Point, PointF, Rect, RectF, Size, SizeF, Color, Int, UInt, Bool,
207 * Double, LongLong, ULongLong, DateTime and Date.
208 *
209 * @param key The key to search for
210 * @param aDefault A default value returned if the key was not found
211 * @return The value for this key, or @p aDefault.
212 *
213 * @see writeEntry(), deleteEntry(), hasKey()
214 */
215 template<typename T>
216 T readEntry(const QString &key, const T &aDefault) const
217 {
218 return readEntry(key.toUtf8().constData(), aDefault);
219 }
220 /**
221 * Overload for readEntry<T>(const QString&, const T&) const
222 * @param key name of key, encoded in UTF-8
223 */
224 template<typename T>
225 T readEntry(const char *key, const T &aDefault) const;
226
227 /**
228 * Reads the value of an entry specified by @p key in the current group
229 *
230 * @param key the key to search for
231 * @param aDefault a default value returned if the key was not found
232 * @return the value for this key, or @p aDefault if the key was not found
233 *
234 * @see writeEntry(), deleteEntry(), hasKey()
235 */
236 QVariant readEntry(const QString &key, const QVariant &aDefault) const;
237 /**
238 * Overload for readEntry(const QString&, const QVariant&) const
239 * @param key name of key, encoded in UTF-8
240 */
241 QVariant readEntry(const char *key, const QVariant &aDefault) const;
242
243 /**
244 * Reads the string value of an entry specified by @p key in the current group
245 *
246 * If you want to read a path, please use readPathEntry().
247 *
248 * @param key the key to search for
249 * @param aDefault a default value returned if the key was not found
250 * @return the value for this key, or @p aDefault if the key was not found
251 *
252 * @see readPathEntry(), writeEntry(), deleteEntry(), hasKey()
253 */
254 QString readEntry(const QString &key, const QString &aDefault) const;
255 /**
256 * Overload for readEntry(const QString&, const QString&) const
257 * @param key name of key, encoded in UTF-8
258 */
259 QString readEntry(const char *key, const QString &aDefault) const;
260
261 /** Overload for readEntry(const QString&, const QString&) const */
262 QString readEntry(const QString &key, const char *aDefault = nullptr) const;
263 /**
264 * Overload for readEntry(const QString&, const QString&) const
265 * @param key name of key, encoded in UTF-8
266 */
267 QString readEntry(const char *key, const char *aDefault = nullptr) const;
268
269 /**
270 * @copydoc readEntry(const char*, const QStringList&) const
271 *
272 * @warning This function doesn't convert the items returned
273 * to any type. It's actually a list of QVariant::String's. If you
274 * want the items converted to a specific type use
275 * readEntry(const char*, const QList<T>&) const
276 */
277 QVariantList readEntry(const QString &key, const QVariantList &aDefault) const;
278 /**
279 * Overload for readEntry(const QString&, const QVariantList&) const
280 * @param key name of key, encoded in UTF-8
281 */
282 QVariantList readEntry(const char *key, const QVariantList &aDefault) const;
283
284 /**
285 * Reads a list of strings from the config object
286 *
287 * @param key The key to search for
288 * @param aDefault The default value to use if the key does not exist
289 * @return The list, or @p aDefault if @p key does not exist
290 *
291 * @see readXdgListEntry(), writeEntry(), deleteEntry(), hasKey()
292 */
293 QStringList readEntry(const QString &key, const QStringList &aDefault) const;
294 /**
295 * Overload for readEntry(const QString&, const QStringList&) const
296 * @param key name of key, encoded in UTF-8
297 */
298 QStringList readEntry(const char *key, const QStringList &aDefault) const;
299
300 /**
301 * Reads a list of values from the config object
302 *
303 * @param key the key to search for
304 * @param aDefault the default value to use if the key does not exist
305 * @return the list, or @p aDefault if @p key does not exist
306 *
307 * @see readXdgListEntry(), writeEntry(), deleteEntry(), hasKey()
308 */
309 template<typename T>
310 QList<T> readEntry(const QString &key, const QList<T> &aDefault) const
311 {
312 return readEntry(key.toUtf8().constData(), aDefault);
313 }
314 /**
315 * Overload for readEntry<T>(const QString&, const QList<T>&) const
316 * @param key name of key, encoded in UTF-8
317 */
318 template<typename T>
319 QList<T> readEntry(const char *key, const QList<T> &aDefault) const;
320
321 /**
322 * Reads a list of strings from the config object, following XDG
323 * desktop entry spec separator semantics
324 *
325 * @param pKey the key to search for
326 * @param aDefault the default value to use if the key does not exist
327 * @return the list, or @p aDefault if @p pKey does not exist
328 *
329 * @see readEntry(const QString&, const QStringList&) const
330 */
331 QStringList readXdgListEntry(const QString &pKey, const QStringList &aDefault = QStringList()) const;
332 /**
333 * Overload for readXdgListEntry(const QString&, const QStringList&) const
334 * @param key name of key, encoded in UTF-8
335 */
336 QStringList readXdgListEntry(const char *key, const QStringList &aDefault = QStringList()) const;
337
338 /**
339 * Reads a path
340 *
341 * Read the value of an entry specified by @p pKey in the current group
342 * and interpret it as a path. This means, dollar expansion is activated
343 * for this value, so that e.g. $HOME gets expanded.
344 *
345 * @param pKey The key to search for.
346 * @param aDefault A default value returned if the key was not found.
347 * @return The value for this key. Can be QString() if @p aDefault is null.
348 */
349 QString readPathEntry(const QString &pKey, const QString &aDefault) const;
350 /**
351 * Overload for readPathEntry(const QString&, const QString&) const
352 * @param key name of key, encoded in UTF-8
353 */
354 QString readPathEntry(const char *key, const QString &aDefault) const;
355
356 /**
357 * Reads a list of paths
358 *
359 * Read the value of an entry specified by @p pKey in the current group
360 * and interpret it as a list of paths. This means, dollar expansion is activated
361 * for this value, so that e.g. $HOME gets expanded.
362 *
363 * @param pKey the key to search for
364 * @param aDefault a default value returned if the key was not found
365 * @return the list, or @p aDefault if the key does not exist
366 */
367 QStringList readPathEntry(const QString &pKey, const QStringList &aDefault) const;
368 /**
369 * Overload for readPathEntry(const QString&, const QStringList&) const
370 * @param key name of key, encoded in UTF-8
371 */
372 QStringList readPathEntry(const char *key, const QStringList &aDefault) const;
373
374 /**
375 * Reads an untranslated string entry
376 *
377 * You should not normally need to use this.
378 *
379 * @param pKey the key to search for
380 * @param aDefault a default value returned if the key was not found
381 * @return the value for this key, or @p aDefault if the key does not exist
382 */
383 QString readEntryUntranslated(const QString &pKey, const QString &aDefault = QString()) const;
384 /**
385 * Overload for readEntryUntranslated(const QString&, const QString&) const
386 * @param key name of key, encoded in UTF-8
387 */
388 QString readEntryUntranslated(const char *key, const QString &aDefault = QString()) const;
389
390 /**
391 * Writes a value to the configuration object.
392 *
393 * @param key the key to write to
394 * @param value the value to write
395 * @param pFlags the flags to use when writing this entry
396 *
397 * @see readEntry(), writeXdgListEntry(), deleteEntry()
398 */
399 void writeEntry(const QString &key, const QVariant &value, WriteConfigFlags pFlags = Normal);
400 /**
401 * Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags)
402 * @param key name of key, encoded in UTF-8
403 */
404 void writeEntry(const char *key, const QVariant &value, WriteConfigFlags pFlags = Normal);
405
406 /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
407 void writeEntry(const QString &key, const QString &value, WriteConfigFlags pFlags = Normal);
408 /**
409 * Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags)
410 * @param key name of key, encoded in UTF-8
411 */
412 void writeEntry(const char *key, const QString &value, WriteConfigFlags pFlags = Normal);
413
414 /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
415 void writeEntry(const QString &key, const QByteArray &value, WriteConfigFlags pFlags = Normal);
416 /**
417 * Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags)
418 * @param key name of key, encoded in UTF-8
419 */
420 void writeEntry(const char *key, const QByteArray &value, WriteConfigFlags pFlags = Normal);
421
422 /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
423 void writeEntry(const QString &key, const char *value, WriteConfigFlags pFlags = Normal);
424 /**
425 * Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags)
426 * @param key name of key, encoded in UTF-8
427 */
428 void writeEntry(const char *key, const char *value, WriteConfigFlags pFlags = Normal);
429
430 /**
431 * Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags)
432 * @param key name of key, encoded in UTF-8
433 */
434 template<typename T>
435 void writeEntry(const char *key, const T &value, WriteConfigFlags pFlags = Normal);
436 /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
437 template<typename T>
438 void writeEntry(const QString &key, const T &value, WriteConfigFlags pFlags = Normal)
439 {
440 writeEntry(key.toUtf8().constData(), value, pFlags);
441 }
442
443 /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
444 void writeEntry(const QString &key, const QStringList &value, WriteConfigFlags pFlags = Normal);
445 /**
446 * Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags)
447 * @param key name of key, encoded in UTF-8
448 */
449 void writeEntry(const char *key, const QStringList &value, WriteConfigFlags pFlags = Normal);
450
451 /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
452 void writeEntry(const QString &key, const QVariantList &value, WriteConfigFlags pFlags = Normal);
453 /**
454 * Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags)
455 * @param key name of key, encoded in UTF-8
456 */
457 void writeEntry(const char *key, const QVariantList &value, WriteConfigFlags pFlags = Normal);
458
459 /** Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags) */
460 template<typename T>
461 void writeEntry(const QString &key, const QList<T> &value, WriteConfigFlags pFlags = Normal)
462 {
463 writeEntry(key.toUtf8().constData(), value, pFlags);
464 }
465 /**
466 * Overload for writeEntry(const QString&, const QVariant&, WriteConfigFlags)
467 * @param key name of key, encoded in UTF-8
468 */
469 template<typename T>
470 void writeEntry(const char *key, const QList<T> &value, WriteConfigFlags pFlags = Normal);
471
472 /**
473 * Writes a list of strings to the config object, following XDG
474 * desktop entry spec separator semantics
475 *
476 * @param pKey the key to write to
477 * @param value the list to write
478 * @param pFlags the flags to use when writing this entry
479 *
480 * @see writeEntry(), readXdgListEntry()
481 */
482 void writeXdgListEntry(const QString &pKey, const QStringList &value, WriteConfigFlags pFlags = Normal);
483 /**
484 * Overload for writeXdgListEntry(const QString&, const QStringList&, WriteConfigFlags)
485 * @param key name of key, encoded in UTF-8
486 */
487 void writeXdgListEntry(const char *key, const QStringList &value, WriteConfigFlags pFlags = Normal);
488
489 /**
490 * Writes a file path to the configuration
491 *
492 * If the path is located under $HOME, the user's home directory
493 * is replaced with $HOME in the persistent storage.
494 * The path should therefore be read back with readPathEntry()
495 *
496 * @param pKey the key to write to
497 * @param path the path to write
498 * @param pFlags the flags to use when writing this entry
499 *
500 * @see writeEntry(), readPathEntry()
501 */
502 void writePathEntry(const QString &pKey, const QString &path, WriteConfigFlags pFlags = Normal);
503 /**
504 * Overload for writePathEntry(const QString&, const QString&, WriteConfigFlags)
505 * @param key name of key, encoded in UTF-8
506 */
507 void writePathEntry(const char *Key, const QString &path, WriteConfigFlags pFlags = Normal);
508
509 /**
510 * Writes a list of paths to the configuration
511 *
512 * If any of the paths are located under $HOME, the user's home directory
513 * is replaced with $HOME in the persistent storage.
514 * The paths should therefore be read back with readPathEntry()
515 *
516 * @param pKey the key to write to
517 * @param value the list to write
518 * @param pFlags the flags to use when writing this entry
519 *
520 * @see writeEntry(), readPathEntry()
521 */
522 void writePathEntry(const QString &pKey, const QStringList &value, WriteConfigFlags pFlags = Normal);
523 /**
524 * Overload for writePathEntry(const QString&, const QStringList&, WriteConfigFlags)
525 * @param key name of key, encoded in UTF-8
526 */
527 void writePathEntry(const char *key, const QStringList &value, WriteConfigFlags pFlags = Normal);
528
529 /**
530 * Deletes the entry specified by @p pKey in the current group
531 *
532 * This also hides system wide defaults.
533 *
534 * @param pKey the key to delete
535 * @param pFlags the flags to use when deleting this entry
536 *
537 * @see deleteGroup(), readEntry(), writeEntry()
538 */
539 void deleteEntry(const QString &pKey, WriteConfigFlags pFlags = Normal);
540 /**
541 * Overload for deleteEntry(const QString&, WriteConfigFlags)
542 * @param key name of key, encoded in UTF-8
543 */
544 void deleteEntry(const char *key, WriteConfigFlags pFlags = Normal);
545
546 /**
547 * Checks whether the key has an entry in this group
548 *
549 * Use this to determine if a key is not specified for the current
550 * group (hasKey() returns false).
551 *
552 * If this returns @c false for a key, readEntry() (and its variants)
553 * will return the default value passed to them.
554 *
555 * @param key the key to search for
556 * @return @c true if the key is defined in this group by any of the
557 * configuration sources, @c false otherwise
558 *
559 * @see readEntry()
560 */
561 bool hasKey(const QString &key) const;
562 /**
563 * Overload for hasKey(const QString&) const
564 * @param key name of key, encoded in UTF-8
565 */
566 bool hasKey(const char *key) const;
567
568 /**
569 * Whether this group may be changed
570 *
571 * @return @c false if the group may be changed, @c true otherwise
572 */
573 bool isImmutable() const override;
574
575 /**
576 * Checks if it is possible to change the given entry
577 *
578 * If isImmutable() returns @c true, then this method will return
579 * @c true for all inputs.
580 *
581 * @param key the key to check
582 * @return @c false if the key may be changed using this configuration
583 * group object, @c true otherwise
584 */
585 bool isEntryImmutable(const QString &key) const;
586 /**
587 * Overload for isEntryImmutable(const QString&) const
588 * @param key name of key, encoded in UTF-8
589 */
590 bool isEntryImmutable(const char *key) const;
591
592 /**
593 * Reverts an entry to the default settings.
594 *
595 * Reverts the entry with key @p key in the current group in the
596 * application specific config file to either the system wide (default)
597 * value or the value specified in the global KDE config file.
598 *
599 * To revert entries in the global KDE config file, the global KDE config
600 * file should be opened explicitly in a separate config object.
601 *
602 * @note This is @em not the same as deleting the key, as instead the
603 * global setting will be copied to the configuration file that this
604 * object manipulates.
605 *
606 * @param key The key of the entry to revert.
607 */
608 void revertToDefault(const QString &key, WriteConfigFlags pFlag = WriteConfigFlags());
609
610 /**
611 * Overload for revertToDefault(const QString&, WriteConfigFlags)
612 * @param key name of key, encoded in UTF-8
613 */
614 void revertToDefault(const char *key, WriteConfigFlags pFlag = WriteConfigFlags());
615
616 /**
617 * Whether a default is specified for an entry in either the
618 * system wide configuration file or the global KDE config file
619 *
620 * If an application computes a default value at runtime for
621 * a certain entry, e.g. like:
622 * \code
623 * QColor computedDefault = qApp->palette().color(QPalette::Active, QPalette::Text);
624 * QColor color = group.readEntry(key, computedDefault);
625 * \endcode
626 * then it may wish to make the following check before
627 * writing back changes:
628 * \code
629 * if ( (value == computedDefault) && !group.hasDefault(key) )
630 * group.revertToDefault(key);
631 * else
632 * group.writeEntry(key, value);
633 * \endcode
634 *
635 * This ensures that as long as the entry is not modified to differ from
636 * the computed default, the application will keep using the computed default
637 * and will follow changes the computed default makes over time.
638 *
639 * @param key the key of the entry to check
640 * @return @c true if the global or system settings files specify a default
641 * for @p key in this group, @c false otherwise
642 */
643 bool hasDefault(const QString &key) const;
644 /**
645 * Overload for hasDefault(const QString&) const
646 * @param key name of key, encoded in UTF-8
647 */
648 bool hasDefault(const char *key) const;
649
650 /**
651 * Returns a map (tree) of entries for all entries in this group
652 *
653 * Only the actual entry string is returned, none of the
654 * other internal data should be included.
655 *
656 * @return a map of entries in this group, indexed by key
657 */
658 QMap<QString, QString> entryMap() const;
659
660protected:
661 bool hasGroupImpl(const QString &groupName) const override;
662 KConfigGroup groupImpl(const QString &groupName) override;
663 const KConfigGroup groupImpl(const QString &groupName) const override;
664 void deleteGroupImpl(const QString &groupName, WriteConfigFlags flags) override;
665 bool isGroupImmutableImpl(const QString &groupName) const override;
666
667private:
668 QExplicitlySharedDataPointer<KConfigGroupPrivate> d;
669
670 friend class KConfigGroupPrivate;
671
672 /**
673 * Return the data in @p value converted to a QVariant
674 *
675 * @param pKey the name of the entry being converted, this is only used for error
676 * reporting
677 * @param value the UTF-8 data to be converted
678 * @param aDefault the default value if @p pKey is not found
679 * @return @p value converted to QVariant, or @p aDefault if @p value is invalid or cannot be converted.
680 */
681 static QVariant convertToQVariant(const char *pKey, const QByteArray &value, const QVariant &aDefault);
682 // exported for usage by KServices' KService & KServiceAction
683 friend class KServicePrivate; // XXX yeah, ugly^5
684 friend class KServiceAction;
685};
686
687Q_DECLARE_TYPEINFO(KConfigGroup, Q_RELOCATABLE_TYPE);
688
689#define KCONFIGGROUP_ENUMERATOR_ERROR(ENUM) "The Qt MetaObject system does not seem to know about \"" ENUM "\" please use Q_ENUM or Q_FLAG to register it."
690
691/**
692 * To add support for your own enums in KConfig, you can declare them with Q_ENUM()
693 * in a QObject subclass (which will make moc generate the code to turn the
694 * enum into a string and vice-versa), and then (in the cpp code)
695 * use the macro
696 * <code>KCONFIGGROUP_DECLARE_ENUM_QOBJECT(MyClass, MyEnum)</code>
697 *
698 */
699#define KCONFIGGROUP_DECLARE_ENUM_QOBJECT(Class, Enum) \
700 template<> \
701 Class::Enum KConfigGroup::readEntry(const char *key, const Class::Enum &def) const \
702 { \
703 const QMetaObject *M_obj = &Class::staticMetaObject; \
704 const int M_index = M_obj->indexOfEnumerator(#Enum); \
705 if (M_index == -1) \
706 qFatal(KCONFIGGROUP_ENUMERATOR_ERROR(#Enum)); \
707 const QMetaEnum M_enum = M_obj->enumerator(M_index); \
708 const QByteArray M_data = readEntry(key, QByteArray(M_enum.valueToKey(def))); \
709 return static_cast<Class::Enum>(M_enum.keyToValue(M_data.constData())); \
710 } \
711 template<> \
712 void KConfigGroup::writeEntry(const char *key, const Class::Enum &value, KConfigBase::WriteConfigFlags flags) \
713 { \
714 const QMetaObject *M_obj = &Class::staticMetaObject; \
715 const int M_index = M_obj->indexOfEnumerator(#Enum); \
716 if (M_index == -1) \
717 qFatal(KCONFIGGROUP_ENUMERATOR_ERROR(#Enum)); \
718 const QMetaEnum M_enum = M_obj->enumerator(M_index); \
719 writeEntry(key, QByteArray(M_enum.valueToKey(value)), flags); \
720 }
721
722/**
723 * Similar to KCONFIGGROUP_DECLARE_ENUM_QOBJECT but for flags declared with Q_FLAG()
724 * (where multiple values can be set at the same time)
725 */
726#define KCONFIGGROUP_DECLARE_FLAGS_QOBJECT(Class, Flags) \
727 template<> \
728 Class::Flags KConfigGroup::readEntry(const char *key, const Class::Flags &def) const \
729 { \
730 const QMetaObject *M_obj = &Class::staticMetaObject; \
731 const int M_index = M_obj->indexOfEnumerator(#Flags); \
732 if (M_index == -1) \
733 qFatal(KCONFIGGROUP_ENUMERATOR_ERROR(#Flags)); \
734 const QMetaEnum M_enum = M_obj->enumerator(M_index); \
735 const QByteArray M_data = readEntry(key, QByteArray(M_enum.valueToKeys(def))); \
736 return static_cast<Class::Flags>(M_enum.keysToValue(M_data.constData())); \
737 } \
738 template<> \
739 void KConfigGroup::writeEntry(const char *key, const Class::Flags &value, KConfigBase::WriteConfigFlags flags) \
740 { \
741 const QMetaObject *M_obj = &Class::staticMetaObject; \
742 const int M_index = M_obj->indexOfEnumerator(#Flags); \
743 if (M_index == -1) \
744 qFatal(KCONFIGGROUP_ENUMERATOR_ERROR(#Flags)); \
745 const QMetaEnum M_enum = M_obj->enumerator(M_index); \
746 writeEntry(key, QByteArray(M_enum.valueToKeys(value)), flags); \
747 }
748
749#include "kconfigconversioncheck_p.h"
750
751template<typename T>
752T KConfigGroup::readEntry(const char *key, const T &defaultValue) const
753{
754 KConfigConversionCheck::to_QVariant<T>();
755 return qvariant_cast<T>(readEntry(key, QVariant::fromValue(defaultValue)));
756}
757
758template<typename T>
759QList<T> KConfigGroup::readEntry(const char *key, const QList<T> &defaultValue) const
760{
761 KConfigConversionCheck::to_QVariant<T>();
762 KConfigConversionCheck::to_QString<T>();
763
764 QVariantList data;
765
766 for (const T &value : defaultValue) {
767 data.append(QVariant::fromValue(value));
768 }
769
770 QList<T> list;
771 const auto variantList = readEntry<QVariantList>(key, defaultValue: data);
772 for (const QVariant &value : variantList) {
773 Q_ASSERT(value.canConvert<T>());
774 list.append(qvariant_cast<T>(value));
775 }
776
777 return list;
778}
779
780template<typename T>
781void KConfigGroup::writeEntry(const char *key, const T &value, WriteConfigFlags pFlags)
782{
783 KConfigConversionCheck::to_QVariant<T>();
784 writeEntry(key, QVariant::fromValue(value), pFlags);
785}
786
787template<typename T>
788void KConfigGroup::writeEntry(const char *key, const QList<T> &list, WriteConfigFlags pFlags)
789{
790 KConfigConversionCheck::to_QVariant<T>();
791 KConfigConversionCheck::to_QString<T>();
792 QVariantList data;
793 for (const T &value : list) {
794 data.append(QVariant::fromValue(value));
795 }
796
797 writeEntry(key, value: data, pFlags);
798}
799
800#endif // KCONFIGGROUP_H
801

source code of kconfig/src/core/kconfiggroup.h