File indexing completed on 2024-04-21 14:56:36

0001 /*
0002     SPDX-FileCopyrightText: 2001, 2002 Ellis Whitehead <ellis@kde.org>
0003     SPDX-FileCopyrightText: 2007 Andreas Hartmetz <ahartmetz@gmail.com>
0004     SPDX-FileCopyrightText: 2020 David Redondo <kde@david-redondo.de>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #ifndef KSHORTCUTRECORDER_H
0010 #define KSHORTCUTRECORDER_H
0011 
0012 #include <kguiaddons_export.h>
0013 
0014 #include <QKeySequence>
0015 #include <QObject>
0016 #include <QWindow>
0017 
0018 #include <memory>
0019 
0020 class KeySequenceRecorderPrivate;
0021 
0022 /**
0023  * @class KeySequenceRecorder keysequencerecorder.h KeySequenceRecorder
0024  *
0025  * @short Record a QKeySequence by listening to key events in a window.
0026  *
0027  * After calling startRecording key events in the set window will be captured until a valid
0028  * QKeySequence has been recorded and gotKeySequence is emitted. See multiKeyShortcutsAllowed and
0029  * modifierlessAllowed for what constitutes a valid key sequence.
0030  *
0031  * During recording any shortcuts are inhibited and cannot be triggered. Either by using the
0032  * <a href="https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml">
0033  * keyboard-shortcuts-inhibit protocol </a> on Wayland or grabbing the keyboard.
0034  *
0035  * For graphical elements that record key sequences and can optionally perform conflict checking
0036  * against existing shortcuts see KKeySequenceWidget and KeySequenceItem.
0037  * @since 5.77
0038  * @see KKeySequenceWidget, KeySequenceItem
0039  */
0040 
0041 class KGUIADDONS_EXPORT KeySequenceRecorder : public QObject
0042 {
0043     Q_OBJECT
0044 
0045     /**
0046      * Whether key events are currently recorded
0047      */
0048     Q_PROPERTY(bool isRecording READ isRecording NOTIFY recordingChanged)
0049     /**
0050      * The recorded key sequence.
0051      * After construction this is empty.
0052      *
0053      * During recording it is continuously updated with the newest user input.
0054      *
0055      * After recording it contains the last recorded QKeySequence
0056      */
0057     Q_PROPERTY(QKeySequence currentKeySequence READ currentKeySequence WRITE setCurrentKeySequence NOTIFY currentKeySequenceChanged)
0058     /**
0059      * The window in which the key events are happening that should be recorded
0060      */
0061     Q_PROPERTY(QWindow *window READ window WRITE setWindow NOTIFY windowChanged)
0062     /**
0063      * If key presses of "plain" keys without a modifier are considered to be a valid finished
0064      * key combination.
0065      * Plain keys  include letter and symbol keys and text editing keys (Return, Space, Tab,
0066      * Backspace, Delete). Other keys like F1, Cursor keys, Insert, PageDown will always work.
0067      *
0068      * By default this is `false`.
0069      */
0070     Q_PROPERTY(bool modifierlessAllowed READ modifierlessAllowed WRITE setModifierlessAllowed NOTIFY modifierlessAllowedChanged)
0071     /** Controls the amount of key combinations that are captured until recording stops and gotKeySequence
0072      * is emitted.
0073      * By default  this is `true` and "Emacs-style" key sequences are recorded. Recording does not
0074      * stop until four valid key combination have been recorded. Afterwards `currentKeySequence().count()`
0075      * will be 4.
0076      *
0077      * Otherwise only one key combination is recorded before gotKeySequence is emitted with a
0078      * QKeySequence with a `count()` of  1.
0079      * @see QKeySequence
0080      */
0081     Q_PROPERTY(bool multiKeyShortcutsAllowed READ multiKeyShortcutsAllowed WRITE setMultiKeyShortcutsAllowed NOTIFY multiKeyShortcutsAllowedChanged)
0082 
0083     /**
0084      * It makes it acceptable for the key sequence to be just a modifier (e.g. Shift or Control)
0085      *
0086      * By default, if only a modifier is pressed and then released, the component will remain waiting for the sequence.
0087      * When enabled, it will take the modifier key as the key sequence.
0088      *
0089      * By default this is `false`.
0090      */
0091     Q_PROPERTY(bool modifierOnlyAllowed READ modifierOnlyAllowed WRITE setModifierOnlyAllowed NOTIFY modifierOnlyAllowedChanged)
0092 public:
0093     /**
0094      * Constructor.
0095      *
0096      * @par window The window whose key events will be recorded.
0097      * @see window
0098      */
0099     explicit KeySequenceRecorder(QWindow *window, QObject *parent = nullptr);
0100     ~KeySequenceRecorder() override;
0101 
0102     /**
0103      * Start recording.
0104      * Calling startRecording when window() is `nullptr` has no effect.
0105      */
0106     Q_INVOKABLE void startRecording();
0107 
0108     bool isRecording() const;
0109 
0110     QKeySequence currentKeySequence() const;
0111     void setCurrentKeySequence(const QKeySequence &sequence);
0112 
0113     QWindow *window() const;
0114     void setWindow(QWindow *window);
0115 
0116     bool multiKeyShortcutsAllowed() const;
0117     void setMultiKeyShortcutsAllowed(bool allowed);
0118 
0119     void setModifierlessAllowed(bool allowed);
0120     bool modifierlessAllowed() const;
0121 
0122     void setModifierOnlyAllowed(bool allowed);
0123     bool modifierOnlyAllowed() const;
0124 
0125 public Q_SLOTS:
0126     /**
0127      * Stops the recording session
0128      */
0129     void cancelRecording();
0130 
0131 Q_SIGNALS:
0132     /**
0133      * This signal is emitted when a key sequence has been recorded.
0134      *
0135      * Compared to currentKeySequenceChanged and currentKeySequence this is signal is not emitted
0136      * continuously during recording but only after recording has finished.
0137      */
0138     void gotKeySequence(const QKeySequence &keySequence);
0139 
0140     void recordingChanged();
0141     void windowChanged();
0142     void currentKeySequenceChanged();
0143     void multiKeyShortcutsAllowedChanged();
0144     void modifierlessAllowedChanged();
0145     void modifierOnlyAllowedChanged();
0146 
0147 private:
0148     friend class KeySequenceRecorderPrivate;
0149     std::unique_ptr<KeySequenceRecorderPrivate> const d;
0150 };
0151 
0152 #endif