File indexing completed on 2024-12-22 04:13:10

0001 /*
0002  *  SPDX-FileCopyrightText: 2005 C. Boemann <cbo@boemann.dk>
0003  *  SPDX-FileCopyrightText: 2009 Dmitry Kazakov <dimula73@gmail.com>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 #ifndef KIS_CURVE_WIDGET_H
0008 #define KIS_CURVE_WIDGET_H
0009 
0010 // Qt includes.
0011 
0012 #include <QWidget>
0013 #include <QColor>
0014 #include <QPointF>
0015 #include <QPixmap>
0016 #include <QMouseEvent>
0017 #include <QKeyEvent>
0018 #include <QEvent>
0019 #include <QPaintEvent>
0020 #include <QList>
0021 #include <optional>
0022 
0023 #include <kritaui_export.h>
0024 
0025 class QSpinBox;
0026 class KisCubicCurve;
0027 
0028 /**
0029  * KisCurveWidget is a widget that shows a single curve that can be edited
0030  * by the user. The user can grab the curve and move it; this creates
0031  * a new control point. Control points can be deleted by selecting a point
0032  * and pressing the delete key.
0033  *
0034  * (From: https://techbase.kde.org/Projects/Widgets_and_Classes#KisCurveWidget)
0035  * KisCurveWidget allows editing of spline based y=f(x) curves. Handy for cases
0036  * where you want the user to control such things as tablet pressure
0037  * response, color transformations, acceleration by time, aeroplane lift
0038  *by angle of attack.
0039  */
0040 class KRITAUI_EXPORT KisCurveWidget : public QWidget
0041 {
0042     Q_OBJECT
0043     Q_PROPERTY(bool pointSelected READ pointSelected NOTIFY pointSelectedChanged);
0044 
0045 public:
0046     friend class CurveEditorItem;
0047     /**
0048      * Create a new curve widget with a default curve, that is a straight
0049      * line from bottom-left to top-right.
0050      */
0051     KisCurveWidget(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
0052 
0053     ~KisCurveWidget() override;
0054 
0055     /**
0056      * Reset the curve to the default shape
0057      */
0058     void reset(void);
0059 
0060     /**
0061      * Set a background pixmap. The background pixmap will be drawn under
0062      * the grid and the curve.
0063      *
0064      * XXX: or is the pixmap what is drawn to the  left and bottom of the curve
0065      * itself?
0066      */
0067     void setPixmap(const QPixmap & pix);
0068     QPixmap getPixmap();
0069     
0070     /**
0071      * Whether or not there is a point selected
0072      * This does NOT include the first and last points
0073      */
0074     bool pointSelected() const;
0075 
0076     bool setCurrentPoint(QPointF pt);
0077     std::optional<QPointF> currentPoint() const;
0078 
0079 Q_SIGNALS:
0080 
0081     /**
0082      * Emitted whenever a control point has changed position.
0083      */
0084     void modified(void);
0085     void curveChanged(const KisCubicCurve &);
0086     /**
0087      * Emitted whenever the status of whether a control point is selected or not changes
0088      */
0089     void pointSelectedChanged();
0090     /**
0091      * Emitted to notify that the start() function in compressor can be activated.
0092      * Thanks to that, blocking signals in curve widget blocks "sending signals"
0093      * (calling start() function) *to* the signal compressor.
0094      * It effectively makes signals work nearly the same way they worked before
0095      * adding the signal compressor in between.
0096      */
0097     void compressorShouldEmitModified();
0098 
0099     void shouldSyncIOControls();
0100     void shouldFocusIOControls();
0101 
0102 
0103 protected Q_SLOTS:
0104     void notifyModified();
0105 
0106     /**
0107      * This function is called when compressorShouldEmitModified() is emitted.
0108      * For why it's needed, \see compressorShouldEmitModified()
0109      */
0110     void slotCompressorShouldEmitModified();
0111 
0112 
0113 
0114 protected:
0115 
0116     void keyPressEvent(QKeyEvent *) override;
0117     void paintEvent(QPaintEvent *) override;
0118     void mousePressEvent(QMouseEvent * e) override;
0119     void mouseReleaseEvent(QMouseEvent * e) override;
0120     void mouseMoveEvent(QMouseEvent * e) override;
0121     void leaveEvent(QEvent *) override;
0122     void resizeEvent(QResizeEvent *e) override;
0123 
0124 public:
0125 
0126     /**
0127      * @return get a list with all defined points. If you want to know what the
0128      * y value for a given x is on the curve defined by these points, use getCurveValue().
0129      * @see getCurveValue
0130      */
0131     KisCubicCurve curve();
0132 
0133     /**
0134      * Connect/disconnect external spinboxes to the curve
0135      * @p inMin / @p inMax - is the range for input values
0136      * @p outMin / @p outMax - is the range for output values
0137      */
0138     void setupInOutControls(QSpinBox *in, QSpinBox *out, int inMin, int inMax, int outMin, int outMax);
0139     void dropInOutControls();
0140 
0141     /**
0142      * Handy function that creates new point in the middle
0143      * of the curve and sets focus on the @p m_intIn field,
0144      * so the user can move this point anywhere in a moment
0145      */
0146     void addPointInTheMiddle();
0147 
0148 public Q_SLOTS:
0149     /**
0150      * Replace the current curve with a curve specified by the curve defined by the control
0151      * points in @p inlist.
0152      */
0153     void setCurve(KisCubicCurve inlist);
0154 
0155 private:
0156 
0157     class Private;
0158     Private * const d {nullptr};
0159 };
0160 
0161 
0162 #endif /* KIS_CURVE_WIDGET_H */