Kirigami2

mnemonicattached.h
1 /*
2  * SPDX-FileCopyrightText: 2017 Marco Martin <[email protected]>
3  *
4  * SPDX-License-Identifier: LGPL-2.0-or-later
5  */
6 
7 #ifndef MNEMONICATTACHED_H
8 #define MNEMONICATTACHED_H
9 
10 #include <QObject>
11 #include <QQuickWindow>
12 
13 /**
14  * @brief This attached property allows to define keyboard sequences to trigger
15  * actions based upon their text.
16  *
17  * A mnemonic, otherwise known as an accelerator, is an accessibility feature to
18  * signal to the user that a certain action (typically in a menu) can be
19  * triggered by pressing Alt + a certain key that is indicated by an ampersand
20  * sign (&). For instance, a File menu could be marked in code as &File and
21  * would be displayed to the user with an underscore under the letter F. This
22  * allows to invoke actions without having to navigate the UI with a mouse.
23  *
24  * This class automates the management of mnemonics, so if a key is already
25  * taken, the next available key is used. Likewise, certain components get
26  * increased priority: an "OK/Cancel" buttons in a Dialog will have priority
27  * over fields of a org::kde::kirigami::FormLayout.
28  *
29  * Mnemonics are already managed by visual QtQuick and Kirigami controls, so
30  * only use this class to implement your own visual QML controls.
31  *
32  * @see ::ControlType
33  *
34  * @since org.kde.kirigami 2.3
35  */
36 class MnemonicAttached : public QObject
37 {
38  Q_OBJECT
39  /**
40  * @brief This property holds the label of the control that we want to
41  * compute a mnemonic for.
42  *
43  * For example: ``"Label:"`` or ``"&Ok"``
44  */
45  Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged)
46 
47  /**
48  * @brief This property holds the user-visible final label.
49  *
50  * The user-visible final label, which will have the shortcut letter
51  * underlined, such as "&lt;u&gt;O&lt;/u&gt;k".
52  */
53  Q_PROPERTY(QString richTextLabel READ richTextLabel NOTIFY richTextLabelChanged)
54 
55  /**
56  * @brief This property holds the label with an "&" mnemonic in the place
57  * which defines the shortcut key.
58  *
59  * @note The "&" will be automatically added if it is not set by the
60  * user.
61  */
62  Q_PROPERTY(QString mnemonicLabel READ mnemonicLabel NOTIFY mnemonicLabelChanged)
63 
64  /**
65  * @brief This property sets whether this mnemonic is enabled.
66  *
67  * Set this to @c false to disable the accelerator marker (&) and its
68  * respective shortcut.
69  *
70  * default: ``true``
71  */
72  Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
73 
74  /**
75  * @brief This property holds the control type that this mnemonic is
76  * attached to.
77  *
78  * @note Different types of controls have different importance and priority
79  * for shortcut assignment.
80  *
81  * @see ::ControlType
82  */
83  Q_PROPERTY(MnemonicAttached::ControlType controlType READ controlType WRITE setControlType NOTIFY controlTypeChanged)
84 
85  /**
86  * @brief This property holds the final key sequence.
87  *
88  * @note The final key sequence will be Alt+alphanumeric char.
89  */
90  Q_PROPERTY(QKeySequence sequence READ sequence NOTIFY sequenceChanged)
91 
92  /**
93  * @brief This property holds whether the user is pressing alt and
94  * accelerators should be shown.
95  *
96  * @since KDE Frameworks 5.72
97  * @since org.kde.kirigami 2.15
98  */
99  Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
100 
101 public:
102  enum ControlType {
103  ActionElement, /**< pushbuttons, checkboxes etc */
104  DialogButton, /**< buttons for dialogs */
105  MenuItem, /**< Menu items */
106  FormLabel, /**< Buddy label in a FormLayout*/
107  SecondaryControl, /**< Other controls that are considered not much important and low priority for shortcuts */
108  };
110 
111  explicit MnemonicAttached(QObject *parent = nullptr);
112  ~MnemonicAttached() override;
113 
114  void setLabel(const QString &text);
115  QString label() const;
116 
117  QString richTextLabel() const;
118  QString mnemonicLabel() const;
119 
120  void setEnabled(bool enabled);
121  bool enabled() const;
122 
123  void setControlType(MnemonicAttached::ControlType controlType);
124  ControlType controlType() const;
125 
127 
128  void setActive(bool active);
129  bool active() const;
130 
131  // QML attached property
132  static MnemonicAttached *qmlAttachedProperties(QObject *object);
133 
134 protected:
135  bool eventFilter(QObject *watched, QEvent *e) override;
136  void updateSequence();
137 
138 Q_SIGNALS:
139  void labelChanged();
140  void enabledChanged();
141  void sequenceChanged();
142  void richTextLabelChanged();
143  void mnemonicLabelChanged();
144  void controlTypeChanged();
145  void activeChanged();
146 
147 private:
148  void calculateWeights();
149  bool installEventFilterForWindow(QQuickWindow *wnd);
150  bool removeEventFilterForWindow(QQuickWindow *wnd);
151 
152  // TODO: to have support for DIALOG_BUTTON_EXTRA_WEIGHT etc, a type enum should be exported
153  enum {
154  // Additional weight for first character in string
155  FIRST_CHARACTER_EXTRA_WEIGHT = 50,
156  // Additional weight for the beginning of a word
157  WORD_BEGINNING_EXTRA_WEIGHT = 50,
158  // Additional weight for a 'wanted' accelerator ie string with '&'
159  WANTED_ACCEL_EXTRA_WEIGHT = 150,
160  // Default weight for an 'action' widget (ie, pushbuttons)
161  ACTION_ELEMENT_WEIGHT = 50,
162  // Additional weight for the dialog buttons (large, we basically never want these reassigned)
163  DIALOG_BUTTON_EXTRA_WEIGHT = 300,
164  // Weight for FormLayout labels (low)
165  FORM_LABEL_WEIGHT = 20,
166  // Weight for Secondary controls which are considered less important (low)
167  SECONDARY_CONTROL_WEIGHT = 10,
168  // Default weight for menu items
169  MENU_ITEM_WEIGHT = 250,
170  };
171 
172  // order word letters by weight
173  int m_weight = 0;
174  int m_baseWeight = 0;
175  ControlType m_controlType = SecondaryControl;
176  QMap<int, QChar> m_weights;
177 
178  QString m_label;
179  QString m_actualRichTextLabel;
180  QString m_richTextLabel;
181  QString m_mnemonicLabel;
182  QKeySequence m_sequence;
183  bool m_enabled = true;
184  bool m_active = false;
185 
186  QPointer<QQuickWindow> m_window;
187 
188  // global mapping of mnemonics
189  // TODO: map by QWindow
190  static QHash<QKeySequence, MnemonicAttached *> s_sequenceToObject;
191 };
192 
193 QML_DECLARE_TYPEINFO(MnemonicAttached, QML_HAS_ATTACHED_PROPERTIES)
194 
195 #endif // MnemonicATTACHED_H
Q_OBJECTQ_OBJECT
Q_PROPERTY(...)
Q_ENUM(...)
bool active
This property holds whether the user is pressing alt and accelerators should be shown.
@ FormLabel
Buddy label in a FormLayout.
bool enabled
This property sets whether this mnemonic is enabled.
QString label
This property holds the label of the control that we want to compute a mnemonic for.
@ MenuItem
Menu items.
QString richTextLabel
This property holds the user-visible final label.
Q_SIGNALSQ_SIGNALS
QString mnemonicLabel
This property holds the label with an "&" mnemonic in the place which defines the shortcut key.
This attached property allows to define keyboard sequences to trigger actions based upon their text.
QKeySequence sequence
This property holds the final key sequence.
@ DialogButton
buttons for dialogs
@ ActionElement
pushbuttons, checkboxes etc
QObject * parent() const const
@ SecondaryControl
Other controls that are considered not much important and low priority for shortcuts.
MnemonicAttached::ControlType controlType
This property holds the control type that this mnemonic is attached to.
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Dec 5 2023 04:08:21 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.