Krita Source Code Documentation
Loading...
Searching...
No Matches
KKeySequenceButton Class Reference

#include <kkeysequencewidget_p.h>

+ Inheritance diagram for KKeySequenceButton:

Public Member Functions

 KKeySequenceButton (KisKKeySequenceWidgetPrivate *d, QWidget *parent)
 
 ~KKeySequenceButton () override
 

Protected Member Functions

bool event (QEvent *event) override
 
void keyPressEvent (QKeyEvent *event) override
 
void keyReleaseEvent (QKeyEvent *event) override
 

Private Attributes

KisKKeySequenceWidgetPrivate *const d
 

Detailed Description

Definition at line 12 of file kkeysequencewidget_p.h.

Constructor & Destructor Documentation

◆ KKeySequenceButton()

KKeySequenceButton::KKeySequenceButton ( KisKKeySequenceWidgetPrivate * d,
QWidget * parent )
inlineexplicit

Definition at line 17 of file kkeysequencewidget_p.h.

18 : QPushButton(parent),
19 d(d) {}
KisKKeySequenceWidgetPrivate *const d

◆ ~KKeySequenceButton()

KKeySequenceButton::~KKeySequenceButton ( )
override

Definition at line 598 of file kkeysequencewidget.cpp.

599{
600}

Member Function Documentation

◆ event()

bool KKeySequenceButton::event ( QEvent * event)
overrideprotected

Reimplemented for internal reasons.

Definition at line 603 of file kkeysequencewidget.cpp.

604{
605 if (d->isRecording && e->type() == QEvent::KeyPress) {
606 keyPressEvent(static_cast<QKeyEvent *>(e));
607 return true;
608 }
609
610 // The shortcut 'alt+c' ( or any other dialog local action shortcut )
611 // ended the recording and triggered the action associated with the
612 // action. In case of 'alt+c' ending the dialog. It seems that those
613 // ShortcutOverride events get sent even if grabKeyboard() is active.
614 if (d->isRecording && e->type() == QEvent::ShortcutOverride) {
615 e->accept();
616 return true;
617 }
618
619 if (d->isRecording && e->type() == QEvent::ContextMenu) {
620 // is caused by Qt::Key_Menu
621 e->accept();
622 return true;
623 }
624
625 return QPushButton::event(e);
626}
void keyPressEvent(QKeyEvent *event) override

References d, KisKKeySequenceWidgetPrivate::isRecording, and keyPressEvent().

◆ keyPressEvent()

void KKeySequenceButton::keyPressEvent ( QKeyEvent * event)
overrideprotected

Here is the trap, which is different on every OS. On Windows, Qt has incomprehensible rules on translating AltGr-related key sequences into shortcuts. On macOS symbols may confuse Qt when using Cmd+Shift-based shortcuts. * So we should just ask Qt itself what it expects to receive as a shortcut :)

That is exactly what Qt's QKeySequenceEdit does internally.

TODO: in the future replace the whole widget with QKeySequenceEdit, it uses QKeyMapper directly.

Take the first element, which is usually the shortcut form the latin layout of the keyboard

Definition at line 825 of file kkeysequencewidget.cpp.

