1 /*
2 
3     SPDX-FileCopyrightText: 2006-2009 John Tapsell <tapsell@kde.org>
4 
5     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
6 */
7 
8 //#define USE_QIMAGE
9 
10 // SVG support causes it to crash at the moment :(
11 // (when re-enabling this remember to also link against plasma-framework)
12 //#define SVG_SUPPORT
13 
14 // Use a separate child widget to draw the graph in
15 #ifndef KSYSGUARD_KSIGNALPLOTTER_P_H
16 #define KSYSGUARD_KSIGNALPLOTTER_P_H
17 
18 #ifndef GRAPHICS_SIGNAL_PLOTTER
19 #define USE_SEPERATE_WIDGET
20 #include <QPaintEvent>
21 #include <QWidget>
22 #endif
23 
24 #ifdef SVG_SUPPORT
25 namespace Plasma
26 {
27 class SVG;
28 }
29 #endif
30 
31 #ifdef USE_SEPERATE_WIDGET
32 class GraphWidget;
33 #endif
34 
35 class KSignalPlotter;
36 
37 class KSignalPlotterPrivate
38 {
39 public:
40     KSignalPlotterPrivate(KSignalPlotter *q_ptr);
41 
42     void drawWidget(QPainter *p, const QRect &boundingBox);
43     void drawBackground(QPainter *p, const QRect &boundingBox) const;
44     void drawThinFrame(QPainter *p, const QRect &boundingBox);
45     void calculateNiceRange();
46     void drawBeamToScrollableImage(QPainter *p, int index);
47     void drawBeam(QPainter *p, const QRect &boundingBox, int horizontalScale, int index);
48     void drawAxisText(QPainter *p, const QRect &boundingBox);
49     void drawHorizontalLines(QPainter *p, const QRect &boundingBox) const;
50     void drawVerticalLines(QPainter *p, const QRect &boundingBox, int correction = 0) const;
51     void redrawScrollableImage();
52     void reorderBeams(const QList<int> &newOrder);
53 
54     void recalculateMaxMinValueForSample(const QList<qreal> &sampleBuf, int time);
55     void rescale();
56     void updateDataBuffers();
57     void setupStyle();
58 #ifdef GRAPHICS_SIGNAL_PLOTTER
59     void themeChanged();
60 #endif
61 
62     /** Return the given value as a string, with the given precision */
63     QString scaledValueAsString(qreal value, int precision) const;
64     void addSample(const QList<qreal> &sampleBuf);
65 #ifdef SVG_SUPPORT
66     void updateSvgBackground(const QRect &boundingBox);
67     Plasma::SVG *mSvgRenderer;
68 #endif
69     QString mSvgFilename;
70 
71     QPixmap mBackgroundImage; /// A cache of the background of the widget. Contains the SVG or just white background with lines
72 #ifdef USE_QIMAGE
73     QImage mScrollableImage; /// The scrollable image for the widget.  Contains the SVG lines
74 #else
75     QPixmap mScrollableImage; /// The scrollable image for the widget.  Contains the SVG lines
76 #endif
77     int mScrollOffset; /// The scrollable image is, well, scrolled in a wrap-around window.  mScrollOffset determines where the left hand side of the
78                        /// mScrollableImage should be drawn relative to the right hand side of view.  0 <= mScrollOffset < mScrollableImage.width()
79     qreal mMinValue; /// The minimum value (unscaled) currently being displayed
80     qreal mMaxValue; /// The maximum value (unscaled) currently being displayed
81 
82     qreal mUserMinValue; /// The minimum value (unscaled) set by changeRange().  This is the _maximum_ value that the range will start from.
83     qreal mUserMaxValue; /// The maximum value (unscaled) set by changeRange().  This is the _minimum_ value that the range will reach to.
84     unsigned int
85         mRescaleTime; /// The number of data points passed since a value that is within 70% of the current maximum was found.  This is for scaling the graph
86 
87     qreal mNiceMinValue; /// The minimum value rounded down to a 'nice' value
88     qreal mNiceMaxValue; /// The maximum value rounded up to a 'nice' value.  The idea is to round the value, say, 93 to 100.
89     qreal mNiceRange; /// mNiceMaxValue - mNiceMinValue
90     int mPrecision; /// The number of decimal place required to unambiguously label the axis
91 
92     qreal mScaleDownBy; /// @see setScaleDownBy
93     bool mUseAutoRange; /// @see setUseAutoRange
94 
95     /**  Whether to show a white line on the left and bottom of the widget, for a 3D effect */
96     bool mShowThinFrame;
97 
98     bool mShowVerticalLines;
99     uint mVerticalLinesDistance;
100     bool mVerticalLinesScroll;
101     uint mVerticalLinesOffset;
102     uint mHorizontalScale;
103     int mHorizontalLinesCount;
104 
105     bool mShowHorizontalLines;
106 
107     bool mStackBeams; /// Set to add the beam values onto each other
108     int mFillOpacity; /// Fill the area underneath the beams
109 
110     bool mShowAxis;
111 
112     QList<QList<qreal>> mBeamData; // Every item in the linked list contains a set of data points to plot.  The first item is the newest
113     QList<QColor> mBeamColors; // These colors match up against the QList<qreal>  in mBeamData
114     QList<QColor> mBeamColorsLight; // These colors match up against the QList<qreal> in mBeamData, and are lighter than mBeamColors.  Done for gradient effects
115 
116     unsigned int mMaxSamples; // This is what mBeamData.size() should equal when full.  When we start off and have no data then mSamples will be higher.  If we
117                               // resize the widget so it's smaller, then for a short while this will be smaller
118     int mNewestIndex; // The index to the newest item added.  newestIndex+1   is the second newest, and so on
119 
120     KLocalizedString mUnit;
121 
122     int mAxisTextWidth;
123     int mActualAxisTextWidth; // Sometimes there just is not enough room for all the requested axisTextWidth
124     QRect mPlottingArea; /// The area in which the beams are drawn.  Saved to make update() more efficient
125 
126     bool mSmoothGraph; /// Whether to smooth the graph by averaging using the formula (value*2 + last_value)/3.
127     KSignalPlotter *q;
128     bool mAxisTextOverlapsPlotter; // Whether we need to redraw the axis text on every update
129 #ifdef USE_SEPERATE_WIDGET
130     GraphWidget *mGraphWidget; ///< This is the widget that draws the actual graph
131 #endif
132 };
133 
134 #ifdef USE_SEPERATE_WIDGET
135 /* A class to draw the actual widget.  This is used for the QWidget version of KSignalPlotter in order to speed up redraws */
136 class GraphWidget : public QWidget
137 {
138 public:
139     explicit GraphWidget(QWidget *parent);
140     void paintEvent(QPaintEvent *event) override;
141 
142     KSignalPlotterPrivate *signalPlotterPrivate;
143 };
144 #endif
145 
146 #endif // KSYSGUARD_KSIGNALPLOTTER_P_H
147