File indexing completed on 2024-12-08 03:43:56
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2001, 2002 Ellis Whitehead <ellis@kde.org> 0004 SPDX-FileCopyrightText: 2007 Andreas Hartmetz <ahartmetz@gmail.com> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #ifndef KKEYSEQUENCEWIDGET_H 0010 #define KKEYSEQUENCEWIDGET_H 0011 0012 #include <kxmlgui_export.h> 0013 0014 #include <QList> 0015 #include <QPushButton> 0016 0017 class KKeySequenceWidgetPrivate; 0018 class QAction; 0019 class KActionCollection; 0020 0021 /** 0022 * @class KKeySequenceWidget kkeysequencewidget.h KKeySequenceWidget 0023 * 0024 * @short A widget to input a QKeySequence. 0025 * 0026 * This widget lets the user choose a QKeySequence, which is usually used as a 0027 * shortcut key. The recording is initiated by calling captureKeySequence() or 0028 * the user clicking into the widget. 0029 * 0030 * The widgets provides support for conflict handling. See 0031 * setCheckForConflictsAgainst() for more information. 0032 * 0033 * \image html kkeysequencewidget.png "KKeySequenceWidget" 0034 * 0035 * @author Mark Donohoe <donohoe@kde.org> 0036 */ 0037 class KXMLGUI_EXPORT KKeySequenceWidget : public QWidget 0038 { 0039 Q_OBJECT 0040 0041 /// @since 5.65 0042 Q_PROPERTY(QKeySequence keySequence READ keySequence WRITE setKeySequence NOTIFY keySequenceChanged) 0043 0044 Q_PROPERTY(bool multiKeyShortcutsAllowed READ multiKeyShortcutsAllowed WRITE setMultiKeyShortcutsAllowed) 0045 0046 Q_PROPERTY(ShortcutTypes checkForConflictsAgainst READ checkForConflictsAgainst WRITE setCheckForConflictsAgainst) 0047 0048 Q_PROPERTY(bool modifierlessAllowed READ isModifierlessAllowed WRITE setModifierlessAllowed) 0049 0050 public: 0051 /// An enum about validation when setting a key sequence. 0052 ///@see setKeySequence() 0053 enum Validation { 0054 /// Validate key sequence 0055 Validate = 0, 0056 /// Use key sequence without validation 0057 NoValidate = 1, 0058 }; 0059 0060 /** 0061 * Constructor. 0062 */ 0063 explicit KKeySequenceWidget(QWidget *parent = nullptr); 0064 0065 /** 0066 * Destructs the widget. 0067 */ 0068 ~KKeySequenceWidget() override; 0069 0070 /** 0071 * \name Configuration 0072 * 0073 * Configuration options for the widget. 0074 * @see ShortcutTypes 0075 */ 0076 //@{ 0077 0078 enum ShortcutType { 0079 None = 0x00, //!< No checking for conflicts 0080 LocalShortcuts = 0x01, //!< Check with local shortcuts. @see setCheckActionCollections() 0081 StandardShortcuts = 0x02, //!< Check against standard shortcuts. @see KStandardShortcut 0082 GlobalShortcuts = 0x04, //!< Check against global shortcuts. @see KGlobalAccel 0083 }; 0084 /** 0085 * Stores a combination of #ShortcutType values. 0086 */ 0087 Q_DECLARE_FLAGS(ShortcutTypes, ShortcutType) 0088 Q_FLAG(ShortcutTypes) 0089 0090 /** 0091 * Configure if the widget should check for conflicts with existing 0092 * shortcuts. 0093 * 0094 * When capturing a key sequence for local shortcuts you should check 0095 * against GlobalShortcuts and your other local shortcuts. This is the 0096 * default. 0097 * 0098 * You have to provide the local actions to check against with 0099 * setCheckActionCollections(). 0100 * 0101 * When capturing a key sequence for a global shortcut you should 0102 * check against StandardShortcuts, GlobalShortcuts and your local 0103 * shortcuts. 0104 * 0105 * There are two ways to react to a user agreeing to steal a shortcut: 0106 * 0107 * 1. Listen to the stealShortcut() signal and steal the shortcuts 0108 * manually. It's your responsibility to save that change later when 0109 * you think it is appropriate. 0110 * 0111 * 2. Call applyStealShortcut() and KKeySequenceWidget will steal the 0112 * shortcut. This will save the actionCollections the shortcut is part 0113 * of so make sure it doesn't inadvertly save some unwanted changes 0114 * too. Read its documentation for some limitation when handling 0115 * global shortcuts. 0116 * 0117 * If you want to do the conflict checking yourself here are some code 0118 * snippets for global ... 0119 * 0120 * \code 0121 * QStringList conflicting = KGlobalAccel::findActionNameSystemwide(keySequence); 0122 * if (!conflicting.isEmpty()) { 0123 * // Inform and ask the user about the conflict and reassigning 0124 * // the keys sequence 0125 * if (!KGlobalAccel::promptStealShortcutSystemwide(q, conflicting, keySequence)) { 0126 * return true; 0127 * } 0128 * KGlobalAccel::stealShortcutSystemwide(keySequence); 0129 * } 0130 * \endcode 0131 * 0132 * ... and standard shortcuts 0133 * 0134 * \code 0135 * KStandardShortcut::StandardShortcut ssc = KStandardShortcut::find(keySequence); 0136 * if (ssc != KStandardShortcut::AccelNone) { 0137 * // We have a conflict 0138 * } 0139 * \endcode 0140 * 0141 * 0142 * @since 4.2 0143 */ 0144 void setCheckForConflictsAgainst(ShortcutTypes types); 0145 0146 /** 0147 * The shortcut types we check for conflicts. 0148 * 0149 * @see setCheckForConflictsAgainst() 0150 * @since 4.2 0151 */ 0152 ShortcutTypes checkForConflictsAgainst() const; 0153 0154 /** 0155 * Allow multikey shortcuts? 0156 */ 0157 void setMultiKeyShortcutsAllowed(bool); 0158 bool multiKeyShortcutsAllowed() const; 0159 0160 /** 0161 * This only applies to user input, not to setKeySequence(). 0162 * Set whether to accept "plain" keys without modifiers (like Ctrl, Alt, Meta). 0163 * Plain keys by our definition include letter and symbol keys and 0164 * text editing keys (Return, Space, Tab, Backspace, Delete). 0165 * "Special" keys like F1, Cursor keys, Insert, PageDown will always work. 0166 */ 0167 void setModifierlessAllowed(bool allow); 0168 0169 /** 0170 * @see setModifierlessAllowed() 0171 */ 0172 bool isModifierlessAllowed(); 0173 0174 /** 0175 * Set whether a small button to set an empty key sequence should be displayed next to the 0176 * main input widget. The default is to show the clear button. 0177 */ 0178 void setClearButtonShown(bool show); 0179 0180 //@} 0181 0182 /** 0183 * Checks whether the key sequence @p seq is available to grab. 0184 * 0185 * The sequence is checked under the same rules as if it has been typed by 0186 * the user. This method is useful if you get key sequences from another 0187 * input source and want to check if it is save to set them. 0188 * 0189 * @since 4.2 0190 */ 0191 bool isKeySequenceAvailable(const QKeySequence &seq) const; 0192 0193 /** 0194 * Return the currently selected key sequence. 0195 */ 0196 QKeySequence keySequence() const; 0197 0198 /** 0199 * Set a list of action collections to check against for conflictuous shortcut. 0200 * 0201 * @see setCheckForConflictsAgainst() 0202 * 0203 * If a QAction with a conflicting shortcut is found inside this list and 0204 * its shortcut can be configured (KActionCollection::isShortcutConfigurable() 0205 * returns true) the user will be prompted whether to steal the shortcut 0206 * from this action. 0207 * 0208 * @since 4.1 0209 */ 0210 void setCheckActionCollections(const QList<KActionCollection *> &actionCollections); 0211 0212 /** 0213 * If the component using this widget supports shortcuts contexts, it has 0214 * to set its component name so we can check conflicts correctly. 0215 */ 0216 void setComponentName(const QString &componentName); 0217 0218 Q_SIGNALS: 0219 0220 /** 0221 * This signal is emitted when the current key sequence has changed, be it by user 0222 * input or programmatically. 0223 */ 0224 void keySequenceChanged(const QKeySequence &seq); 0225 0226 /** 0227 * This signal is emitted after the user agreed to steal a shortcut from 0228 * an action. This is only done for local shortcuts. So you can be sure \a 0229 * action is one of the actions you provided with setCheckActionList() or 0230 * setCheckActionCollections(). 0231 * 0232 * If you listen to that signal and don't call applyStealShortcut() you 0233 * are supposed to steal the shortcut and save this change. 0234 */ 0235 void stealShortcut(const QKeySequence &seq, QAction *action); 0236 0237 public Q_SLOTS: 0238 0239 /** 0240 * Capture a shortcut from the keyboard. This call will only return once a key sequence 0241 * has been captured or input was aborted. 0242 * If a key sequence was input, keySequenceChanged() will be emitted. 0243 * 0244 * @see setModifierlessAllowed() 0245 */ 0246 void captureKeySequence(); 0247 0248 /** 0249 * Set the key sequence. 0250 * 0251 * If @p val == Validate, and the call is actually changing the key sequence, 0252 * conflictuous shortcut will be checked. 0253 */ 0254 void setKeySequence(const QKeySequence &seq, Validation val = NoValidate); 0255 0256 /** 0257 * Clear the key sequence. 0258 */ 0259 void clearKeySequence(); 0260 0261 /** 0262 * Actually remove the shortcut that the user wanted to steal, from the 0263 * action that was using it. This only applies to actions provided to us 0264 * by setCheckActionCollections() and setCheckActionList(). 0265 * 0266 * Global and Standard Shortcuts have to be stolen immediately when the 0267 * user gives his consent (technical reasons). That means those changes 0268 * will be active even if you never call applyStealShortcut(). 0269 * 0270 * To be called before you apply your changes. No local shortcuts are 0271 * stolen until this function is called. 0272 */ 0273 void applyStealShortcut(); 0274 0275 private: 0276 friend class KKeySequenceWidgetPrivate; 0277 KKeySequenceWidgetPrivate *const d; 0278 0279 bool event(QEvent *ev) override; 0280 0281 Q_DISABLE_COPY(KKeySequenceWidget) 0282 }; 0283 0284 Q_DECLARE_OPERATORS_FOR_FLAGS(KKeySequenceWidget::ShortcutTypes) 0285 0286 #endif // KKEYSEQUENCEWIDGET_H