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 #ifndef PRESSURECURVEWIDGET_H
0021 #define PRESSURECURVEWIDGET_H
0022 
0023 // Qt includes
0024 #include <QColor>
0025 #include <QPoint>
0026 #include <QSize>
0027 #include <QWidget>
0028 
0029 class QMouseEvent;
0030 class QPaintEvent;
0031 
0032 namespace Wacom
0033 {
0034 /**
0035  * This widget implements a visual way to adjust the press curve for wacom tablets
0036  * It shows the beziercurve and two control points to adjust the curve
0037  * Furthermore if Qt detects the tablet device the pressure is animated
0038  * as filled area below the curve to give a better feel what the changes to the press curve mean
0039  * This step is not necessary to change the press curve settings, but a nice visual help.
0040  * Qt relies on the xorg.conf to detect the tablet correctly because it use hardcoded names for it
0041  * name them "stylus", "pen", "eraser" to get it working.
0042  *
0043  * @see https://doc.qt.io/qt-5/qtabletevent.html
0044  */
0045 class PressureCurveWidget : public QWidget
0046 {
0047     Q_OBJECT
0048 
0049 public:
0050     /**
0051      * default constructor
0052      *
0053      * @param parent the parent widget that holds this one
0054      */
0055     explicit PressureCurveWidget(QWidget *parent = nullptr);
0056 
0057     /**
0058      * Sets the start values for the bezier presscurve via this control points
0059      *
0060      * @bug if this widget has no fixed size, the width()/height() return the
0061      *      the values as specified in the .ui file or when the widget is created
0062      *      The automatic layout changes took place before somehow and thus
0063      *      leads to a wrong placement of the control points
0064      * @param p1 x value of the first point
0065      * @param p2 y value of the first point
0066      * @param p3 x value of the second point
0067      * @param p4 y value of the second point
0068      */
0069     void setControlPoints(qreal p1, qreal p2, qreal p3, qreal p4);
0070 
0071 protected:
0072     /**
0073      * Called whenever the mouse is pressed in the widget
0074      * Selects the control point if the mouse click was on it
0075      *
0076      * @param event the mouse event
0077      */
0078     void mousePressEvent(QMouseEvent *event) override;
0079 
0080     /**
0081      * Drags the control points around
0082      * based on the active selected control point specified in the mousePressEvent
0083      * the selected control point is moved around and changes the presscurve directly
0084      *
0085      * @param event the mouse event
0086      */
0087     void mouseMoveEvent(QMouseEvent *event) override;
0088 
0089     /**
0090      * Dragging the controlpoint stopped
0091      * Resets the selection of the active control point to move around
0092      *
0093      * @param event the mouse event
0094      */
0095     void mouseReleaseEvent(QMouseEvent *event) override;
0096 
0097     /**
0098      * Changes the position of the controlpoints with the same ratio than the widget resize
0099      * This way the presscurve stays the same all the time
0100      *
0101      * @param event the resize event
0102      */
0103     void resizeEvent(QResizeEvent *event) override;
0104 
0105     /**
0106      * If the tablet was detected by Qt this animates the pressure as filled area below the presscurve
0107      * Qt detects the tablet only if it was configured via the xorg.conf. Otherwise it does not know about it
0108      * Furthermore the tablet input devices must have the standard names "stylus" and "eraser"
0109      *
0110      * @param event the Tablet event
0111      */
0112     void tabletEvent(QTabletEvent *event) override;
0113 
0114     /**
0115      * Draws the background grid, controlpoints and the presscurve on the widget
0116      * Does it with antialias support
0117      *
0118      * @param event the paint event
0119      */
0120     void paintEvent(QPaintEvent *event) override;
0121 
0122     /**
0123      * Finds the nearest controlpoint the uses clicks on
0124      * Will be called for mouse and tabletevent and sets m_activePoint
0125      * with the number of the clicked point.
0126      *
0127      * @param pos the position of the mouse/pen click
0128      */
0129     void setNearestPoint(const QPointF &pos);
0130 
0131     /**
0132      * Moves both control points according to the user interaction
0133      * Both points will be changed even if only one is selected
0134      * The reason lies deep in the Linux Wacom driver that expect the beziercurve
0135      * to be this way. So point 2 is always point 1 with mirrored x/y coordinates
0136      *
0137      * @param pos the new position
0138      */
0139     void moveControlPoint(const QPointF &pos);
0140 
0141 signals:
0142     /**
0143      * This signal will be fired if the position of the control points change
0144      * Used to inform the parent widget of this change to be able to display the new values
0145      * Furthermore the changed presscurve will be set via the xsetwacom driver immediately thus
0146      * allow the user to see the changes in action right now
0147      *
0148      * @param points the presscurve points in a format expected by the xsetwacom driver (like "0 100 0 100")
0149      */
0150     void controlPointsChanged(const QString &points);
0151 
0152 private:
0153     QPointF m_cP1; /**< Control point 1 */
0154     QPointF m_cP2; /**< Control point 2 */
0155     int m_pointSize = 10; /**< Size of the control point */
0156     int m_activePoint = 0; /**< The point that is dragged around */
0157     QColor m_pointColor = Qt::red; /**< Color of the points */
0158     QColor m_curveColor = Qt::black; /**< Color of the curve */
0159     qreal m_pressure = 0; /**< Buffers the current stylus pressure. (0.0 - 1.0) used to animate the pressure */
0160     QColor m_pressAreaColor = Qt::blue; /**< Color of the press indication area */
0161 };
0162 
0163 }
0164 
0165 #endif // PRESSURECURVEWIDGET_H