File indexing completed on 2024-04-28 16:55:13

0001 /***************************************************************************
0002  *   Copyright (C) 2010 by Dario Freddi <drf@kde.org>                      *
0003  *                                                                         *
0004  *   This program is free software; you can redistribute it and/or modify  *
0005  *   it under the terms of the GNU General Public License as published by  *
0006  *   the Free Software Foundation; either version 2 of the License, or     *
0007  *   (at your option) any later version.                                   *
0008  *                                                                         *
0009  *   This program is distributed in the hope that it will be useful,       *
0010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0012  *   GNU General Public License for more details.                          *
0013  *                                                                         *
0014  *   You should have received a copy of the GNU General Public License     *
0015  *   along with this program; if not, write to the                         *
0016  *   Free Software Foundation, Inc.,                                       *
0017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
0018  ***************************************************************************/
0019 
0020 
0021 #ifndef POWERDEVIL_POWERDEVILACTION_H
0022 #define POWERDEVIL_POWERDEVILACTION_H
0023 
0024 #include "powerdevilpolicyagent.h"
0025 
0026 #include <QObject>
0027 #include <QVariantMap>
0028 
0029 class KConfigGroup;
0030 
0031 namespace PowerDevil
0032 {
0033 class BackendInterface;
0034 class Core;
0035 
0036 /**
0037  * @brief The base class for Power Management Actions
0038  *
0039  * The Action class is the very base class for writing a new Power Management action.
0040  * Developers wishing to implement their own action are supposed to subclass Action.
0041  *
0042  * @par Creating a brand new Action
0043  *
0044  * If you are already familiar with KDE's plugin system, you have to know that actions are
0045  * nothing but a KService plugin which will be loaded on demand. Each action has an ID associated to it
0046  * which represents it in the config file and uniquely identifies it in the loading phase.
0047  *
0048  * In addition to standard parameters, the .desktop file representing your action should contain the following
0049  * entries:
0050  *
0051  * @code
0052  * X-KDE-PowerDevil-Action-ID=YourActionID
0053  * X-KDE-PowerDevil-Action-UIComponentLibrary=myactionplugin_config
0054  * X-KDE-PowerDevil-Action-ConfigPriority=98
0055  * @endcode
0056  *
0057  * The @c UIComponentLibrary field refers to the library which contains the configuration UI
0058  * for your action. Please see ActionConfig documentation for more details.
0059  *
0060  * The @c ConfigPriority is relevant to the configuration UI as well, and determines where your config UI will appear.
0061  * The higher the number, the higher your config UI will be in the list of actions. Choose this value wisely: usually
0062  * only very basic power management functions should have a value > 50.
0063  *
0064  * The most important functions you need to reimplement are loadAction and triggerImpl. The first is called
0065  * whenever an action is loaded, carrying the action's configuration. The other is called whenever
0066  * the action is triggered. You usually want to process the action here as triggerImpl is guaranteed
0067  * to be called just when policies are satisfied.
0068  *
0069  * @par Runtime requirements
0070  *
0071  * Some actions might be available only when the system satisfies certain hardware or software runtime requirements.
0072  * In this case, powerdevil provides a way for the action to advertise to the outside whether it is supported or
0073  * not. This can be done by reimplementing @c isSupported and adding to the .desktop file the field
0074  *
0075  * @code
0076  * X-KDE-PowerDevil-Action-HasRuntimeRequirement=true
0077  * @endcode
0078  *
0079  * Done that, powerdevil will take care of exposing your action only if support for it is advertised. In addition,
0080  * the UI will expose the configuration of your action only if its support is advertised. Of course, this means the
0081  * action will be temporarily loaded by the config UI to verify its support. If your action is performing some tasks in
0082  * the constructor besides setting policies, first of all revise your design since you probably don't need or want to
0083  * do that. If you really cannot avoid that, you MUST check for an OPTIONAL parameter in the QVariantList coming
0084  * from the plugin's constructor. If it exists, it's a boolean and it is true, the action is being loaded just for
0085  * a support check, and you should refrain from doing any actions which would affect the system. This parameter is also
0086  * used in tests.
0087  *
0088  * @par Handling policies from within the action
0089  *
0090  * As you might know, the KDE Power Management system features a very efficient policy handler, which
0091  * prevents Power Management actions when certain condition occurs. The integration with Actions is very easy:
0092  * in your Action's constructor, you want to call setRequiredPolicies, stating which policies have to be
0093  * satisfied to perform the action. For example, if your action should not be performed whenever the session
0094  * cannot be interrupted, you would pass @c InterruptSession.
0095  *
0096  * Done that, your action is already obeying to the policy. trigger, in fact, calls triggerImpl just when
0097  * the policies are allowing your action to be performed.
0098  *
0099  * @since 4.6
0100  */
0101 class Q_DECL_EXPORT Action : public QObject
0102 {
0103     Q_OBJECT
0104     Q_DISABLE_COPY(Action)
0105 
0106 public:
0107     /**
0108      * Default constructor
0109      */
0110     explicit Action(QObject *parent);
0111     /**
0112      * Default destructor
0113      */
0114     ~Action() override;
0115 
0116     /**
0117      * Reimplement this function when creating a new Action. This function is called whenever the action is loaded or
0118      * its configuration changes. It carries the KConfigGroup associated with your action and generated from your
0119      * config interface.
0120      *
0121      * @param config The action's configuration which should be loaded.
0122      * @returns Whether the action has been successfully loaded.
0123      *
0124      * @see ActionConfig
0125      */
0126     virtual bool loadAction(const KConfigGroup &config) = 0;
0127     /**
0128      * Unloads the action. You usually shouldn't reimplement this function: reimplement onUnloadAction instead.
0129      *
0130      * @returns Whether the action has been successfully unloaded
0131      */
0132     virtual bool unloadAction();
0133 
0134     /**
0135      * This function is meant to find out if this action is available on this system. Actions
0136      * CAN reimplement this function if they are dependent on specific hardware/software requirements.
0137      * By default, this function will always return true.
0138      *
0139      * Should this function return false, the core will delete and ignore the action right after creation.
0140      *
0141      * @returns Whether this action is supported or not by the current system
0142      */
0143     virtual bool isSupported();
0144 
0145     /**
0146      * Triggers the action with the given argument. This function is meant to be used by the caller only -
0147      * if you are implementing your own action, reimplement triggerImpl instead.
0148      *
0149      * @param args The arguments for triggering the action
0150      */
0151     void trigger(const QVariantMap &args);
0152 
0153 protected:
0154     /**
0155      * Registers an idle timeout for this action. Call this function and not KIdleTime directly to take advantage
0156      * of Action's automated handling of idle timeouts. Also, please reimplement onIdleTimeout instead of listening
0157      * to KIdleTime's signals to catch idle timeout events.
0158      *
0159      * @param msec The idle timeout to be registered in milliseconds.
0160      */
0161     void registerIdleTimeout(int msec);
0162     /**
0163      * Sets the required policies needed for this Action to run. Usually, you want to call this function in your
0164      * Action's constructor.
0165      *
0166      * @param requiredPolicies A set of policies which are required to run this action. It can be empty if your
0167      *                         Action does not rely on policies.
0168      */
0169     void setRequiredPolicies(PowerDevil::PolicyAgent::RequiredPolicies requiredPolicies);
0170 
0171     /**
0172      * This function's body should undertake the Action's execution. It has to be reimplemented in a new Action.
0173      *
0174      * @param args The arguments for triggering the action
0175      */
0176     virtual void triggerImpl(const QVariantMap &args) = 0;
0177 
0178     /**
0179      * @returns The BackendInterface
0180      */
0181     PowerDevil::BackendInterface *backend() const;
0182     /**
0183      * @returns The PowerDevil Core
0184      */
0185     PowerDevil::Core *core();
0186 
0187 protected Q_SLOTS:
0188     /**
0189      * This function is called whenever a profile is loaded. Please note that this is slightly different from
0190      * loadAction: in fact a profile can be reloaded without having the action change its configuration.
0191      * If your action should do something as soon as a profile switches, it should be done inside this function.
0192      */
0193     virtual void onProfileLoad() = 0;
0194     /**
0195      * This slot is triggered whenever an idle timeout registered with registerIdleTimeout is reached.
0196      *
0197      * @param msec The idle timeout reached in milliseconds
0198      */
0199     virtual void onIdleTimeout(int msec) = 0;
0200     /**
0201      * This slot is triggered whenever the PC wakes up from an Idle state. It is @b always called after a registered
0202      * idle timeout has been reached.
0203      */
0204     virtual void onWakeupFromIdle() = 0;
0205     /**
0206      * This function is called when the profile is unloaded.
0207      */
0208     virtual void onProfileUnload() = 0;
0209     /**
0210      * This function is called when the action is unloaded. You usually want to put what would have gone in your
0211      * destructor here.
0212      *
0213      * @returns Whether the action was unloaded successfully.
0214      */
0215     virtual bool onUnloadAction();
0216 
0217 Q_SIGNALS:
0218     void actionTriggered(bool result, const QString &error = QString());
0219 
0220 private:
0221     class Private;
0222     Private * const d;
0223 
0224     friend class Core;
0225     friend class ActionPool;
0226 };
0227 
0228 }
0229 
0230 #endif // POWERDEVIL_POWERDEVILACTION_H