291 lines
8.7 KiB
C++
291 lines
8.7 KiB
C++
#pragma once
|
|
|
|
#include <QCanvasPainterItem>
|
|
#include <QColor>
|
|
#include <qobject.h>
|
|
#include <qqmlintegration.h>
|
|
#include <qtmetamacros.h>
|
|
#include <qvariant.h>
|
|
|
|
#include <QString>
|
|
|
|
#include <limits>
|
|
|
|
namespace ZShell::components {
|
|
|
|
class LineGraphRenderer;
|
|
|
|
// A line graph with an optional grid, axis labels, y auto-scaling, a moving
|
|
// average, smoothed Catmull-Rom curve, an area fill and a marker. Static: it draws
|
|
// whatever `values` holds at the given x steps, unlike Sparkline which slides a
|
|
// rolling buffer. Both share curve smoothing and device-pixel alignment through
|
|
// internal::linegeometry.
|
|
class LineGraph : public QCanvasPainterItem {
|
|
Q_OBJECT
|
|
QML_ELEMENT
|
|
|
|
Q_PROPERTY(
|
|
QVariantList values READ values WRITE setValues NOTIFY valuesChanged
|
|
FINAL)
|
|
Q_PROPERTY(int xSteps READ xSteps WRITE setXSteps NOTIFY xStepsChanged FINAL)
|
|
Q_PROPERTY(qreal yMin READ yMin WRITE setYMin NOTIFY yMinChanged FINAL)
|
|
Q_PROPERTY(qreal yMax READ yMax WRITE setYMax NOTIFY yMaxChanged FINAL)
|
|
Q_PROPERTY(
|
|
qreal yPaddingTop READ yPaddingTop WRITE setYPaddingTop NOTIFY
|
|
yPaddingTopChanged FINAL)
|
|
Q_PROPERTY(
|
|
qreal yPaddingBottom READ yPaddingBottom WRITE setYPaddingBottom NOTIFY
|
|
yPaddingBottomChanged FINAL)
|
|
Q_PROPERTY(
|
|
int verticalLineStep READ verticalLineStep WRITE setVerticalLineStep
|
|
NOTIFY verticalLineStepChanged FINAL)
|
|
Q_PROPERTY(
|
|
int horizontalLineStep READ horizontalLineStep WRITE
|
|
setHorizontalLineStep NOTIFY horizontalLineStepChanged FINAL)
|
|
Q_PROPERTY(
|
|
bool firstXLine READ firstXLine WRITE setFirstXLine NOTIFY
|
|
firstXLineChanged FINAL)
|
|
Q_PROPERTY(
|
|
bool lastXLine READ lastXLine WRITE setLastXLine NOTIFY
|
|
lastXLineChanged FINAL)
|
|
Q_PROPERTY(
|
|
int minHorizontalLines READ minHorizontalLines WRITE
|
|
setMinHorizontalLines NOTIFY minHorizontalLinesChanged FINAL)
|
|
Q_PROPERTY(
|
|
XLabelMode xLabelMode READ xLabelMode WRITE setXLabelMode NOTIFY
|
|
xLabelModeChanged FINAL)
|
|
Q_PROPERTY(
|
|
bool useTwelveHourClock READ useTwelveHourClock WRITE
|
|
setUseTwelveHourClock NOTIFY useTwelveHourClockChanged FINAL)
|
|
Q_PROPERTY(
|
|
YLabelMode yLabelMode READ yLabelMode WRITE setYLabelMode NOTIFY
|
|
yLabelModeChanged FINAL)
|
|
Q_PROPERTY(
|
|
QString yLabelSuffix READ yLabelSuffix WRITE setYLabelSuffix NOTIFY
|
|
yLabelSuffixChanged FINAL)
|
|
Q_PROPERTY(
|
|
int yLabelDecimals READ yLabelDecimals WRITE setYLabelDecimals NOTIFY
|
|
yLabelDecimalsChanged FINAL)
|
|
Q_PROPERTY(
|
|
qreal smoothing READ smoothing WRITE setSmoothing NOTIFY
|
|
smoothingChanged FINAL)
|
|
Q_PROPERTY(
|
|
bool curveSmoothing READ curveSmoothing WRITE setCurveSmoothing NOTIFY
|
|
curveSmoothingChanged FINAL)
|
|
Q_PROPERTY(
|
|
qreal markerX READ markerX WRITE setMarkerX NOTIFY markerXChanged FINAL)
|
|
Q_PROPERTY(
|
|
qreal markerGap READ markerGap WRITE setMarkerGap NOTIFY
|
|
markerGapChanged FINAL)
|
|
Q_PROPERTY(
|
|
QColor lineColor READ lineColor WRITE setLineColor NOTIFY
|
|
lineColorChanged FINAL)
|
|
Q_PROPERTY(
|
|
QColor gridColor READ gridColor WRITE setGridColor NOTIFY
|
|
gridColorChanged FINAL)
|
|
Q_PROPERTY(
|
|
QColor markerColor READ markerColor WRITE setMarkerColor NOTIFY
|
|
markerColorChanged FINAL)
|
|
Q_PROPERTY(
|
|
QColor labelColor READ labelColor WRITE setLabelColor NOTIFY
|
|
labelColorChanged FINAL)
|
|
Q_PROPERTY(
|
|
qreal gridAlpha READ gridAlpha WRITE setGridAlpha NOTIFY
|
|
gridAlphaChanged FINAL)
|
|
Q_PROPERTY(
|
|
qreal labelAlpha READ labelAlpha WRITE setLabelAlpha NOTIFY
|
|
labelAlphaChanged FINAL)
|
|
Q_PROPERTY(
|
|
qreal fillAlpha READ fillAlpha WRITE setFillAlpha NOTIFY
|
|
fillAlphaChanged FINAL)
|
|
Q_PROPERTY(
|
|
qreal lineWidth READ lineWidth WRITE setLineWidth NOTIFY
|
|
lineWidthChanged FINAL)
|
|
Q_PROPERTY(
|
|
qreal markerDotRadius READ markerDotRadius WRITE setMarkerDotRadius
|
|
NOTIFY markerDotRadiusChanged FINAL)
|
|
Q_PROPERTY(
|
|
qreal labelFontSize READ labelFontSize WRITE setLabelFontSize NOTIFY
|
|
labelFontSizeChanged FINAL)
|
|
|
|
public:
|
|
// How an x tick (integer index 0..xSteps) is labelled. Hour renders an
|
|
// hour-of-day, honouring useTwelveHourClock.
|
|
enum class XLabelMode { None, Number, Hour };
|
|
Q_ENUM(XLabelMode)
|
|
|
|
// How a y tick value is labelled. Value renders the number rounded to
|
|
// yLabelDecimals places, followed by yLabelSuffix.
|
|
enum class YLabelMode { Off, Value };
|
|
Q_ENUM(YLabelMode)
|
|
|
|
explicit LineGraph(QQuickItem* parent = nullptr);
|
|
|
|
[[nodiscard]] QVariantList values() const;
|
|
void setValues(const QVariantList& values);
|
|
|
|
[[nodiscard]] int xSteps() const;
|
|
void setXSteps(int xSteps);
|
|
|
|
[[nodiscard]] qreal yMin() const;
|
|
void setYMin(qreal value);
|
|
|
|
[[nodiscard]] qreal yMax() const;
|
|
void setYMax(qreal value);
|
|
|
|
[[nodiscard]] qreal yPaddingTop() const;
|
|
void setYPaddingTop(qreal value);
|
|
|
|
[[nodiscard]] qreal yPaddingBottom() const;
|
|
void setYPaddingBottom(qreal value);
|
|
|
|
[[nodiscard]] int verticalLineStep() const;
|
|
void setVerticalLineStep(int step);
|
|
|
|
[[nodiscard]] int horizontalLineStep() const;
|
|
void setHorizontalLineStep(int step);
|
|
|
|
[[nodiscard]] bool firstXLine() const;
|
|
void setFirstXLine(bool show);
|
|
|
|
[[nodiscard]] bool lastXLine() const;
|
|
void setLastXLine(bool show);
|
|
|
|
[[nodiscard]] int minHorizontalLines() const;
|
|
void setMinHorizontalLines(int count);
|
|
|
|
[[nodiscard]] XLabelMode xLabelMode() const;
|
|
void setXLabelMode(XLabelMode mode);
|
|
|
|
[[nodiscard]] bool useTwelveHourClock() const;
|
|
void setUseTwelveHourClock(bool use);
|
|
|
|
[[nodiscard]] YLabelMode yLabelMode() const;
|
|
void setYLabelMode(YLabelMode mode);
|
|
|
|
[[nodiscard]] QString yLabelSuffix() const;
|
|
void setYLabelSuffix(const QString& suffix);
|
|
|
|
[[nodiscard]] int yLabelDecimals() const;
|
|
void setYLabelDecimals(int decimals);
|
|
|
|
[[nodiscard]] qreal smoothing() const;
|
|
void setSmoothing(qreal smoothing);
|
|
|
|
[[nodiscard]] bool curveSmoothing() const;
|
|
void setCurveSmoothing(bool enabled);
|
|
|
|
[[nodiscard]] qreal markerX() const;
|
|
void setMarkerX(qreal markerX);
|
|
|
|
[[nodiscard]] qreal markerGap() const;
|
|
void setMarkerGap(qreal gap);
|
|
|
|
[[nodiscard]] QColor lineColor() const;
|
|
void setLineColor(const QColor& color);
|
|
|
|
[[nodiscard]] QColor gridColor() const;
|
|
void setGridColor(const QColor& color);
|
|
|
|
[[nodiscard]] QColor markerColor() const;
|
|
void setMarkerColor(const QColor& color);
|
|
|
|
[[nodiscard]] QColor labelColor() const;
|
|
void setLabelColor(const QColor& color);
|
|
|
|
[[nodiscard]] qreal gridAlpha() const;
|
|
void setGridAlpha(qreal alpha);
|
|
|
|
[[nodiscard]] qreal labelAlpha() const;
|
|
void setLabelAlpha(qreal alpha);
|
|
|
|
[[nodiscard]] qreal fillAlpha() const;
|
|
void setFillAlpha(qreal alpha);
|
|
|
|
[[nodiscard]] qreal lineWidth() const;
|
|
void setLineWidth(qreal width);
|
|
|
|
[[nodiscard]] qreal markerDotRadius() const;
|
|
void setMarkerDotRadius(qreal radius);
|
|
|
|
[[nodiscard]] qreal labelFontSize() const;
|
|
void setLabelFontSize(qreal size);
|
|
|
|
signals:
|
|
void valuesChanged();
|
|
void xStepsChanged();
|
|
void yMinChanged();
|
|
void yMaxChanged();
|
|
void yPaddingTopChanged();
|
|
void yPaddingBottomChanged();
|
|
void verticalLineStepChanged();
|
|
void horizontalLineStepChanged();
|
|
void firstXLineChanged();
|
|
void lastXLineChanged();
|
|
void minHorizontalLinesChanged();
|
|
void xLabelModeChanged();
|
|
void useTwelveHourClockChanged();
|
|
void yLabelModeChanged();
|
|
void yLabelSuffixChanged();
|
|
void yLabelDecimalsChanged();
|
|
void smoothingChanged();
|
|
void curveSmoothingChanged();
|
|
void markerXChanged();
|
|
void markerGapChanged();
|
|
void lineColorChanged();
|
|
void gridColorChanged();
|
|
void markerColorChanged();
|
|
void labelColorChanged();
|
|
void gridAlphaChanged();
|
|
void labelAlphaChanged();
|
|
void fillAlphaChanged();
|
|
void lineWidthChanged();
|
|
void markerDotRadiusChanged();
|
|
void labelFontSizeChanged();
|
|
|
|
protected:
|
|
[[nodiscard]] QCanvasPainterItemRenderer* createItemRenderer()
|
|
const override;
|
|
|
|
// Device-pixel snapping and stroke width are quantized in device pixels, so
|
|
// they must use the ratio the window actually has.
|
|
void itemChange(ItemChange change, const ItemChangeData& value) override;
|
|
|
|
private:
|
|
friend class LineGraphRenderer;
|
|
|
|
QVariantList m_values;
|
|
int m_xSteps = 24;
|
|
qreal m_yMin = std::numeric_limits<qreal>::quiet_NaN();
|
|
qreal m_yMax = std::numeric_limits<qreal>::quiet_NaN();
|
|
qreal m_yPaddingTop = 0.0;
|
|
qreal m_yPaddingBottom = 0.0;
|
|
int m_verticalLineStep = 0;
|
|
int m_horizontalLineStep = 0;
|
|
bool m_firstXLine = true;
|
|
bool m_lastXLine = false;
|
|
int m_minHorizontalLines = 0;
|
|
XLabelMode m_xLabelMode = XLabelMode::None;
|
|
bool m_useTwelveHourClock = false;
|
|
YLabelMode m_yLabelMode = YLabelMode::Off;
|
|
QString m_yLabelSuffix;
|
|
int m_yLabelDecimals = 0;
|
|
qreal m_smoothing = 0.0;
|
|
bool m_curveSmoothing = true;
|
|
qreal m_markerX = -1.0;
|
|
qreal m_markerGap = 2.0;
|
|
QColor m_lineColor = Qt::white;
|
|
QColor m_gridColor = Qt::white;
|
|
QColor m_markerColor = Qt::white;
|
|
QColor m_labelColor = Qt::white;
|
|
qreal m_gridAlpha = 0.12;
|
|
qreal m_labelAlpha = 0.6;
|
|
qreal m_fillAlpha = 0.15;
|
|
qreal m_lineWidth = 2.0;
|
|
qreal m_markerDotRadius = 4.0;
|
|
qreal m_labelFontSize = 8.0;
|
|
qreal m_dpr = 1.0;
|
|
};
|
|
|
|
} // namespace ZShell::components
|