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 "buttonpagewidget.h" 0021 #include "ui_buttonpagewidget.h" 0022 0023 #include "buttonactionselectiondialog.h" 0024 #include "buttonactionselectorwidget.h" 0025 #include "profilemanagement.h" 0026 0027 // common includes 0028 #include "buttonshortcut.h" 0029 #include "dbustabletinterface.h" 0030 #include "deviceprofile.h" 0031 #include "property.h" 0032 #include "stringutils.h" 0033 #include "tabletinfo.h" 0034 0035 // stdlib 0036 #include <memory> 0037 0038 // KDE includes 0039 0040 // Qt includes 0041 #include <QDBusInterface> 0042 #include <QDBusReply> 0043 #include <QDialog> 0044 #include <QFile> 0045 #include <QKeySequence> 0046 #include <QLabel> 0047 #include <QList> 0048 #include <QPixmap> 0049 #include <QPointer> 0050 #include <QStandardPaths> 0051 0052 using namespace Wacom; 0053 0054 QString findLayoutFile(const QString &filename) 0055 { 0056 if (filename.isEmpty()) 0057 return QString(); 0058 0059 const QString builtinLayout = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QString::fromLatin1("wacomtablet/images/%1.png").arg(filename)); 0060 if (QFile::exists(builtinLayout)) { 0061 return builtinLayout; 0062 } else if (QFile::exists(filename)) { 0063 return filename; 0064 } 0065 0066 return QString(); 0067 } 0068 0069 ButtonPageWidget::ButtonPageWidget(QWidget *parent) 0070 : QWidget(parent) 0071 , ui(new Ui::ButtonPageWidget) 0072 { 0073 setupUi(); 0074 reloadWidget(); 0075 } 0076 0077 ButtonPageWidget::~ButtonPageWidget() 0078 { 0079 delete ui; 0080 } 0081 0082 void ButtonPageWidget::setTabletId(const QString &tabletId) 0083 { 0084 _tabletId = tabletId; 0085 } 0086 0087 void ButtonPageWidget::saveToProfile(ProfileManagementInterface &profileManagement) 0088 { 0089 DeviceProfile padProfile = profileManagement.loadDeviceProfile(DeviceType::Pad); 0090 0091 // save button shortcuts 0092 ButtonActionSelectorWidget *buttonSelector; 0093 0094 for (int i = 1; i < 19; ++i) { 0095 buttonSelector = this->findChild<ButtonActionSelectorWidget *>(QString::fromLatin1("button%1ActionSelector").arg(i)); 0096 0097 if (buttonSelector && buttonSelector->isEnabled()) { 0098 padProfile.setButton(i, buttonSelector->getShortcut().toString()); 0099 } else { 0100 // Make sure only valid buttons are set. 0101 // If invalid button numbers are set they might overwrite mapped buttons. 0102 // For instance, if button 4 gets mapped to 9, then setting button 9 will 0103 // overwrite the value from button 4 unless the device actually has a 0104 // button 9 which would then in turn have another mapping to another X11 0105 // button number, e.g. 13. 0106 padProfile.setButton(i, QString()); 0107 } 0108 } 0109 0110 // save strip shortcuts - reset invalid ones - same reasons as above 0111 QString stripLUp, stripRUp, stripLDown, stripRDown; 0112 0113 if (ui->touchStripGroupBox->isEnabled()) { 0114 if (ui->leftStripWidget->isEnabled()) { 0115 stripLUp = ui->leftStripUpSelector->getShortcut().toString(); 0116 stripLDown = ui->leftStripDownSelector->getShortcut().toString(); 0117 } 0118 0119 if (ui->rightStripWidget->isEnabled()) { 0120 stripRUp = ui->rightStripUpSelector->getShortcut().toString(); 0121 stripRDown = ui->rightStripDownSelector->getShortcut().toString(); 0122 } 0123 } 0124 0125 padProfile.setProperty(Property::StripLeftUp, stripLUp); 0126 padProfile.setProperty(Property::StripLeftDown, stripLDown); 0127 padProfile.setProperty(Property::StripRightUp, stripRUp); 0128 padProfile.setProperty(Property::StripRightDown, stripRDown); 0129 0130 // save wheel and ring shortcuts - reset invalid values - same reasons as above 0131 QString absWUp, absWDown; 0132 0133 if (ui->touchRingGroupBox->isEnabled() || ui->wheelGroupBox->isEnabled()) { 0134 // ring and wheel shortcuts are treated the same but only one value may be written, 0135 // as the other one could be empty. Use whichever value we can get our hands on first. 0136 if (ui->ringUpSelector->getShortcut().isSet()) { 0137 absWUp = ui->ringUpSelector->getShortcut().toString(); 0138 } else { 0139 absWUp = ui->wheelUpSelector->getShortcut().toString(); 0140 } 0141 0142 if (ui->ringDownSelector->getShortcut().isSet()) { 0143 absWDown = ui->ringDownSelector->getShortcut().toString(); 0144 } else { 0145 absWDown = ui->wheelDownSelector->getShortcut().toString(); 0146 } 0147 } 0148 0149 padProfile.setProperty(Property::AbsWheelUp, absWUp); 0150 padProfile.setProperty(Property::AbsWheel2Up, absWUp); 0151 padProfile.setProperty(Property::AbsWheelDown, absWDown); 0152 padProfile.setProperty(Property::AbsWheel2Down, absWDown); 0153 0154 // save device profile 0155 profileManagement.saveDeviceProfile(padProfile); 0156 } 0157 0158 void ButtonPageWidget::loadFromProfile(ProfileManagementInterface &profileManagement) 0159 { 0160 DeviceProfile padProfile = profileManagement.loadDeviceProfile(DeviceType::Pad); 0161 QString propertyValue; 0162 0163 for (int i = 1; i < 19; i++) { 0164 auto buttonSelector = this->findChild<ButtonActionSelectorWidget *>(QString::fromLatin1("button%1ActionSelector").arg(i)); 0165 propertyValue = padProfile.getButton(i); 0166 0167 if (buttonSelector) { 0168 buttonSelector->setShortcut(ButtonShortcut(propertyValue)); 0169 } 0170 } 0171 0172 // set wheel and ring shortcuts 0173 propertyValue = padProfile.getProperty(Property::AbsWheelUp); 0174 ui->wheelUpSelector->setShortcut(ButtonShortcut(propertyValue)); 0175 ui->ringUpSelector->setShortcut(ButtonShortcut(propertyValue)); 0176 0177 propertyValue = padProfile.getProperty(Property::AbsWheelDown); 0178 ui->wheelDownSelector->setShortcut(ButtonShortcut(propertyValue)); 0179 ui->ringDownSelector->setShortcut(ButtonShortcut(propertyValue)); 0180 0181 // set strip shortcuts 0182 propertyValue = padProfile.getProperty(Property::StripLeftUp); 0183 ui->leftStripUpSelector->setShortcut(ButtonShortcut(propertyValue)); 0184 0185 propertyValue = padProfile.getProperty(Property::StripLeftDown); 0186 ui->leftStripDownSelector->setShortcut(ButtonShortcut(propertyValue)); 0187 0188 propertyValue = padProfile.getProperty(Property::StripRightUp); 0189 ui->rightStripUpSelector->setShortcut(ButtonShortcut(propertyValue)); 0190 0191 propertyValue = padProfile.getProperty(Property::StripRightDown); 0192 ui->rightStripDownSelector->setShortcut(ButtonShortcut(propertyValue)); 0193 } 0194 0195 void ButtonPageWidget::reloadWidget() 0196 { 0197 const int padButtons = DBusTabletInterface::instance().getInformation(_tabletId, TabletInfo::NumPadButtons.key()).value().toInt(); 0198 0199 QLabel *buttonLabel = nullptr; 0200 ButtonActionSelectorWidget *buttonSelector = nullptr; 0201 for (int i = 1; i < 19; i++) { 0202 buttonSelector = this->findChild<ButtonActionSelectorWidget *>(QString::fromLatin1("button%1ActionSelector").arg(i)); 0203 buttonLabel = this->findChild<QLabel *>(QString::fromLatin1("button%1Label").arg(i)); 0204 0205 if (!buttonSelector || !buttonLabel) { 0206 continue; 0207 } 0208 0209 // we have to disable the widgets as well because when writing 0210 // the configuration file we can not reliably determine their state 0211 // based on visibility. 0212 if (i <= padButtons) { 0213 buttonLabel->setVisible(true); 0214 buttonSelector->setEnabled(true); 0215 buttonSelector->setVisible(true); 0216 } else { 0217 buttonLabel->setVisible(false); 0218 buttonSelector->setEnabled(false); 0219 buttonSelector->setVisible(false); 0220 } 0221 } 0222 0223 const QString padLayoutProperty = DBusTabletInterface::instance().getInformation(_tabletId, TabletInfo::ButtonLayout.key()); 0224 const QString layoutFile = findLayoutFile(padLayoutProperty); 0225 if (!layoutFile.isEmpty()) { 0226 // FIXME: libwacom svg's are large in size and have small labels 0227 // This looks ugly for some devices/with some themes, think of a better layout 0228 ui->padImage->setPixmap(QPixmap(layoutFile)); 0229 } 0230 0231 const bool anyButtonsOrLayout = padButtons > 0 || (!layoutFile.isEmpty()); 0232 ui->buttonGroupBox->setVisible(anyButtonsOrLayout); 0233 0234 bool hasLeftTouchStrip = StringUtils::asBool(DBusTabletInterface::instance().getInformation(_tabletId, TabletInfo::HasLeftTouchStrip.key())); 0235 bool hasRightTouchStrip = StringUtils::asBool(DBusTabletInterface::instance().getInformation(_tabletId, TabletInfo::HasRightTouchStrip.key())); 0236 0237 if (!hasLeftTouchStrip && !hasRightTouchStrip) { 0238 ui->touchStripGroupBox->setEnabled(false); 0239 ui->touchStripGroupBox->setVisible(false); 0240 0241 } else { 0242 ui->touchStripGroupBox->setEnabled(true); 0243 ui->touchStripGroupBox->setVisible(true); 0244 0245 // Hide the strip input widgets directly instead of 0246 // their parent widget, to keep the layout stable. 0247 // Hiding the parent widget will mess up the layout! 0248 // Also disable the widgets so we can reliable determine 0249 // which settings to save. 0250 if (!hasLeftTouchStrip) { 0251 ui->leftStripWidget->setEnabled(false); 0252 ui->leftStripUpLabel->setVisible(false); 0253 ui->leftStripUpSelector->setVisible(false); 0254 ui->leftStripDownLabel->setVisible(false); 0255 ui->leftStripDownSelector->setVisible(false); 0256 } else { 0257 ui->leftStripWidget->setEnabled(true); 0258 ui->leftStripUpLabel->setVisible(true); 0259 ui->leftStripUpSelector->setVisible(true); 0260 ui->leftStripDownLabel->setVisible(true); 0261 ui->leftStripDownSelector->setVisible(true); 0262 } 0263 0264 if (!hasRightTouchStrip) { 0265 ui->rightStripWidget->setEnabled(false); 0266 ui->rightStripUpLabel->setVisible(false); 0267 ui->rightStripUpSelector->setVisible(false); 0268 ui->rightStripDownLabel->setVisible(false); 0269 ui->rightStripDownSelector->setVisible(false); 0270 } else { 0271 ui->rightStripWidget->setEnabled(true); 0272 ui->rightStripUpLabel->setVisible(true); 0273 ui->rightStripUpSelector->setVisible(true); 0274 ui->rightStripDownLabel->setVisible(true); 0275 ui->rightStripDownSelector->setVisible(true); 0276 } 0277 } 0278 0279 if (!StringUtils::asBool(DBusTabletInterface::instance().getInformation(_tabletId, TabletInfo::HasTouchRing.key()))) { 0280 ui->touchRingGroupBox->setEnabled(false); 0281 ui->touchRingGroupBox->setVisible(false); 0282 } else { 0283 ui->touchRingGroupBox->setEnabled(true); 0284 ui->touchRingGroupBox->setVisible(true); 0285 } 0286 0287 if (!StringUtils::asBool(DBusTabletInterface::instance().getInformation(_tabletId, TabletInfo::HasWheel.key()))) { 0288 ui->wheelGroupBox->setEnabled(false); 0289 ui->wheelGroupBox->setVisible(false); 0290 } else { 0291 ui->wheelGroupBox->setEnabled(true); 0292 ui->wheelGroupBox->setVisible(true); 0293 } 0294 } 0295 0296 void ButtonPageWidget::onButtonActionChanged() 0297 { 0298 emit changed(); 0299 } 0300 0301 void ButtonPageWidget::setupUi() 0302 { 0303 ui->setupUi(this); 0304 0305 connect(ui->button1ActionSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0306 connect(ui->button2ActionSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0307 connect(ui->button3ActionSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0308 connect(ui->button4ActionSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0309 connect(ui->button5ActionSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0310 connect(ui->button6ActionSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0311 connect(ui->button7ActionSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0312 connect(ui->button8ActionSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0313 connect(ui->button9ActionSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0314 connect(ui->button10ActionSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0315 connect(ui->button11ActionSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0316 connect(ui->button12ActionSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0317 connect(ui->button13ActionSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0318 connect(ui->button14ActionSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0319 connect(ui->button15ActionSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0320 connect(ui->button16ActionSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0321 connect(ui->button17ActionSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0322 connect(ui->button18ActionSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0323 0324 connect(ui->leftStripUpSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0325 connect(ui->leftStripDownSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0326 connect(ui->rightStripUpSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0327 connect(ui->rightStripDownSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0328 0329 connect(ui->ringUpSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0330 connect(ui->ringDownSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0331 0332 connect(ui->wheelUpSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0333 connect(ui->wheelDownSelector, SIGNAL(buttonActionChanged(ButtonShortcut)), this, SLOT(onButtonActionChanged())); 0334 } 0335 0336 #include "moc_buttonpagewidget.cpp"