1 /*
2     This file is part of the KDE libraries
3     SPDX-FileCopyrightText: 2003 Benjamin C Meyer <ben+kdelibs at meyerhome dot net>
4     SPDX-FileCopyrightText: 2003 Waldo Bastian <bastian@kde.org>
5 
6     SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #ifndef KCONFIGDIALOG_H
10 #define KCONFIGDIALOG_H
11 
12 #include <KPageDialog>
13 #include <memory>
14 
15 #include "kconfigwidgets_export.h"
16 
17 class KConfig;
18 class KCoreConfigSkeleton;
19 class KConfigDialogManager;
20 
21 /**
22  * @class KConfigDialog kconfigdialog.h KConfigDialog
23  *
24  * \short Standard %KDE configuration dialog class
25  *
26  * The KConfigDialog class provides an easy and uniform means of displaying
27  * a settings dialog using KPageDialog, KConfigDialogManager and a
28  * KConfigSkeleton derived settings class.
29  *
30  * KConfigDialog handles the enabling and disabling of buttons, creation
31  * of the dialog, and deletion of the widgets.  Because of
32  * KConfigDialogManager, this class also manages: restoring
33  * the settings, resetting them to the default values, and saving them. This
34  * requires that the names of the widgets corresponding to configuration entries
35  * have to have the same name plus an additional "kcfg_" prefix. For example the
36  * widget named "kcfg_MyOption" would be associated with the configuration entry
37  * "MyOption".
38  *
39  * Here is an example usage of KConfigDialog:
40  *
41  * @code
42  * void KCoolApp::showSettings(){
43  *     if (KConfigDialog::showDialog(QStringLiteral("settings"))) {
44  *       return;
45  *     }
46  *     KConfigDialog *dialog = new KConfigDialog(this, QStringLiteral("settings"), MySettings::self());
47  *     dialog->setFaceType(KPageDialog::List);
48  *     dialog->addPage(new General(0, "General"), i18n("General"));
49  *     dialog->addPage(new Appearance(0, "Style"), i18n("Appearance"));
50  *     connect(dialog, &KConfigDialog::settingsChanged, mainWidget, &Bar::loadSettings);
51  *     connect(dialog, &KConfigDialog::settingsChanged, this, &Foo::loadSettings);
52  *     dialog->show();
53  * }
54  * @endcode
55  *
56  * Other than the above code, each class that has settings in the dialog should
57  * have a loadSettings() type slot to read settings and perform any
58  * necessary changes.
59  *
60  * For dialog appearance options (like buttons, default button, ...) please see
61  * @ref KPageDialog.
62  *
63  * @see KConfigSkeleton
64  * @author Waldo Bastian <bastian@kde.org>
65  */
66 class KCONFIGWIDGETS_EXPORT KConfigDialog : public KPageDialog
67 {
68     Q_OBJECT
69 
70 Q_SIGNALS:
71     /**
72      * A widget in the dialog was modified.
73      */
74     void widgetModified();
75 
76     /**
77      * One or more of the settings have been permanently changed such as if
78      * the user clicked on the Apply or Ok button.
79      * @param dialogName the name of the dialog.
80      */
81     void settingsChanged(const QString &dialogName);
82 
83 public:
84     /**
85      * @param parent - The parent of this object.  Even though the class
86      * deletes itself the parent should be set so the dialog can be centered
87      * with the application on the screen.
88      *
89      * @param name - The name of this object.  The name is used in determining if
90      * there can be more than one dialog at a time.  Use names such as:
91      * "Font Settings" or "Color Settings" and not just "Settings" in
92      * applications where there is more than one dialog.
93      *
94      * @param config - Config object containing settings.
95      */
96     KConfigDialog(QWidget *parent, const QString &name, KCoreConfigSkeleton *config);
97 
98     /**
99      * Deconstructor, removes name from the list of open dialogs.
100      * Deletes private class.
101      * @see exists()
102      */
103     ~KConfigDialog() override;
104 
105     /**
106      * Adds page to the dialog and to KConfigDialogManager.  When an
107      * application is done adding pages show() should be called to
108      * display the dialog.
109      * @param page - Pointer to the page that is to be added to the dialog.
110      * This object is reparented.
111      * @param itemName - Name of the page.
112      * @param pixmapName - Name of the icon that should be used, if needed, when
113      *        displaying the page. The string may either be the name of a themed
114      *        icon (e.g. "document-save"), which the internal icon loader will be
115      *        used to retrieve, or an absolute path to the pixmap on disk.
116      * @param header - Header text use in the list modes. Ignored in Tabbed
117      *        mode. If empty, the itemName text is used when needed.
118      * @param manage - Whether KConfigDialogManager should manage the page or not.
119      * @returns The KPageWidgetItem associated with the page.
120      */
121     KPageWidgetItem *
122     addPage(QWidget *page, const QString &itemName, const QString &pixmapName = QString(), const QString &header = QString(), bool manage = true);
123 
124     /**
125      * Adds page to the dialog that is managed by a custom KConfigDialogManager.
126      * This is useful for dialogs that contain settings spread over more than
127      * one configuration file and thus have/need more than one KConfigSkeleton.
128      * When an application is done adding pages show() should be called to
129      * display the dialog.
130      * @param page - Pointer to the page that is to be added to the dialog.
131      * This object is reparented.
132      * @param config - Config object containing corresponding settings.
133      * @param itemName - Name of the page.
134      * @param pixmapName - Name of the icon that should be used, if needed, when
135      *        displaying the page. The string may either be the name of a themed
136      *        icon (e.g. "document-save"), which the internal icon loader will be
137      *        used to retrieve, or an absolute path to the pixmap on disk.
138      * @param header - Header text use in the list modes. Ignored in Tabbed
139      *        mode. If empty, the itemName text is used when needed.
140      * @returns The KPageWidgetItem associated with the page.
141      */
142     KPageWidgetItem *
143     addPage(QWidget *page, KCoreConfigSkeleton *config, const QString &itemName, const QString &pixmapName = QString(), const QString &header = QString());
144 
145     /**
146      * See if a dialog with the name 'name' already exists.
147      * @see showDialog()
148      * @param name - Dialog name to look for.
149      * @return Pointer to widget or NULL if it does not exist.
150      */
151     static KConfigDialog *exists(const QString &name);
152 
153     /**
154      * Attempts to show the dialog with the name 'name'.
155      * @see exists()
156      * @param name - The name of the dialog to show.
157      * @return True if the dialog 'name' exists and was shown.
158      */
159     static bool showDialog(const QString &name);
160 
161 protected Q_SLOTS:
162     /**
163      * Update the settings from the dialog.
164      * Virtual function for custom additions.
165      *
166      * Example use: User clicks Ok or Apply button in a configure dialog.
167      */
168     virtual void updateSettings();
169 
170     /**
171      * Update the dialog based on the settings.
172      * Virtual function for custom additions.
173      *
174      * Example use: Initialisation of dialog.
175      * Example use: User clicks Reset button in a configure dialog.
176      */
177     virtual void updateWidgets();
178 
179     /**
180      * Update the dialog based on the default settings.
181      * Virtual function for custom additions.
182      *
183      * Example use: User clicks Defaults button in a configure dialog.
184      */
185     virtual void updateWidgetsDefault();
186 
187     /**
188      * Updates the Apply and Default buttons.
189      * Connect to this slot if you implement your own hasChanged()
190      * or isDefault() methods for widgets not managed by KConfig.
191      * @since 4.3
192      */
193     void updateButtons();
194 
195     /**
196      * Some setting was changed. Emit the signal with the dialogs name.
197      * Connect to this slot if there are widgets not managed by KConfig.
198      * @since 4.3
199      */
200     void settingsChangedSlot();
201 
202     /**
203      * Sets the help path and topic.
204      *
205      * The HTML file will be found using the X-DocPath entry in the application's desktop file.
206      * It can be either a relative path, or a website URL.
207      *
208      * @param anchor      This has to be a defined anchor in your
209      *                    docbook sources or website. If empty the main index
210      *                    is loaded.
211      * @param appname     This allows you to specify the .desktop file to get the help path from.
212      *                    If empty the QCoreApplication::applicationName() is used.
213      */
214     void setHelp(const QString &anchor, const QString &appname = QString());
215 
216     /**
217      * Displays help for this config dialog.
218      * @since 5.0
219      */
220     virtual void showHelp();
221 
222 protected:
223     /**
224      * Returns whether the current state of the dialog is
225      * different from the current configuration.
226      * Virtual function for custom additions.
227      */
228     virtual bool hasChanged();
229 
230     /**
231      * Returns whether the current state of the dialog is
232      * the same as the default configuration.
233      */
234     virtual bool isDefault();
235 
236     /**
237      * @internal
238      */
239     void showEvent(QShowEvent *e) override;
240 
241 private Q_SLOTS:
242     /**
243      * Slot which cleans up the KConfigDialogManager of the page.
244      * */
245     void onPageRemoved(KPageWidgetItem *item);
246 
247 private:
248     friend class KConfigDialogPrivate;
249     std::unique_ptr<class KConfigDialogPrivate> const d;
250 
251     Q_DISABLE_COPY(KConfigDialog)
252 };
253 
254 #endif // KCONFIGDIALOG_H
255