1 /*************************************************************************** 2 * Copyright (C) 2010 by Dario Freddi <drf@kde.org> * 3 * * 4 * This program is free software; you can redistribute it and/or modify * 5 * it under the terms of the GNU General Public License as published by * 6 * the Free Software Foundation; either version 2 of the License, or * 7 * (at your option) any later version. * 8 * * 9 * This program is distributed in the hope that it will be useful, * 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 12 * GNU General Public License for more details. * 13 * * 14 * You should have received a copy of the GNU General Public License * 15 * along with this program; if not, write to the * 16 * Free Software Foundation, Inc., * 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * 18 ***************************************************************************/ 19 20 21 #ifndef POWERDEVIL_POWERDEVILACTION_H 22 #define POWERDEVIL_POWERDEVILACTION_H 23 24 #include "powerdevilpolicyagent.h" 25 26 #include <QObject> 27 #include <QVariantMap> 28 29 class KConfigGroup; 30 31 namespace PowerDevil 32 { 33 class BackendInterface; 34 class Core; 35 36 /** 37 * @brief The base class for Power Management Actions 38 * 39 * The Action class is the very base class for writing a new Power Management action. 40 * Developers wishing to implement their own action are supposed to subclass Action. 41 * 42 * @par Creating a brand new Action 43 * 44 * If you are already familiar with KDE's plugin system, you have to know that actions are 45 * nothing but a KService plugin which will be loaded on demand. Each action has an ID associated to it 46 * which represents it in the config file and uniquely identifies it in the loading phase. 47 * 48 * In addition to standard parameters, the .desktop file representing your action should contain the following 49 * entries: 50 * 51 * @code 52 * X-KDE-ServiceTypes=PowerDevil/Action 53 * X-KDE-PowerDevil-Action-ID=YourActionID 54 * X-KDE-PowerDevil-Action-IsBundled=false 55 * X-KDE-PowerDevil-Action-UIComponentLibrary=myactionplugin_config 56 * X-KDE-PowerDevil-Action-ConfigPriority=98 57 * @endcode 58 * 59 * The @c UIComponentLibrary field refers to the library which contains the configuration UI 60 * for your action. Please see ActionConfig documentation for more details. 61 * 62 * The @c ConfigPriority is relevant to the configuration UI as well, and determines where your config UI will appear. 63 * The higher the number, the higher your config UI will be in the list of actions. Choose this value wisely: usually 64 * only very basic power management functions should have a value > 50. 65 * 66 * The most important functions you need to reimplement are loadAction and triggerImpl. The first is called 67 * whenever an action is loaded, carrying the action's configuration. The other is called whenever 68 * the action is triggered. You usually want to process the action here as triggerImpl is guaranteed 69 * to be called just when policies are satisfied. 70 * 71 * @par Runtime requirements 72 * 73 * Some actions might be available only when the system satisfies certain hardware or software runtime requirements. 74 * In this case, powerdevil provides a way for the action to advertise to the outside whether it is supported or 75 * not. This can be done by reimplementing @c isSupported and adding to the .desktop file the field 76 * 77 * @code 78 * X-KDE-PowerDevil-Action-HasRuntimeRequirement=true 79 * @endcode 80 * 81 * Done that, powerdevil will take care of exposing your action only if support for it is advertised. In addition, 82 * the UI will expose the configuration of your action only if its support is advertised. Of course, this means the 83 * action will be temporarily loaded by the config UI to verify its support. If your action is performing some tasks in 84 * the constructor besides setting policies, first of all revise your design since you probably don't need or want to 85 * do that. If you really cannot avoid that, you MUST check for an OPTIONAL parameter in the QVariantList coming 86 * from the plugin's constructor. If it exists, it's a boolean and it is true, the action is being loaded just for 87 * a support check, and you should refrain from doing any actions which would affect the system. This parameter is also 88 * used in tests. 89 * 90 * @par Handling policies from within the action 91 * 92 * As you might know, the KDE Power Management system features a very efficient policy handler, which 93 * prevents Power Management actions when certain condition occurs. The integration with Actions is very easy: 94 * in your Action's constructor, you want to call setRequiredPolicies, stating which policies have to be 95 * satisfied to perform the action. For example, if your action should not be performed whenever the session 96 * cannot be interrupted, you would pass @c InterruptSession. 97 * 98 * Done that, your action is already obeying to the policy. trigger, in fact, calls triggerImpl just when 99 * the policies are allowing your action to be performed. 100 * 101 * @since 4.6 102 */ 103 class Q_DECL_EXPORT Action : public QObject 104 { 105 Q_OBJECT 106 Q_DISABLE_COPY(Action) 107 108 public: 109 /** 110 * Default constructor 111 */ 112 explicit Action(QObject *parent); 113 /** 114 * Default destructor 115 */ 116 ~Action() override; 117 118 /** 119 * Reimplement this function when creating a new Action. This function is called whenever the action is loaded or 120 * its configuration changes. It carries the KConfigGroup associated with your action and generated from your 121 * config interface. 122 * 123 * @param config The action's configuration which should be loaded. 124 * @returns Whether the action has been successfully loaded. 125 * 126 * @see ActionConfig 127 */ 128 virtual bool loadAction(const KConfigGroup &config) = 0; 129 /** 130 * Unloads the action. You usually shouldn't reimplement this function: reimplement onUnloadAction instead. 131 * 132 * @returns Whether the action has been successfully unloaded 133 */ 134 virtual bool unloadAction(); 135 136 /** 137 * This function is meant to find out if this action is available on this system. Actions 138 * CAN reimplement this function if they are dependent on specific hardware/software requirements. 139 * By default, this function will always return true. 140 * 141 * Should this function return false, the core will delete and ignore the action right after creation. 142 * 143 * @returns Whether this action is supported or not by the current system 144 */ 145 virtual bool isSupported(); 146 147 /** 148 * Triggers the action with the given argument. This function is meant to be used by the caller only - 149 * if you are implementing your own action, reimplement triggerImpl instead. 150 * 151 * @param args The arguments for triggering the action 152 */ 153 void trigger(const QVariantMap &args); 154 155 protected: 156 /** 157 * Registers an idle timeout for this action. Call this function and not KIdleTime directly to take advantage 158 * of Action's automated handling of idle timeouts. Also, please reimplement onIdleTimeout instead of listening 159 * to KIdleTime's signals to catch idle timeout events. 160 * 161 * @param msec The idle timeout to be registered in milliseconds. 162 */ 163 void registerIdleTimeout(int msec); 164 /** 165 * Sets the required policies needed for this Action to run. Usually, you want to call this function in your 166 * Action's constructor. 167 * 168 * @param requiredPolicies A set of policies which are required to run this action. It can be empty if your 169 * Action does not rely on policies. 170 */ 171 void setRequiredPolicies(PowerDevil::PolicyAgent::RequiredPolicies requiredPolicies); 172 173 /** 174 * This function's body should undertake the Action's execution. It has to be reimplemented in a new Action. 175 * 176 * @param args The arguments for triggering the action 177 */ 178 virtual void triggerImpl(const QVariantMap &args) = 0; 179 180 /** 181 * @returns The BackendInterface 182 */ 183 PowerDevil::BackendInterface *backend() const; 184 /** 185 * @returns The PowerDevil Core 186 */ 187 PowerDevil::Core *core(); 188 189 protected Q_SLOTS: 190 /** 191 * This function is called whenever a profile is loaded. Please note that this is slightly different from 192 * loadAction: in fact a profile can be reloaded without having the action change its configuration. 193 * If your action should do something as soon as a profile switches, it should be done inside this function. 194 */ 195 virtual void onProfileLoad() = 0; 196 /** 197 * This slot is triggered whenever an idle timeout registered with registerIdleTimeout is reached. 198 * 199 * @param msec The idle timeout reached in milliseconds 200 */ 201 virtual void onIdleTimeout(int msec) = 0; 202 /** 203 * This slot is triggered whenever the PC wakes up from an Idle state. It is @b always called after a registered 204 * idle timeout has been reached. 205 */ 206 virtual void onWakeupFromIdle() = 0; 207 /** 208 * This function is called when the profile is unloaded. 209 */ 210 virtual void onProfileUnload() = 0; 211 /** 212 * This function is called when the action is unloaded. You usually want to put what would have gone in your 213 * destructor here. 214 * 215 * @returns Whether the action was unloaded successfully. 216 */ 217 virtual bool onUnloadAction(); 218 219 Q_SIGNALS: 220 void actionTriggered(bool result, const QString &error = QString()); 221 222 private: 223 class Private; 224 Private * const d; 225 226 friend class Core; 227 friend class ActionPool; 228 }; 229 230 } 231 232 #endif // POWERDEVIL_POWERDEVILACTION_H 233