96 lines
2.8 KiB
C++
96 lines
2.8 KiB
C++
#pragma once
|
|
|
|
#include <qcolor.h>
|
|
#include <qelapsedtimer.h>
|
|
#include <qpainterpath.h>
|
|
#include <qquickpainteditem.h>
|
|
|
|
#include "internal/circularbuffer.hpp"
|
|
|
|
namespace ZShell::components {
|
|
|
|
class SparklineContent : public QQuickPaintedItem {
|
|
Q_OBJECT
|
|
|
|
public:
|
|
explicit SparklineContent(QQuickItem* parent = nullptr);
|
|
|
|
void paint(QPainter* painter) override;
|
|
|
|
void setLine1(internal::CircularBuffer* buffer);
|
|
void setLine2(internal::CircularBuffer* buffer);
|
|
void setLine1Color(const QColor& color);
|
|
void setLine2Color(const QColor& color);
|
|
void setLine1FillAlpha(qreal alpha);
|
|
void setLine2FillAlpha(qreal alpha);
|
|
void setMaxValue(qreal value);
|
|
void setLineWidth(qreal width);
|
|
void setCurveSmoothing(bool enabled);
|
|
void setHistoryLength(int length);
|
|
void setSliding(bool sliding);
|
|
|
|
void setViewportSize(qreal viewportWidth, qreal viewportHeight);
|
|
|
|
// How often a new sample arrives, in milliseconds. With this set the slide
|
|
// phase is read from the sample clock rather than from `progress`, which
|
|
// makes the wrap exact; without it the phase is the value QML supplies.
|
|
void setSlideInterval(qreal intervalMs);
|
|
|
|
// Offsets the item for the slide. Kept here rather than in SparklineItem
|
|
// because the quantization needs both stepX() and the window's dpr.
|
|
void setSlideProgress(qreal progress);
|
|
|
|
[[nodiscard]] qreal stepX() const;
|
|
|
|
protected:
|
|
// The stroke width, sample spacing and plot bounds are quantized in device
|
|
// pixels, so they have to be built with the ratio the window actually has.
|
|
void itemChange(ItemChange change, const ItemChangeData& value) override;
|
|
|
|
private:
|
|
struct LineGeometry {
|
|
QPainterPath stroke;
|
|
QPainterPath fill;
|
|
bool hasData = false;
|
|
};
|
|
|
|
[[nodiscard]] qreal slidePhase(qreal progress) const;
|
|
|
|
void invalidate();
|
|
void rebuildIfNeeded();
|
|
[[nodiscard]] LineGeometry buildGeometry(
|
|
internal::CircularBuffer* buffer) const;
|
|
void connectBuffer(internal::CircularBuffer* buffer);
|
|
void applyGeometry();
|
|
void onSampleArrived();
|
|
|
|
internal::CircularBuffer* m_line1 = nullptr;
|
|
internal::CircularBuffer* m_line2 = nullptr;
|
|
QColor m_line1Color;
|
|
QColor m_line2Color;
|
|
qreal m_line1FillAlpha = 0.15;
|
|
qreal m_line2FillAlpha = 0.2;
|
|
qreal m_maxValue = 1024.0;
|
|
qreal m_lineWidth = 2.0;
|
|
bool m_curveSmoothing = false;
|
|
int m_historyLength = 30;
|
|
bool m_sliding = true;
|
|
|
|
qreal m_viewportW = 0.0;
|
|
qreal m_viewportH = 0.0;
|
|
// The height actually painted, snapped so the texture maps 1:1 onto device
|
|
// rows. The plot bounds are built from this, not from the slot's height.
|
|
qreal m_paintedH = 0.0;
|
|
qreal m_dpr = 1.0;
|
|
qreal m_slideIntervalMs = 0.0;
|
|
// Restarted whenever a sample arrives, so the slide phase follows the sample
|
|
// cadence instead of the animation's timeline.
|
|
QElapsedTimer m_sampleClock;
|
|
|
|
LineGeometry m_geom1;
|
|
LineGeometry m_geom2;
|
|
bool m_dirty = true;
|
|
};
|
|
|
|
} // namespace ZShell::components
|