File indexing completed on 2024-05-19 15:09:25
0001 /* 0002 This file is part of the KDE project 0003 0004 SPDX-FileCopyrightText: 2014 Fredrik Höglund <fredrik@kde.org> 0005 SPDX-FileCopyrightText: 2014 Marco Martin <mart@kde.org> 0006 0007 SPDX-License-Identifier: LGPL-2.0-or-later 0008 */ 0009 0010 #ifndef PLASMA_PLOTTER_H 0011 #define PLASMA_PLOTTER_H 0012 0013 #include <epoxy/gl.h> 0014 0015 // qopengl.h declares GLdouble as a typedef of float when Qt is built 0016 // with GLES support. This conflicts with the epoxy/gl_generated.h 0017 // declaration, so we have to prevent the Qt header from being #included. 0018 #define QOPENGL_H 0019 0020 #ifndef QOPENGLF_APIENTRY 0021 #define QOPENGLF_APIENTRY GLAPIENTRY 0022 #endif 0023 0024 #ifndef QOPENGLF_APIENTRYP 0025 #define QOPENGLF_APIENTRYP GLAPIENTRYP 0026 #endif 0027 0028 #include <QMutex> 0029 #include <QPointer> 0030 #include <QQmlListProperty> 0031 #include <QQuickItem> 0032 #include <QQuickWindow> 0033 0034 class PlotSGNode; 0035 0036 /** 0037 * a Plotter can draw a graph of values arriving from an arbitrary number of data sources 0038 * to show their evolution in time. 0039 * an example can be a plot of the network transfer speed or CPU temperature over time. 0040 * Multiple plots can be fitted in the same graph, either stacked or intersected. 0041 */ 0042 class PlotData : public QObject 0043 { 0044 Q_OBJECT 0045 /** 0046 * text Label of the data set: note this is purely a model, it will need a Label somewhere to be actually painted 0047 */ 0048 Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged) 0049 0050 /** 0051 * Color to plot this data set 0052 */ 0053 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) 0054 0055 /** 0056 * All the values currently in this data set 0057 */ 0058 Q_PROPERTY(QList<qreal> values READ values NOTIFY valuesChanged) 0059 0060 /** 0061 * Maximum value of this data set 0062 */ 0063 Q_PROPERTY(qreal max READ max NOTIFY maxChanged) 0064 0065 /** 0066 * Minimum value of this data set 0067 */ 0068 Q_PROPERTY(qreal min READ min NOTIFY minChanged) 0069 0070 public: 0071 PlotData(QObject *parent = nullptr); 0072 0073 void setColor(const QColor &color); 0074 QColor color() const; 0075 0076 void addSample(qreal value); 0077 0078 QList<qreal> values() const; 0079 0080 QVector<qreal> m_normalizedValues; 0081 0082 qreal max() const; 0083 qreal min() const; 0084 0085 void setSampleSize(int size); 0086 0087 QString label() const; 0088 void setLabel(const QString &label); 0089 0090 Q_SIGNALS: 0091 void colorChanged(); 0092 void valuesChanged(); 0093 void maxChanged(); 0094 void minChanged(); 0095 void labelChanged(); 0096 0097 private: 0098 QString m_label; 0099 QColor m_color; 0100 QList<qreal> m_values; 0101 0102 qreal m_min; 0103 qreal m_max; 0104 int m_sampleSize; 0105 }; 0106 0107 class Plotter : public QQuickItem 0108 { 0109 Q_OBJECT 0110 Q_PROPERTY(QQmlListProperty<PlotData> dataSets READ dataSets) 0111 0112 /** 0113 * maximum value among all graphs 0114 */ 0115 Q_PROPERTY(qreal max READ max NOTIFY maxChanged) 0116 0117 /** 0118 * minimum value among all graphs 0119 */ 0120 Q_PROPERTY(qreal min READ min NOTIFY minChanged) 0121 0122 /** 0123 * draw at most n samples, if new samples are pushed old values are started to be thrown away 0124 */ 0125 Q_PROPERTY(int sampleSize READ sampleSize WRITE setSampleSize NOTIFY sampleSizeChanged) 0126 0127 /** 0128 * if true stack the graphs one on top of each other instead of just painting one on top of each other 0129 */ 0130 Q_PROPERTY(bool stacked READ isStacked WRITE setStacked NOTIFY stackedChanged) 0131 0132 /** 0133 * If true, the graph is automatically scaled to always fit in the Plotter area 0134 */ 0135 Q_PROPERTY(bool autoRange READ isAutoRange WRITE setAutoRange NOTIFY autoRangeChanged) 0136 0137 /** 0138 * Always represents the values scaled between this and rangeMin 0139 * If autoRange is true, this property just holds the minimum value 0140 */ 0141 Q_PROPERTY(qreal rangeMax READ rangeMax WRITE setRangeMax NOTIFY rangeMaxChanged) 0142 0143 /** 0144 * Always represents the values scaled between this and rangeMax 0145 * If autoRange is true, this property just holds the maximum value 0146 */ 0147 Q_PROPERTY(qreal rangeMin READ rangeMin WRITE setRangeMin NOTIFY rangeMinChanged) 0148 0149 /** 0150 * Color of the grid lines 0151 */ 0152 Q_PROPERTY(QColor gridColor READ gridColor WRITE setGridColor NOTIFY gridColorChanged) 0153 0154 /** 0155 * The number of horizontal lines drawn across the view between 0 and rangeMax at the top of the plotter at rangeMax 0156 * This does not include the bottom line 0157 * Setting this to 0 will disable grid lines 0158 * 0159 * The default value is 5 0160 */ 0161 Q_PROPERTY(int horizontalGridLineCount READ horizontalGridLineCount WRITE setHorizontalGridLineCount NOTIFY horizontalGridLineCountChanged) 0162 0163 // Q_CLASSINFO("DefaultProperty", "dataSets") 0164 0165 public: 0166 Plotter(QQuickItem *parent = nullptr); 0167 ~Plotter() override; 0168 0169 qreal max() const; 0170 qreal min() const; 0171 0172 int sampleSize() const; 0173 void setSampleSize(int size); 0174 0175 bool isStacked() const; 0176 void setStacked(bool stacked); 0177 0178 bool isAutoRange() const; 0179 void setAutoRange(bool autorange); 0180 0181 qreal rangeMax() const; 0182 void setRangeMax(qreal max); 0183 0184 qreal rangeMin() const; 0185 void setRangeMin(qreal min); 0186 0187 void setHorizontalGridLineCount(int count); 0188 int horizontalGridLineCount(); 0189 0190 void setGridColor(const QColor &color); 0191 QColor gridColor() const; 0192 0193 QQmlListProperty<PlotData> dataSets(); 0194 static void dataSet_append(QQmlListProperty<PlotData> *list, PlotData *item); 0195 static int dataSet_count(QQmlListProperty<PlotData> *list); 0196 static PlotData *dataSet_at(QQmlListProperty<PlotData> *list, int pos); 0197 static void dataSet_clear(QQmlListProperty<PlotData> *list); 0198 0199 Q_INVOKABLE void addSample(qreal value); 0200 Q_INVOKABLE void addSample(const QList<qreal> &value); 0201 0202 protected: 0203 void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; 0204 0205 private: 0206 QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData) override final; 0207 QPainterPath interpolate(const QVector<qreal> &p, qreal x0, qreal x1) const; 0208 void normalizeData(); 0209 0210 Q_SIGNALS: 0211 void maxChanged(); 0212 void minChanged(); 0213 void sampleSizeChanged(); 0214 void stackedChanged(); 0215 void autoRangeChanged(); 0216 void rangeMaxChanged(); 0217 void rangeMinChanged(); 0218 void gridColorChanged(); 0219 void horizontalGridLineCountChanged(); 0220 0221 private Q_SLOTS: 0222 void render(); 0223 0224 private: 0225 QList<PlotData *> m_plotData; 0226 0227 GLuint m_fbo = 0; 0228 PlotSGNode *m_node = nullptr; 0229 qreal m_min; 0230 qreal m_max; 0231 qreal m_rangeMax; 0232 qreal m_rangeMin; 0233 int m_sampleSize; 0234 int m_horizontalLineCount; 0235 bool m_stacked; 0236 bool m_autoRange; 0237 QColor m_gridColor; 0238 0239 QMatrix4x4 m_matrix; 0240 bool m_initialized = false; 0241 bool m_haveMSAA; 0242 bool m_haveFramebufferBlit; 0243 bool m_haveInternalFormatQuery; 0244 GLenum m_internalFormat; 0245 int m_samples; 0246 QPointer<QQuickWindow> m_window; 0247 QMutex m_mutex; 0248 }; 0249 0250 #endif