Add SVG icon rendering/cache

This commit is contained in:
Petr Mrázek
2013-03-20 07:59:35 +01:00
parent 7d7e4034f4
commit e4806ab08d
6 changed files with 187 additions and 36 deletions

127
gui/iconcache.cpp Normal file
View File

@ -0,0 +1,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"

43
gui/iconcache.h Normal file
View File

@ -0,0 +1,43 @@
#pragma once
#include <QMutex>
#include <QtGui/QIcon>
class Private;
class IconCache
{
public:
static IconCache* instance()
{
if (!m_Instance)
{
mutex.lock();
if (!m_Instance)
m_Instance = new IconCache;
mutex.unlock();
}
return m_Instance;
}
static void drop()
{
mutex.lock();
delete m_Instance;
m_Instance = 0;
mutex.unlock();
}
QIcon getIcon(QString name);
private:
IconCache();
// hide copy constructor
IconCache(const IconCache &);
// hide assign op
IconCache& operator=(const IconCache &);
static IconCache* m_Instance;
static QMutex mutex;
Private* d;
};

View File

@ -1,6 +1,7 @@
#include "instancemodel.h"
#include <instance.h>
#include <QIcon>
#include "iconcache.h"
InstanceModel::InstanceModel ( const InstanceList& instances, QObject *parent )
: QAbstractListModel ( parent ), m_instances ( &instances )
@ -70,11 +71,15 @@ QVariant InstanceModel::data ( const QModelIndex& index, int role ) const
}
case Qt::DecorationRole:
{
IconCache * ic = IconCache::instance();
// FIXME: replace with an icon cache/renderer
/*
QString path = ":/icons/instances/";
path += pdata->iconKey();
QIcon icon(path);
return icon;
*/
QString key = pdata->iconKey();
return ic->getIcon(key);
//else return QIcon(":/icons/multimc/scalable/apps/multimc.svg");
}
// for now.

View File

@ -71,6 +71,7 @@ MainWindow::MainWindow ( QWidget *parent ) :
pal.setBrush(QPalette::Base, QBrush(QPixmap(QString::fromUtf8(":/backgrounds/kitteh"))));
view->setPalette(pal);
*/
view->setStyleSheet(
"QListView\
{\