File indexing completed on 2024-06-16 04:35:04

0001 /*
0002     SPDX-FileCopyrightText: 2016 Nicolas Carion
0003     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 */
0005 
0006 #pragma once
0007 
0008 #include "../../../bpoint.h"
0009 #include <QWidget>
0010 #include <memory>
0011 
0012 #include <QPainter>
0013 
0014 /** State of a point being moved */
0015 enum class State_t { NORMAL, DRAG };
0016 
0017 /** @class __dummy_AbstractCurveWidget
0018     @brief This class is a workaround to be able to use templating in the actual class
0019     Note that Qt doesn't support templated signals, so we have to define a signal for
0020     all possible Point type
0021 */
0022 class __dummy_AbstractCurveWidget : public QWidget
0023 {
0024     Q_OBJECT
0025 public:
0026     __dummy_AbstractCurveWidget(QWidget *parent)
0027         : QWidget(parent)
0028     {
0029     }
0030 
0031 Q_SIGNALS:
0032     /**
0033      * Emitted whenever a control point has changed position.
0034      */
0035     void modified();
0036     /**
0037        Signal sent when the current point changes. The point is returned, as well as a flag that determines if the point is the first or last.
0038     */
0039     void currentPoint(const QPointF &p, bool extremal);
0040     void currentPoint(const BPoint &p, bool extremal);
0041     void resized(const QSize &s);
0042 
0043 public Q_SLOTS:
0044     /** @brief Delete current spline point if it is not a extremal point (first or last)
0045      */
0046     virtual void slotDeleteCurrentPoint() = 0;
0047     virtual void slotZoomIn() = 0;
0048     virtual void slotZoomOut() = 0;
0049     virtual void reset() = 0;
0050 };
0051 
0052 /** @brief Base class of all the widgets representing a curve of points
0053 
0054  */
0055 template <typename Curve_t> class AbstractCurveWidget : public __dummy_AbstractCurveWidget
0056 {
0057 public:
0058     typedef typename Curve_t::Point_t Point_t; // NOLINT
0059     ~AbstractCurveWidget() override = default;
0060 
0061     /** @param parent Optional parent of the widget
0062      */
0063     AbstractCurveWidget(QWidget *parent = nullptr);
0064 
0065     /** @brief Returns whether the points are controlled with additional handles
0066      */
0067     virtual bool hasHandles() { return false; }
0068 
0069     /** @brief Sets the maximal number of points of the curve
0070      */
0071     void setMaxPoints(int max);
0072 
0073     /** @brief Sets the background pixmap to @param pixmap.
0074         The background pixmap will be drawn under the grid and the curve*/
0075     void setPixmap(const QPixmap &pixmap);
0076 
0077     /** @brief Number of lines used in grid. */
0078     int gridLines() const;
0079 
0080     /** @brief Sets the number of grid lines to draw (in one direction) to @param lines. */
0081     void setGridLines(int lines);
0082 
0083     /** @brief Constructs the curve from @param string
0084      */
0085     void setFromString(const QString &string);
0086 
0087     /** @brief Resets the curve to an empty one
0088      */
0089     void reset() override;
0090 
0091     /** @brief Returns a string corresponding to the curve
0092      */
0093     QString toString();
0094 
0095     /** @brief Replaces current point with @param p (index stays the same).
0096      * @param final (default = true) Q_EMIT signal modified? */
0097     void updateCurrentPoint(const Point_t &p, bool final = true);
0098 
0099     /** @brief Returns the selected point or else empty point. */
0100     Point_t getCurrentPoint();
0101 
0102     /** @brief Returns the list of all the points. */
0103     virtual QList<Point_t> getPoints() const = 0;
0104 
0105 public:
0106     /** @brief Delete current spline point if it is not a extremal point (first or last)
0107      */
0108     void slotDeleteCurrentPoint() override;
0109     void slotZoomIn() override;
0110     void slotZoomOut() override;
0111 
0112 protected:
0113     void paintBackground(QPainter *p);
0114     int heightForWidth(int w) const override;
0115     void resizeEvent(QResizeEvent *event) override;
0116     void leaveEvent(QEvent *) override;
0117     void mouseReleaseEvent(QMouseEvent *e) override;
0118     void keyPressEvent(QKeyEvent *) override;
0119     /**
0120        Utility function to check if current selected point is the first or the last
0121     */
0122     bool isCurrentPointExtremal();
0123 
0124     int m_zoomLevel{0};
0125     int m_gridLines{3};
0126     /** Background */
0127     QPixmap m_pixmap;
0128     /** A copy of m_pixmap but scaled to fit the size of the edit region */
0129     std::shared_ptr<QPixmap> m_pixmapCache;
0130     /** Whether we have to regenerate the pixmap cache because the pixmap or the size of the edit region changed. */
0131     bool m_pixmapIsDirty{true};
0132 
0133     int m_currentPointIndex{-1};
0134     int m_maxPoints{1000000};
0135     int m_wWidth, m_wHeight;
0136 
0137     State_t m_state{State_t::NORMAL};
0138     Curve_t m_curve;
0139 
0140     double m_grabRadius{10};
0141 };
0142 
0143 #include "abstractcurvewidget.ipp"