1 /*
2     This file is part of the KDE libraries
3     SPDX-FileCopyrightText: 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
4 
5     SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #ifndef KCMODULE_H
9 #define KCMODULE_H
10 
11 #include <kconfigwidgets_export.h>
12 
13 #ifndef KCONFIGWIDGETS_NO_KAUTH
14 #include <KAuthAction>
15 #endif
16 
17 #include <QVariant>
18 #include <QWidget>
19 #include <memory>
20 
21 class KAboutData;
22 class KConfigDialogManager;
23 class KCoreConfigSkeleton;
24 class KConfigSkeleton;
25 class KCModulePrivate;
26 
27 /**
28  * @class KCModule kcmodule.h KCModule
29  *
30  * The base class for configuration modules.
31  *
32  * Configuration modules are realized as plugins that are loaded only when
33  * needed.
34  *
35  * The module in principle is a simple widget displaying the
36  * item to be changed. The module has a very small interface.
37  *
38  * All the necessary glue logic and the GUI bells and whistles
39  * are provided by the control center and must not concern
40  * the module author.
41  *
42  * To write a config module, you have to create a library
43  * that contains a factory function like the following:
44  *
45  * \code
46  * #include <KPluginFactory>
47  *
48  * K_PLUGIN_FACTORY(MyKCModuleFactory, registerPlugin<MyKCModule>() )
49  * \endcode
50  *
51  * The constructor of the KCModule then looks like this:
52  * \code
53  * YourKCModule::YourKCModule( QWidget* parent )
54  *   : KCModule( parent )
55  * {
56  *   KAboutData *about = new KAboutData(
57  *     <kcm name>, i18n( "..." ),
58  *     KDE_VERSION_STRING, QString(), KAboutLicense::GPL,
59  *     i18n( "Copyright 2006 ..." ) );
60  *   about->addAuthor( i18n(...) );
61  *   setAboutData( about );
62  *   .
63  *   .
64  *   .
65  * }
66  * \endcode
67  *
68  * If you want to make the KCModule available only conditionally (i.e. show in
69  * the list of available modules only if some test succeeds) then you can use
70  * Hidden in the .desktop file. An example:
71  * \code
72  * Hidden[$e]=$(if test -e /dev/js*; then echo "false"; else echo "true"; fi)
73  * \endcode
74  * The example executes the given code in a shell and uses the stdout output for
75  * the Hidden value (so it's either Hidden=true or Hidden=false).
76  *
77  * See http://techbase.kde.org/Development/Tutorials/KCM_HowTo
78  * for more detailed documentation.
79  *
80  * @author Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
81  */
82 class KCONFIGWIDGETS_EXPORT KCModule : public QWidget
83 {
84     Q_OBJECT
85 
86 public:
87     /**
88      * An enumeration type for the buttons used by this module.
89      * You should only use Help, Default and Apply. The rest is obsolete.
90      * NoAdditionalButton can be used when we do not want have other button that Ok Cancel
91      *
92      * @see KCModule::buttons
93      * @see KCModule::setButtons
94      * @see Buttons
95      */
96     enum Button { NoAdditionalButton = 0, Help = 1, Default = 2, Apply = 4, Export = 8 };
97     /**
98      * Stores a combination of #Button values.
99      */
100     Q_DECLARE_FLAGS(Buttons, Button)
101 
102 #if KCONFIGWIDGETS_ENABLE_DEPRECATED_SINCE(5, 85)
103     /**
104      * Base class for all KControlModules.
105      *
106      * @note do not emit changed signals here, since they are not yet connected
107      *       to any slot.
108      * @param aboutData becomes owned by the KCModule
109      * @deprecated since 5.85, use other constructor and setAboutData()
110      */
111     KCONFIGWIDGETS_DEPRECATED_VERSION(5, 85, "Use other constructor and setAboutData()")
112     explicit KCModule(const KAboutData *aboutData, QWidget *parent = nullptr, const QVariantList &args = QVariantList());
113 #endif
114 
115     /**
116      * Base class for all KControlModules.
117      *
118      * @note do not emit changed signals here, since they are not yet connected
119      *       to any slot.
120      */
121     explicit KCModule(QWidget *parent = nullptr, const QVariantList &args = QVariantList());
122 
123     /**
124      * Destroys the module.
125      */
126     ~KCModule() override;
127 
128     /**
129      * Return a quick-help text.
130      *
131      * This method may be called when the module is docked. The quick help would generally
132      * be used as "what's this" text if the view container supports the "what's this"
133      * system.
134      * The quick-help text should contain a short description of the module and
135      * links to the module's help files. You can use QML formatting tags in the text.
136      *
137      * @note make sure the quick help text gets translated (use i18n()).
138      */
139     virtual QString quickHelp() const;
140 
141     /**
142      * This is generally only called for the KBugReport.
143      * If you override you should  have it return a pointer to a constant.
144      *
145      *
146      * @returns the KAboutData for this module
147      */
148     virtual const KAboutData *aboutData() const;
149 
150     /**
151      * This sets the KAboutData returned by aboutData()
152      * The about data is now owned by KCModule.
153      */
154     void setAboutData(const KAboutData *about);
155 
156     /**
157      * Indicate which buttons will be used.
158      *
159      * The return value is a value or'ed together from
160      * the Button enumeration type.
161      *
162      * @see KCModule::setButtons
163      */
164     Buttons buttons() const;
165 
166     /**
167      * Get the RootOnly message for this module.
168      *
169      * When the module must be run as root, or acts differently
170      * for root and a normal user, it is sometimes useful to
171      * customize the message that appears at the top of the module
172      * when used as a normal user. This function returns this
173      * customized message. If none has been set, a default message
174      * will be used.
175      *
176      * @see KCModule::setRootOnlyMessage
177      */
178     QString rootOnlyMessage() const;
179 
180     /**
181      * Tell if KControl should show a RootOnly message when run as
182      * a normal user.
183      *
184      * In some cases, the module don't want a RootOnly message to
185      * appear (for example if it has already one). This function
186      * tells KControl if a RootOnly message should be shown
187      *
188      * @see KCModule::setUseRootOnlyMessage
189      */
190     bool useRootOnlyMessage() const;
191 
192     KAboutData componentData() const;
193 
194     /**
195      * @return a list of @ref KConfigDialogManager's in use, if any.
196      */
197     QList<KConfigDialogManager *> configs() const;
198 
199     /**
200      * @brief Set if the module's save() method requires authorization to be executed.
201      *
202      * The module can set this property to @c true if it requires authorization.
203      * It will still have to execute the action itself using the KAuth library, so
204      * this method is not technically needed to perform the action, but
205      * using this and/or the setAuthAction() method will ensure that hosting
206      * applications like System Settings or kcmshell behave correctly.
207      *
208      * Called with @c true, this method will set the action to  "org.kde.kcontrol.name.save" where
209      * "name" is aboutData()->appName() return value. This default action won't be set if
210      * the aboutData() object is not valid.
211      *
212      * Note that called with @c false, this method will reset the action name set with setAuthAction().
213      *
214      * @param needsAuth Tells if the module's save() method requires authorization to be executed.
215      */
216     void setNeedsAuthorization(bool needsAuth);
217 
218     /**
219      * Returns the value previously set with setNeedsAuthorization() or setAuthAction(). By default it's @c false.
220      *
221      * @return @c true if the module's save() method requires authorization, @c false otherwise
222      */
223     bool needsAuthorization() const;
224 
225     /**
226      * Returns whether an indicator is shown when a setting differs from default.
227      *
228      * @since 5.73
229      */
230     bool defaultsIndicatorsVisible() const;
231 
232 #ifndef KCONFIGWIDGETS_NO_KAUTH
233     /**
234      * @brief Set if the module's save() method requires authorization to be executed
235      *
236      * It will still have to execute the action itself using the KAuth library, so
237      * this method is not technically needed to perform the action, but
238      * using this method will ensure that hosting
239      * applications like System Settings or kcmshell behave correctly.
240      *
241      * @param action the action that will be used by this KCModule
242      */
243     void setAuthAction(const KAuth::Action &action);
244 
245     /**
246      * Returns the action previously set with setAuthAction(). By default its an invalid action.
247      *
248      * @return The action that has to be authorized to execute the save() method.
249      */
250     KAuth::Action authAction() const;
251 #endif
252 
253 #if KCONFIGWIDGETS_ENABLE_DEPRECATED_SINCE(5, 0)
254     /**
255      * Returns the value set by setExportText();
256      * @deprecated since 5.0, obsolete feature
257      */
258     KCONFIGWIDGETS_DEPRECATED_VERSION(5, 0, "Obsolete feature")
259     QString exportText() const;
260 #endif
261 
262 #if KCONFIGWIDGETS_ENABLE_DEPRECATED_SINCE(5, 0)
263     /**
264      * Sets the export QString value, used for exporting data.
265      * @deprecated since 5.0, obsolete feature
266      */
267     KCONFIGWIDGETS_DEPRECATED_VERSION(5, 0, "Obsolete feature")
268     void setExportText(const QString &);
269 #endif
270 
271 public Q_SLOTS:
272     /**
273      * Load the configuration data into the module.
274      *
275      * The load method sets the user interface elements of the
276      * module to reflect the current settings stored in the
277      * configuration files.
278      *
279      * This method is invoked whenever the module should read its configuration
280      * (most of the times from a config file) and update the user interface.
281      * This happens when the user clicks the "Reset" button in the control
282      * center, to undo all of his changes and restore the currently valid
283      * settings. It is also called right after construction.
284      */
285     virtual void load();
286 
287     /**
288      * Save the configuration data.
289      *
290      * The save method stores the config information as shown
291      * in the user interface in the config files.
292      *
293      * If necessary, this method also updates the running system,
294      * e.g. by restarting applications. This normally does not apply for
295      * KSettings::Dialog modules where the updating is taken care of by
296      * KSettings::Dispatcher.
297      *
298      * save is called when the user clicks "Apply" or "Ok".
299      *
300      * If you use KConfigXT, saving is taken care off automatically and
301      * you do not need to load manually. However, if you for some reason reimplement it and
302      * also are using KConfigXT, you must call this function, otherwise the saving of KConfigXT
303      * options will not work. Call it at the very end of your reimplementation, to avoid
304      * changed() signals getting emitted when you modify widgets.
305      */
306     virtual void save();
307 
308     /**
309      * Sets the configuration to sensible default values.
310      *
311      * This method is called when the user clicks the "Default"
312      * button. It should set the display to useful values.
313      *
314      * If you use KConfigXT, you do not have to reimplement this function since
315      * the fetching and settings of default values is done automatically. However, if you
316      * reimplement and also are using KConfigXT, remember to call the base function at the
317      * very end of your reimplementation.
318      */
319     virtual void defaults();
320 
321     /**
322      * Show an indicator when settings value differ from default
323      *
324      * @since 5.73
325      */
326     void setDefaultsIndicatorsVisible(bool show);
327 
328 protected:
329     /**
330      * Adds a KCoreConfigskeleton @p config to watch the widget @p widget
331      *
332      * This function is useful if you need to handle multiple configuration files.
333      *
334      * @return a pointer to the KCoreConfigDialogManager in use
335      * @param config the KCoreConfigSkeleton to use
336      * @param widget the widget to watch
337      */
338     KConfigDialogManager *addConfig(KCoreConfigSkeleton *config, QWidget *widget);
339 
340 #if KCONFIGWIDGETS_ENABLE_DEPRECATED_SINCE(5, 84)
341     // No deprecation warning by compiler here, as the replacement will be
342     // automatically picked by the compiler in the future, being the method
343     // overload using the base-class of the argument type.
344     // Avoids the need to do extra-casting right now on the caller side.
345     /**
346      * Adds a KConfigskeleton @p config to watch the widget @p widget
347      *
348      * This function is useful if you need to handle multiple configuration files.
349      *
350      * @return a pointer to the KConfigDialogManager in use
351      * @param config the KConfigSkeleton to use
352      * @param widget the widget to watch
353      * @deprecated since 5.84, use addConfig(KCoreConfigSkeleton *config, QWidget *widget);
354      */
355     KConfigDialogManager *addConfig(KConfigSkeleton *config, QWidget *widget);
356 #endif
357 
358     /**
359      * Sets the quick help.
360      */
361     void setQuickHelp(const QString &help);
362 
363     void showEvent(QShowEvent *ev) override;
364 
365     friend class KCModuleProxy;
366 
367 Q_SIGNALS:
368 
369     /**
370      * Indicate that the state of the modules contents has changed.
371      *
372      * This signal is emitted whenever the state of the configuration
373      * shown in the module changes. It allows the module container to
374      * keep track of unsaved changes.
375      */
376     void changed(bool state); // clazy:exclude=overloaded-signal
377 
378     /**
379      * Indicate that the state of the modules contents matches the default
380      * settings.
381      *
382      * This signal is emitted whenever the state of the configuration
383      * shown in the module changes. It allows the module container to
384      * keep track of defaults.
385      *
386      * @since 5.65
387      */
388     void defaulted(bool state);
389 
390     /**
391      * Indicate that the module's quickhelp has changed.
392      *
393      * Emit this signal whenever the module's quickhelp changes.
394      * Modules implemented as tabbed dialogs might want to implement
395      * per-tab quickhelp for example.
396      *
397      */
398     void quickHelpChanged();
399 
400     /**
401      * Indicate that the module's root message has changed.
402      *
403      * Emits this signal whenever the module's root message changes.
404      *
405      * @since 4.4
406      *
407      */
408     void rootOnlyMessageChanged(bool use, QString message);
409 
410     /**
411      * Emitted when show defaults indicators changed
412      * @since 5.73
413      */
414     void defaultsIndicatorsVisibleChanged(bool show);
415 
416 protected Q_SLOTS:
417 
418 #if KCONFIGWIDGETS_ENABLE_DEPRECATED_SINCE(5, 64)
419     /**
420      * Calling this slot is equivalent to emitting changed(true).
421      * @deprecated Since 5.64, use markAsChanged
422      */
423     KCONFIGWIDGETS_DEPRECATED_VERSION(5, 64, "Use KCModule::markAsChanged()")
424     void changed();
425 #endif
426 
427     /**
428      * Calling this slot is equivalent to emitting changed(true).
429      * @since 5.64
430      */
431     void markAsChanged();
432 
433     /**
434      * A managed widget was changed, the widget settings and the current
435      * settings are compared and a corresponding changed() signal is emitted
436      */
437     void widgetChanged();
438 
439 #ifndef KCONFIGWIDGETS_NO_KAUTH
440     /**
441      * The status of the auth action, if one, has changed
442      */
443     void authStatusChanged(KAuth::Action::AuthStatus status);
444 #endif
445 
446 protected:
447     /**
448      * Sets the buttons to display.
449      *
450      * Help: shows a "Help" button.
451      *
452      * Default: shows a "Use Defaults" button.
453      *
454      * Apply: in kcontrol this will show an "Apply" and "Reset" button,
455      *        in kcmshell this will show an "Ok", "Apply", "Reset" and "Cancel" button.
456      *
457      * If Apply is not specified, kcmshell will show a "Close" button.
458      *
459      * @see KCModule::buttons
460      */
461     void setButtons(Buttons btn);
462 
463     /**
464      * Sets the RootOnly message.
465      *
466      * This message will be shown at the top of the module if useRootOnlyMessage is
467      * set. If no message is set, a default one will be used.
468      *
469      * @see KCModule::rootOnlyMessage
470      */
471     void setRootOnlyMessage(const QString &message);
472 
473     /**
474      * Change whether or not the RootOnly message should be shown.
475      *
476      * Following the value of @p on, the RootOnly message will be
477      * shown or not.
478      *
479      * @see KCModule::useRootOnlyMessage
480      */
481     void setUseRootOnlyMessage(bool on);
482 
483     /**
484      * Returns the changed state of automatically managed widgets in this dialog
485      */
486     bool managedWidgetChangeState() const;
487 
488     /**
489      * Returns the defaulted state of automatically managed widgets in this dialog
490      *
491      * @since 5.65
492      */
493     bool managedWidgetDefaultState() const;
494 
495     /**
496      * Call this method when your manually managed widgets change state between
497      * changed and not changed
498      */
499     void unmanagedWidgetChangeState(bool);
500 
501     /**
502      * Call this method when your manually managed widgets change state between
503      * defaulted and not defaulted
504      *
505      * @since 5.65
506      */
507     void unmanagedWidgetDefaultState(bool);
508 
509 private:
510     std::unique_ptr<KCModulePrivate> const d;
511 };
512 
513 Q_DECLARE_OPERATORS_FOR_FLAGS(KCModule::Buttons)
514 
515 #endif // KCMODULE_H
516