File indexing completed on 2025-01-26 05:09:30

0001 /*
0002  * This file is part of the KDE wacomtablet project. For copyright
0003  * information and license terms see the AUTHORS and COPYING files
0004  * in the top-level directory of this distribution.
0005  *
0006  * This program is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU General Public License as
0008  * published by the Free Software Foundation; either version 2 of
0009  * the License, or (at your option) any later version.
0010  *
0011  * This program is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014  * GNU General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU General Public License
0017  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0018  */
0019 
0020 #include "buttonactionselectionwidget.h"
0021 #include "ui_buttonactionselectionwidget.h"
0022 
0023 #include "buttonshortcut.h"
0024 
0025 #include <QString>
0026 
0027 using namespace Wacom;
0028 
0029 namespace Wacom
0030 {
0031 class ButtonActionSelectionWidgetPrivate
0032 {
0033 public:
0034     ButtonActionSelectionWidgetPrivate()
0035         : ui(new Ui::ButtonActionSelectionWidget)
0036     {
0037     }
0038     ~ButtonActionSelectionWidgetPrivate()
0039     {
0040         delete ui;
0041     }
0042 
0043     Ui::ButtonActionSelectionWidget *ui;
0044     ButtonShortcut shortcut;
0045 };
0046 }
0047 
0048 ButtonActionSelectionWidget::ButtonActionSelectionWidget(QWidget *parent)
0049     : QWidget(parent)
0050     , d_ptr(new ButtonActionSelectionWidgetPrivate)
0051 {
0052     setupUi();
0053 }
0054 
0055 ButtonActionSelectionWidget::~ButtonActionSelectionWidget()
0056 {
0057     delete this->d_ptr;
0058 }
0059 
0060 const ButtonShortcut &ButtonActionSelectionWidget::getShortcut() const
0061 {
0062     Q_D(const ButtonActionSelectionWidget);
0063     return d->shortcut;
0064 }
0065 
0066 void ButtonActionSelectionWidget::setShortcut(const ButtonShortcut &shortcut)
0067 {
0068     Q_D(ButtonActionSelectionWidget);
0069 
0070     d->shortcut = shortcut;
0071 
0072     updateMouseButtonSeletion(shortcut);
0073     updateModifierWidgets(shortcut);
0074     updateShortcutWidgets(shortcut);
0075     updateCurrentActionName(shortcut);
0076 }
0077 
0078 void ButtonActionSelectionWidget::onClearButtonClicked(bool checked)
0079 {
0080     Q_UNUSED(checked);
0081 
0082     setShortcut(ButtonShortcut());
0083 }
0084 
0085 void ButtonActionSelectionWidget::onActionLineEditSelectionChanged()
0086 {
0087     Q_D(ButtonActionSelectionWidget);
0088     d->ui->actionNameLineEdit->deselect();
0089 }
0090 
0091 void ButtonActionSelectionWidget::onModifierChanged(int state)
0092 {
0093     Q_D(const ButtonActionSelectionWidget);
0094 
0095     Q_UNUSED(state);
0096 
0097     // build new shortcut sequence
0098     QString shortcutString;
0099 
0100     if (d->ui->ctrlModifierCheckBox->isChecked()) {
0101         shortcutString.append(QString::fromLatin1(" %1").arg(QLatin1String(" Ctrl")));
0102     }
0103 
0104     if (d->ui->altModifierCheckBox->isChecked()) {
0105         shortcutString.append(QString::fromLatin1(" %1").arg(QLatin1String(" Alt")));
0106     }
0107 
0108     if (d->ui->metaModifierCheckBox->isChecked()) {
0109         shortcutString.append(QString::fromLatin1(" %1").arg(QLatin1String(" Meta")));
0110     }
0111 
0112     if (d->ui->shiftModifierCheckBox->isChecked()) {
0113         shortcutString.append(QString::fromLatin1(" %1").arg(QLatin1String(" Shift")));
0114     }
0115 
0116     setShortcut(ButtonShortcut(shortcutString));
0117 }
0118 
0119 void ButtonActionSelectionWidget::onMouseSelectionChanged(int index)
0120 {
0121     Q_D(const ButtonActionSelectionWidget);
0122 
0123     int button = d->ui->mouseComboBox->itemData(index).toInt();
0124     setShortcut(ButtonShortcut(button));
0125 }
0126 
0127 void ButtonActionSelectionWidget::onShortcutChanged(QKeySequence sequence)
0128 {
0129     // By adding the "key" modifier, we make sure that shortcuts
0130     // like "1" do not get mistaken as a mouse button action.
0131     setShortcut(ButtonShortcut(QString::fromLatin1("key %1").arg(sequence.toString())));
0132 }
0133 
0134 void ButtonActionSelectionWidget::setupUi()
0135 {
0136     Q_D(ButtonActionSelectionWidget);
0137 
0138     // setup main widget
0139     d->ui->setupUi(this);
0140 
0141     // set mouse and keyboard label icons
0142     d->ui->mouseIconLabel->setPixmap(QIcon::fromTheme(QLatin1String("input-mouse")).pixmap(QSize(48, 48)));
0143     d->ui->keyboardIconLabel->setPixmap(QIcon::fromTheme(QLatin1String("input-keyboard")).pixmap(QSize(48, 48)));
0144 
0145     // add mouse buttons to dropdown menu
0146     d->ui->mouseComboBox->addItem(i18nc("Select a mouse button from a dropwdown.", "Click to select..."), 0);
0147 
0148     ButtonShortcut shortcut;
0149     for (int i = 1; i < 33; ++i) {
0150         shortcut.setButton(i);
0151         d->ui->mouseComboBox->addItem(shortcut.toDisplayString(), i);
0152     }
0153 
0154     // add icons to clear buttons (the icon direction must be the layout direction inverted)
0155     QLatin1String clearIconStr("edit-clear-locationbar-rtl");
0156     if (!qApp->isLeftToRight())
0157         clearIconStr = QLatin1String("edit-clear-locationbar-ltr");
0158     d->ui->mouseClearButton->setIcon(QIcon::fromTheme(clearIconStr));
0159     d->ui->modifierClearButton->setIcon(QIcon::fromTheme(clearIconStr));
0160 
0161     connect(d->ui->mouseComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onMouseSelectionChanged(int)));
0162     connect(d->ui->mouseClearButton, SIGNAL(clicked(bool)), this, SLOT(onClearButtonClicked(bool)));
0163 
0164     connect(d->ui->ctrlModifierCheckBox, SIGNAL(stateChanged(int)), this, SLOT(onModifierChanged(int)));
0165     connect(d->ui->altModifierCheckBox, SIGNAL(stateChanged(int)), this, SLOT(onModifierChanged(int)));
0166     connect(d->ui->metaModifierCheckBox, SIGNAL(stateChanged(int)), this, SLOT(onModifierChanged(int)));
0167     connect(d->ui->shiftModifierCheckBox, SIGNAL(stateChanged(int)), this, SLOT(onModifierChanged(int)));
0168     connect(d->ui->modifierClearButton, SIGNAL(clicked(bool)), this, SLOT(onClearButtonClicked(bool)));
0169 
0170     connect(d->ui->shortcutSelectorWidget, SIGNAL(keySequenceChanged(QKeySequence)), this, SLOT(onShortcutChanged(QKeySequence)));
0171 
0172     connect(d->ui->actionNameLineEdit, SIGNAL(selectionChanged()), this, SLOT(onActionLineEditSelectionChanged()));
0173 
0174     setShortcut(ButtonShortcut());
0175 }
0176 
0177 void ButtonActionSelectionWidget::updateCurrentActionName(const ButtonShortcut &shortcut)
0178 {
0179     Q_D(ButtonActionSelectionWidget);
0180 
0181     // update current action
0182     d->ui->actionNameLineEdit->setText(shortcut.toDisplayString());
0183 }
0184 
0185 void ButtonActionSelectionWidget::updateModifierWidgets(const ButtonShortcut &shortcut)
0186 {
0187     Q_D(ButtonActionSelectionWidget);
0188 
0189     if (shortcut.isModifier()) {
0190         // shortcut is a modifier sequence - set checkboxes accordingly
0191         QString shortcutString = shortcut.toString();
0192         bool isChecked = false;
0193 
0194         isChecked = shortcutString.contains(QLatin1String("ctrl"), Qt::CaseInsensitive);
0195         updateQCheckBox(*(d->ui->ctrlModifierCheckBox), isChecked);
0196 
0197         isChecked = shortcutString.contains(QLatin1String("alt"), Qt::CaseInsensitive);
0198         updateQCheckBox(*(d->ui->altModifierCheckBox), isChecked);
0199 
0200         isChecked =
0201             (shortcutString.contains(QLatin1String("super"), Qt::CaseInsensitive) || shortcutString.contains(QLatin1String("meta"), Qt::CaseInsensitive));
0202         updateQCheckBox(*(d->ui->metaModifierCheckBox), isChecked);
0203 
0204         isChecked = shortcutString.contains(QLatin1String("shift"), Qt::CaseInsensitive);
0205         updateQCheckBox(*(d->ui->shiftModifierCheckBox), isChecked);
0206 
0207     } else {
0208         // not a modifier shortcut
0209         updateQCheckBox(*(d->ui->ctrlModifierCheckBox), false);
0210         updateQCheckBox(*(d->ui->altModifierCheckBox), false);
0211         updateQCheckBox(*(d->ui->metaModifierCheckBox), false);
0212         updateQCheckBox(*(d->ui->shiftModifierCheckBox), false);
0213     }
0214 }
0215 
0216 void ButtonActionSelectionWidget::updateMouseButtonSeletion(const ButtonShortcut &shortcut)
0217 {
0218     Q_D(ButtonActionSelectionWidget);
0219 
0220     // find new selection index for the given button
0221     int newIndex = d->ui->mouseComboBox->findData(shortcut.getButton());
0222 
0223     // update combo box selection if button is not yet selected
0224     if (newIndex != d->ui->mouseComboBox->currentIndex() && d->ui->mouseComboBox->count() > 0) {
0225         d->ui->mouseComboBox->blockSignals(true);
0226         d->ui->mouseComboBox->setCurrentIndex(newIndex >= 0 ? newIndex : 0);
0227         d->ui->mouseComboBox->blockSignals(false);
0228     }
0229 }
0230 
0231 void ButtonActionSelectionWidget::updateQCheckBox(QCheckBox &checkbox, bool isChecked) const
0232 {
0233     if (checkbox.isChecked() != isChecked) {
0234         checkbox.blockSignals(true);
0235         checkbox.setChecked(isChecked);
0236         checkbox.blockSignals(false);
0237     }
0238 }
0239 
0240 void ButtonActionSelectionWidget::updateShortcutWidgets(const ButtonShortcut &shortcut)
0241 {
0242     Q_D(ButtonActionSelectionWidget);
0243 
0244     if (shortcut.isKeystroke()) {
0245         // shortcut is a key sequence - update it if not yet set
0246         QKeySequence qkeySequence = QKeySequence::fromString(shortcut.toQKeySequenceString());
0247 
0248         if (d->ui->shortcutSelectorWidget->keySequence() != qkeySequence) {
0249             d->ui->shortcutSelectorWidget->blockSignals(true);
0250             d->ui->shortcutSelectorWidget->setKeySequence(qkeySequence);
0251             d->ui->shortcutSelectorWidget->blockSignals(false);
0252         }
0253 
0254     } else {
0255         // not a keyboard shortcut - clear sequence if not yet cleared
0256         if (!d->ui->shortcutSelectorWidget->keySequence().isEmpty()) {
0257             d->ui->shortcutSelectorWidget->blockSignals(true);
0258             d->ui->shortcutSelectorWidget->clearKeySequence();
0259             d->ui->shortcutSelectorWidget->blockSignals(false);
0260         }
0261     }
0262 }
0263 
0264 #include "moc_buttonactionselectionwidget.cpp"