summaryrefslogtreecommitdiffstats
path: root/gui/iconcache.cpp
blob: 520a7839a68ace9f6f02330fa5ee9ee096649dfe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include "iconcache.h"
#include <QMap>
#include <QWebView>
#include <QWebFrame>
#include <QEventLoop>
#include <QWebElement>

IconCache* IconCache::m_Instance = 0;
QMutex IconCache::mutex;
#define MAX_SIZE 1024

class Private : public QWebView
{
	Q_OBJECT

public:
	QString name;
	QSize size;
	QMap<QString, QIcon> icons;

public:
	Private()
	{
		connect(this, SIGNAL(loadFinished(bool)), this, SLOT(svgLoaded(bool)));
		setFixedSize(MAX_SIZE, MAX_SIZE);

		QPalette pal = palette();
		pal.setColor(QPalette::Base, Qt::transparent);
		setPalette(pal);
		setAttribute(Qt::WA_OpaquePaintEvent, false);
		size = QSize(128,128);
	}
	void renderSVGIcon(QString name);

signals:
	void svgRendered();

private slots:
	void svgLoaded(bool ok);
};

void Private::svgLoaded(bool ok)
{
	if (!ok)
	{
		emit svgRendered();
		return;
	}
	// check for SVG root tag
	QString root = page()->currentFrame()->documentElement().tagName();
	if (root.compare("svg", Qt::CaseInsensitive) != 0)
	{
		emit svgRendered();
		return;
	}

    // get the size of the svg image, check if it's valid
	auto elem = page()->currentFrame()->documentElement();
	double width = elem.attribute("width").toDouble();
	double height = elem.attribute("height").toDouble();
    if (width == 0.0 || height == 0.0 || width == MAX_SIZE || height == MAX_SIZE)
	{
		emit svgRendered();
		return;
	}

	// create the target surface
	QSize t = size.isValid() ? size : QSize(width, height);
	QImage img(t, QImage::Format_ARGB32_Premultiplied);
	img.fill(Qt::transparent);

	// prepare the painter, scale to required size
	QPainter p(&img);
	if(size.isValid())
	{
		p.scale(size.width() / width, size.height() / height);
	}

	// the best quality
	p.setRenderHint(QPainter::Antialiasing);
	p.setRenderHint(QPainter::TextAntialiasing);
	p.setRenderHint(QPainter::SmoothPixmapTransform);

	page()->mainFrame()->render(&p,QWebFrame::ContentsLayer);
	p.end();

	icons[name] = QIcon(QPixmap::fromImage(img));
	emit svgRendered();
}

void Private::renderSVGIcon ( QString name )
{
	// use event loop to wait for signal
	QEventLoop loop;
	this->name = name;
	QString prefix = "qrc:/icons/instances/";
	QObject::connect(this, SIGNAL(svgRendered()), &loop, SLOT(quit()));
	load(QUrl(prefix + name));
	loop.exec();
}

IconCache::IconCache():d(new Private())
{
}

QIcon IconCache::getIcon ( QString name )
{
	if(name == "default")
		name = "infinity";
	{
		auto iter = d->icons.find(name);
		if(iter != d->icons.end())
			return *iter;
	}
	d->renderSVGIcon(name);
	auto iter = d->icons.find(name);
	if(iter != d->icons.end())
		return *iter;
	
	// Fallback for icons that don't exist.
	QString path = ":/icons/instances/infinity";
	//path += name;
	d->icons[name] = QIcon(path);
	return d->icons[name];
}

#include "iconcache.moc"