File indexing completed on 2025-01-26 05:09:32
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 "tabletpagewidget.h" 0021 #include "ui_tabletpagewidget.h" 0022 0023 #include "dbustabletinterface.h" 0024 #include "deviceprofile.h" 0025 #include "profilemanagement.h" 0026 #include "property.h" 0027 #include "screensinfo.h" 0028 #include "stringutils.h" 0029 #include "tabletareaselectiondialog.h" 0030 #include "x11wacom.h" 0031 0032 #include <QStringList> 0033 0034 using namespace Wacom; 0035 0036 TabletPageWidget::TabletPageWidget(QWidget *parent) 0037 : QWidget(parent) 0038 , ui(new Ui::TabletPageWidget) 0039 { 0040 setupUi(); 0041 } 0042 0043 TabletPageWidget::~TabletPageWidget() 0044 { 0045 delete ui; 0046 } 0047 0048 void TabletPageWidget::setTabletId(const QString &tabletId) 0049 { 0050 _tabletId = tabletId; 0051 } 0052 0053 void TabletPageWidget::loadFromProfile(ProfileManagementInterface &profileManagement) 0054 { 0055 DeviceProfile stylusProfile = profileManagement.loadDeviceProfile(DeviceType::Stylus); 0056 0057 setRotation(stylusProfile.getProperty(Property::Rotate)); 0058 setScreenSpace(stylusProfile.getProperty(Property::ScreenSpace)); 0059 setScreenMap(stylusProfile.getProperty(Property::ScreenMap)); 0060 setTrackingMode(stylusProfile.getProperty(Property::Mode)); 0061 } 0062 0063 void TabletPageWidget::reloadWidget() 0064 { 0065 // get all tablet device names we need 0066 QDBusReply<QString> stylusDeviceNameReply = DBusTabletInterface::instance().getDeviceName(_tabletId, DeviceType::Stylus.key()); 0067 QDBusReply<QString> touchDeviceNameReply = DBusTabletInterface::instance().getDeviceName(_tabletId, DeviceType::Touch.key()); 0068 0069 // update name and maximum tablet area for all devices 0070 _deviceNameStylus.clear(); 0071 _deviceNameTouch.clear(); 0072 _tabletGeometry = TabletArea(); 0073 _screenMap = ScreenMap(); 0074 0075 if (stylusDeviceNameReply.isValid()) { 0076 _deviceNameStylus = stylusDeviceNameReply.value(); 0077 _tabletGeometry = X11Wacom::getMaximumTabletArea(stylusDeviceNameReply.value()); 0078 _screenMap = ScreenMap(_tabletGeometry); 0079 } 0080 0081 if (touchDeviceNameReply.isValid()) { 0082 _deviceNameTouch = touchDeviceNameReply.value(); 0083 } 0084 } 0085 0086 void TabletPageWidget::saveToProfile(ProfileManagementInterface &profileManagement) 0087 { 0088 DeviceProfile padProfile = profileManagement.loadDeviceProfile(DeviceType::Pad); 0089 DeviceProfile stylusProfile = profileManagement.loadDeviceProfile(DeviceType::Stylus); 0090 DeviceProfile eraserProfile = profileManagement.loadDeviceProfile(DeviceType::Eraser); 0091 DeviceProfile touchProfile = profileManagement.loadDeviceProfile(DeviceType::Touch); 0092 0093 stylusProfile.setProperty(Property::Rotate, getRotation()); 0094 eraserProfile.setProperty(Property::Rotate, getRotation()); 0095 touchProfile.setProperty(Property::Rotate, getRotation()); 0096 padProfile.setProperty(Property::Rotate, QString()); // make sure it is not set on the pad - will mess up touch 0097 0098 stylusProfile.setProperty(Property::ScreenSpace, getScreenSpaceAsString()); 0099 eraserProfile.setProperty(Property::ScreenSpace, getScreenSpaceAsString()); 0100 padProfile.setProperty(Property::ScreenSpace, QString()); // should not be set on the pad, causes trouble 0101 padProfile.setProperty(Property::Area, QString()); // should not be set on the pad, causes trouble 0102 0103 stylusProfile.setProperty(Property::ScreenMap, getScreenMapAsString()); 0104 eraserProfile.setProperty(Property::ScreenMap, getScreenMapAsString()); 0105 padProfile.setProperty(Property::ScreenMap, QString()); // make sure it is not set on the pad 0106 0107 stylusProfile.setProperty(Property::Mode, getTrackingMode()); 0108 eraserProfile.setProperty(Property::Mode, getTrackingMode()); 0109 0110 profileManagement.saveDeviceProfile(padProfile); 0111 profileManagement.saveDeviceProfile(stylusProfile); 0112 profileManagement.saveDeviceProfile(eraserProfile); 0113 0114 if (!_deviceNameTouch.isEmpty()) { 0115 profileManagement.saveDeviceProfile(touchProfile); 0116 } 0117 } 0118 0119 void TabletPageWidget::onAutoRotateChanged(int state) 0120 { 0121 setAutoRotationEnabled(state == Qt::Checked); 0122 onProfileChanged(); 0123 } 0124 0125 void TabletPageWidget::onProfileChanged() 0126 { 0127 emit changed(); 0128 } 0129 0130 void TabletPageWidget::onTabletMappingClicked() 0131 { 0132 // get current rotation settings 0133 // we need to invert it as our rotation settings in this widget have a canvas viewpoint 0134 const ScreenRotation *lookupRotation = ScreenRotation::find(getRotation()); 0135 ScreenRotation rotation = lookupRotation ? lookupRotation->invert() : ScreenRotation::NONE; 0136 0137 TabletAreaSelectionDialog selectionDialog; 0138 selectionDialog.setupWidget(getScreenMap(), _deviceNameStylus, rotation); 0139 selectionDialog.select(getScreenSpace()); 0140 0141 if (selectionDialog.exec() == QDialog::Accepted) { 0142 setScreenMap(selectionDialog.getScreenMap()); 0143 setScreenSpace(selectionDialog.getScreenSpace()); 0144 onProfileChanged(); 0145 } 0146 } 0147 0148 void TabletPageWidget::onRotationChanged() 0149 { 0150 // determine rotation 0151 const ScreenRotation *lookupRotation = ScreenRotation::find(getRotation()); 0152 0153 // we need to invert it as our rotation settings in this widget have a canvas viewpoint 0154 // and our private member variable has a tablet viewpoint 0155 emit rotationChanged(lookupRotation ? lookupRotation->invert() : ScreenRotation::NONE); 0156 } 0157 0158 void TabletPageWidget::onTrackingModeAbsolute(bool activated) 0159 { 0160 if (!activated) { 0161 return; 0162 } 0163 0164 setTrackingMode(QLatin1String("absolute")); 0165 onProfileChanged(); 0166 } 0167 0168 void TabletPageWidget::onTrackingModeRelative(bool activated) 0169 { 0170 if (!activated) { 0171 return; 0172 } 0173 0174 setTrackingMode(QLatin1String("relative")); 0175 onProfileChanged(); 0176 } 0177 0178 const QString TabletPageWidget::getRotation() const 0179 { 0180 QString rotation = ScreenRotation::NONE.key(); 0181 0182 if (isAutoRotationEnabled()) { 0183 if (isAutoRotateInversionEnabled()) { 0184 rotation = ScreenRotation::AUTO_INVERTED.key(); 0185 } else { 0186 rotation = ScreenRotation::AUTO.key(); 0187 } 0188 } else { 0189 int index = ui->rotatationSelectionComboBox->currentIndex(); 0190 rotation = ui->rotatationSelectionComboBox->itemData(index).toString(); 0191 } 0192 0193 return rotation; 0194 } 0195 0196 const ScreenMap &TabletPageWidget::getScreenMap() const 0197 { 0198 return _screenMap; 0199 } 0200 0201 const QString TabletPageWidget::getScreenMapAsString() const 0202 { 0203 return getScreenMap().toString(); 0204 } 0205 0206 const ScreenSpace &TabletPageWidget::getScreenSpace() const 0207 { 0208 return _screenSpace; 0209 } 0210 0211 const QString TabletPageWidget::getScreenSpaceAsString() const 0212 { 0213 return getScreenSpace().toString(); 0214 } 0215 0216 const QString TabletPageWidget::getTrackingMode() const 0217 { 0218 if (ui->trackAbsoluteRadioButton->isChecked()) { 0219 return QLatin1String("absolute"); 0220 } 0221 0222 return QLatin1String("relative"); 0223 } 0224 0225 bool TabletPageWidget::isAutoRotateInversionEnabled() const 0226 { 0227 return ui->rotateWithScreenInvertCheckBox->isChecked(); 0228 } 0229 0230 bool TabletPageWidget::isAutoRotationEnabled() const 0231 { 0232 return ui->rotateWithScreenCheckBox->isChecked(); 0233 } 0234 0235 void TabletPageWidget::setAutoRotateInversionEnabled(bool value) 0236 { 0237 ui->rotateWithScreenInvertCheckBox->blockSignals(true); 0238 ui->rotateWithScreenInvertCheckBox->setChecked(value); 0239 ui->rotateWithScreenInvertCheckBox->blockSignals(false); 0240 } 0241 0242 void TabletPageWidget::setAutoRotationEnabled(bool value) 0243 { 0244 ui->rotatationSelectionComboBox->setEnabled(!value); 0245 ui->rotateWithScreenInvertCheckBox->setEnabled(value); 0246 0247 if (value) { 0248 setRotation(ScreenRotation::NONE.key()); 0249 } else { 0250 setAutoRotateInversionEnabled(false); 0251 } 0252 0253 ui->rotateWithScreenCheckBox->blockSignals(true); 0254 ui->rotateWithScreenCheckBox->setChecked(value); 0255 ui->rotateWithScreenCheckBox->blockSignals(false); 0256 } 0257 0258 void TabletPageWidget::setRotation(const QString &value) 0259 { 0260 const ScreenRotation *lookup = ScreenRotation::find(value); 0261 ScreenRotation rotation = lookup ? *lookup : ScreenRotation::NONE; 0262 QString rotationValue = rotation.key(); 0263 0264 if (rotation == ScreenRotation::AUTO) { 0265 setAutoRotationEnabled(true); 0266 rotationValue = ScreenRotation::NONE.key(); 0267 0268 } else if (rotation == ScreenRotation::AUTO_INVERTED) { 0269 setAutoRotationEnabled(true); 0270 setAutoRotateInversionEnabled(true); 0271 rotationValue = ScreenRotation::NONE.key(); 0272 } 0273 0274 int rotationIndex = ui->rotatationSelectionComboBox->findData(rotationValue); 0275 0276 ui->rotatationSelectionComboBox->blockSignals(true); 0277 ui->rotatationSelectionComboBox->setCurrentIndex(rotationIndex >= 0 ? rotationIndex : 0); 0278 ui->rotatationSelectionComboBox->blockSignals(false); 0279 0280 onRotationChanged(); 0281 } 0282 0283 void TabletPageWidget::setScreenMap(const ScreenMap &screenMap) 0284 { 0285 _screenMap = screenMap; 0286 0287 assertValidTabletMapping(); 0288 } 0289 0290 void TabletPageWidget::setScreenMap(const QString &value) 0291 { 0292 setScreenMap(ScreenMap(value)); 0293 } 0294 0295 void TabletPageWidget::setScreenSpace(const ScreenSpace &screenSpace) 0296 { 0297 _screenSpace = screenSpace; 0298 0299 assertValidTabletMapping(); 0300 } 0301 0302 void TabletPageWidget::setScreenSpace(const QString &value) 0303 { 0304 setScreenSpace(ScreenSpace(value)); 0305 } 0306 0307 void TabletPageWidget::setTrackingMode(const QString &value) 0308 { 0309 ui->trackAbsoluteRadioButton->blockSignals(true); 0310 ui->trackRelativeRadioButton->blockSignals(true); 0311 0312 if (value.contains(QLatin1String("absolute"), Qt::CaseInsensitive)) { 0313 ui->trackAbsoluteRadioButton->setChecked(true); 0314 ui->trackRelativeRadioButton->setChecked(false); 0315 } else { 0316 ui->trackAbsoluteRadioButton->setChecked(false); 0317 ui->trackRelativeRadioButton->setChecked(true); 0318 } 0319 0320 ui->trackAbsoluteRadioButton->blockSignals(false); 0321 ui->trackRelativeRadioButton->blockSignals(false); 0322 0323 assertValidTabletMapping(); 0324 } 0325 0326 void TabletPageWidget::assertValidTabletMapping() 0327 { 0328 bool isWarningVisible = false; 0329 0330 if (ui->trackRelativeRadioButton->isChecked()) { 0331 // Relative mode is selected. In relative mode a 0332 // device can not be mapped to a single monitor 0333 ScreenSpace screenSpace = getScreenSpace(); 0334 0335 if (screenSpace.isMonitor()) { 0336 isWarningVisible = true; 0337 } 0338 } 0339 0340 ui->trackingWarningIcon->setVisible(isWarningVisible); 0341 ui->trackingWarningLabel->setVisible(isWarningVisible); 0342 } 0343 0344 void TabletPageWidget::setupUi() 0345 { 0346 ui->setupUi(this); 0347 0348 // init screen mapping warning 0349 ui->trackingWarningIcon->setPixmap(QIcon::fromTheme(QLatin1String("dialog-warning")).pixmap(QSize(16, 16))); 0350 ui->trackingWarningIcon->setVisible(false); 0351 ui->trackingWarningLabel->setVisible(false); 0352 0353 // fill rotation combo box 0354 // xsetwacom's rotation is based on coordinate rotation, but we are asking the user for a tablet rotation. 0355 // Therefore we have to swap the values for clockwise and counterclockwise rotation. 0356 ui->rotatationSelectionComboBox->addItem(i18nc("Either no orientation or the current screen orientation is applied to the tablet.", "Default Orientation"), 0357 ScreenRotation::NONE.key()); 0358 ui->rotatationSelectionComboBox->addItem(i18nc("The tablet will be rotated clockwise.", "Rotate Tablet Clockwise"), ScreenRotation::CCW.key()); 0359 ui->rotatationSelectionComboBox->addItem(i18nc("The tablet will be rotated counterclockwise.", "Rotate Tablet Counterclockwise"), ScreenRotation::CW.key()); 0360 ui->rotatationSelectionComboBox->addItem(i18nc("The tablet will be rotated up side down.", "Rotate Tablet Upside-Down"), ScreenRotation::HALF.key()); 0361 } 0362 0363 #include "moc_tabletpagewidget.cpp"