1/*
2 SPDX-FileCopyrightText: 2001, 2002 Ellis Whitehead <ellis@kde.org>
3 SPDX-FileCopyrightText: 2007 Andreas Hartmetz <ahartmetz@gmail.com>
4 SPDX-FileCopyrightText: 2020 David Redondo <kde@david-redondo.de>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
9#ifndef KKEYSEQUENCERECORDER_H
10#define KKEYSEQUENCERECORDER_H
11
12#include <kguiaddons_export.h>
13
14#include <QKeySequence>
15#include <QObject>
16#include <QWindow>
17
18#include <memory>
19
20class KKeySequenceRecorderPrivate;
21
22/*!
23 * \class KKeySequenceRecorder
24 * \inmodule KGuiAddons
25 * \brief Record a QKeySequence by listening to key events in a window.
26 *
27 * After calling startRecording key events in the set window will be captured until a valid
28 * QKeySequence has been recorded and gotKeySequence is emitted. See multiKeyShortcutsAllowed and
29 * modifierlessAllowed for what constitutes a valid key sequence.
30 *
31 * During recording any shortcuts are inhibited and cannot be triggered. Either by using the
32 * \l {https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml}
33 * {keyboard-shortcuts-inhibit protocol} on Wayland or grabbing the keyboard.
34 *
35 * For graphical elements that record key sequences and can optionally perform conflict checking
36 * against existing shortcuts see KKeySequenceWidget and KeySequenceItem.
37 *
38 * Porting from KF5 to KF6:
39 *
40 * The class KeySequenceRecorder was renamed to KKeySequenceRecorder.
41 *
42 * \sa KKeySequenceWidget
43 * \sa KeySequenceItem
44 *
45 * \since 6.0
46 */
47class KGUIADDONS_EXPORT KKeySequenceRecorder : public QObject
48{
49 Q_OBJECT
50
51 /*!
52 * \property KKeySequenceRecorder::isRecording
53 *
54 * Whether key events are currently recorded
55 */
56 Q_PROPERTY(bool isRecording READ isRecording NOTIFY recordingChanged)
57 /*!
58 * \property KKeySequenceRecorder::currentKeySequence
59 *
60 * The recorded key sequence.
61 * After construction this is empty.
62 *
63 * During recording it is continuously updated with the newest user input.
64 *
65 * After recording it contains the last recorded QKeySequence
66 */
67 Q_PROPERTY(QKeySequence currentKeySequence READ currentKeySequence WRITE setCurrentKeySequence NOTIFY currentKeySequenceChanged)
68 /*!
69 * \property KKeySequenceRecorder::window
70 *
71 * The window in which the key events are happening that should be recorded
72 */
73 Q_PROPERTY(QWindow *window READ window WRITE setWindow NOTIFY windowChanged)
74 /*!
75 * \property KKeySequenceRecorder::modifierlessAllowed
76 *
77 * If key presses of "plain" keys without a modifier are considered to be a valid finished
78 * key combination.
79 * Plain keys include letter and symbol keys and text editing keys (Return, Space, Tab,
80 * Backspace, Delete). Other keys like F1, Cursor keys, Insert, PageDown will always work.
81 *
82 * By default this is \c false.
83 *
84 * \deprecated[6.12]
85 *
86 * Use the patterns property instead.
87 */
88 Q_PROPERTY(bool modifierlessAllowed READ modifierlessAllowed WRITE setModifierlessAllowed NOTIFY modifierlessAllowedChanged)
89 /*!
90 * \property KKeySequenceRecorder::multiKeyShortcutsAllowed
91 *
92 * Controls the amount of key combinations that are captured until recording stops and gotKeySequence
93 * is emitted.
94 * By default this is \c true and "Emacs-style" key sequences are recorded. Recording does not
95 * stop until four valid key combination have been recorded. Afterwards currentKeySequence().count()
96 * will be 4.
97 *
98 * Otherwise only one key combination is recorded before gotKeySequence is emitted with a
99 * QKeySequence with a count() of 1.
100 * \sa QKeySequence
101 */
102 Q_PROPERTY(bool multiKeyShortcutsAllowed READ multiKeyShortcutsAllowed WRITE setMultiKeyShortcutsAllowed NOTIFY multiKeyShortcutsAllowedChanged)
103
104 /*!
105 * \property KKeySequenceRecorder::modifierOnlyAllowed
106 *
107 * It makes it acceptable for the key sequence to be just a modifier (e.g. Shift or Control)
108 *
109 * By default, if only a modifier is pressed and then released, the component will remain waiting for the sequence.
110 * When enabled, it will take the modifier key as the key sequence.
111 *
112 * By default this is \c false.
113 *
114 * \deprecated[6.12]
115 * Use the patterns property instead.
116 */
117 Q_PROPERTY(bool modifierOnlyAllowed READ modifierOnlyAllowed WRITE setModifierOnlyAllowed NOTIFY modifierOnlyAllowedChanged)
118
119 /*!
120 * \property KKeySequenceRecorder::patterns
121 *
122 * Specifies what components the recorded shortcut must have, for example whether the shortcut
123 * must contain only modifier keys (Modifier) or modifiers keys and a normal key (ModifierAndKey).
124 *
125 * The patterns property can contain one or more recording patterns. For example, if the recorder
126 * accepts both normal and modifier only shortcuts, e.g. Modifier | ModifierAndKey.
127 *
128 * By default this is ModifierAndKey.
129 *
130 * \since 6.12
131 */
132 Q_PROPERTY(Patterns patterns READ patterns WRITE setPatterns NOTIFY patternsChanged)
133
134public:
135 /*!
136 * The Pattern type specifies what components the recorded shortcut must have, e.g. modifiers or just a key.
137 *
138 * \value Modifier The recorded shortcut must contain one or more modifier keys (Meta, Shift, Ctrl, or Alt).
139 * \value Key The recorded shortcut must contain only one regular key, e.g. "A".
140 * \value ModifierAndKey The recorded shortcut must contain one or more modifier keys followed by a regular key,
141 * e.g. Meta+A.
142 * Note: with this pattern, special keys like "Insert" without any pressed modifier will be
143 * captured too. Please do not rely on this behavior and instead use Key | ModifierAndKey
144 * explicitly. The future versions of KKeySequenceRecorder are expected not to record special
145 * keys in the ModifierAndKey mode.
146 */
147 enum Pattern {
148 Modifier = 0x1,
149 Key = 0x2,
150 ModifierAndKey = 0x4,
151 };
152 Q_DECLARE_FLAGS(Patterns, Pattern)
153 Q_FLAG(Patterns)
154
155 /*!
156 * Constructor.
157 *
158 * \a window The window whose key events will be recorded.
159 *
160 * \sa window
161 */
162 explicit KKeySequenceRecorder(QWindow *window, QObject *parent = nullptr);
163 ~KKeySequenceRecorder() override;
164
165 /*!
166 * Start recording.
167 * Calling startRecording when window() is \c nullptr has no effect.
168 */
169 Q_INVOKABLE void startRecording();
170
171 bool isRecording() const;
172
173 QKeySequence currentKeySequence() const;
174 void setCurrentKeySequence(const QKeySequence &sequence);
175
176 QWindow *window() const;
177 void setWindow(QWindow *window);
178
179 bool multiKeyShortcutsAllowed() const;
180 void setMultiKeyShortcutsAllowed(bool allowed);
181
182#if KGUIADDONS_ENABLE_DEPRECATED_SINCE(6, 12)
183 /*!
184 * \deprecated[6.12]
185 * Use setPatterns() instead
186 */
187 KGUIADDONS_DEPRECATED_VERSION(6, 12, "use setPatterns() instead") void setModifierlessAllowed(bool allowed);
188
189 /*!
190 * \deprecated[6.12]
191 * Use patterns() instead
192 */
193 KGUIADDONS_DEPRECATED_VERSION(6, 12, "use patterns() instead") bool modifierlessAllowed() const;
194
195 /*!
196 * \deprecated[6.12]
197 * Use setPatterns() instead
198 */
199 KGUIADDONS_DEPRECATED_VERSION(6, 12, "use setPatterns() instead") void setModifierOnlyAllowed(bool allowed);
200
201 /*!
202 * \deprecated[6.12]
203 * Use patterns() instead
204 */
205 KGUIADDONS_DEPRECATED_VERSION(6, 12, "use patterns() instead") bool modifierOnlyAllowed() const;
206#endif
207
208 void setPatterns(Patterns patterns);
209 Patterns patterns() const;
210
211public Q_SLOTS:
212 /*!
213 * Stops the recording session
214 */
215 void cancelRecording();
216
217Q_SIGNALS:
218 /*!
219 * This signal is emitted when a key sequence has been recorded.
220 *
221 * Compared to currentKeySequenceChanged and currentKeySequence this is signal is not emitted
222 * continuously during recording but only after recording has finished.
223 */
224 void gotKeySequence(const QKeySequence &keySequence);
225
226 void recordingChanged();
227 void windowChanged();
228 void currentKeySequenceChanged();
229 void multiKeyShortcutsAllowedChanged();
230#if KGUIADDONS_ENABLE_DEPRECATED_SINCE(6, 12)
231 KGUIADDONS_DEPRECATED_VERSION(6, 12, "use patternsChanged() instead") void modifierlessAllowedChanged();
232 KGUIADDONS_DEPRECATED_VERSION(6, 12, "use patternsChanged() instead") void modifierOnlyAllowedChanged();
233#endif
234 void patternsChanged();
235
236private:
237 friend class KKeySequenceRecorderPrivate;
238 std::unique_ptr<KKeySequenceRecorderPrivate> const d;
239};
240
241Q_DECLARE_OPERATORS_FOR_FLAGS(KKeySequenceRecorder::Patterns)
242
243#endif
244

source code of kguiaddons/src/recorder/kkeysequencerecorder.h