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