826{
827 int keyQt = e->key();
828 if (keyQt == -1) {
829 // Qt sometimes returns garbage keycodes, I observed -1, if it doesn't know a key.
830 // We cannot do anything useful with those (several keys have -1, indistinguishable)
831 // and QKeySequence.toString() will also yield a garbage string.
832 KMessageBox::error(this,
833 i18n("The key you just pressed is not supported by Qt."),
834 i18n("Unsupported Key"));
835 return d->cancelRecording();
836 }
837
838 uint newModifiers = e->modifiers() & (Qt::SHIFT | Qt::CTRL | Qt::ALT | Qt::META);
839
840 //don't have the return or space key appear as first key of the sequence when they
841 //were pressed to start editing - catch and them and imitate their effect
842 if (!d->isRecording && ((keyQt == Qt::Key_Return || keyQt == Qt::Key_Space))) {
843 d->startRecording();
844 d->modifierKeys = newModifiers;
846 return;
847 }
848
849 // We get events even if recording isn't active.
850 if (!d->isRecording) {
851 return QPushButton::keyPressEvent(e);
852 }
853
854 e->accept();
855 d->modifierKeys = newModifiers;
856
857 switch (keyQt) {
858 case Qt::Key_AltGr: //or else we get unicode salad
859 return;
860 case Qt::Key_Shift:
861 case Qt::Key_Control:
862 case Qt::Key_Alt:
863 case Qt::Key_Meta:
864 case Qt::Key_Super_L:
865 case Qt::Key_Super_R:
868 break;
869 default:
870
871 if (d->nKey == 0 && !(d->modifierKeys & ~Qt::SHIFT)) {
872 // It's the first key and no modifier pressed. Check if this is
873 // allowed
875 || d->allowModifierless)) {
876 // No it's not
877 return;
878 }
879 }
880
881 // We now have a valid key press.
882 if (keyQt) {
895#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
896 const QList<int> vec = QKeyMapper::possibleKeys(e);
897#else
898 const QList<QKeyCombination> vec = QKeyMapper::possibleKeys(e);
899#endif
900
901 if (!vec.isEmpty() && e->modifiers() != Qt::NoModifier) {
906 keyQt = vec.first();
907 } else if ((keyQt == Qt::Key_Backtab) && (d->modifierKeys & Qt::SHIFT)) {
908 keyQt = Qt::Key_Tab | d->modifierKeys;
909 } else if (isShiftAsModifierAllowed(keyQt)) {
910 keyQt |= d->modifierKeys;
911 } else {
912 keyQt |= (d->modifierKeys & ~Qt::SHIFT);
913 }
914
915 if (d->nKey == 0) {
916 d->keySequence = QKeySequence(keyQt);
917 } else {
918 d->keySequence =
920 }
921
922 d->nKey++;
923 if ((!d->multiKeyShortcutsAllowed) || (d->nKey >= 4)) {
924 d->doneRecording();
925 return;
926 }
929 }
930 }
931}
unsigned int uint
static bool isOkWhenModifierless(int keyQt)
void doneRecording(bool validate=true)
static QKeySequence appendToSequence(const QKeySequence &seq, int keyQt)

References KisKKeySequenceWidgetPrivate::allowModifierless, KisKKeySequenceWidgetPrivate::appendToSequence(), KisKKeySequenceWidgetPrivate::cancelRecording(), KisKKeySequenceWidgetPrivate::controlModifierlessTimeout(), d, KisKKeySequenceWidgetPrivate::doneRecording(), KisKKeySequenceWidgetPrivate::isOkWhenModifierless(), KisKKeySequenceWidgetPrivate::isRecording, KisKKeySequenceWidgetPrivate::keySequence, KisKKeySequenceWidgetPrivate::modifierKeys, KisKKeySequenceWidgetPrivate::multiKeyShortcutsAllowed, KisKKeySequenceWidgetPrivate::nKey, KisKKeySequenceWidgetPrivate::startRecording(), and KisKKeySequenceWidgetPrivate::updateShortcutDisplay().

◆ keyReleaseEvent()

void KKeySequenceButton::keyReleaseEvent ( QKeyEvent * event)
overrideprotected

Definition at line 933 of file kkeysequencewidget.cpp.

934{
935 if (e->key() == -1) {
936 // ignore garbage, see keyPressEvent()
937 return;
938 }
939
940 if (!d->isRecording) {
941 return QPushButton::keyReleaseEvent(e);
942 }
943
944 e->accept();
945
946 uint newModifiers = e->modifiers() & (Qt::SHIFT | Qt::CTRL | Qt::ALT | Qt::META);
947
948#ifdef Q_OS_ANDROID
949 // On Android, releasing a modifier will still carry the modifiers on the
950 // release event, so we have to clear those out explicitly.
951 switch (e->key()) {
952 case Qt::Key_Shift:
953 newModifiers &= ~Qt::SHIFT;
954 break;
955 case Qt::Key_Control:
956 newModifiers &= ~Qt::CTRL;
957 break;
958 case Qt::Key_Alt:
959 case Qt::Key_AltGr:
960 newModifiers &= ~Qt::ALT;
961 break;
962 case Qt::Key_Meta:
963 newModifiers &= ~Qt::META;
964 break;
965 }
966#endif
967
968 //if a modifier that belongs to the shortcut was released...
969 if ((newModifiers & d->modifierKeys) < d->modifierKeys) {
970 d->modifierKeys = newModifiers;
973 }
974}

References KisKKeySequenceWidgetPrivate::controlModifierlessTimeout(), d, KisKKeySequenceWidgetPrivate::isRecording, KisKKeySequenceWidgetPrivate::modifierKeys, and KisKKeySequenceWidgetPrivate::updateShortcutDisplay().

Member Data Documentation

◆ d

KisKKeySequenceWidgetPrivate* const KKeySequenceButton::d
private

Definition at line 32 of file kkeysequencewidget_p.h.


The documentation for this class was generated from the following files: