File indexing completed on 2024-12-22 05:17:22
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 "dialog.h" 0021 #include "ui_dialog.h" 0022 0023 #include "hwbuttondialog.h" 0024 #include "tabletdatabase.h" 0025 0026 #include <KConfigGroup> 0027 #include <KSharedConfig> 0028 0029 #include <QAbstractButton> 0030 #include <QMap> 0031 #include <QMapIterator> 0032 #include <QProcess> 0033 0034 using namespace Wacom; 0035 0036 Dialog::Dialog(QWidget *parent) 0037 : QDialog(parent) 0038 , m_ui(new Ui::Dialog) 0039 , m_hwbDialog(0) 0040 { 0041 m_ui->setupUi(this); 0042 0043 connect(m_ui->refreshButton, SIGNAL(clicked()), SLOT(refreshTabletList())); 0044 connect(m_ui->listTablets, SIGNAL(currentIndexChanged(int)), SLOT(changeTabletSelection(int))); 0045 0046 connect(m_ui->hasStatusLEDsLeft, SIGNAL(toggled(bool)), SLOT(onHasStatusLEDsLeftChanged(bool))); 0047 connect(m_ui->hasStatusLEDsRight, SIGNAL(toggled(bool)), SLOT(onhasStatusLEDsRightChanged(bool))); 0048 connect(m_ui->hasTouchRing, SIGNAL(toggled(bool)), SLOT(onhasTouchRingChanged(bool))); 0049 connect(m_ui->hasTouchStripLeft, SIGNAL(toggled(bool)), SLOT(onhasTouchStripLeftChanged(bool))); 0050 connect(m_ui->hasTouchStripRight, SIGNAL(toggled(bool)), SLOT(onhasTouchStripRightChanged(bool))); 0051 connect(m_ui->hasWheel, SIGNAL(toggled(bool)), SLOT(onhasWheelChanged(bool))); 0052 0053 connect(m_ui->expressKeyNumbers, SIGNAL(valueChanged(int)), SLOT(onExpressKeyNumbersChanged(int))); 0054 0055 connect(m_ui->buttonBox, SIGNAL(clicked(QAbstractButton *)), SLOT(buttonBoxClicked(QAbstractButton *))); 0056 0057 connect(m_ui->mapButtons, SIGNAL(clicked()), SLOT(onMapButtons())); 0058 0059 connect(m_ui->comboTouchSensor, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &Dialog::onPairedIdChanged); 0060 connect(m_ui->radioNormalTablet, &QRadioButton::toggled, this, &Dialog::onNormalTabletSet); 0061 connect(m_ui->radioParentTablet, &QRadioButton::toggled, this, &Dialog::onParentTabletSet); 0062 connect(m_ui->radioTouchSensor, &QRadioButton::toggled, this, &Dialog::onTouchSensorSet); 0063 0064 m_ui->mapButtons->setEnabled(false); 0065 0066 refreshTabletList(); 0067 } 0068 0069 Dialog::~Dialog() 0070 { 0071 delete m_ui; 0072 } 0073 0074 void Dialog::refreshTabletList() 0075 { 0076 m_ui->listTablets->blockSignals(true); 0077 m_ui->comboTouchSensor->blockSignals(true); 0078 0079 m_ui->listTablets->clear(); 0080 m_ui->comboTouchSensor->clear(); 0081 0082 m_tabletList.clear(); 0083 0084 // fetch all connected tablets 0085 QLatin1String program("xsetwacom"); 0086 QStringList arguments; 0087 arguments << QLatin1String("--list") << QLatin1String("devices"); 0088 0089 QProcess listDevices; 0090 listDevices.start(program, arguments); 0091 listDevices.waitForFinished(); 0092 0093 QString listDevicesString = QString::fromLatin1(listDevices.readAll()); 0094 QStringList listDevicesStringList = listDevicesString.split(QLatin1String("\n")); 0095 0096 // for each tablet device fetch the device id 0097 QMap<QString, QStringList> tabletList; 0098 foreach (const QString &s, listDevicesStringList) { 0099 QString device = s.split(QLatin1String("\t")).first(); 0100 device = device.trimmed(); 0101 0102 if (device.isEmpty()) { 0103 continue; 0104 } 0105 0106 QProcess checkTabletID; 0107 arguments.clear(); 0108 arguments << QLatin1String("--get") << device << QLatin1String("TabletID"); 0109 checkTabletID.start(program, arguments); 0110 checkTabletID.waitForFinished(); 0111 0112 QString checkTabletIDString = QString::fromLatin1(checkTabletID.readAll()); 0113 checkTabletIDString.remove(QLatin1String("\n")); 0114 QString tabletID = checkTabletIDString.trimmed(); 0115 0116 QStringList tl = tabletList.value(tabletID); 0117 tl << device; 0118 tabletList.insert(tabletID, tl); 0119 } 0120 0121 // for each device id figure out the common base name 0122 // for most this is the name without "pad", "stylus", "touch" etc 0123 // for some like the Wacom Pen and Touch we remove "Finger" as well 0124 QMapIterator<QString, QStringList> i(tabletList); 0125 while (i.hasNext()) { 0126 i.next(); 0127 0128 QString name; 0129 QStringList deviceList = i.value(); 0130 QString firstDevice = deviceList.takeFirst(); 0131 bool end = false; 0132 0133 for (int j = 0; j < firstDevice.length(); j++) { 0134 QChar c = firstDevice.at(j); 0135 0136 foreach (const QString &s, deviceList) { 0137 if (s.at(j) != c) { 0138 end = true; 0139 break; 0140 } 0141 } 0142 0143 if (end) { 0144 break; 0145 } 0146 0147 name.append(c); 0148 } 0149 0150 // create the Tablet entry 0151 Tablet t; 0152 t.serialID = i.key().toInt(); 0153 t.company = QLatin1String("Wacom"); 0154 t.name = name.trimmed(); 0155 t.devices = i.value(); 0156 0157 QString hexNumber = QString::number(t.serialID, 16); 0158 while (hexNumber.length() < 4) { 0159 hexNumber.prepend(QLatin1String("0")); 0160 } 0161 0162 TabletInformation ti; 0163 if (TabletDatabase::instance().lookupTablet(hexNumber.toUpper(), ti)) { 0164 t.buttonNumber = ti.getInt(TabletInfo::NumPadButtons); 0165 int leds = ti.getInt(TabletInfo::StatusLEDs); 0166 t.hasStatusLEDsLeft = leds > 4; 0167 t.hasStatusLEDsRight = leds > 0; 0168 t.hasTouchRing = ti.getBool(TabletInfo::HasTouchRing); 0169 t.hasTouchStripLeft = ti.getBool(TabletInfo::HasLeftTouchStrip); 0170 t.hasTouchStripRight = ti.getBool(TabletInfo::HasRightTouchStrip); 0171 t.hasWheel = ti.getBool(TabletInfo::HasWheel); 0172 0173 t.company = ti.get(TabletInfo::CompanyName); 0174 t.name = ti.get(TabletInfo::TabletName); 0175 0176 t.model = ti.get(TabletInfo::TabletModel); 0177 t.layout = ti.get(TabletInfo::ButtonLayout); 0178 0179 // set default button map 0180 for (int i = 1; i <= t.buttonNumber; i++) { 0181 t.hwMapping << i; 0182 } 0183 0184 const auto buttonMap = ti.getButtonMap(); 0185 for (const auto &key : buttonMap.keys()) { 0186 const auto keyIndex = key.toInt() - 1; 0187 if (keyIndex < t.buttonNumber) { 0188 t.hwMapping[keyIndex] = buttonMap.value(key).toInt(); 0189 } 0190 } 0191 0192 auto pairedID = ti.get(TabletInfo::TouchSensorId); 0193 if (pairedID.isEmpty()) { 0194 t.hasPairedID = false; 0195 } else { 0196 t.hasPairedID = true; 0197 t.pairedID = pairedID; 0198 } 0199 t.isTouchSensor = ti.getBool(TabletInfo::IsTouchSensor); 0200 } 0201 0202 m_tabletList.append(t); 0203 0204 m_ui->listTablets->addItem(t.name); 0205 m_ui->comboTouchSensor->addItem(t.name); 0206 } 0207 0208 m_ui->listTablets->setCurrentIndex(0); 0209 m_ui->listTablets->blockSignals(false); 0210 m_ui->comboTouchSensor->setCurrentIndex(0); 0211 m_ui->comboTouchSensor->blockSignals(false); 0212 0213 changeTabletSelection(0); 0214 } 0215 0216 bool Dialog::validIndex() 0217 { 0218 return !m_tabletList.isEmpty() && m_tabletList.size() > m_ui->listTablets->currentIndex(); 0219 } 0220 0221 void Dialog::changeTabletSelection(int index) 0222 { 0223 if (!validIndex()) { 0224 return; 0225 } 0226 0227 Tablet t = m_tabletList.at(index); 0228 0229 QString hexNumber = QString::number(t.serialID, 16); 0230 0231 while (hexNumber.length() < 4) { 0232 hexNumber.prepend(QLatin1String("0")); 0233 } 0234 0235 m_ui->listSerialId->setText(QString::fromLatin1("%1 [%2]").arg(t.serialID).arg(hexNumber.toUpper())); 0236 0237 m_ui->listDevices->setText(t.devices.join(QLatin1String("\n"))); 0238 m_ui->hasStatusLEDsLeft->setChecked(t.hasStatusLEDsLeft); 0239 m_ui->hasStatusLEDsRight->setChecked(t.hasStatusLEDsRight); 0240 m_ui->hasTouchRing->setChecked(t.hasTouchRing); 0241 m_ui->hasTouchStripLeft->setChecked(t.hasTouchStripLeft); 0242 m_ui->hasTouchStripRight->setChecked(t.hasTouchStripRight); 0243 m_ui->hasWheel->setChecked(t.hasWheel); 0244 m_ui->expressKeyNumbers->setValue(t.buttonNumber); 0245 m_ui->radioNormalTablet->setChecked(!t.isTouchSensor && !t.hasPairedID); 0246 m_ui->radioTouchSensor->setChecked(t.isTouchSensor); 0247 m_ui->radioParentTablet->setChecked(t.hasPairedID); 0248 m_ui->comboTouchSensor->setEnabled(t.hasPairedID); 0249 0250 int tabletIndex = 0; 0251 for (const auto &tablet : m_tabletList) { 0252 if (QString::fromLatin1("%1").arg(tablet.serialID, 4, 16, QChar::fromLatin1('0')) == t.pairedID) { 0253 m_ui->comboTouchSensor->setCurrentIndex(tabletIndex); 0254 break; 0255 } 0256 ++tabletIndex; 0257 } 0258 0259 showHWButtonMap(); 0260 } 0261 0262 void Dialog::onHasStatusLEDsLeftChanged(bool toggled) 0263 { 0264 if (!validIndex()) { 0265 return; 0266 } 0267 0268 Tablet t = m_tabletList.at(m_ui->listTablets->currentIndex()); 0269 t.hasStatusLEDsLeft = toggled; 0270 m_tabletList.replace(m_ui->listTablets->currentIndex(), t); 0271 } 0272 0273 void Dialog::onhasStatusLEDsRightChanged(bool toggled) 0274 { 0275 if (!validIndex()) { 0276 return; 0277 } 0278 0279 Tablet t = m_tabletList.at(m_ui->listTablets->currentIndex()); 0280 t.hasStatusLEDsRight = toggled; 0281 m_tabletList.replace(m_ui->listTablets->currentIndex(), t); 0282 } 0283 0284 void Dialog::onhasTouchRingChanged(bool toggled) 0285 { 0286 if (!validIndex()) { 0287 return; 0288 } 0289 0290 Tablet t = m_tabletList.at(m_ui->listTablets->currentIndex()); 0291 t.hasTouchRing = toggled; 0292 m_tabletList.replace(m_ui->listTablets->currentIndex(), t); 0293 } 0294 0295 void Dialog::onhasTouchStripLeftChanged(bool toggled) 0296 { 0297 if (!validIndex()) { 0298 return; 0299 } 0300 0301 Tablet t = m_tabletList.at(m_ui->listTablets->currentIndex()); 0302 t.hasTouchStripLeft = toggled; 0303 m_tabletList.replace(m_ui->listTablets->currentIndex(), t); 0304 } 0305 0306 void Dialog::onhasTouchStripRightChanged(bool toggled) 0307 { 0308 if (!validIndex()) { 0309 return; 0310 } 0311 0312 Tablet t = m_tabletList.at(m_ui->listTablets->currentIndex()); 0313 t.hasTouchStripRight = toggled; 0314 m_tabletList.replace(m_ui->listTablets->currentIndex(), t); 0315 } 0316 0317 void Dialog::onhasWheelChanged(bool toggled) 0318 { 0319 if (!validIndex()) { 0320 return; 0321 } 0322 0323 Tablet t = m_tabletList.at(m_ui->listTablets->currentIndex()); 0324 t.hasWheel = toggled; 0325 m_tabletList.replace(m_ui->listTablets->currentIndex(), t); 0326 } 0327 0328 void Dialog::onExpressKeyNumbersChanged(int buttons) 0329 { 0330 if (!validIndex()) { 0331 return; 0332 } 0333 0334 Tablet t = m_tabletList.at(m_ui->listTablets->currentIndex()); 0335 t.buttonNumber = buttons; 0336 m_tabletList.replace(m_ui->listTablets->currentIndex(), t); 0337 0338 m_ui->mapButtons->setEnabled(m_ui->expressKeyNumbers->value() > 0); 0339 0340 showHWButtonMap(); 0341 } 0342 0343 void Dialog::buttonBoxClicked(QAbstractButton *button) 0344 { 0345 QDialogButtonBox::StandardButton stdButton = m_ui->buttonBox->standardButton(button); 0346 switch (stdButton) { 0347 case QDialogButtonBox::Close: 0348 qApp->quit(); 0349 break; 0350 0351 case QDialogButtonBox::Save: { 0352 if (!validIndex()) { 0353 return; 0354 } 0355 0356 Tablet t = m_tabletList.at(m_ui->listTablets->currentIndex()); 0357 saveTabletInfo(t); 0358 break; 0359 } 0360 case QDialogButtonBox::SaveAll: { 0361 foreach (const Tablet &t, m_tabletList) { 0362 saveTabletInfo(t); 0363 } 0364 break; 0365 } 0366 default: 0367 return; 0368 } 0369 } 0370 0371 void Dialog::onPairedIdChanged(int index) 0372 { 0373 Tablet t = m_tabletList.at(m_ui->listTablets->currentIndex()); 0374 t.pairedID = QString::fromLatin1("%1").arg(m_tabletList.at(index).serialID, 4, 16, QChar::fromLatin1('0')); 0375 m_tabletList.replace(m_ui->listTablets->currentIndex(), t); 0376 } 0377 0378 void Dialog::onNormalTabletSet(bool enabled) 0379 { 0380 if (enabled) { 0381 const int index = m_ui->listTablets->currentIndex(); 0382 if (index != -1) { 0383 Tablet t = m_tabletList.at(index); 0384 t.isTouchSensor = false; 0385 t.hasPairedID = false; 0386 m_tabletList.replace(index, t); 0387 m_ui->comboTouchSensor->setEnabled(false); 0388 } 0389 } 0390 } 0391 0392 void Dialog::onParentTabletSet(bool enabled) 0393 { 0394 const int index = m_ui->listTablets->currentIndex(); 0395 if (enabled && index != -1) { 0396 Tablet t = m_tabletList.at(index); 0397 t.isTouchSensor = false; 0398 t.hasPairedID = true; 0399 m_tabletList.replace(index, t); 0400 m_ui->comboTouchSensor->setEnabled(true); 0401 } else { 0402 m_ui->comboTouchSensor->setEnabled(false); 0403 } 0404 } 0405 0406 void Dialog::onTouchSensorSet(bool enabled) 0407 { 0408 const int index = m_ui->listTablets->currentIndex(); 0409 if (enabled && index != -1) { 0410 Tablet t = m_tabletList.at(index); 0411 t.isTouchSensor = true; 0412 t.hasPairedID = false; 0413 m_tabletList.replace(index, t); 0414 m_ui->comboTouchSensor->setEnabled(false); 0415 } 0416 } 0417 0418 void Dialog::onMapButtons() 0419 { 0420 m_hwbDialog = new HWButtonDialog(m_ui->expressKeyNumbers->value(), this); 0421 0422 int ret = m_hwbDialog->exec(); 0423 0424 Tablet t = m_tabletList.at(m_ui->listTablets->currentIndex()); 0425 if (ret == QDialog::Accepted) { 0426 t.hwMapping = m_hwbDialog->buttonMap(); 0427 } else { 0428 t.hwMapping.clear(); 0429 } 0430 0431 m_tabletList.replace(m_ui->listTablets->currentIndex(), t); 0432 showHWButtonMap(); 0433 } 0434 0435 void Dialog::showHWButtonMap() 0436 { 0437 Tablet t = m_tabletList.at(m_ui->listTablets->currentIndex()); 0438 0439 QString text; 0440 for (int i = 0; i < t.hwMapping.size(); ++i) { 0441 text.append(i18n("Button %1 maps to Button %2", (i + 1), t.hwMapping.at(i))); 0442 text.append(QLatin1String("\n")); 0443 } 0444 0445 m_ui->buttonMappingLabel->setText(text); 0446 } 0447 0448 void Dialog::saveTabletInfo(const Tablet &t) 0449 { 0450 KConfig config(QLatin1String("tabletdblocalrc")); 0451 0452 QString hexNumber = QString::number(t.serialID, 16); 0453 0454 while (hexNumber.length() < 4) { 0455 hexNumber.prepend(QLatin1String("0")); 0456 } 0457 KConfigGroup tabletGroup(&config, hexNumber.toUpper()); 0458 tabletGroup.deleteGroup(); 0459 tabletGroup.config()->sync(); 0460 0461 tabletGroup.writeEntry("model", t.model); 0462 tabletGroup.writeEntry("layout", t.layout); 0463 tabletGroup.writeEntry("name", t.name); 0464 0465 int leds = 0; 0466 if (t.hasStatusLEDsLeft && t.hasStatusLEDsRight) { 0467 leds = 8; 0468 } else if (t.hasStatusLEDsLeft || t.hasStatusLEDsRight) { 0469 leds = 4; 0470 } 0471 0472 tabletGroup.writeEntry("statusleds", leds); 0473 tabletGroup.writeEntry("wheel", t.hasWheel); 0474 tabletGroup.writeEntry("touchring", t.hasTouchRing); 0475 tabletGroup.writeEntry("touchstripl", t.hasTouchStripLeft); 0476 tabletGroup.writeEntry("touchstripr", t.hasTouchStripRight); 0477 0478 tabletGroup.writeEntry("padbuttons", t.buttonNumber); 0479 for (int i = 0; i < t.hwMapping.size(); i++) { 0480 tabletGroup.writeEntry(QString::fromLatin1("hwbutton%1").arg(i + 1), t.hwMapping.at(i)); 0481 } 0482 0483 if (t.isTouchSensor) { 0484 tabletGroup.writeEntry("istouchsensor", t.isTouchSensor); 0485 } 0486 if (t.hasPairedID) { 0487 tabletGroup.writeEntry("touchsensorid", t.pairedID); 0488 } 0489 0490 tabletGroup.config()->sync(); 0491 } 0492 0493 #include "moc_dialog.cpp"