view include/gui/widgets/graph.h @ 118:39521c47c7a3

*: another huge megacommit, SORRY The torrents page works a lot better now Added the edit option to the anime list right click menu Vectorized currently playing files Available player and extensions are now loaded at runtime from files in (dotpath)/players.json and (dotpath)/extensions.json These paths are not permanent and will likely be moved to (dotpath)/recognition ... ... ...
author Paper <mrpapersonic@gmail.com>
date Tue, 07 Nov 2023 23:40:54 -0500
parents b315f3759c56
children 03b444cbe55f
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:
		static constexpr int SPACING = 5;
		inline unsigned long GetTotal() {
			unsigned long count = 0;
			for (const auto& item : map)
				count += item.second;
			return count;
		}
		QSize minimumSizeHint() const override {
			QFontMetrics metric(font());
			return QSize(100, metric.height() * map.size() + 2 * (map.size() - 2));
		};
		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;
		}
		void paintEvent(QPaintEvent* event) override {
			const QRect rect = event->rect();
			const int height_of_each = QFontMetrics(font()).height();
			const int size = GetTotal();
			const int text_width = GetTextWidth();
			int current_y = rect.y();

			/* now we do the actual painting */
			QPainter painter(this);

			for (const auto& item : map) {
				painter.drawText(QRect(rect.x(), current_y, text_width, height_of_each), Qt::AlignRight | Qt::AlignVCenter, QString::number(item.first));

				if (size) {
					painter.save();

					QPen pen(Qt::transparent, 0);
					painter.setPen(pen);

					QPainterPath path;
					path.addRect(rect.x() + text_width + SPACING, current_y, (static_cast<double>(item.second)/size)*(rect.width() - text_width - SPACING), height_of_each);
					painter.fillPath(path, Qt::darkBlue);
					painter.drawPath(path);

					painter.restore();
				}
				current_y += height_of_each + 2;
			}
		};
		std::unordered_map<T, unsigned long> map = {};
};

#endif // __gui__widgets__graph_h