File indexing completed on 2024-05-12 09:41:26

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