162 lines
3.5 KiB
C++
162 lines
3.5 KiB
C++
#pragma once
|
|
|
|
#include "../mischelpers_global.h"
|
|
|
|
class MISCHELPERS_EXPORT CHistoryGraph: public QObject
|
|
{
|
|
public:
|
|
CHistoryGraph(bool bSimpleMode = false, QColor BkG = Qt::white, QObject* parent = NULL) : QObject(parent) {
|
|
m_SimpleMode = bSimpleMode;
|
|
m_BkG = BkG;
|
|
}
|
|
~CHistoryGraph() {}
|
|
|
|
void AddValue(int Id, QColor Color)
|
|
{
|
|
m_Values.insert(Id, { 0.0, Color });
|
|
}
|
|
|
|
void SetValue(int Id, float Value)
|
|
{
|
|
m_Values[Id].Value = Value;
|
|
}
|
|
|
|
void Update(int CellHeight, int CellWidth)
|
|
{
|
|
Update(m_Graph, m_BkG, m_Values, CellHeight, CellWidth, m_SimpleMode);
|
|
}
|
|
|
|
QImage GetImage() const { return m_Graph; }
|
|
|
|
struct SValue
|
|
{
|
|
float Value;
|
|
QColor Color;
|
|
};
|
|
|
|
static void Update(QImage& m_Graph, const QColor& m_BkG, const QMap<int, SValue>& m_Values, int CellHeight, int CellWidth, bool m_SimpleMode = true)
|
|
{
|
|
// init / resize
|
|
if(m_Graph.height() != CellWidth /*|| m_Graph.width() != curHeight*/)
|
|
{
|
|
QImage Graph = QImage(CellHeight, CellWidth, QImage::Format_RGB32);
|
|
QPainter qp(&Graph);
|
|
qp.fillRect(-1, -1, CellHeight+1, CellWidth+1, m_BkG);
|
|
if (!m_Graph.isNull())
|
|
qp.drawImage(0, Graph.height() - m_Graph.height(), m_Graph);
|
|
m_Graph = Graph;
|
|
}
|
|
|
|
// shift
|
|
uchar *dest = m_Graph.bits();
|
|
int pos = m_Graph.sizeInBytes() - m_Graph.bytesPerLine();
|
|
memmove(dest, dest + m_Graph.bytesPerLine(), pos);
|
|
QPainter qp(&m_Graph);
|
|
|
|
// draw new data points
|
|
int top = 0;
|
|
|
|
#if 0
|
|
foreach(const SValue& Value, m_Values)
|
|
{
|
|
int x = (float)(m_Graph.width()) * Value.Value;
|
|
if (x > top)
|
|
top = x;
|
|
|
|
qp.setPen(Value.Color);
|
|
qp.drawLine(0, m_Graph.height() - 1, x, m_Graph.height());
|
|
}
|
|
|
|
qp.setPen(Qt::white);
|
|
qp.drawLine(top, m_Graph.height() - 1, m_Graph.width()-1, m_Graph.height());
|
|
#else
|
|
dest += pos;
|
|
memset(dest, 0, m_Graph.bytesPerLine()); // fill line black
|
|
ASSERT(m_Graph.depth() == 32);
|
|
int max = m_Graph.width();
|
|
//ASSERT(max * 4 == m_Graph.bytesPerLine());
|
|
|
|
foreach(const SValue& Value, m_Values)
|
|
{
|
|
int x = (float)(max) * Value.Value;
|
|
if (x > max)
|
|
x = max;
|
|
if (x > top)
|
|
top = x;
|
|
x *= 4;
|
|
|
|
int r, g, b;
|
|
Value.Color.getRgb(&r, &g, &b);
|
|
|
|
|
|
for (int i = 0; i < x; i += 4)
|
|
{
|
|
if (m_SimpleMode || *(quint32*)(dest + i) == 0)
|
|
{
|
|
dest[i ] = b;
|
|
dest[i + 1] = g;
|
|
dest[i + 2] = r;
|
|
}
|
|
else
|
|
{
|
|
#define DIV 4/5
|
|
int cb = (int)dest[i ]*DIV + b*DIV;
|
|
int cg = (int)dest[i + 1]*DIV + g*DIV;
|
|
int cr = (int)dest[i + 2]*DIV + r*DIV;
|
|
|
|
dest[i ] = qMin(cb, 255);
|
|
dest[i + 1] = qMin(cg, 255);
|
|
dest[i + 2] = qMin(cr, 255);
|
|
}
|
|
}
|
|
}
|
|
|
|
// fill what's left of the line
|
|
/*top *= 4;
|
|
if (top < m_Graph.bytesPerLine()) // fill rest white
|
|
memset(dest + top, 0xFF, m_Graph.bytesPerLine() - top);*/
|
|
{
|
|
int r, g, b;
|
|
m_BkG.getRgb(&r, &g, &b);
|
|
|
|
top *= 4;
|
|
max *= 4;
|
|
for (int i = top; i < max; i += 4)
|
|
{
|
|
dest[i] = b;
|
|
dest[i + 1] = g;
|
|
dest[i + 2] = r;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
protected:
|
|
QImage m_Graph;
|
|
QColor m_BkG;
|
|
QMap<int, SValue> m_Values;
|
|
bool m_SimpleMode;
|
|
};
|
|
|
|
class CHistoryWidget: public QWidget
|
|
{
|
|
public:
|
|
CHistoryWidget(CHistoryGraph* pHistoryGraph, QWidget* parent = NULL) : QWidget(parent) { m_pHistoryGraph = pHistoryGraph; }
|
|
~CHistoryWidget() {}
|
|
|
|
protected:
|
|
void paintEvent(QPaintEvent* e)
|
|
{
|
|
if (m_pHistoryGraph)
|
|
{
|
|
QImage HistoryGraph = m_pHistoryGraph->GetImage();
|
|
QPainter qp(this);
|
|
qp.translate(width() - HistoryGraph.height() - 1, height());
|
|
qp.rotate(270);
|
|
qp.drawImage(0, 0, HistoryGraph);
|
|
}
|
|
}
|
|
|
|
QPointer<CHistoryGraph> m_pHistoryGraph;
|
|
};
|