Mercurial > minori
view include/gui/widgets/graph.h @ 253:b3549da699a6
*: ooooh! stupid big commit!
oops
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Tue, 06 Feb 2024 16:56:32 -0500 |
parents | 45a0967485f1 |
children | 862d0d8619f6 |
line wrap: on
line source
#ifndef __gui__widgets__graph_h #define __gui__widgets__graph_h /* This class is defined as a template, so that means everything gets defined here as well :) */ #include <QWidget> #include <QDebug> #include <QSize> #include <QPaintEvent> #include <QSize> #include <QRect> #include <QPainter> #include <QPainterPath> #include <QPen> #include <algorithm> #include <unordered_map> template<typename T> class Graph final : public QWidget { public: Graph(QWidget* parent = nullptr) : QWidget(parent) {}; void AddItem(T key, unsigned long val) { map[key] = val; update(); updateGeometry(); }; void Clear() { map.clear(); update(); updateGeometry(); }; protected: std::unordered_map<T, unsigned long> map = {}; QSize minimumSizeHint() const override { QFontMetrics metric(font()); /* wtf?... */ return QSize(100, metric.height() * map.size() + (2 * (map.size() - 2))); } /* helper functions */ inline unsigned long GetTotal() { unsigned long count = 0; for (const auto& item : map) count += item.second; return count; } inline unsigned long GetTextWidth() { unsigned long ret = 0; QFontMetrics metric(font()); for (const auto& item : map) { unsigned long width = metric.horizontalAdvance(QString::number(item.first), -1); if (width > ret) ret = width; } return ret; } void paintEvent(QPaintEvent* event) override { static constexpr int HORIZ_SPACING = 5; static constexpr int VERT_SPACING = 2; /* these are retrieved from the QPaintEvent */ const QRect rect = event->rect(); const int width = event->rect().width(); const int x = rect.x(); int y = rect.y(); /* these are calculated from font metrics and such */ const int total = GetTotal(); const int text_width = GetTextWidth() + 10; const int each_height = QFontMetrics(font()).height(); /* now we do the actual painting */ QPainter painter(this); for (const auto& [key, value] : map) { painter.drawText(QRect(x, y, text_width, each_height), Qt::AlignVCenter, QString::number(key)); /* only draw this if we actually have any data */ if (total) { QPainterPath path; path.addRect(x + text_width + HORIZ_SPACING, y, (static_cast<double>(value)/total) * (width - text_width - HORIZ_SPACING), each_height); painter.fillPath(path, Qt::darkBlue); painter.drawPath(path); } y += each_height + VERT_SPACING; } } }; #endif // __gui__widgets__graph_h