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
20class QAction;
21class 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 */
47class KGLOBALACCEL_EXPORT KGlobalAccel : public QObject
48{
49 Q_OBJECT
50
51public:
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
322Q_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
345private:
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
356KGLOBALACCEL_EXPORT QDBusArgument &operator<<(QDBusArgument &argument, const KGlobalAccel::MatchType &type);
357KGLOBALACCEL_EXPORT const QDBusArgument &operator>>(const QDBusArgument &argument, KGlobalAccel::MatchType &type);
358
359#endif // _KGLOBALACCEL_H_
360

source code of kglobalaccel/src/kglobalaccel.h