File indexing completed on 2024-04-28 05:31:46

0001 /*
0002 
0003     SPDX-FileCopyrightText: 2006-2009 John Tapsell <tapsell@kde.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0006 */
0007 
0008 //#define USE_QIMAGE
0009 
0010 // SVG support causes it to crash at the moment :(
0011 // (when re-enabling this remember to also link against plasma-framework)
0012 //#define SVG_SUPPORT
0013 
0014 // Use a separate child widget to draw the graph in
0015 #ifndef KSYSGUARD_KSIGNALPLOTTER_P_H
0016 #define KSYSGUARD_KSIGNALPLOTTER_P_H
0017 
0018 #ifndef GRAPHICS_SIGNAL_PLOTTER
0019 #define USE_SEPERATE_WIDGET
0020 #include <QPaintEvent>
0021 #include <QWidget>
0022 #endif
0023 
0024 #ifdef SVG_SUPPORT
0025 namespace Plasma
0026 {
0027 class SVG;
0028 }
0029 #endif
0030 
0031 #ifdef USE_SEPERATE_WIDGET
0032 class GraphWidget;
0033 #endif
0034 
0035 class KSignalPlotter;
0036 
0037 class KSignalPlotterPrivate
0038 {
0039 public:
0040     KSignalPlotterPrivate(KSignalPlotter *q_ptr);
0041 
0042     void drawWidget(QPainter *p, const QRect &boundingBox);
0043     void drawBackground(QPainter *p, const QRect &boundingBox) const;
0044     void drawThinFrame(QPainter *p, const QRect &boundingBox);
0045     void calculateNiceRange();
0046     void drawBeamToScrollableImage(QPainter *p, int index);
0047     void drawBeam(QPainter *p, const QRect &boundingBox, int horizontalScale, int index);
0048     void drawAxisText(QPainter *p, const QRect &boundingBox);
0049     void drawHorizontalLines(QPainter *p, const QRect &boundingBox) const;
0050     void drawVerticalLines(QPainter *p, const QRect &boundingBox, int correction = 0) const;
0051     void redrawScrollableImage();
0052     void reorderBeams(const QList<int> &newOrder);
0053 
0054     void recalculateMaxMinValueForSample(const QList<qreal> &sampleBuf, int time);
0055     void rescale();
0056     void updateDataBuffers();
0057     void setupStyle();
0058 #ifdef GRAPHICS_SIGNAL_PLOTTER
0059     void themeChanged();
0060 #endif
0061 
0062     /** Return the given value as a string, with the given precision */
0063     QString scaledValueAsString(qreal value, int precision) const;
0064     void addSample(const QList<qreal> &sampleBuf);
0065 #ifdef SVG_SUPPORT
0066     void updateSvgBackground(const QRect &boundingBox);
0067     Plasma::SVG *mSvgRenderer;
0068 #endif
0069     QString mSvgFilename;
0070 
0071     QPixmap mBackgroundImage; /// A cache of the background of the widget. Contains the SVG or just white background with lines
0072 #ifdef USE_QIMAGE
0073     QImage mScrollableImage; /// The scrollable image for the widget.  Contains the SVG lines
0074 #else
0075     QPixmap mScrollableImage; /// The scrollable image for the widget.  Contains the SVG lines
0076 #endif
0077     int mScrollOffset; /// The scrollable image is, well, scrolled in a wrap-around window.  mScrollOffset determines where the left hand side of the
0078                        /// mScrollableImage should be drawn relative to the right hand side of view.  0 <= mScrollOffset < mScrollableImage.width()
0079     qreal mMinValue; /// The minimum value (unscaled) currently being displayed
0080     qreal mMaxValue; /// The maximum value (unscaled) currently being displayed
0081 
0082     qreal mUserMinValue; /// The minimum value (unscaled) set by changeRange().  This is the _maximum_ value that the range will start from.
0083     qreal mUserMaxValue; /// The maximum value (unscaled) set by changeRange().  This is the _minimum_ value that the range will reach to.
0084     unsigned int
0085         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
0086 
0087     qreal mNiceMinValue; /// The minimum value rounded down to a 'nice' value
0088     qreal mNiceMaxValue; /// The maximum value rounded up to a 'nice' value.  The idea is to round the value, say, 93 to 100.
0089     qreal mNiceRange; /// mNiceMaxValue - mNiceMinValue
0090     int mPrecision; /// The number of decimal place required to unambiguously label the axis
0091 
0092     qreal mScaleDownBy; /// @see setScaleDownBy
0093     bool mUseAutoRange; /// @see setUseAutoRange
0094 
0095     /**  Whether to show a white line on the left and bottom of the widget, for a 3D effect */
0096     bool mShowThinFrame;
0097 
0098     bool mShowVerticalLines;
0099     uint mVerticalLinesDistance;
0100     bool mVerticalLinesScroll;
0101     uint mVerticalLinesOffset;
0102     uint mHorizontalScale;
0103     int mHorizontalLinesCount;
0104 
0105     bool mShowHorizontalLines;
0106 
0107     bool mStackBeams; /// Set to add the beam values onto each other
0108     int mFillOpacity; /// Fill the area underneath the beams
0109 
0110     bool mShowAxis;
0111 
0112     QList<QList<qreal>> mBeamData; // Every item in the linked list contains a set of data points to plot.  The first item is the newest
0113     QList<QColor> mBeamColors; // These colors match up against the QList<qreal>  in mBeamData
0114     QList<QColor> mBeamColorsLight; // These colors match up against the QList<qreal> in mBeamData, and are lighter than mBeamColors.  Done for gradient effects
0115 
0116     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
0117                               // resize the widget so it's smaller, then for a short while this will be smaller
0118     int mNewestIndex; // The index to the newest item added.  newestIndex+1   is the second newest, and so on
0119 
0120     KLocalizedString mUnit;
0121 
0122     int mAxisTextWidth;
0123     int mActualAxisTextWidth; // Sometimes there just is not enough room for all the requested axisTextWidth
0124     QRect mPlottingArea; /// The area in which the beams are drawn.  Saved to make update() more efficient
0125 
0126     bool mSmoothGraph; /// Whether to smooth the graph by averaging using the formula (value*2 + last_value)/3.
0127     KSignalPlotter *q;
0128     bool mAxisTextOverlapsPlotter; // Whether we need to redraw the axis text on every update
0129 #ifdef USE_SEPERATE_WIDGET
0130     GraphWidget *mGraphWidget; ///< This is the widget that draws the actual graph
0131 #endif
0132 };
0133 
0134 #ifdef USE_SEPERATE_WIDGET
0135 /* A class to draw the actual widget.  This is used for the QWidget version of KSignalPlotter in order to speed up redraws */
0136 class GraphWidget : public QWidget
0137 {
0138 public:
0139     explicit GraphWidget(QWidget *parent);
0140     void paintEvent(QPaintEvent *event) override;
0141 
0142     KSignalPlotterPrivate *signalPlotterPrivate;
0143 };
0144 #endif
0145 
0146 #endif // KSYSGUARD_KSIGNALPLOTTER_P_H