Mercurial > minori
view include/gui/widgets/graph.h @ 187:9613d72b097e
*: multiple performance improvements
like marking `static const` when it makes sense...
date: change old stupid heap-based method to a structure which should
make copying the thing actually make a copy.
also many performance-based changes, like removing the std::tie
dependency and forward-declaring nlohmann json
*: replace every instance of QString::fromUtf8 to Strings::ToQString.
the main difference is that our function will always convert exactly
what is in the string, while some other times it would only convert
up to the nearest NUL byte
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Wed, 06 Dec 2023 13:43:54 -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