cf12defd28
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
176 lines
5.7 KiB
C++
176 lines
5.7 KiB
C++
/*
|
|
* SPDX-FileCopyrightText: 2017 Marco Martin <mart@kde.org>
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.0-or-later
|
|
*/
|
|
|
|
#ifndef MNEMONICATTACHED_H
|
|
#define MNEMONICATTACHED_H
|
|
|
|
#include <QObject>
|
|
#include <QQuickWindow>
|
|
|
|
#include <QQmlEngine>
|
|
|
|
/**
|
|
* This Attached property is used to calculate automated keyboard sequences
|
|
* to trigger actions based upon their text: if an "&" mnemonic is
|
|
* used (ie "&Ok"), the system will attempt to assign the desired letter giving
|
|
* it priority, otherwise a letter among the ones in the label will be used if
|
|
* possible and not conflicting.
|
|
* Different kinds of controls will have different priorities in assigning the
|
|
* shortcut: for instance the "Ok/Cancel" buttons in a dialog will have priority
|
|
* over fields of a FormLayout.
|
|
* @see ControlType
|
|
*
|
|
* Usually the developer shouldn't use this directly as base components
|
|
* already use this, but only when implementing a custom graphical Control.
|
|
* @since 2.3
|
|
*/
|
|
class MnemonicAttached : public QObject
|
|
{
|
|
Q_OBJECT
|
|
QML_NAMED_ELEMENT_OFF_OFF_OFF_OFF_OFF_OFF(MnemonicData)
|
|
QML_ATTACHED_OFF_OFF_OFF_OFF_OFF_OFF(MnemonicAttached)
|
|
QML_UNCREATABLE_OFF_OFF_OFF_OFF_OFF_OFF("Cannot create objects of type MnemonicData, use it as an attached property")
|
|
/**
|
|
* The label of the control we want to compute a mnemonic for, instance
|
|
* "Label:" or "&Ok"
|
|
*/
|
|
Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged FINAL)
|
|
|
|
/**
|
|
* The user-visible final label, which will have the shortcut letter underlined,
|
|
* such as "<u>O</u>k"
|
|
*/
|
|
Q_PROPERTY(QString richTextLabel READ richTextLabel NOTIFY richTextLabelChanged FINAL)
|
|
|
|
/**
|
|
* The label with an "&" mnemonic in the place which will have the shortcut
|
|
* assigned, regardless of whether the & was assigned by the user or automatically generated.
|
|
*/
|
|
Q_PROPERTY(QString mnemonicLabel READ mnemonicLabel NOTIFY mnemonicLabelChanged FINAL)
|
|
|
|
/**
|
|
* Only if true this mnemonic will be considered for the global assignment
|
|
* default: true
|
|
*/
|
|
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged FINAL)
|
|
|
|
/**
|
|
* The type of control this mnemonic is attached: different types of controls have different importance and priority for shortcut assignment.
|
|
* @see ControlType
|
|
*/
|
|
Q_PROPERTY(MnemonicAttached::ControlType controlType READ controlType WRITE setControlType NOTIFY controlTypeChanged FINAL)
|
|
|
|
/**
|
|
* The final key sequence assigned, if any: it will be Alt+alphanumeric char
|
|
*/
|
|
Q_PROPERTY(QKeySequence sequence READ sequence NOTIFY sequenceChanged FINAL)
|
|
|
|
/**
|
|
* True when the user is pressing alt and the accelerators should be shown
|
|
*
|
|
* @since 5.72
|
|
* @since 2.15
|
|
*/
|
|
Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged FINAL)
|
|
|
|
public:
|
|
enum ControlType {
|
|
ActionElement, /**< pushbuttons, checkboxes etc */
|
|
DialogButton, /**< buttons for dialogs */
|
|
MenuItem, /**< Menu items */
|
|
FormLabel, /**< Buddy label in a FormLayout*/
|
|
SecondaryControl, /**< Other controls that are considered not much important and low priority for shortcuts */
|
|
};
|
|
Q_ENUM(ControlType)
|
|
|
|
explicit MnemonicAttached(QObject *parent = nullptr);
|
|
~MnemonicAttached() override;
|
|
|
|
void setLabel(const QString &text);
|
|
QString label() const;
|
|
|
|
QString richTextLabel() const;
|
|
QString mnemonicLabel() const;
|
|
|
|
void setEnabled(bool enabled);
|
|
bool enabled() const;
|
|
|
|
void setControlType(MnemonicAttached::ControlType controlType);
|
|
ControlType controlType() const;
|
|
|
|
QKeySequence sequence();
|
|
|
|
void setActive(bool active);
|
|
bool active() const;
|
|
|
|
// QML attached property
|
|
static MnemonicAttached *qmlAttachedProperties(QObject *object);
|
|
|
|
protected:
|
|
void updateSequence();
|
|
|
|
Q_SIGNALS:
|
|
void labelChanged();
|
|
void enabledChanged();
|
|
void sequenceChanged();
|
|
void richTextLabelChanged();
|
|
void mnemonicLabelChanged();
|
|
void controlTypeChanged();
|
|
void activeChanged();
|
|
|
|
private:
|
|
QWindow *window() const;
|
|
|
|
void onAltPressed();
|
|
void onAltReleased();
|
|
|
|
void calculateWeights();
|
|
|
|
// TODO: to have support for DIALOG_BUTTON_EXTRA_WEIGHT etc, a type enum should be exported
|
|
enum {
|
|
// Additional weight for first character in string
|
|
FIRST_CHARACTER_EXTRA_WEIGHT = 50,
|
|
// Additional weight for the beginning of a word
|
|
WORD_BEGINNING_EXTRA_WEIGHT = 50,
|
|
// Additional weight for a 'wanted' accelerator ie string with '&'
|
|
WANTED_ACCEL_EXTRA_WEIGHT = 150,
|
|
// Default weight for an 'action' widget (ie, pushbuttons)
|
|
ACTION_ELEMENT_WEIGHT = 50,
|
|
// Additional weight for the dialog buttons (large, we basically never want these reassigned)
|
|
DIALOG_BUTTON_EXTRA_WEIGHT = 300,
|
|
// Weight for FormLayout labels (low)
|
|
FORM_LABEL_WEIGHT = 20,
|
|
// Weight for Secondary controls which are considered less important (low)
|
|
SECONDARY_CONTROL_WEIGHT = 10,
|
|
// Default weight for menu items
|
|
MENU_ITEM_WEIGHT = 250,
|
|
};
|
|
|
|
// order word letters by weight
|
|
int m_weight = 0;
|
|
int m_baseWeight = 0;
|
|
ControlType m_controlType = SecondaryControl;
|
|
QMap<int, QChar> m_weights;
|
|
|
|
QString m_label;
|
|
QString m_actualRichTextLabel;
|
|
QString m_richTextLabel;
|
|
QString m_mnemonicLabel;
|
|
QKeySequence m_sequence;
|
|
bool m_enabled = true;
|
|
bool m_active = false;
|
|
|
|
QPointer<QQuickWindow> m_window;
|
|
|
|
// global mapping of mnemonics
|
|
// TODO: map by QWindow
|
|
static QHash<QKeySequence, MnemonicAttached *> s_sequenceToObject;
|
|
};
|
|
|
|
QML_DECLARE_TYPEINFO(MnemonicAttached, QML_HAS_ATTACHED_PROPERTIES)
|
|
|
|
#endif // MnemonicATTACHED_H
|