1 | /* |
2 | This file is part of the KDE libraries |
3 | SPDX-FileCopyrightText: 2001, 2002 Ellis Whitehead <ellis@kde.org> |
4 | SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org> |
5 | SPDX-FileCopyrightText: 2007 Andreas Hartmetz <ahartmetz@gmail.com> |
6 | |
7 | SPDX-License-Identifier: LGPL-2.0-or-later |
8 | */ |
9 | |
10 | #ifndef _KGLOBALACCEL_H_ |
11 | #define _KGLOBALACCEL_H_ |
12 | |
13 | #include "kglobalshortcutinfo.h" |
14 | #include <kglobalaccel_export.h> |
15 | |
16 | #include <QKeySequence> |
17 | #include <QList> |
18 | #include <QObject> |
19 | |
20 | class QAction; |
21 | class OrgKdeKglobalaccelComponentInterface; |
22 | |
23 | /*! |
24 | * \class KGlobalAccel |
25 | * \inmodule KGlobalAccel |
26 | * \brief Configurable global shortcut support. |
27 | * |
28 | * KGlobalAccel allows you to have global accelerators that are independent of |
29 | * the focused window. Unlike regular shortcuts, the application's window does not need focus |
30 | * for them to be activated. |
31 | * |
32 | * Here's an example how to register the Meta + E global shortcut: |
33 | * |
34 | * \code |
35 | * QAction *action = new QAction(); |
36 | * action->setObjectName(QStringLiteral("actionId")); |
37 | * action->setText(QStringLiteral("human readable name")); |
38 | * KGlobalAccel::self()->setDefaultShortcut(action, QList<QKeySequence>() << (Qt::META | Qt::Key_E)); |
39 | * KGlobalAccel::self()->setShortcut(action, QList<QKeySequence>() << (Qt::META | Qt::Key_E)); |
40 | * connect(action, &QAction::triggered, []() { |
41 | * qDebug() << "global shortcut trigerred"; |
42 | * }); |
43 | * \endcode |
44 | * |
45 | * \sa KKeySequenceRecorder |
46 | */ |
47 | class KGLOBALACCEL_EXPORT KGlobalAccel : public QObject |
48 | { |
49 | Q_OBJECT |
50 | |
51 | public: |
52 | /*! |
53 | * \enum KGlobalAccel::GlobalShortcutLoading |
54 | * |
55 | * An enum about global shortcut setter semantics |
56 | * |
57 | * \value Autoloading |
58 | * Look up the action in global settings (using its main component's name and text()) and |
59 | * set the shortcut as saved there. |
60 | * \sa setGlobalShortcut() |
61 | * \value NoAutoloading |
62 | * Prevent autoloading of saved global shortcut for action. |
63 | */ |
64 | enum GlobalShortcutLoading { |
65 | Autoloading = 0x0, |
66 | NoAutoloading = 0x4, |
67 | }; |
68 | |
69 | /*! |
70 | * \enum KGlobalAccel::actionIdFields |
71 | * |
72 | * Index for actionId QStringLists |
73 | * |
74 | * \value ComponentUnique |
75 | * Components Unique Name (ID). |
76 | * \value ActionUnique |
77 | * Actions Unique Name (ID). |
78 | * \value ComponentFriendly |
79 | * Components Friendly Translated Name |
80 | * \value ActionFriendly |
81 | * Actions Friendly Translated Name |
82 | */ |
83 | enum actionIdFields { |
84 | ComponentUnique = 0, |
85 | ActionUnique = 1, |
86 | ComponentFriendly = 2, |
87 | ActionFriendly = 3, |
88 | }; |
89 | |
90 | /*! |
91 | * \enum KGlobalAccel::MatchType |
92 | * |
93 | * Keysequence match semantics. |
94 | * |
95 | * Assuming we have an Emacs-style shortcut, for example (Alt+B, Alt+F, Alt+G) already assigned, |
96 | * how a new shortcut is compared depends on which value of the enum is used. |
97 | * |
98 | * \value Equal Exact matching: (Alt+B, Alt+F, Alt+G) |
99 | * \value Shadows Sequence shadowing: (Alt+B, Alt+F), (Alt+F, Alt+G) |
100 | * \value Shadowed Sequence being shadowed: (Alt+B, Alt+F, Alt+G, <any key>), (<any key>, Alt+B, Alt+F, Alt+G) |
101 | * |
102 | * \since 5.90 |
103 | */ |
104 | enum MatchType { |
105 | Equal, |
106 | Shadows, |
107 | Shadowed, |
108 | }; |
109 | Q_ENUM(MatchType) |
110 | |
111 | /*! |
112 | * Returns (and creates if necessary) the singleton instance |
113 | */ |
114 | static KGlobalAccel *self(); |
115 | |
116 | /*! |
117 | * Take away the given shortcut \a seq from the named action it belongs to. |
118 | * This applies to all actions with global shortcuts in any KDE application. |
119 | * |
120 | * \sa promptStealShortcutSystemwide() |
121 | */ |
122 | static void stealShortcutSystemwide(const QKeySequence &seq); |
123 | |
124 | /*! |
125 | * Clean the shortcuts for component \a componentUnique. |
126 | * |
127 | * If the component is not active all global shortcut registrations are |
128 | * purged and the component is removed completely. |
129 | * |
130 | * If the component is active all global shortcut registrations not in use |
131 | * will be purged. If there is no shortcut registration left the component |
132 | * is purged too. |
133 | * |
134 | * If a purged component or shortcut is activated the next time it will |
135 | * reregister itself. All you probably will lose on wrong usage are the |
136 | * user's set shortcuts. |
137 | * |
138 | * If you make sure your component is running and all global shortcuts it |
139 | * has are active this function can be used to clean up the registry. |
140 | * |
141 | * Handle with care! |
142 | * |
143 | * If the method return \c true at least one shortcut was purged so handle |
144 | * all previously acquired information with care. |
145 | */ |
146 | static bool cleanComponent(const QString &componentUnique); |
147 | |
148 | /*! |
149 | * Returns \c true if the component with the given \a componentName exists; otherwise returns \c false. |
150 | */ |
151 | static bool isComponentActive(const QString &componentName); |
152 | |
153 | /*! |
154 | * Returns a list of global shortcuts registered for the shortcut \a seq using |
155 | * the given matching \a type. |
156 | * |
157 | * If the list contains more that one entry it means the component |
158 | * that registered the shortcuts uses global shortcut contexts. All |
159 | * returned shortcuts belong to the same component. |
160 | * |
161 | * \since 5.90 |
162 | */ |
163 | static QList<KGlobalShortcutInfo> globalShortcutsByKey(const QKeySequence &seq, MatchType type = Equal); |
164 | |
165 | /*! |
166 | * Returns \c true if the shortcut \a seq is available for the \a component; otherwise returns |
167 | * \c false. |
168 | * |
169 | * The component is only of interest if the current application uses global shortcut |
170 | * contexts. In that case a global shortcut by \a component in an inactive |
171 | * global shortcut contexts does not block the \a seq for us. |
172 | * |
173 | * \since 4.2 |
174 | */ |
175 | static bool isGlobalShortcutAvailable(const QKeySequence &seq, const QString &component = QString()); |
176 | |
177 | /*! |
178 | * Show a messagebox to inform the user that a global shortcut is already occupied, |
179 | * and ask to take it away from its current action(s). This is GUI only, so nothing will |
180 | * be actually changed. |
181 | * |
182 | * Returns \c true if user confirms that it is okay to re-assign the global shorcut; |
183 | * otherwise returns \c false. |
184 | * |
185 | * \sa stealShortcutSystemwide() |
186 | * |
187 | * \since 4.2 |
188 | */ |
189 | static bool promptStealShortcutSystemwide(QWidget *parent, const QList<KGlobalShortcutInfo> &shortcuts, const QKeySequence &seq); |
190 | |
191 | /*! |
192 | * Assign a default global \a shortcut for a given \a action. |
193 | * |
194 | * For more information about global shortcuts and \a loadFlag, see setShortcut(). |
195 | * |
196 | * Upon shortcut change the globalShortcutChanged() will be triggered so other applications get notified. |
197 | * |
198 | * Returns \c true if the shortcut has been set successfully; otherwise returns \c false. |
199 | * |
200 | * \sa globalShortcutChanged() |
201 | * |
202 | * \since 5.0 |
203 | */ |
204 | bool setDefaultShortcut(QAction *action, const QList<QKeySequence> &shortcut, GlobalShortcutLoading loadFlag = Autoloading); |
205 | |
206 | /*! |
207 | * Assign a global shortcut for the given action. |
208 | * |
209 | * Global shortcuts allow an action to respond to key shortcuts independently of the focused window, |
210 | * i.e. the action will trigger if the keys were pressed no matter where in the X session. |
211 | * |
212 | * The action must have a per main component unique |
213 | * action->objectName() to enable cross-application bookkeeping. If the action->objectName() is |
214 | * empty this method will do nothing and will return false. |
215 | * |
216 | * It is mandatory that the action->objectName() doesn't change once the shortcut has been |
217 | * successfully registered. |
218 | * |
219 | * \note KActionCollection::insert(name, action) will set action's objectName to name so you often |
220 | * don't have to set an objectName explicitly. |
221 | * |
222 | * When an action, identified by main component name and objectName(), is assigned |
223 | * a global shortcut for the first time on a KDE installation the assignment will |
224 | * be saved. The shortcut will then be restored every time setGlobalShortcut() is |
225 | * called with \a loadFlag == Autoloading. |
226 | * |
227 | * If you actually want to change the global shortcut you have to set |
228 | * \a loadFlag to NoAutoloading. The new shortcut will be automatically saved again. |
229 | * |
230 | * \a action specifies the action for which the shortcut will be assigned. |
231 | * |
232 | * \a shortcut specifies the global shortcut(s) to assign. Will be ignored unless \a loadFlag is |
233 | * set to NoAutoloading or this is the first time ever you call this method (see above). |
234 | * |
235 | * If \a loadFlag is KGlobalAccel::Autoloading, assign the global shortcut this action has |
236 | * previously had if any. That way user preferences and changes made to avoid clashes will be |
237 | * conserved. If KGlobalAccel::NoAutoloading the given shortcut will be assigned without |
238 | * looking up old values. You should only do this if the user wants to change the shortcut or |
239 | * if you have another very good reason. Key combinations that clash with other shortcuts will be |
240 | * dropped. |
241 | * |
242 | * \note the default shortcut will never be influenced by autoloading - it will be set as given. |
243 | * \sa shortcut(), globalShortcutChanged() |
244 | * \since 5.0 |
245 | */ |
246 | bool setShortcut(QAction *action, const QList<QKeySequence> &shortcut, GlobalShortcutLoading loadFlag = Autoloading); |
247 | |
248 | /*! |
249 | * Sets both active and default \a shortcuts for the given \a action. |
250 | * |
251 | * If more control for loading the shortcuts is needed use the variants offering more control. |
252 | * |
253 | * Returns \c true if the shortcut has been set successfully; otherwise returns \c false. |
254 | * |
255 | * \sa setShortcut(), setDefaultShortcut() |
256 | * \since 5.0 |
257 | */ |
258 | static bool setGlobalShortcut(QAction *action, const QList<QKeySequence> &shortcuts); |
259 | |
260 | /*! |
261 | * Sets both active and default \a shortcut for the given \a action. |
262 | * |
263 | * This method is suited for the case that only one shortcut is to be configured. |
264 | * |
265 | * If more control for loading the shortcuts is needed use the variants offering more control. |
266 | * |
267 | * Returns \c true if the shortcut has been set successfully; otherwise returns \c false. |
268 | * |
269 | * \sa setShortcut(), setDefaultShortcut() |
270 | * \since 5.0 |
271 | */ |
272 | static bool setGlobalShortcut(QAction *action, const QKeySequence &shortcut); |
273 | |
274 | /*! |
275 | * Get the global default shortcut for this \a action, if one exists. Global shortcuts |
276 | * allow your actions to respond to accellerators independently of the focused window. |
277 | * Unlike regular shortcuts, the application's window does not need focus |
278 | * for them to be activated. |
279 | * |
280 | * \sa setDefaultShortcut() |
281 | * \since 5.0 |
282 | */ |
283 | QList<QKeySequence> defaultShortcut(const QAction *action) const; |
284 | |
285 | /*! |
286 | * Get the global shortcut for this \a action, if one exists. Global shortcuts |
287 | * allow your actions to respond to accellerators independently of the focused window. |
288 | * Unlike regular shortcuts, the application's window does not need focus |
289 | * for them to be activated. |
290 | * |
291 | * \note that this method only works together with setShortcut() because the action pointer |
292 | * is used to retrieve the result. If you would like to retrieve the shortcut as stored |
293 | * in the global settings, use the globalShortcut(componentName, actionId) instead. |
294 | * |
295 | * \sa setShortcut() |
296 | * \since 5.0 |
297 | */ |
298 | QList<QKeySequence> shortcut(const QAction *action) const; |
299 | |
300 | /*! |
301 | * Retrieves the shortcut as defined in global settings by |
302 | * \a componentName (e.g. "kwin") and \a actionId (e.g. "Kill Window"). |
303 | * |
304 | * \since 5.10 |
305 | */ |
306 | QList<QKeySequence> globalShortcut(const QString &componentName, const QString &actionId) const; |
307 | |
308 | /*! |
309 | * Unregister and remove all defined global shortcuts for the given \a action. |
310 | * |
311 | * \since 5.0 |
312 | */ |
313 | void removeAllShortcuts(QAction *action); |
314 | |
315 | /*! |
316 | * Returns true if a shortcut or a default shortcut has been registered for the given \a action. |
317 | * |
318 | * \since 5.0 |
319 | */ |
320 | bool hasShortcut(const QAction *action) const; |
321 | |
322 | Q_SIGNALS: |
323 | /*! |
324 | * Emitted when the global shortcut is changed. A global shortcut is subject to be changed by |
325 | * the global shortcuts kcm. |
326 | * |
327 | * \a action specifies the action for which the changed shortcut was registered. |
328 | * |
329 | * \a seq indicates the key sequence that corresponds to the changed shortcut. |
330 | * |
331 | * \sa setGlobalShortcut(), setDefaultShortcut() |
332 | * \since 5.0 |
333 | */ |
334 | void globalShortcutChanged(QAction *action, const QKeySequence &seq); |
335 | /*! |
336 | * Emitted when a global shortcut for the given \a action is activated or deactivated. |
337 | * |
338 | * The global shorcut will be activated when the keys are pressed and deactivated when the |
339 | * keys are released. \a active indicates whether the global shortcut is active. |
340 | * |
341 | * \since 5.94 |
342 | */ |
343 | void globalShortcutActiveChanged(QAction *action, bool active); |
344 | |
345 | private: |
346 | KGLOBALACCEL_NO_EXPORT KGlobalAccel(); |
347 | KGLOBALACCEL_NO_EXPORT ~KGlobalAccel() override; |
348 | |
349 | KGLOBALACCEL_NO_EXPORT OrgKdeKglobalaccelComponentInterface *getComponent(const QString &componentUnique); |
350 | |
351 | class KGlobalAccelPrivate *const d; |
352 | |
353 | friend class KGlobalAccelSingleton; |
354 | }; |
355 | |
356 | KGLOBALACCEL_EXPORT QDBusArgument &operator<<(QDBusArgument &argument, const KGlobalAccel::MatchType &type); |
357 | KGLOBALACCEL_EXPORT const QDBusArgument &operator>>(const QDBusArgument &argument, KGlobalAccel::MatchType &type); |
358 | |
359 | #endif // _KGLOBALACCEL_H_ |
360 | |