File indexing completed on 2023-09-24 08:07:37

0001 /*
0002  * This file is part of KQuickCharts
0003  * SPDX-FileCopyrightText: 2019 Arjen Hiemstra <ahiemstra@heimr.nl>
0004  *
0005  * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0006  */
0007 
0008 #ifndef LINECHART_H
0009 #define LINECHART_H
0010 
0011 #include <memory>
0012 
0013 #include "XYChart.h"
0014 
0015 class LineChartNode;
0016 
0017 /**
0018  * An attached property that is exposed to point delegates created in line charts.
0019  *
0020  * \sa LineChart::pointDelegate
0021  */
0022 class LineChartAttached : public QObject
0023 {
0024     Q_OBJECT
0025     /**
0026      * The value at the current point.
0027      */
0028     Q_PROPERTY(QVariant value READ value NOTIFY valueChanged)
0029     /**
0030      * The color at the current point.
0031      */
0032     Q_PROPERTY(QColor color READ color NOTIFY colorChanged)
0033     /**
0034      * The name at the current point.
0035      */
0036     Q_PROPERTY(QString name READ name NOTIFY nameChanged)
0037     /**
0038      * The short name at the current point.
0039      */
0040     Q_PROPERTY(QString shortName READ shortName NOTIFY shortNameChanged)
0041 
0042 public:
0043     LineChartAttached(QObject *parent = nullptr);
0044 
0045     QVariant value() const;
0046     void setValue(const QVariant &value);
0047     Q_SIGNAL void valueChanged();
0048 
0049     QColor color() const;
0050     void setColor(const QColor &color);
0051     Q_SIGNAL void colorChanged();
0052 
0053     QString name() const;
0054     void setName(const QString &newName);
0055     Q_SIGNAL void nameChanged();
0056 
0057     QString shortName() const;
0058     void setShortName(const QString &newShortName);
0059     Q_SIGNAL void shortNameChanged();
0060 
0061 private:
0062     QVariant m_value;
0063     QColor m_color;
0064     QString m_name;
0065     QString m_shortName;
0066 };
0067 
0068 /**
0069  * A line chart.
0070  *
0071  * ## Usage example
0072  *
0073  * \snippet snippets/linechart.qml example
0074  *
0075  * \image html linechart.png "The resulting line chart."
0076  */
0077 class LineChart : public XYChart
0078 {
0079     Q_OBJECT
0080 
0081     /**
0082      * Smooth the lines in the chart instead of making hard corners.
0083      */
0084     Q_PROPERTY(bool smooth READ smooth WRITE setSmooth NOTIFY smoothChanged)
0085     /**
0086      * The width of a line in the chart.
0087      */
0088     Q_PROPERTY(qreal lineWidth READ lineWidth WRITE setLineWidth NOTIFY lineWidthChanged)
0089     /**
0090      * The opacity of the area below a line.
0091      *
0092      * The default is 0.0. Note that if fillColorSource is set, this value is
0093      * ignored.
0094      */
0095     Q_PROPERTY(qreal fillOpacity READ fillOpacity WRITE setFillOpacity NOTIFY fillOpacityChanged)
0096     /**
0097      * A data source that supplies color values for the line charts' fill area.
0098      *
0099      * If this is not set (the default), the normal color source will be used,
0100      * with the fillOpacity used as its opacity.
0101      */
0102     Q_PROPERTY(ChartDataSource *fillColorSource READ fillColorSource WRITE setFillColorSource NOTIFY fillColorSourceChanged)
0103     /**
0104      * A delegate that will be placed at each line chart point.
0105      *
0106      * When this is not null, the specified component will be used to
0107      * instantiate an object for each point in the chart. These objects will
0108      * then be placed centered at positions corresponding to the points on the
0109      * chart. Each instance will have access to the attached properties of
0110      * LineChartAttached through LineChart attached object.
0111      *
0112      * \note The component assigned to this property is expected to create a
0113      *       QQuickItem, since the created object needs to be positioned.
0114      */
0115     Q_PROPERTY(QQmlComponent *pointDelegate READ pointDelegate WRITE setPointDelegate NOTIFY pointDelegateChanged)
0116 
0117 public:
0118     explicit LineChart(QQuickItem *parent = nullptr);
0119 
0120     bool smooth() const;
0121     void setSmooth(bool smooth);
0122     Q_SIGNAL void smoothChanged();
0123 
0124     qreal lineWidth() const;
0125     void setLineWidth(qreal width);
0126     Q_SIGNAL void lineWidthChanged();
0127 
0128     qreal fillOpacity() const;
0129     void setFillOpacity(qreal opacity);
0130     Q_SIGNAL void fillOpacityChanged();
0131 
0132     ChartDataSource *fillColorSource() const;
0133     void setFillColorSource(ChartDataSource *newFillColorSource);
0134     Q_SIGNAL void fillColorSourceChanged();
0135 
0136     QQmlComponent *pointDelegate() const;
0137     void setPointDelegate(QQmlComponent *newPointDelegate);
0138     Q_SIGNAL void pointDelegateChanged();
0139 
0140     static LineChartAttached *qmlAttachedProperties(QObject *object)
0141     {
0142         return new LineChartAttached(object);
0143     }
0144 
0145 protected:
0146     void updatePolish() override;
0147     QSGNode *updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData *data) override;
0148     void onDataChanged() override;
0149 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0150     void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
0151 #else
0152     void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override;
0153 #endif
0154 private:
0155     void updateLineNode(LineChartNode *node, const QColor &lineColor, const QColor &fillColor, ChartDataSource *valueSource);
0156     void createPointDelegates(const QVector<QVector2D> &values, int sourceIndex);
0157     void updatePointDelegate(QQuickItem *delegate, const QVector2D &position, const QVariant &value, int sourceIndex);
0158 
0159     bool m_smooth = false;
0160     qreal m_lineWidth = 1.0;
0161     qreal m_fillOpacity = 0.0;
0162     bool m_rangeInvalid = true;
0163     ChartDataSource *m_fillColorSource = nullptr;
0164     QHash<ChartDataSource *, QVector<QVector2D>> m_values;
0165     QQmlComponent *m_pointDelegate = nullptr;
0166     QHash<ChartDataSource *, QVector<QQuickItem *>> m_pointDelegates;
0167 };
0168 
0169 QML_DECLARE_TYPEINFO(LineChart, QML_HAS_ATTACHED_PROPERTIES)
0170 
0171 #endif // LINECHART_H