File indexing completed on 2024-04-21 03:56:00
0001 /* 0002 * SPDX-FileCopyrightText: 2017 Marco Martin <mart@kde.org> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #ifndef MNEMONICATTACHED_H 0008 #define MNEMONICATTACHED_H 0009 0010 #include <QObject> 0011 #include <QQuickWindow> 0012 0013 #include <QQmlEngine> 0014 0015 /** 0016 * This Attached property is used to calculate automated keyboard sequences 0017 * to trigger actions based upon their text: if an "&" mnemonic is 0018 * used (ie "&Ok"), the system will attempt to assign the desired letter giving 0019 * it priority, otherwise a letter among the ones in the label will be used if 0020 * possible and not conflicting. 0021 * Different kinds of controls will have different priorities in assigning the 0022 * shortcut: for instance the "Ok/Cancel" buttons in a dialog will have priority 0023 * over fields of a FormLayout. 0024 * @see ControlType 0025 * 0026 * Usually the developer shouldn't use this directly as base components 0027 * already use this, but only when implementing a custom graphical Control. 0028 * @since 2.3 0029 */ 0030 class MnemonicAttached : public QObject 0031 { 0032 Q_OBJECT 0033 QML_NAMED_ELEMENT(MnemonicData) 0034 QML_ATTACHED(MnemonicAttached) 0035 QML_UNCREATABLE("Cannot create objects of type MnemonicData, use it as an attached property") 0036 /** 0037 * The label of the control we want to compute a mnemonic for, instance 0038 * "Label:" or "&Ok" 0039 */ 0040 Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged FINAL) 0041 0042 /** 0043 * The user-visible final label, which will have the shortcut letter underlined, 0044 * such as "<u>O</u>k" 0045 */ 0046 Q_PROPERTY(QString richTextLabel READ richTextLabel NOTIFY richTextLabelChanged FINAL) 0047 0048 /** 0049 * The label with an "&" mnemonic in the place which will have the shortcut 0050 * assigned, regardless of whether the & was assigned by the user or automatically generated. 0051 */ 0052 Q_PROPERTY(QString mnemonicLabel READ mnemonicLabel NOTIFY mnemonicLabelChanged FINAL) 0053 0054 /** 0055 * Only if true this mnemonic will be considered for the global assignment 0056 * default: true 0057 */ 0058 Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged FINAL) 0059 0060 /** 0061 * The type of control this mnemonic is attached: different types of controls have different importance and priority for shortcut assignment. 0062 * @see ControlType 0063 */ 0064 Q_PROPERTY(MnemonicAttached::ControlType controlType READ controlType WRITE setControlType NOTIFY controlTypeChanged FINAL) 0065 0066 /** 0067 * The final key sequence assigned, if any: it will be Alt+alphanumeric char 0068 */ 0069 Q_PROPERTY(QKeySequence sequence READ sequence NOTIFY sequenceChanged FINAL) 0070 0071 /** 0072 * True when the user is pressing alt and the accelerators should be shown 0073 * 0074 * @since 5.72 0075 * @since 2.15 0076 */ 0077 Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged FINAL) 0078 0079 public: 0080 enum ControlType { 0081 ActionElement, /**< pushbuttons, checkboxes etc */ 0082 DialogButton, /**< buttons for dialogs */ 0083 MenuItem, /**< Menu items */ 0084 FormLabel, /**< Buddy label in a FormLayout*/ 0085 SecondaryControl, /**< Other controls that are considered not much important and low priority for shortcuts */ 0086 }; 0087 Q_ENUM(ControlType) 0088 0089 explicit MnemonicAttached(QObject *parent = nullptr); 0090 ~MnemonicAttached() override; 0091 0092 void setLabel(const QString &text); 0093 QString label() const; 0094 0095 QString richTextLabel() const; 0096 QString mnemonicLabel() const; 0097 0098 void setEnabled(bool enabled); 0099 bool enabled() const; 0100 0101 void setControlType(MnemonicAttached::ControlType controlType); 0102 ControlType controlType() const; 0103 0104 QKeySequence sequence(); 0105 0106 void setActive(bool active); 0107 bool active() const; 0108 0109 // QML attached property 0110 static MnemonicAttached *qmlAttachedProperties(QObject *object); 0111 0112 protected: 0113 void updateSequence(); 0114 0115 Q_SIGNALS: 0116 void labelChanged(); 0117 void enabledChanged(); 0118 void sequenceChanged(); 0119 void richTextLabelChanged(); 0120 void mnemonicLabelChanged(); 0121 void controlTypeChanged(); 0122 void activeChanged(); 0123 0124 private: 0125 QWindow *window() const; 0126 0127 void onAltPressed(); 0128 void onAltReleased(); 0129 0130 void calculateWeights(); 0131 0132 // TODO: to have support for DIALOG_BUTTON_EXTRA_WEIGHT etc, a type enum should be exported 0133 enum { 0134 // Additional weight for first character in string 0135 FIRST_CHARACTER_EXTRA_WEIGHT = 50, 0136 // Additional weight for the beginning of a word 0137 WORD_BEGINNING_EXTRA_WEIGHT = 50, 0138 // Additional weight for a 'wanted' accelerator ie string with '&' 0139 WANTED_ACCEL_EXTRA_WEIGHT = 150, 0140 // Default weight for an 'action' widget (ie, pushbuttons) 0141 ACTION_ELEMENT_WEIGHT = 50, 0142 // Additional weight for the dialog buttons (large, we basically never want these reassigned) 0143 DIALOG_BUTTON_EXTRA_WEIGHT = 300, 0144 // Weight for FormLayout labels (low) 0145 FORM_LABEL_WEIGHT = 20, 0146 // Weight for Secondary controls which are considered less important (low) 0147 SECONDARY_CONTROL_WEIGHT = 10, 0148 // Default weight for menu items 0149 MENU_ITEM_WEIGHT = 250, 0150 }; 0151 0152 // order word letters by weight 0153 int m_weight = 0; 0154 int m_baseWeight = 0; 0155 ControlType m_controlType = SecondaryControl; 0156 QMap<int, QChar> m_weights; 0157 0158 QString m_label; 0159 QString m_actualRichTextLabel; 0160 QString m_richTextLabel; 0161 QString m_mnemonicLabel; 0162 QKeySequence m_sequence; 0163 bool m_enabled = true; 0164 bool m_active = false; 0165 0166 QPointer<QQuickWindow> m_window; 0167 0168 // global mapping of mnemonics 0169 // TODO: map by QWindow 0170 static QHash<QKeySequence, MnemonicAttached *> s_sequenceToObject; 0171 }; 0172 0173 QML_DECLARE_TYPEINFO(MnemonicAttached, QML_HAS_ATTACHED_PROPERTIES) 0174 0175 #endif // MnemonicATTACHED_H