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