Mercurial > minori
view include/gui/widgets/graph.h @ 365:f81bed4e04ac
*: megacommit that probably breaks things
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Wed, 02 Oct 2024 23:06:43 -0400 |
parents | f31305b9f60a |
children |
line wrap: on
line source
#ifndef MINORI_GUI_WIDGETS_GRAPH_H_ #define MINORI_GUI_WIDGETS_GRAPH_H_ /* This class is defined as a template, so that means everything gets defined here as well :) */ #include <QDebug> #include <QPaintEvent> #include <QPainter> #include <QPainterPath> #include <QPen> #include <QRect> #include <QSize> #include <QWidget> #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: static constexpr int HORIZ_SPACING = 5; static constexpr int VERT_SPACING = 3; std::unordered_map<T, unsigned long> map = {}; QSize minimumSizeHint() const override { QFontMetrics metric(font()); /* wtf?... */ return QSize(100, (metric.height() * map.size()) + (VERT_SPACING * map.size())); } /* 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.boundingRect(QString::number(item.first)).width(); if (width > ret) ret = width; } return ret; } inline unsigned long GetValueWidth() { unsigned long ret = 0; QFontMetrics metric(font()); for (const auto& item : map) { unsigned long width = metric.boundingRect(QString::number(item.second)).width(); if (width > ret) ret = width; } return ret; } void paintEvent(QPaintEvent* event) override { /* these are retrieved from the QPaintEvent */ const QRect rect = event->rect(); const int width = 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(); const int value_width = GetValueWidth(); const int each_height = QFontMetrics(font()).height(); /* now we do the actual painting */ QPainter painter(this); for (const auto& [key, value] : map) { int offset = 0; painter.drawText(QRect(x, y, text_width, each_height), Qt::AlignVCenter | Qt::AlignRight, QString::number(key)); offset += text_width + HORIZ_SPACING; /* only draw this if we actually have any data */ if (total) { const int rect_width = (static_cast<double>(value) / total) * (width - offset - HORIZ_SPACING - value_width); painter.save(); QPen pen(painter.pen()); pen.setStyle(Qt::NoPen); painter.setPen(pen); QPainterPath path; path.addRect(x + offset, y, rect_width, each_height); painter.fillPath(path, Qt::darkGreen); painter.drawPath(path); offset += rect_width; painter.restore(); } offset += HORIZ_SPACING; painter.drawText(QRect(x + offset, y, value_width, each_height), Qt::AlignVCenter | Qt::AlignLeft, QString::number(value)); y += each_height + VERT_SPACING; } } }; #endif // MINORI_GUI_WIDGETS_GRAPH_H_