1 /* 2 This file is part of the KDE project 3 4 SPDX-FileCopyrightText: 2014 Fredrik Höglund <fredrik@kde.org> 5 SPDX-FileCopyrightText: 2014 Marco Martin <mart@kde.org> 6 7 SPDX-License-Identifier: LGPL-2.0-or-later 8 */ 9 10 #ifndef PLASMA_PLOTTER_H 11 #define PLASMA_PLOTTER_H 12 13 #include <epoxy/gl.h> 14 15 // qopengl.h declares GLdouble as a typedef of float when Qt is built 16 // with GLES support. This conflicts with the epoxy/gl_generated.h 17 // declaration, so we have to prevent the Qt header from being #included. 18 #define QOPENGL_H 19 20 #ifndef QOPENGLF_APIENTRY 21 #define QOPENGLF_APIENTRY GLAPIENTRY 22 #endif 23 24 #ifndef QOPENGLF_APIENTRYP 25 #define QOPENGLF_APIENTRYP GLAPIENTRYP 26 #endif 27 28 #include <QMutex> 29 #include <QPointer> 30 #include <QQmlListProperty> 31 #include <QQuickItem> 32 #include <QQuickWindow> 33 34 class PlotSGNode; 35 36 /** 37 * a Plotter can draw a graph of values arriving from an arbitrary number of data sources 38 * to show their evolution in time. 39 * an example can be a plot of the network transfer speed or CPU temperature over time. 40 * Multiple plots can be fitted in the same graph, either stacked or intersected. 41 */ 42 class PlotData : public QObject 43 { 44 Q_OBJECT 45 /** 46 * text Label of the data set: note this is purely a model, it will need a Label somewhere to be actually painted 47 */ 48 Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged) 49 50 /** 51 * Color to plot this data set 52 */ 53 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) 54 55 /** 56 * All the values currently in this data set 57 */ 58 Q_PROPERTY(QList<qreal> values READ values NOTIFY valuesChanged) 59 60 /** 61 * Maximum value of this data set 62 */ 63 Q_PROPERTY(qreal max READ max NOTIFY maxChanged) 64 65 /** 66 * Minimum value of this data set 67 */ 68 Q_PROPERTY(qreal min READ min NOTIFY minChanged) 69 70 public: 71 PlotData(QObject *parent = nullptr); 72 73 void setColor(const QColor &color); 74 QColor color() const; 75 76 void addSample(qreal value); 77 78 QList<qreal> values() const; 79 80 QVector<qreal> m_normalizedValues; 81 82 qreal max() const; 83 qreal min() const; 84 85 void setSampleSize(int size); 86 87 QString label() const; 88 void setLabel(const QString &label); 89 90 Q_SIGNALS: 91 void colorChanged(); 92 void valuesChanged(); 93 void maxChanged(); 94 void minChanged(); 95 void labelChanged(); 96 97 private: 98 QString m_label; 99 QColor m_color; 100 QList<qreal> m_values; 101 102 qreal m_min; 103 qreal m_max; 104 int m_sampleSize; 105 }; 106 107 class Plotter : public QQuickItem 108 { 109 Q_OBJECT 110 Q_PROPERTY(QQmlListProperty<PlotData> dataSets READ dataSets) 111 112 /** 113 * maximum value among all graphs 114 */ 115 Q_PROPERTY(qreal max READ max NOTIFY maxChanged) 116 117 /** 118 * minimum value among all graphs 119 */ 120 Q_PROPERTY(qreal min READ min NOTIFY minChanged) 121 122 /** 123 * draw at most n samples, if new samples are pushed old values are started to be thrown away 124 */ 125 Q_PROPERTY(int sampleSize READ sampleSize WRITE setSampleSize NOTIFY sampleSizeChanged) 126 127 /** 128 * if true stack the graphs one on top of each other instead of just painting one on top of each other 129 */ 130 Q_PROPERTY(bool stacked READ isStacked WRITE setStacked NOTIFY stackedChanged) 131 132 /** 133 * If true, the graph is automatically scaled to always fit in the Plotter area 134 */ 135 Q_PROPERTY(bool autoRange READ isAutoRange WRITE setAutoRange NOTIFY autoRangeChanged) 136 137 /** 138 * Always represents the values scaled between this and rangeMin 139 * If autoRange is true, this property just holds the minimum value 140 */ 141 Q_PROPERTY(qreal rangeMax READ rangeMax WRITE setRangeMax NOTIFY rangeMaxChanged) 142 143 /** 144 * Always represents the values scaled between this and rangeMax 145 * If autoRange is true, this property just holds the maximum value 146 */ 147 Q_PROPERTY(qreal rangeMin READ rangeMin WRITE setRangeMin NOTIFY rangeMinChanged) 148 149 /** 150 * Color of the grid lines 151 */ 152 Q_PROPERTY(QColor gridColor READ gridColor WRITE setGridColor NOTIFY gridColorChanged) 153 154 /** 155 * The number of horizontal lines drawn across the view between 0 and rangeMax at the top of the plotter at rangeMax 156 * This does not include the bottom line 157 * Setting this to 0 will disable grid lines 158 * 159 * The default value is 5 160 */ 161 Q_PROPERTY(int horizontalGridLineCount READ horizontalGridLineCount WRITE setHorizontalGridLineCount NOTIFY horizontalGridLineCountChanged) 162 163 // Q_CLASSINFO("DefaultProperty", "dataSets") 164 165 public: 166 Plotter(QQuickItem *parent = nullptr); 167 ~Plotter() override; 168 169 qreal max() const; 170 qreal min() const; 171 172 int sampleSize() const; 173 void setSampleSize(int size); 174 175 bool isStacked() const; 176 void setStacked(bool stacked); 177 178 bool isAutoRange() const; 179 void setAutoRange(bool autorange); 180 181 qreal rangeMax() const; 182 void setRangeMax(qreal max); 183 184 qreal rangeMin() const; 185 void setRangeMin(qreal min); 186 187 void setHorizontalGridLineCount(int count); 188 int horizontalGridLineCount(); 189 190 void setGridColor(const QColor &color); 191 QColor gridColor() const; 192 193 QQmlListProperty<PlotData> dataSets(); 194 static void dataSet_append(QQmlListProperty<PlotData> *list, PlotData *item); 195 static int dataSet_count(QQmlListProperty<PlotData> *list); 196 static PlotData *dataSet_at(QQmlListProperty<PlotData> *list, int pos); 197 static void dataSet_clear(QQmlListProperty<PlotData> *list); 198 199 Q_INVOKABLE void addSample(qreal value); 200 Q_INVOKABLE void addSample(const QList<qreal> &value); 201 202 protected: 203 void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; 204 205 private: 206 QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData) override final; 207 QPainterPath interpolate(const QVector<qreal> &p, qreal x0, qreal x1) const; 208 void normalizeData(); 209 210 Q_SIGNALS: 211 void maxChanged(); 212 void minChanged(); 213 void sampleSizeChanged(); 214 void stackedChanged(); 215 void autoRangeChanged(); 216 void rangeMaxChanged(); 217 void rangeMinChanged(); 218 void gridColorChanged(); 219 void horizontalGridLineCountChanged(); 220 221 private Q_SLOTS: 222 void render(); 223 224 private: 225 QList<PlotData *> m_plotData; 226 227 GLuint m_fbo = 0; 228 PlotSGNode *m_node = nullptr; 229 qreal m_min; 230 qreal m_max; 231 qreal m_rangeMax; 232 qreal m_rangeMin; 233 int m_sampleSize; 234 int m_horizontalLineCount; 235 bool m_stacked; 236 bool m_autoRange; 237 QColor m_gridColor; 238 239 QMatrix4x4 m_matrix; 240 bool m_initialized = false; 241 bool m_haveMSAA; 242 bool m_haveFramebufferBlit; 243 bool m_haveInternalFormatQuery; 244 GLenum m_internalFormat; 245 int m_samples; 246 QPointer<QQuickWindow> m_window; 247 QMutex m_mutex; 248 }; 249 250 #endif 251