Mercurial > minori
comparison include/gui/widgets/graph.h @ 202:71832ffe425a
animia: re-add kvm fd source
this is all being merged from my wildly out-of-date laptop. SORRY!
in other news, I edited the CI file to install the wayland client
as well, so the linux CI build might finally get wayland stuff.
| author | Paper <paper@paper.us.eu.org> |
|---|---|
| date | Tue, 02 Jan 2024 06:05:06 -0500 |
| parents | 45a0967485f1 |
| children | 862d0d8619f6 |
comparison
equal
deleted
inserted
replaced
| 201:8f6f8dd2eb23 | 202:71832ffe425a |
|---|---|
| 13 #include <QPainterPath> | 13 #include <QPainterPath> |
| 14 #include <QPen> | 14 #include <QPen> |
| 15 #include <algorithm> | 15 #include <algorithm> |
| 16 #include <unordered_map> | 16 #include <unordered_map> |
| 17 | 17 |
| 18 template <typename T> | 18 template<typename T> |
| 19 class Graph final : public QWidget { | 19 class Graph final : public QWidget { |
| 20 public: | 20 public: |
| 21 Graph(QWidget* parent = nullptr) : QWidget(parent) {}; | 21 Graph(QWidget* parent = nullptr) : QWidget(parent) {}; |
| 22 void AddItem(T key, unsigned long val) { map[key] = val; update(); updateGeometry(); }; | 22 void AddItem(T key, unsigned long val) { map[key] = val; update(); updateGeometry(); }; |
| 23 void Clear() { map.clear(); update(); updateGeometry(); }; | 23 void Clear() { map.clear(); update(); updateGeometry(); }; |
| 24 | 24 |
| 25 protected: | 25 protected: |
| 26 static constexpr int SPACING = 5; | 26 std::unordered_map<T, unsigned long> map = {}; |
| 27 | |
| 28 QSize minimumSizeHint() const override { | |
| 29 QFontMetrics metric(font()); | |
| 30 /* wtf?... */ | |
| 31 return QSize(100, metric.height() * map.size() + (2 * (map.size() - 2))); | |
| 32 } | |
| 33 | |
| 34 /* helper functions */ | |
| 27 inline unsigned long GetTotal() { | 35 inline unsigned long GetTotal() { |
| 28 unsigned long count = 0; | 36 unsigned long count = 0; |
| 37 | |
| 29 for (const auto& item : map) | 38 for (const auto& item : map) |
| 30 count += item.second; | 39 count += item.second; |
| 40 | |
| 31 return count; | 41 return count; |
| 32 } | 42 } |
| 33 QSize minimumSizeHint() const override { | 43 |
| 34 QFontMetrics metric(font()); | |
| 35 return QSize(100, metric.height() * map.size() + 2 * (map.size() - 2)); | |
| 36 }; | |
| 37 inline unsigned long GetTextWidth() { | 44 inline unsigned long GetTextWidth() { |
| 38 unsigned long ret = 0; | 45 unsigned long ret = 0; |
| 39 QFontMetrics metric(font()); | 46 QFontMetrics metric(font()); |
| 47 | |
| 40 for (const auto& item : map) { | 48 for (const auto& item : map) { |
| 41 unsigned long width = metric.boundingRect(QString::number(item.first)).width(); | 49 unsigned long width = metric.horizontalAdvance(QString::number(item.first), -1); |
| 42 if (width > ret) | 50 if (width > ret) |
| 43 ret = width; | 51 ret = width; |
| 44 } | 52 } |
| 53 | |
| 45 return ret; | 54 return ret; |
| 46 } | 55 } |
| 56 | |
| 47 void paintEvent(QPaintEvent* event) override { | 57 void paintEvent(QPaintEvent* event) override { |
| 58 static constexpr int HORIZ_SPACING = 5; | |
| 59 static constexpr int VERT_SPACING = 2; | |
| 60 | |
| 61 /* these are retrieved from the QPaintEvent */ | |
| 48 const QRect rect = event->rect(); | 62 const QRect rect = event->rect(); |
| 49 const int height_of_each = QFontMetrics(font()).height(); | 63 const int width = event->rect().width(); |
| 50 const int size = GetTotal(); | 64 const int x = rect.x(); |
| 51 const int text_width = GetTextWidth(); | 65 int y = rect.y(); |
| 52 int current_y = rect.y(); | 66 |
| 67 /* these are calculated from font metrics and such */ | |
| 68 const int total = GetTotal(); | |
| 69 const int text_width = GetTextWidth() + 10; | |
| 70 const int each_height = QFontMetrics(font()).height(); | |
| 53 | 71 |
| 54 /* now we do the actual painting */ | 72 /* now we do the actual painting */ |
| 55 QPainter painter(this); | 73 QPainter painter(this); |
| 56 | 74 |
| 57 for (const auto& item : map) { | 75 for (const auto& [key, value] : map) { |
| 58 painter.drawText(QRect(rect.x(), current_y, text_width, height_of_each), Qt::AlignRight | Qt::AlignVCenter, QString::number(item.first)); | 76 painter.drawText(QRect(x, y, text_width, each_height), Qt::AlignVCenter, QString::number(key)); |
| 59 | 77 |
| 60 if (size) { | 78 /* only draw this if we actually have any data */ |
| 61 painter.save(); | 79 if (total) { |
| 62 | |
| 63 QPen pen(Qt::transparent, 0); | |
| 64 painter.setPen(pen); | |
| 65 | |
| 66 QPainterPath path; | 80 QPainterPath path; |
| 67 path.addRect(rect.x() + text_width + SPACING, current_y, (static_cast<double>(item.second)/size)*(rect.width() - text_width - SPACING), height_of_each); | 81 path.addRect(x + text_width + HORIZ_SPACING, y, (static_cast<double>(value)/total) * (width - text_width - HORIZ_SPACING), each_height); |
| 68 painter.fillPath(path, Qt::darkBlue); | 82 painter.fillPath(path, Qt::darkBlue); |
| 69 painter.drawPath(path); | 83 painter.drawPath(path); |
| 84 } | |
| 70 | 85 |
| 71 painter.restore(); | 86 y += each_height + VERT_SPACING; |
| 72 } | |
| 73 current_y += height_of_each + 2; | |
| 74 } | 87 } |
| 75 }; | 88 } |
| 76 std::unordered_map<T, unsigned long> map = {}; | |
| 77 }; | 89 }; |
| 78 | 90 |
| 79 #endif // __gui__widgets__graph_h | 91 #endif // __gui__widgets__graph_h |
