File indexing completed on 2025-01-26 05:09:31
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 "pressurecurvewidget.h" 0021 0022 // Qt includes 0023 #include <QDebug> 0024 #include <QMouseEvent> 0025 #include <QPainter> 0026 #include <QPainterPath> 0027 #include <QResizeEvent> 0028 #include <QTabletEvent> 0029 0030 using namespace Wacom; 0031 0032 PressureCurveWidget::PressureCurveWidget(QWidget *parent) 0033 : QWidget(parent) 0034 { 0035 setBackgroundRole(QPalette::Base); 0036 setAutoFillBackground(true); 0037 } 0038 0039 void PressureCurveWidget::setControlPoints(qreal p1, qreal p2, qreal p3, qreal p4) 0040 { 0041 // change y values upside down (xsetwacom has 0,0 in the lower left QWidget in the upper left) 0042 p2 = 100 - p2; 0043 p4 = 100 - p4; 0044 m_cP1 = QPointF((p1 / 100.0) * width(), (p2 / 100.0) * height()); 0045 m_cP2 = QPointF((p3 / 100.0) * width(), (p4 / 100.0) * height()); 0046 } 0047 0048 void PressureCurveWidget::mousePressEvent(QMouseEvent *event) 0049 { 0050 setNearestPoint(event->localPos()); 0051 } 0052 0053 void PressureCurveWidget::mouseMoveEvent(QMouseEvent *event) 0054 { 0055 moveControlPoint(event->localPos()); 0056 update(); 0057 } 0058 0059 void PressureCurveWidget::mouseReleaseEvent(QMouseEvent *event) 0060 { 0061 Q_UNUSED(event); 0062 m_activePoint = 0; 0063 } 0064 0065 void PressureCurveWidget::resizeEvent(QResizeEvent *event) 0066 { 0067 // avoid unpredictable ratio on first initialisation 0068 if (event->oldSize().width() == -1 || event->oldSize().width() == 0 || event->oldSize().height() == 0) { 0069 return; 0070 } 0071 0072 const qreal xRatio = static_cast<qreal>(event->size().width()) / event->oldSize().width(); 0073 const qreal yRatio = static_cast<qreal>(event->size().height()) / event->oldSize().height(); 0074 0075 m_cP1.setX(m_cP1.x() * xRatio); 0076 m_cP1.setY(m_cP1.y() * yRatio); 0077 m_cP2.setX(m_cP2.x() * xRatio); 0078 m_cP2.setY(m_cP2.y() * yRatio); 0079 } 0080 0081 void PressureCurveWidget::tabletEvent(QTabletEvent *event) 0082 { 0083 event->accept(); 0084 m_pressure = event->pressure(); 0085 0086 constexpr qreal threshold = 0.001; 0087 if (m_pressure <= threshold) { 0088 m_activePoint = 0; 0089 } 0090 0091 if (m_activePoint > 0) { 0092 moveControlPoint(event->pos()); 0093 } else if (m_pressure > threshold) { 0094 setNearestPoint(event->pos()); 0095 } 0096 0097 update(); 0098 } 0099 0100 void PressureCurveWidget::setNearestPoint(const QPointF &pos) 0101 { 0102 qreal d1 = QLineF(pos, m_cP1).length(); 0103 qreal d2 = QLineF(pos, m_cP2).length(); 0104 0105 if (d1 < m_pointSize) { 0106 m_activePoint = 1; 0107 } else if (d2 < m_pointSize) { 0108 m_activePoint = 2; 0109 } 0110 } 0111 0112 void PressureCurveWidget::moveControlPoint(const QPointF &pos) 0113 { 0114 int x; 0115 int y; 0116 0117 if (pos.x() > width()) { 0118 x = width(); 0119 } else if (pos.x() < 0) { 0120 x = 0; 0121 } else { 0122 x = qRound(pos.x()); 0123 } 0124 0125 if (pos.y() > height()) { 0126 y = height(); 0127 } else if (pos.y() < 0) { 0128 y = 0; 0129 } else { 0130 y = qRound(pos.y()); 0131 } 0132 0133 switch (m_activePoint) { 0134 case 1: 0135 m_cP1 = QPoint(x, y); 0136 m_cP2 = QPoint(y, x); // seems xsetwacom is expecting to be both controllpoints the same with switches xy values 0137 // makes no sense to me, but otherwise the wacom driver complains 0138 // the wacom_utility does it the same way though 0139 break; 0140 case 2: 0141 m_cP2 = QPoint(x, y); 0142 m_cP1 = QPoint(y, x); // see above 0143 break; 0144 } 0145 0146 // build string with controlpoints as used in xsetwacom settings 0147 int p1 = qRound((m_cP1.x() / width()) * 100.0); 0148 int p2 = qRound((m_cP1.y() / height()) * 100.0); 0149 int p3 = qRound((m_cP2.x() / width()) * 100.0); 0150 int p4 = qRound((m_cP2.y() / height()) * 100.0); 0151 0152 // change y values upside down 0153 p2 = 100 - p2; 0154 p4 = 100 - p4; 0155 QString pointsString = QString::fromLatin1("%1 %2 %3 %4").arg(p1).arg(p2).arg(p3).arg(p4); 0156 0157 emit controlPointsChanged(pointsString); 0158 } 0159 0160 void PressureCurveWidget::paintEvent(QPaintEvent *event) 0161 { 0162 Q_UNUSED(event); 0163 0164 QPainter painter(this); 0165 painter.setRenderHint(QPainter::Antialiasing, true); 0166 painter.translate(+0.5, +0.5); 0167 0168 // draw the background grid 0169 int yStep = height() / 10; 0170 int xStep = width() / 10; 0171 painter.setPen(QColor(Qt::gray)); 0172 0173 for (int i = 1; i < 10; i++) { 0174 painter.drawLine(i * xStep, 0, i * xStep, height()); 0175 painter.drawLine(0, i * yStep, width(), i * yStep); 0176 } 0177 0178 // draw controllpoint lines 0179 painter.setPen(QColor(Qt::gray)); 0180 painter.drawLine(m_cP1, QPoint(0, height())); 0181 painter.drawLine(m_cP2, QPoint(width(), 0)); 0182 0183 // create presscurve 0184 QPainterPath curvePath; 0185 curvePath.moveTo(0, height()); 0186 curvePath.cubicTo(m_cP1, m_cP2, QPoint(width(), 0)); 0187 0188 // create polygon for the area below the curve 0189 QPainterPath areaBelowCurve(curvePath); 0190 areaBelowCurve.lineTo(width(), height()); 0191 areaBelowCurve.lineTo(0, height()); 0192 QRectF clearRect(m_pressure * width(), 0, width(), height()); 0193 QPainterPath subtract; 0194 subtract.addRect(clearRect); 0195 0196 // draw below curve area 0197 painter.setPen(QPen()); 0198 painter.setBrush(QColor(0, 102, 255)); 0199 painter.drawPath(areaBelowCurve.subtracted(subtract)); 0200 0201 // draw presscurve 0202 QPen curvePen; 0203 curvePen.setWidth(2); 0204 curvePen.setColor(m_curveColor); 0205 painter.setPen(curvePen); 0206 painter.setBrush(QBrush()); 0207 painter.drawPath(curvePath); 0208 0209 // draw controllpoints 0210 painter.setPen(QColor(226, 8, 0)); 0211 painter.setBrush(QColor(226, 8, 0)); 0212 painter.drawEllipse(m_cP1, m_pointSize, m_pointSize); 0213 painter.drawEllipse(m_cP2, m_pointSize, m_pointSize); 0214 } 0215 0216 #include "moc_pressurecurvewidget.cpp"