File indexing completed on 2024-04-21 14:54:17

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #ifndef KCMODULE_H
0009 #define KCMODULE_H
0010 
0011 #include <kconfigwidgets_export.h>
0012 
0013 #if KCONFIGWIDGETS_WITH_KAUTH
0014 #include <KAuth/Action>
0015 #endif
0016 
0017 #include <KPluginMetaData>
0018 #include <QVariant>
0019 #include <QWidget>
0020 #include <memory>
0021 
0022 class KAboutData;
0023 class KConfigDialogManager;
0024 class KCoreConfigSkeleton;
0025 class KConfigSkeleton;
0026 class KCModulePrivate;
0027 
0028 /**
0029  * @class KCModule kcmodule.h KCModule
0030  *
0031  * The base class for configuration modules.
0032  *
0033  * Configuration modules are realized as plugins that are loaded only when
0034  * needed.
0035  *
0036  * The module in principle is a simple widget displaying the
0037  * item to be changed. The module has a very small interface.
0038  *
0039  * All the necessary glue logic and the GUI bells and whistles
0040  * are provided by the control center and must not concern
0041  * the module author.
0042  *
0043  * To write a config module, you have to create a library
0044  * that contains a factory function like the following:
0045  *
0046  * \code
0047  * #include <KPluginFactory>
0048  *
0049  * K_PLUGIN_FACTORY(MyKCModuleFactory, registerPlugin<MyKCModule>() )
0050  * \endcode
0051  *
0052  * The constructor of the KCModule then looks like this:
0053  * \code
0054  * YourKCModule::YourKCModule( QWidget* parent )
0055  *   : KCModule( parent )
0056  * {
0057  *   KAboutData *about = new KAboutData(
0058  *     <kcm name>, i18n( "..." ),
0059  *     KDE_VERSION_STRING, QString(), KAboutLicense::GPL,
0060  *     i18n( "Copyright 2006 ..." ) );
0061  *   about->addAuthor( i18n(...) );
0062  *   setAboutData( about );
0063  *   .
0064  *   .
0065  *   .
0066  * }
0067  * \endcode
0068  *
0069  * If you want to make the KCModule available only conditionally (i.e. show in
0070  * the list of available modules only if some test succeeds) then you can use
0071  * Hidden in the .desktop file. An example:
0072  * \code
0073  * Hidden[$e]=$(if test -e /dev/js*; then echo "false"; else echo "true"; fi)
0074  * \endcode
0075  * The example executes the given code in a shell and uses the stdout output for
0076  * the Hidden value (so it's either Hidden=true or Hidden=false).
0077  *
0078  * See http://techbase.kde.org/Development/Tutorials/KCM_HowTo
0079  * for more detailed documentation.
0080  *
0081  * @author Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
0082  */
0083 class KCONFIGWIDGETS_EXPORT KCModule : public QWidget
0084 {
0085     Q_OBJECT
0086 
0087 public:
0088     /**
0089      * An enumeration type for the buttons used by this module.
0090      * You should only use Help, Default and Apply. The rest is obsolete.
0091      * NoAdditionalButton can be used when we do not want have other button that Ok Cancel
0092      *
0093      * @see KCModule::buttons
0094      * @see KCModule::setButtons
0095      * @see Buttons
0096      */
0097     enum Button { NoAdditionalButton = 0, Help = 1, Default = 2, Apply = 4, Export = 8 };
0098     /**
0099      * Stores a combination of #Button values.
0100      */
0101     Q_DECLARE_FLAGS(Buttons, Button)
0102 
0103 #if KCONFIGWIDGETS_ENABLE_DEPRECATED_SINCE(5, 85)
0104     /**
0105      * Base class for all KControlModules.
0106      *
0107      * @note do not emit changed signals here, since they are not yet connected
0108      *       to any slot.
0109      * @param aboutData becomes owned by the KCModule
0110      * @deprecated since 5.85, use other constructor and setAboutData()
0111      */
0112     KCONFIGWIDGETS_DEPRECATED_VERSION(5, 85, "Use other constructor and setAboutData()")
0113     explicit KCModule(const KAboutData *aboutData, QWidget *parent = nullptr, const QVariantList &args = QVariantList());
0114 #endif
0115 
0116     /**
0117      * Base class for all KControlModules.
0118      *
0119      * @note do not emit changed signals here, since they are not yet connected
0120      *       to any slot.
0121      */
0122     explicit KCModule(QWidget *parent = nullptr, const QVariantList &args = QVariantList());
0123 
0124     /**
0125      * Constructor overload that is compatible with the Qt6 version of the constructor
0126      * @since 5.105
0127      */
0128     explicit KCModule(QObject *parent, const KPluginMetaData & /*data*/ = {}, const QVariantList &args = QVariantList())
0129         : KCModule(qobject_cast<QWidget *>(parent), args)
0130     {
0131     }
0132 
0133     /**
0134      * Destroys the module.
0135      */
0136     ~KCModule() override;
0137 
0138     /**
0139      * Return a quick-help text.
0140      *
0141      * This method may be called when the module is docked. The quick help would generally
0142      * be used as "what's this" text if the view container supports the "what's this"
0143      * system.
0144      * The quick-help text should contain a short description of the module and
0145      * links to the module's help files. You can use QML formatting tags in the text.
0146      *
0147      * @note make sure the quick help text gets translated (use i18n()).
0148      */
0149     virtual QString quickHelp() const;
0150 
0151 #if KCONFIGWIDGETS_BUILD_DEPRECATED_SINCE(5, 90)
0152     /**
0153      * This is generally only called for the KBugReport.
0154      * If you override you should  have it return a pointer to a constant.
0155      *
0156      *
0157      * @returns the KAboutData for this module
0158      * @deprecated since 5.90. Use the KPluginMetaData the KCModule was instantiated from.
0159      */
0160     KCONFIGWIDGETS_DEPRECATED_VERSION(5, 90, "Use the KPluginMetaData the KCModule was instantiated from")
0161     virtual const KAboutData *aboutData() const;
0162 #endif
0163 
0164 #if KCONFIGWIDGETS_ENABLE_DEPRECATED_SINCE(5, 106)
0165     /**
0166      * This sets the KAboutData returned by aboutData()
0167      * The about data is now owned by KCModule.
0168      *
0169      * @deprecated since 5.106, the about data is only relevant when using setNeedsAuthorization
0170      * Since the implicit KAuth integration will be removed in KF6, you should not longer call this method unless strictly needed
0171      */
0172     KCONFIGWIDGETS_DEPRECATED_VERSION(5, 106, "See API docs")
0173     void setAboutData(const KAboutData *about);
0174 #endif
0175 
0176     /**
0177      * Indicate which buttons will be used.
0178      *
0179      * The return value is a value or'ed together from
0180      * the Button enumeration type.
0181      *
0182      * @see KCModule::setButtons
0183      */
0184     Buttons buttons() const;
0185 
0186     /**
0187      * Get the RootOnly message for this module.
0188      *
0189      * When the module must be run as root, or acts differently
0190      * for root and a normal user, it is sometimes useful to
0191      * customize the message that appears at the top of the module
0192      * when used as a normal user. This function returns this
0193      * customized message. If none has been set, a default message
0194      * will be used.
0195      *
0196      * @see KCModule::setRootOnlyMessage
0197      */
0198     QString rootOnlyMessage() const;
0199 
0200     /**
0201      * Tell if KControl should show a RootOnly message when run as
0202      * a normal user.
0203      *
0204      * In some cases, the module don't want a RootOnly message to
0205      * appear (for example if it has already one). This function
0206      * tells KControl if a RootOnly message should be shown
0207      *
0208      * @see KCModule::setUseRootOnlyMessage
0209      */
0210     bool useRootOnlyMessage() const;
0211 
0212 #if KCONFIGWIDGETS_ENABLE_DEPRECATED_SINCE(5, 90)
0213     /**
0214      * @deprecated since 5.90. Use the KPluginMetaData the KCModule was instantiated from.
0215      */
0216     KCONFIGWIDGETS_DEPRECATED_VERSION(5, 90, "Use the KPluginMetaData the KCModule was instantiated from")
0217     KAboutData componentData() const;
0218 #endif
0219 
0220     /**
0221      * @return a list of @ref KConfigDialogManager's in use, if any.
0222      */
0223     QList<KConfigDialogManager *> configs() const;
0224 
0225     /**
0226      * @brief Set if the module's save() method requires authorization to be executed.
0227      *
0228      * The module can set this property to @c true if it requires authorization.
0229      * It will still have to execute the action itself using the KAuth library, so
0230      * this method is not technically needed to perform the action, but
0231      * using this and/or the setAuthAction() method will ensure that hosting
0232      * applications like System Settings or kcmshell behave correctly.
0233      *
0234      * Called with @c true, this method will set the action to  "org.kde.kcontrol.name.save" where
0235      * "name" is aboutData()->appName() return value. This default action won't be set if
0236      * the aboutData() object is not valid.
0237      *
0238      * Note that called with @c false, this method will reset the action name set with setAuthAction().
0239      *
0240      * @param needsAuth Tells if the module's save() method requires authorization to be executed.
0241      */
0242     void setNeedsAuthorization(bool needsAuth);
0243 
0244     /**
0245      * Returns the value previously set with setNeedsAuthorization() or setAuthAction(). By default it's @c false.
0246      *
0247      * @return @c true if the module's save() method requires authorization, @c false otherwise
0248      */
0249     bool needsAuthorization() const;
0250 
0251     /**
0252      * Returns whether an indicator is shown when a setting differs from default.
0253      *
0254      * @since 5.73
0255      */
0256     bool defaultsIndicatorsVisible() const;
0257 
0258 #if KCONFIGWIDGETS_WITH_KAUTH
0259     /**
0260      * @brief Set if the module's save() method requires authorization to be executed
0261      *
0262      * It will still have to execute the action itself using the KAuth library, so
0263      * this method is not technically needed to perform the action, but
0264      * using this method will ensure that hosting
0265      * applications like System Settings or kcmshell behave correctly.
0266      *
0267      * @param action the action that will be used by this KCModule
0268      */
0269     void setAuthAction(const KAuth::Action &action);
0270 
0271     /**
0272      * Returns the action previously set with setAuthAction(). By default its an invalid action.
0273      *
0274      * @return The action that has to be authorized to execute the save() method.
0275      */
0276     KAuth::Action authAction() const;
0277 #endif
0278 
0279 #if KCONFIGWIDGETS_ENABLE_DEPRECATED_SINCE(5, 0)
0280     /**
0281      * Returns the value set by setExportText();
0282      * @deprecated since 5.0, obsolete feature
0283      */
0284     KCONFIGWIDGETS_DEPRECATED_VERSION(5, 0, "Obsolete feature")
0285     QString exportText() const;
0286 #endif
0287 
0288 #if KCONFIGWIDGETS_ENABLE_DEPRECATED_SINCE(5, 0)
0289     /**
0290      * Sets the export QString value, used for exporting data.
0291      * @deprecated since 5.0, obsolete feature
0292      */
0293     KCONFIGWIDGETS_DEPRECATED_VERSION(5, 0, "Obsolete feature")
0294     void setExportText(const QString &);
0295 #endif
0296 
0297 public Q_SLOTS:
0298     /**
0299      * Load the configuration data into the module.
0300      *
0301      * The load method sets the user interface elements of the
0302      * module to reflect the current settings stored in the
0303      * configuration files.
0304      *
0305      * This method is invoked whenever the module should read its configuration
0306      * (most of the times from a config file) and update the user interface.
0307      * This happens when the user clicks the "Reset" button in the control
0308      * center, to undo all of his changes and restore the currently valid
0309      * settings. It is also called right after construction.
0310      */
0311     virtual void load();
0312 
0313     /**
0314      * Save the configuration data.
0315      *
0316      * The save method stores the config information as shown
0317      * in the user interface in the config files.
0318      *
0319      * If necessary, this method also updates the running system,
0320      * e.g. by restarting applications. This normally does not apply for
0321      * KSettings::Dialog modules where the updating is taken care of by
0322      * KSettings::Dispatcher.
0323      *
0324      * save is called when the user clicks "Apply" or "Ok".
0325      *
0326      * If you use KConfigXT, saving is taken care off automatically and
0327      * you do not need to load manually. However, if you for some reason reimplement it and
0328      * also are using KConfigXT, you must call this function, otherwise the saving of KConfigXT
0329      * options will not work. Call it at the very end of your reimplementation, to avoid
0330      * changed() signals getting emitted when you modify widgets.
0331      */
0332     virtual void save();
0333 
0334     /**
0335      * Sets the configuration to sensible default values.
0336      *
0337      * This method is called when the user clicks the "Default"
0338      * button. It should set the display to useful values.
0339      *
0340      * If you use KConfigXT, you do not have to reimplement this function since
0341      * the fetching and settings of default values is done automatically. However, if you
0342      * reimplement and also are using KConfigXT, remember to call the base function at the
0343      * very end of your reimplementation.
0344      */
0345     virtual void defaults();
0346 
0347     /**
0348      * Show an indicator when settings value differ from default
0349      *
0350      * @since 5.73
0351      */
0352     void setDefaultsIndicatorsVisible(bool show);
0353 
0354     /**
0355      * The returned widget should be used as a parent for widgets you create
0356      * In KF6, KCModule is no longer a QWidget, but the embeddable QWidget is exposed using the widget() method
0357      * This method exists as porting aid
0358      *
0359      * @since 5.105
0360      */
0361     inline QWidget *widget()
0362     {
0363         return this;
0364     }
0365 
0366     /**
0367      * In KF6, the changed signal is removed in favor of the needsSave property
0368      * This method exists as porting aid
0369      *
0370      * @since 5.105
0371      */
0372     inline void setNeedsSave(bool needsSave)
0373     {
0374         Q_EMIT changed(needsSave);
0375     }
0376 
0377 protected:
0378     /**
0379      * Adds a KCoreConfigskeleton @p config to watch the widget @p widget
0380      *
0381      * This function is useful if you need to handle multiple configuration files.
0382      *
0383      * @return a pointer to the KCoreConfigDialogManager in use
0384      * @param config the KCoreConfigSkeleton to use
0385      * @param widget the widget to watch
0386      */
0387     KConfigDialogManager *addConfig(KCoreConfigSkeleton *config, QWidget *widget);
0388 
0389 #if KCONFIGWIDGETS_ENABLE_DEPRECATED_SINCE(5, 84)
0390     // No deprecation warning by compiler here, as the replacement will be
0391     // automatically picked by the compiler in the future, being the method
0392     // overload using the base-class of the argument type.
0393     // Avoids the need to do extra-casting right now on the caller side.
0394     /**
0395      * Adds a KConfigskeleton @p config to watch the widget @p widget
0396      *
0397      * This function is useful if you need to handle multiple configuration files.
0398      *
0399      * @return a pointer to the KConfigDialogManager in use
0400      * @param config the KConfigSkeleton to use
0401      * @param widget the widget to watch
0402      * @deprecated since 5.84, use addConfig(KCoreConfigSkeleton *config, QWidget *widget);
0403      */
0404     KConfigDialogManager *addConfig(KConfigSkeleton *config, QWidget *widget);
0405 #endif
0406 
0407     /**
0408      * Sets the quick help.
0409      */
0410     void setQuickHelp(const QString &help);
0411 
0412     void showEvent(QShowEvent *ev) override;
0413 
0414     friend class KCModuleProxy;
0415 
0416 Q_SIGNALS:
0417 
0418     /**
0419      * Indicate that the state of the modules contents has changed.
0420      *
0421      * This signal is emitted whenever the state of the configuration
0422      * shown in the module changes. It allows the module container to
0423      * keep track of unsaved changes.
0424      */
0425     void changed(bool state); // clazy:exclude=overloaded-signal
0426 
0427     /**
0428      * Indicate that the state of the modules contents matches the default
0429      * settings.
0430      *
0431      * This signal is emitted whenever the state of the configuration
0432      * shown in the module changes. It allows the module container to
0433      * keep track of defaults.
0434      *
0435      * @since 5.65
0436      */
0437     void defaulted(bool state);
0438 
0439     /**
0440      * Indicate that the module's quickhelp has changed.
0441      *
0442      * Emit this signal whenever the module's quickhelp changes.
0443      * Modules implemented as tabbed dialogs might want to implement
0444      * per-tab quickhelp for example.
0445      *
0446      */
0447     void quickHelpChanged();
0448 
0449     /**
0450      * Indicate that the module's root message has changed.
0451      *
0452      * Emits this signal whenever the module's root message changes.
0453      *
0454      * @since 4.4
0455      *
0456      */
0457     void rootOnlyMessageChanged(bool use, QString message);
0458 
0459     /**
0460      * Emitted when show defaults indicators changed
0461      * @since 5.73
0462      */
0463     void defaultsIndicatorsVisibleChanged(bool show);
0464 
0465 protected Q_SLOTS:
0466 
0467 #if KCONFIGWIDGETS_ENABLE_DEPRECATED_SINCE(5, 64)
0468     /**
0469      * Calling this slot is equivalent to emitting changed(true).
0470      * @deprecated Since 5.64, use markAsChanged
0471      */
0472     KCONFIGWIDGETS_DEPRECATED_VERSION(5, 64, "Use KCModule::markAsChanged()")
0473     void changed();
0474 #endif
0475 
0476     /**
0477      * Calling this slot is equivalent to emitting changed(true).
0478      * @since 5.64
0479      */
0480     void markAsChanged();
0481 
0482     /**
0483      * A managed widget was changed, the widget settings and the current
0484      * settings are compared and a corresponding changed() signal is emitted
0485      */
0486     void widgetChanged();
0487 
0488 #if KCONFIGWIDGETS_WITH_KAUTH
0489     /**
0490      * The status of the auth action, if one, has changed
0491      */
0492     void authStatusChanged(KAuth::Action::AuthStatus status);
0493 #endif
0494 
0495 protected:
0496     /**
0497      * Sets the buttons to display.
0498      *
0499      * Help: shows a "Help" button.
0500      *
0501      * Default: shows a "Use Defaults" button.
0502      *
0503      * Apply: in kcontrol this will show an "Apply" and "Reset" button,
0504      *        in kcmshell this will show an "Ok", "Apply", "Reset" and "Cancel" button.
0505      *
0506      * If Apply is not specified, kcmshell will show a "Close" button.
0507      *
0508      * @see KCModule::buttons
0509      */
0510     void setButtons(Buttons btn);
0511 
0512     /**
0513      * Sets the RootOnly message.
0514      *
0515      * This message will be shown at the top of the module if useRootOnlyMessage is
0516      * set. If no message is set, a default one will be used.
0517      *
0518      * @see KCModule::rootOnlyMessage
0519      */
0520     void setRootOnlyMessage(const QString &message);
0521 
0522     /**
0523      * Change whether or not the RootOnly message should be shown.
0524      *
0525      * Following the value of @p on, the RootOnly message will be
0526      * shown or not.
0527      *
0528      * @see KCModule::useRootOnlyMessage
0529      */
0530     void setUseRootOnlyMessage(bool on);
0531 
0532     /**
0533      * Returns the changed state of automatically managed widgets in this dialog
0534      */
0535     bool managedWidgetChangeState() const;
0536 
0537     /**
0538      * Returns the defaulted state of automatically managed widgets in this dialog
0539      *
0540      * @since 5.65
0541      */
0542     bool managedWidgetDefaultState() const;
0543 
0544     /**
0545      * Call this method when your manually managed widgets change state between
0546      * changed and not changed
0547      */
0548     void unmanagedWidgetChangeState(bool);
0549 
0550     /**
0551      * Call this method when your manually managed widgets change state between
0552      * defaulted and not defaulted
0553      *
0554      * @since 5.65
0555      */
0556     void unmanagedWidgetDefaultState(bool);
0557 
0558 private:
0559     std::unique_ptr<KCModulePrivate> const d;
0560 };
0561 
0562 Q_DECLARE_OPERATORS_FOR_FLAGS(KCModule::Buttons)
0563 
0564 #endif // KCMODULE_H