File indexing completed on 2024-04-28 05:36:15

0001 /*
0002  *   SPDX-FileCopyrightText: 2010 Dario Freddi <drf@kde.org>
0003  *
0004  *   SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #pragma once
0008 
0009 #include "powerdevilpolicyagent.h"
0010 
0011 #include <QObject>
0012 #include <QVariantMap>
0013 
0014 #include <chrono>
0015 
0016 #include "powerdevilcore_export.h"
0017 
0018 namespace PowerDevil
0019 {
0020 class Core;
0021 class ProfileSettings;
0022 
0023 /**
0024  * @brief The base class for Power Management Actions
0025  *
0026  * The Action class is the very base class for writing a new Power Management action.
0027  * Developers wishing to implement their own action are supposed to subclass Action.
0028  *
0029  * @par Creating a brand new Action
0030  *
0031  * If you are already familiar with KDE's plugin system, you have to know that actions are
0032  * nothing but a KCoreAddons plugin which will be loaded on demand. Each action has an ID associated to it
0033  * which uniquely identifies it in the loading phase.
0034  *
0035  * In addition to standard parameters, the .json file representing your action should contain the following
0036  * entry:
0037  *
0038  * @code
0039  * X-KDE-PowerDevil-Action-ID: YourActionID
0040  * @endcode
0041  *
0042  * The most important functions you need to reimplement are loadAction and triggerImpl. The first is called
0043  * whenever an action is loaded, carrying the action's configuration. The other is called whenever
0044  * the action is triggered. You usually want to process the action here as triggerImpl is guaranteed
0045  * to be called just when policies are satisfied.
0046  *
0047  * @par Runtime requirements
0048  *
0049  * Some actions might be available only when the system satisfies certain hardware or software runtime requirements.
0050  * In this case, powerdevil provides a way for the action to advertise to the outside whether it is supported or
0051  * not. This can be done by reimplementing @c isSupported and adding to the .json file the field
0052  *
0053  * @code
0054  * X-KDE-PowerDevil-Action-HasRuntimeRequirement: true
0055  * @endcode
0056  *
0057  * Done that, powerdevil will take care of exposing your action only if support for it is advertised. In addition,
0058  * the UI will expose the configuration of your action only if its support is advertised. Of course, this means the
0059  * action will be temporarily loaded by the config UI to verify its support. If your action is performing some tasks in
0060  * the constructor besides setting policies, revise your design since you probably don't need or want to do that.
0061  *
0062  * @par Handling policies from within the action
0063  *
0064  * As you might know, the KDE Power Management system features a very efficient policy handler, which
0065  * prevents Power Management actions when certain condition occurs. The integration with Actions is very easy:
0066  * in your Action's constructor, you want to call setRequiredPolicies, stating which policies have to be
0067  * satisfied to perform the action. For example, if your action should not be performed whenever the session
0068  * cannot be interrupted, you would pass @c InterruptSession.
0069  *
0070  * Done that, your action is already obeying to the policy. trigger, in fact, calls triggerImpl just when
0071  * the policies are allowing your action to be performed.
0072  *
0073  * @since 4.6
0074  */
0075 class POWERDEVILCORE_EXPORT Action : public QObject
0076 {
0077     Q_OBJECT
0078     Q_DISABLE_COPY(Action)
0079 
0080 public:
0081     /**
0082      * Default constructor
0083      */
0084     explicit Action(QObject *parent);
0085     /**
0086      * Default destructor
0087      */
0088     ~Action() override;
0089 
0090     /**
0091      * Reimplement this function when creating a new Action. This function is called whenever the action is loaded or
0092      * its configuration changes. It carries the ProfileSettings associated with the active power management
0093      * profile and generated from your config interface.
0094      *
0095      * @param profileSettings The profile settings containing the action's configuration which should be loaded.
0096      * @returns Whether the action has been successfully loaded. Should return false if not enabled for the given @p profileSettings.
0097      */
0098     virtual bool loadAction(const PowerDevil::ProfileSettings &profileSettings) = 0;
0099     /**
0100      * Unloads the action.
0101      */
0102     void unloadAction();
0103 
0104     /**
0105      * This function is meant to find out if this action is available on this system. Actions
0106      * CAN reimplement this function if they are dependent on specific hardware/software requirements.
0107      * By default, this function will always return true.
0108      *
0109      * Should this function return false, the core will delete and ignore the action right after creation.
0110      *
0111      * @returns Whether this action is supported or not by the current system
0112      */
0113     virtual bool isSupported();
0114 
0115     /**
0116      * Triggers the action with the given argument. This function is meant to be used by the caller only -
0117      * if you are implementing your own action, reimplement triggerImpl instead.
0118      *
0119      * @param args The arguments for triggering the action
0120      */
0121     void trigger(const QVariantMap &args);
0122 
0123 protected:
0124     /**
0125      * Registers an idle timeout for this action. Call this function and not KIdleTime directly to take advantage
0126      * of Action's automated handling of idle timeouts. Also, please reimplement onIdleTimeout instead of listening
0127      * to KIdleTime's signals to catch idle timeout events.
0128      */
0129     void registerIdleTimeout(std::chrono::milliseconds timeout);
0130     /**
0131      * Removes any previously registered idle timeouts for this action.
0132      */
0133     void unregisterIdleTimeouts();
0134     /**
0135      * Sets the required policies needed for this Action to run. Usually, you want to call this function in your
0136      * Action's constructor.
0137      *
0138      * @param requiredPolicies A set of policies which are required to run this action. It can be empty if your
0139      *                         Action does not rely on policies.
0140      */
0141     void setRequiredPolicies(PowerDevil::PolicyAgent::RequiredPolicies requiredPolicies);
0142 
0143     /**
0144      * This function's body should undertake the Action's execution. It has to be reimplemented in a new Action.
0145      *
0146      * @param args The arguments for triggering the action
0147      */
0148     virtual void triggerImpl(const QVariantMap &args) = 0;
0149 
0150     /**
0151      * @returns The PowerDevil Core
0152      */
0153     PowerDevil::Core *core() const;
0154 
0155 protected Q_SLOTS:
0156     /**
0157      * This function is called whenever a profile is loaded. Please note that this is slightly different from
0158      * loadAction: in fact a profile can be reloaded without having the action change its configuration.
0159      * If your action should do something as soon as a profile switches, it should be done inside this function.
0160      */
0161     virtual void onProfileLoad(const QString &previousProfile, const QString &newProfile);
0162     /**
0163      * This slot is triggered whenever an idle timeout registered with registerIdleTimeout is reached.
0164      *
0165      * @param timeout The idle timeout reached
0166      */
0167     virtual void onIdleTimeout(std::chrono::milliseconds timeout);
0168     /**
0169      * This slot is triggered whenever the PC wakes up from an Idle state. It is @b always called after a registered
0170      * idle timeout has been reached.
0171      */
0172     virtual void onWakeupFromIdle();
0173     /**
0174      * This function is called when the profile is unloaded.
0175      */
0176     virtual void onProfileUnload();
0177 
0178 private:
0179     PowerDevil::Core *m_core;
0180 
0181     QList<std::chrono::milliseconds> m_registeredIdleTimeouts;
0182     PowerDevil::PolicyAgent::RequiredPolicies m_requiredPolicies;
0183 
0184     friend class Core;
0185 };
0186 
0187 }