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