File indexing completed on 2024-09-01 13:31:34
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 1998 Mark Donohoe <donohoe@kde.org> 0004 SPDX-FileCopyrightText: 1997 Nicolas Hadacek <hadacek@kde.org> 0005 SPDX-FileCopyrightText: 1998 Matthias Ettrich <ettrich@kde.org> 0006 SPDX-FileCopyrightText: 2001 Ellis Whitehead <ellis@kde.org> 0007 SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org> 0008 SPDX-FileCopyrightText: 2007 Roberto Raggi <roberto@kdevelop.org> 0009 SPDX-FileCopyrightText: 2007 Andreas Hartmetz <ahartmetz@gmail.com> 0010 0011 SPDX-License-Identifier: LGPL-2.0-or-later 0012 */ 0013 0014 #include "config-xmlgui.h" 0015 #include "kshortcutsdialog_p.h" 0016 0017 #include <QAction> 0018 #include <QGridLayout> 0019 #include <QLabel> 0020 #include <QPainter> 0021 #include <QPen> 0022 #include <QRadioButton> 0023 0024 #include <KLocalizedString> 0025 #if HAVE_GLOBALACCEL 0026 #include <KGlobalAccel> 0027 #endif 0028 0029 #include "kkeysequencewidget.h" 0030 0031 void TabConnectedWidget::paintEvent(QPaintEvent *e) 0032 { 0033 QWidget::paintEvent(e); 0034 QPainter p(this); 0035 QPen pen(QPalette().highlight().color()); 0036 pen.setWidth(6); 0037 p.setPen(pen); 0038 p.drawLine(0, 0, width(), 0); 0039 if (qApp->isLeftToRight()) { 0040 p.drawLine(0, 0, 0, height()); 0041 } else { 0042 p.drawLine(width(), 0, width(), height()); 0043 } 0044 } 0045 0046 ShortcutEditWidget::ShortcutEditWidget(QWidget *viewport, const QKeySequence &defaultSeq, const QKeySequence &activeSeq, bool allowLetterShortcuts) 0047 : TabConnectedWidget(viewport) 0048 , m_defaultKeySequence(defaultSeq) 0049 , m_isUpdating(false) 0050 , m_action(nullptr) 0051 , m_noneText(i18nc("No shortcut defined", "None")) 0052 { 0053 QGridLayout *layout = new QGridLayout(this); 0054 0055 m_defaultRadio = new QRadioButton(i18nc("@option:radio", "Default:"), this); 0056 m_defaultLabel = new QLabel(m_noneText, this); 0057 const QString defaultText = defaultSeq.toString(QKeySequence::NativeText); 0058 if (!defaultText.isEmpty()) { 0059 m_defaultLabel->setText(defaultText); 0060 } 0061 0062 m_customRadio = new QRadioButton(i18nc("@option:radio", "Custom:"), this); 0063 m_customEditor = new KKeySequenceWidget(this); 0064 m_customEditor->setModifierlessAllowed(allowLetterShortcuts); 0065 0066 layout->addWidget(m_defaultRadio, 0, 0); 0067 layout->addWidget(m_defaultLabel, 0, 1); 0068 layout->addWidget(m_customRadio, 1, 0); 0069 layout->addWidget(m_customEditor, 1, 1); 0070 layout->setColumnStretch(2, 1); 0071 0072 setKeySequence(activeSeq); 0073 0074 connect(m_defaultRadio, &QRadioButton::toggled, this, &ShortcutEditWidget::defaultToggled); 0075 connect(m_customEditor, &KKeySequenceWidget::keySequenceChanged, this, &ShortcutEditWidget::setCustom); 0076 connect(m_customEditor, &KKeySequenceWidget::stealShortcut, this, &ShortcutEditWidget::stealShortcut); 0077 #if HAVE_GLOBALACCEL 0078 connect(KGlobalAccel::self(), &KGlobalAccel::globalShortcutChanged, this, [this](QAction *action, const QKeySequence &seq) { 0079 if (action != m_action) { 0080 return; 0081 } 0082 setKeySequence(seq); 0083 }); 0084 #endif 0085 } 0086 0087 KKeySequenceWidget::ShortcutTypes ShortcutEditWidget::checkForConflictsAgainst() const 0088 { 0089 return m_customEditor->checkForConflictsAgainst(); 0090 } 0091 0092 // slot 0093 void ShortcutEditWidget::defaultToggled(bool checked) 0094 { 0095 if (m_isUpdating) { 0096 return; 0097 } 0098 0099 m_isUpdating = true; 0100 if (checked) { 0101 // The default key sequence should be activated. We check first if this is 0102 // possible. 0103 if (m_customEditor->isKeySequenceAvailable(m_defaultKeySequence)) { 0104 // Clear the customs widget 0105 m_customEditor->clearKeySequence(); 0106 Q_EMIT keySequenceChanged(m_defaultKeySequence); 0107 } else { 0108 // We tried to switch to the default key sequence and failed. Go 0109 // back. 0110 m_customRadio->setChecked(true); 0111 } 0112 } else { 0113 // The empty key sequence is always valid 0114 Q_EMIT keySequenceChanged(QKeySequence()); 0115 } 0116 m_isUpdating = false; 0117 } 0118 0119 void ShortcutEditWidget::setCheckActionCollections(const QList<KActionCollection *> &checkActionCollections) 0120 { 0121 // We just forward them to out KKeySequenceWidget. 0122 m_customEditor->setCheckActionCollections(checkActionCollections); 0123 } 0124 0125 void ShortcutEditWidget::setCheckForConflictsAgainst(KKeySequenceWidget::ShortcutTypes types) 0126 { 0127 m_customEditor->setCheckForConflictsAgainst(types); 0128 } 0129 0130 void ShortcutEditWidget::setComponentName(const QString &componentName) 0131 { 0132 m_customEditor->setComponentName(componentName); 0133 } 0134 0135 void ShortcutEditWidget::setMultiKeyShortcutsAllowed(bool allowed) 0136 { 0137 // We just forward them to out KKeySequenceWidget. 0138 m_customEditor->setMultiKeyShortcutsAllowed(allowed); 0139 } 0140 0141 bool ShortcutEditWidget::multiKeyShortcutsAllowed() const 0142 { 0143 return m_customEditor->multiKeyShortcutsAllowed(); 0144 } 0145 0146 void ShortcutEditWidget::setAction(QObject *action) 0147 { 0148 m_action = action; 0149 } 0150 0151 // slot 0152 void ShortcutEditWidget::setCustom(const QKeySequence &seq) 0153 { 0154 if (m_isUpdating) { 0155 return; 0156 } 0157 0158 // seq is a const reference to a private variable of KKeySequenceWidget. 0159 // Somewhere below we possible change that one. But we want to emit seq 0160 // whatever happens. So we make a copy. 0161 QKeySequence original = seq; 0162 0163 m_isUpdating = true; 0164 0165 // Check if the user typed in the default sequence into the custom field. 0166 // We do this by calling setKeySequence which will do the right thing. 0167 setKeySequence(original); 0168 0169 Q_EMIT keySequenceChanged(original); 0170 m_isUpdating = false; 0171 } 0172 0173 void ShortcutEditWidget::setKeySequence(const QKeySequence &activeSeq) 0174 { 0175 const QString seqString = activeSeq.isEmpty() ? m_noneText : activeSeq.toString(QKeySequence::NativeText); 0176 if (seqString == m_defaultLabel->text()) { 0177 m_defaultRadio->setChecked(true); 0178 m_customEditor->clearKeySequence(); 0179 } else { 0180 m_customRadio->setChecked(true); 0181 // m_customEditor->setKeySequence does some stuff we only want to 0182 // execute when the sequence really changes. 0183 if (activeSeq != m_customEditor->keySequence()) { 0184 m_customEditor->setKeySequence(activeSeq); 0185 } 0186 } 0187 }