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 | |
20 | class 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 | */ |
47 | class 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 | |
134 | public: |
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 | |
211 | public Q_SLOTS: |
212 | /*! |
213 | * Stops the recording session |
214 | */ |
215 | void cancelRecording(); |
216 | |
217 | Q_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 | |
236 | private: |
237 | friend class KKeySequenceRecorderPrivate; |
238 | std::unique_ptr<KKeySequenceRecorderPrivate> const d; |
239 | }; |
240 | |
241 | Q_DECLARE_OPERATORS_FOR_FLAGS(KKeySequenceRecorder::Patterns) |
242 | |
243 | #endif |
244 | |