1 | // vim: noexpandtab ts=4 sw=4 |
2 | /* This file is part of the KDE libraries |
3 | Copyright (C) 2001, 2002 Ellis Whitehead <ellis@kde.org> |
4 | Copyright (C) 2007 Andreas Hartmetz <ahartmetz@gmail.com> |
5 | |
6 | This library is free software; you can redistribute it and/or |
7 | modify it under the terms of the GNU Library General Public |
8 | License as published by the Free Software Foundation; either |
9 | version 2 of the License, or (at your option) any later version. |
10 | |
11 | This library is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | Library General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU Library General Public License |
17 | along with this library; see the file COPYING.LIB. If not, write to |
18 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
19 | Boston, MA 02110-1301, USA. |
20 | */ |
21 | |
22 | #ifndef KKEYSEQUENCEWIDGET_H |
23 | #define KKEYSEQUENCEWIDGET_H |
24 | |
25 | #include <QtCore/QList> |
26 | #include <QtGui/QPushButton> |
27 | |
28 | #include <kshortcut.h> |
29 | |
30 | |
31 | class KKeySequenceWidgetPrivate; |
32 | class QAction; |
33 | class KAction; |
34 | class KActionCollection; |
35 | |
36 | /** |
37 | * @short A widget to input a QKeySequence. |
38 | * |
39 | * This widget lets the user choose a QKeySequence, which is usually used as a |
40 | * shortcut key. The recording is initiated by calling captureKeySequence() or |
41 | * the user clicking into the widget. |
42 | * |
43 | * The widgets provides support for conflict handling. See |
44 | * setCheckForConflictsAgainst() for more information. |
45 | * |
46 | * \image html kkeysequencewidget.png "KDE Key Sequence Widget" |
47 | * |
48 | * @author Mark Donohoe <donohoe@kde.org> |
49 | * @internal |
50 | */ |
51 | class KDEUI_EXPORT KKeySequenceWidget: public QWidget |
52 | { |
53 | Q_OBJECT |
54 | |
55 | Q_FLAGS(ShortcutTypes) |
56 | |
57 | Q_PROPERTY( |
58 | bool multiKeyShortcutsAllowed |
59 | READ multiKeyShortcutsAllowed |
60 | WRITE setMultiKeyShortcutsAllowed ) |
61 | |
62 | Q_PROPERTY( |
63 | ShortcutTypes checkForConflictsAgainst |
64 | READ checkForConflictsAgainst |
65 | WRITE setCheckForConflictsAgainst ) |
66 | |
67 | Q_PROPERTY( |
68 | bool modifierlessAllowed |
69 | READ isModifierlessAllowed |
70 | WRITE setModifierlessAllowed ) |
71 | |
72 | public: |
73 | ///An enum about validation when setting a key sequence. |
74 | ///@see setKeySequence() |
75 | enum Validation { |
76 | ///Validate key sequence |
77 | Validate = 0, |
78 | ///Use key sequence without validation |
79 | NoValidate = 1 |
80 | }; |
81 | |
82 | /** |
83 | * Constructor. |
84 | */ |
85 | explicit KKeySequenceWidget(QWidget *parent = 0); |
86 | |
87 | /** |
88 | * Destructs the widget. |
89 | */ |
90 | virtual ~KKeySequenceWidget(); |
91 | |
92 | /** |
93 | * \name Configuration |
94 | * |
95 | * Configuration options for the widget. |
96 | */ |
97 | //@{ |
98 | |
99 | enum ShortcutType { |
100 | None = 0x00, //!< No checking for conflicts |
101 | LocalShortcuts = 0x01, //!< Check with local shortcuts. @see setCheckActionCollections() |
102 | StandardShortcuts = 0x02, //!< Check against standard shortcuts. @see KStandardShortcut |
103 | GlobalShortcuts = 0x03 //!< Check against global shortcuts. @see KGlobalAccel |
104 | }; |
105 | Q_DECLARE_FLAGS(ShortcutTypes, ShortcutType) |
106 | |
107 | /** |
108 | * Configure if the widget should check for conflicts with existing |
109 | * shortcuts. |
110 | * |
111 | * When capturing a key sequence for local shortcuts you should check |
112 | * against GlobalShortcuts and your other local shortcuts. This is the |
113 | * default. |
114 | * |
115 | * You have to provide the local actions to check against with |
116 | * setCheckActionCollections(). |
117 | * |
118 | * When capturing a key sequence for a global shortcut you should |
119 | * check against StandardShortcuts, GlobalShortcuts and your local |
120 | * shortcuts. |
121 | * |
122 | * There are two ways to react to a user agreeing to steal a shortcut: |
123 | * |
124 | * 1. Listen to the stealShortcut() signal and steal the shortcuts |
125 | * manually. It's your responsibility to save that change later when |
126 | * you think it is appropriate. |
127 | * |
128 | * 2. Call applyStealShortcut and KKeySequenceWidget will steal the |
129 | * shortcut. This will save the actionCollections the shortcut is part |
130 | * of so make sure it doesn't inadvertly save some unwanted changes |
131 | * too. Read its documentation for some limitation when handling |
132 | * global shortcuts. |
133 | * |
134 | * If you want to do the conflict checking yourself here are some code |
135 | * snippets for global ... |
136 | * |
137 | * \code |
138 | * QStringList conflicting = KGlobalAccel::findActionNameSystemwide(keySequence); |
139 | * if (!conflicting.isEmpty()) { |
140 | * // Inform and ask the user about the conflict and reassigning |
141 | * // the keys sequence |
142 | * if (!KGlobalAccel::promptStealShortcutSystemwide(q, conflicting, keySequence)) { |
143 | * return true; |
144 | * } |
145 | * KGlobalAccel::stealShortcutSystemwide(keySequence); |
146 | * } |
147 | * \endcode |
148 | * |
149 | * ... and standard shortcuts |
150 | * |
151 | * \code |
152 | * KStandardShortcut::StandardShortcut ssc = KStandardShortcut::find(keySequence); |
153 | * if (ssc != KStandardShortcut::AccelNone) { |
154 | * // We have a conflict |
155 | * } |
156 | * \endcode |
157 | * |
158 | * |
159 | * @since 4.2 |
160 | */ |
161 | void setCheckForConflictsAgainst( ShortcutTypes types ); |
162 | |
163 | /** |
164 | * The shortcut types we check for conflicts. |
165 | * |
166 | * @see setCheckForConflictsAgainst() |
167 | * @since 4.2 |
168 | */ |
169 | ShortcutTypes checkForConflictsAgainst() const; |
170 | |
171 | /** |
172 | * Allow multikey shortcuts? |
173 | */ |
174 | void setMultiKeyShortcutsAllowed(bool); |
175 | bool multiKeyShortcutsAllowed() const; |
176 | |
177 | /** |
178 | * This only applies to user input, not to setShortcut(). |
179 | * Set whether to accept "plain" keys without modifiers (like Ctrl, Alt, Meta). |
180 | * Plain keys by our definition include letter and symbol keys and |
181 | * text editing keys (Return, Space, Tab, Backspace, Delete). |
182 | * "Special" keys like F1, Cursor keys, Insert, PageDown will always work. |
183 | */ |
184 | void setModifierlessAllowed(bool allow); |
185 | |
186 | /** |
187 | * @see setModifierlessAllowed() |
188 | */ |
189 | bool isModifierlessAllowed(); |
190 | |
191 | /** |
192 | * Set whether a small button to set an empty key sequence should be displayed next to the |
193 | * main input widget. The default is to show the clear button. |
194 | */ |
195 | void setClearButtonShown(bool show); |
196 | |
197 | //@} |
198 | |
199 | /** |
200 | * Checks whether the key sequence @a seq is available to grab. |
201 | * |
202 | * The sequence is checked under the same rules as if it has been typed by |
203 | * the user. This method is useful if you get key sequences from another |
204 | * input source and want to check if it is save to set them. |
205 | * |
206 | * @since 4.2 |
207 | */ |
208 | bool isKeySequenceAvailable(const QKeySequence &seq) const; |
209 | |
210 | /** |
211 | * Return the currently selected key sequence. |
212 | */ |
213 | QKeySequence keySequence() const; |
214 | |
215 | /** |
216 | * Set a list of action collections to check against for conflictuous shortcut. |
217 | * |
218 | * @see setCheckForConflictsAgainst() |
219 | * |
220 | * If a KAction with a conflicting shortcut is found inside this list and |
221 | * its shortcut can be configured (KAction::isShortcutConfigurable() |
222 | * returns true) the user will be prompted whether to steal the shortcut |
223 | * from this action. |
224 | * |
225 | * @since 4.1 |
226 | */ |
227 | void setCheckActionCollections(const QList<KActionCollection *>& actionCollections); |
228 | |
229 | /** |
230 | * @deprecated since 4.1 |
231 | * use setCheckActionCollections so that KKeySequenceWidget knows |
232 | * in which action collection to call the writeSettings method after stealing |
233 | * a shortcut from an action. |
234 | */ |
235 | #ifndef KDE_NO_DEPRECATED |
236 | KDE_DEPRECATED void setCheckActionList(const QList<QAction*> &checkList); |
237 | #endif |
238 | |
239 | /** |
240 | * If the component using this widget supports shortcuts contexts, it has |
241 | * to set its component name so we can check conflicts correctly. |
242 | */ |
243 | void setComponentName(const QString &componentName); |
244 | |
245 | |
246 | Q_SIGNALS: |
247 | |
248 | /** |
249 | * This signal is emitted when the current key sequence has changed, be it by user |
250 | * input or programmatically. |
251 | */ |
252 | void keySequenceChanged(const QKeySequence &seq); |
253 | |
254 | /** |
255 | * This signal is emitted after the user agreed to steal a shortcut from |
256 | * an action. This is only done for local shortcuts. So you can be sure \a |
257 | * action is one of the actions you provided with setCheckActionList() or |
258 | * setCheckActionCollections(). |
259 | * |
260 | * If you listen to that signal and don't call applyStealShortcut() you |
261 | * are supposed to steal the shortcut and save this change. |
262 | */ |
263 | void stealShortcut(const QKeySequence &seq, KAction *action); |
264 | |
265 | public Q_SLOTS: |
266 | |
267 | /** |
268 | * Capture a shortcut from the keyboard. This call will only return once a key sequence |
269 | * has been captured or input was aborted. |
270 | * If a key sequence was input, keySequenceChanged() will be emitted. |
271 | * |
272 | * @see setModifierlessAllowed() |
273 | */ |
274 | void captureKeySequence(); |
275 | |
276 | /** |
277 | * Set the key sequence. |
278 | * |
279 | * If @p val == Validate, and the call is actually changing the key sequence, |
280 | * conflictuous shortcut will be checked. |
281 | */ |
282 | void setKeySequence(const QKeySequence &seq, Validation val = NoValidate); |
283 | |
284 | /** |
285 | * Clear the key sequence. |
286 | */ |
287 | void clearKeySequence(); |
288 | |
289 | /** |
290 | * Actually remove the shortcut that the user wanted to steal, from the |
291 | * action that was using it. This only applies to actions provided to us |
292 | * by setCheckActionCollections() and setCheckActionList(). |
293 | * |
294 | * Global and Standard Shortcuts have to be stolen immediately when the |
295 | * user gives his consent (technical reasons). That means those changes |
296 | * will be active even if you never call applyStealShortcut(). |
297 | * |
298 | * To be called before you apply your changes. No local shortcuts are |
299 | * stolen until this function is called. |
300 | */ |
301 | void applyStealShortcut(); |
302 | |
303 | private: |
304 | Q_PRIVATE_SLOT(d, void doneRecording()) |
305 | |
306 | private: |
307 | friend class KKeySequenceWidgetPrivate; |
308 | KKeySequenceWidgetPrivate *const d; |
309 | |
310 | Q_DISABLE_COPY(KKeySequenceWidget) |
311 | }; |
312 | |
313 | Q_DECLARE_OPERATORS_FOR_FLAGS(KKeySequenceWidget::ShortcutTypes) |
314 | |
315 | #endif //KKEYSEQUENCEWIDGET_H |
316 | |