/*
    SPDX-FileCopyrightText: 2007 Aaron Seigo <aseigo@kde.org>

    SPDX-License-Identifier: LGPL-2.0-or-later
*/

#ifndef KCONFIGLOADER_H
#define KCONFIGLOADER_H

#include <QIODevice>

#include <kconfiggroup.h>
#include <kconfigskeleton.h>
#include <ksharedconfig.h>

#include <kconfiggui_export.h>

class ConfigLoaderPrivate;

/*!
 * \class KConfigLoader
 * \inmodule KConfigGui
 *
 * \brief A KConfigSkeleton that populates itself based on KConfigXT XML.
 *
 * This class allows one to ship an XML file and reconstitute it into a
 * KConfigSkeleton object at runtime. Common usage might look like this:
 *
 * \code
 * QFile file(xmlFilePath);
 * KConfigLoader appletConfig(configFilePath, &file);
 * \endcode
 *
 * Alternatively, any QIODevice may be used in place of QFile in the
 * example above.
 *
 * KConfigLoader is useful if it is not possible to use compiled code
 * and by that the kconfig compiler cannot be used. Common examples are
 * scripted plugins which want to provide a configuration interface.
 * With the help of KConfigLoader a dynamically loaded ui file can be
 * populated with the stored values and also stored back to the config
 * file.
 *
 * An example for populating a QDialog with a dynamically populated UI
 * with the help of a KConfigDialogManager:
 * \code
 * QDialog *dialog = new QDialog();
 * QFile xmlFile("path/to/kconfigxt.xml");
 * KConfigGroup cg = KSharedConfig::openConfig()->group(QString());
 * KConfigLoader *configLoader = new KConfigLoader(cg, &xmlFile, this);
 *
 * // load the ui file
 * QUiLoader *loader = new QUiLoader(this);
 * QFile uiFile("path/to/userinterface.ui");
 * uiFile.open(QFile::ReadOnly);
 * QWidget *customConfigForm = loader->load(&uiFile, dialog);
 * uiFile.close();
 *
 * KConfigDialogManager *manager = new KConfigDialogManager(customConfigForm, configLoader);
 * if (dialog->exec() == QDialog::Accepted) {
 *     manager->updateSettings();
 * }
 * \endcode
 *
 * Currently the following data types are supported:
 * \list
 * \li bools
 * \li colors
 * \li datetimes
 * \li times
 * \li enumerations
 * \li fonts
 * \li ints
 * \li passwords
 * \li paths
 * \li strings
 * \li stringlists
 * \li uints
 * \li urls
 * \li doubles
 * \li int lists
 * \li longlongs
 * \li path lists
 * \li points
 * \li pointfs
 * \li rects
 * \li rectfs
 * \li sizes
 * \li sizefs
 * \li ulonglongs
 * \li url lists
 * \endlist
 *
 * \sa {https://doc.qt.io/qt-6/quiloader.html}{QUiLoader}, {https://develop.kde.org/docs/features/configuration/kconfig_xt/}{Using KConfigXT}, {https://doc.qt.io/qt-6/designer-using-a-ui-file.html}{Using a Designer UI File in Your C++ Application}
 **/
class KCONFIGGUI_EXPORT KConfigLoader : public KConfigSkeleton
{
public:
    /*!
     * Creates a KConfigSkeleton populated using the definition found in
     * the desired KConfigXT \a xml data, as a child of \a parent.
     *
     * This will in turn be stored in \a configFile.
     **/
    KConfigLoader(const QString &configFile, QIODevice *xml, QObject *parent = nullptr);

    /*!
     * Creates a KConfigSkeleton populated using the definition found in
     * the desired KConfigXT \a xml data, as a child of \a parent.
     *
     * This will in turn be stored in \a config object.
     **/
    KConfigLoader(KSharedConfigPtr config, QIODevice *xml, QObject *parent = nullptr);

    /*!
     * Creates a KConfigSkeleton populated using the definition found in
     * the desired KConfigXT \a xml data, as a child of \a parent.
     *
     * This will in turn be stored in the \a config group to be used as the root for configuration items.
     **/
    KConfigLoader(const KConfigGroup &config, QIODevice *xml, QObject *parent = nullptr);

    ~KConfigLoader() override;

    /*!
     * Finds the item for the given \a group and \a key in the config file.
     *
     * Returns the associated KConfigSkeletonItem, or \c nullptr if none.
     */
    KConfigSkeletonItem *findItem(const QString &group, const QString &key) const;

    /*!
     * Finds an item by its \a name.
     */
    KConfigSkeletonItem *findItemByName(const QString &name) const;

    /*!
     * Returns the property of the item with the given \a name as a variant.
     */
    QVariant property(const QString &name) const;

    /*!
     * Returns whether a \a group exists.
     */
    bool hasGroup(const QString &group) const;

    /*!
     * Returns the list of groups defined by the KConfigXT schema.
     */
    QStringList groupList() const;

protected:
    bool usrSave() override;

private:
    ConfigLoaderPrivate *const d;
};

#endif // multiple inclusion guard
